Packages
phoenix_duskmoon
9.4.3
9.9.2
9.9.1
9.9.0
9.8.0
9.7.1
9.7.0
9.6.4
9.6.3
9.6.2
9.6.1
9.6.0
9.5.4
9.5.3
9.5.2
9.5.1
9.5.0
9.4.3
9.4.2
9.4.1
9.4.0
9.3.0
9.2.0
9.1.4
9.1.3
9.1.1
9.1.1-rc.1
retired
9.0.1
9.0.0-rc.3
9.0.0-rc.2
9.0.0-rc.1
8.0.0
7.2.1
7.2.0
7.1.3
7.1.2
7.1.1
6.3.2
6.3.1
6.3.0
6.2.0
6.1.3
6.1.2
6.1.1
6.1.0
6.0.10
6.0.9
6.0.8
6.0.7
6.0.6
6.0.5
6.0.4
6.0.3
6.0.2
6.0.1
6.0.0
5.2.0-beta.5
5.2.0-beta.4
5.2.0-beta.3
5.2.0-beta.2
5.2.0-beta.1
5.1.0
5.0.6
5.0.5
5.0.4
5.0.3
5.0.2
5.0.1
5.0.0
4.6.6
4.6.5
4.6.4
4.6.3
4.6.2
4.6.1
4.6.0
4.5.2
4.5.1
4.5.0
4.4.4
4.4.3
4.4.2
4.4.1
4.4.0
4.3.2
4.3.1
4.3.0
4.2.0
4.1.1
4.1.0
4.0.0
Duskmoon UI component library for Phoenix LiveView
Current section
Files
Jump to
Current section
Files
priv/static/phoenix_duskmoon.js
// assets/js/phoenix_duskmoon.js
var DM_EVENTS = [
"dm-click",
"dm-change",
"dm-input",
"dm-focus",
"dm-blur",
"dm-submit",
"dm-select",
"dm-close",
"dm-open",
"dm-toggle"
];
var WebComponentHook = {
mounted() {
this._sendListeners = [];
this._setupEventBridging();
this._setupAutomaticForwarding();
},
updated() {
this._setupAutomaticForwarding();
},
destroyed() {
if (this._sendListeners) {
this._sendListeners.forEach(({ event, listener }) => {
this.el.removeEventListener(event, listener);
});
this._sendListeners = null;
}
DM_EVENTS.forEach((dmEvent) => {
const listenerKey = `_dm_listener_${dmEvent}`;
if (this[listenerKey]) {
this.el.removeEventListener(dmEvent, this[listenerKey]);
this[listenerKey] = null;
}
});
},
_setupEventBridging() {
const attrs = this.el.attributes;
const phxTarget = this.el.getAttribute("phx-target");
const pushEvent = (event, payload, callback) => {
if (phxTarget) {
this.pushEventTo(phxTarget, event, payload, callback);
} else {
this.pushEvent(event, payload, callback);
}
};
for (let i = 0;i < attrs.length; i++) {
const attr = attrs[i];
if (/^duskmoon-send-/.test(attr.name)) {
const eventName = attr.name.replace(/^duskmoon-send-/, "");
const [phxEvent, callbackName] = attr.value.split(";");
const listener = ({ detail }) => {
pushEvent(phxEvent, detail || {}, (response) => {
if (callbackName && typeof this[callbackName] === "function") {
this[callbackName](response, detail, eventName);
}
});
};
this.el.addEventListener(eventName, listener);
this._sendListeners.push({ event: eventName, listener });
}
if (/^duskmoon-receive-/.test(attr.name)) {
const eventName = attr.name.replace(/^duskmoon-receive-/, "");
const handler = attr.value;
this.handleEvent(eventName, (payload) => {
if (handler && typeof this.el[handler] === "function") {
this.el[handler](payload);
} else {
this.el.dispatchEvent(new CustomEvent(eventName, {
detail: payload,
bubbles: true,
composed: true
}));
}
});
}
if (attr.name === "duskmoon-receive") {
const [phxEvent, callbackName] = attr.value.split(";");
this.handleEvent(phxEvent, (payload) => {
if (typeof this.el[callbackName] === "function") {
this.el[callbackName](payload);
}
});
}
}
},
_setupAutomaticForwarding() {
const phxTarget = this.el.getAttribute("phx-target");
DM_EVENTS.forEach((dmEvent) => {
const phxAttr = "phx-" + dmEvent.replace("dm-", "");
const phxEvent = this.el.getAttribute(phxAttr);
if (phxEvent) {
const listenerKey = `_dm_listener_${dmEvent}`;
if (this[listenerKey]) {
this.el.removeEventListener(dmEvent, this[listenerKey]);
}
this[listenerKey] = (e) => {
const detail = e.detail || {};
const payload = {
...detail,
value: this.el.value,
name: this.el.name,
checked: this.el.checked
};
if (phxTarget) {
this.pushEventTo(phxTarget, phxEvent, payload);
} else {
this.pushEvent(phxEvent, payload);
}
};
this.el.addEventListener(dmEvent, this[listenerKey]);
}
});
}
};
var FormElementHook = {
...WebComponentHook,
mounted() {
WebComponentHook.mounted.call(this);
this._setupFormIntegration();
},
_setupFormIntegration() {
const name = this.el.getAttribute("name");
const feedbackFor = this.el.getAttribute("phx-feedback-for") || name;
if (feedbackFor) {
this._setupFeedbackObserver(feedbackFor);
}
},
destroyed() {
WebComponentHook.destroyed.call(this);
if (this._feedbackObserver) {
this._feedbackObserver.disconnect();
this._feedbackObserver = null;
}
},
_setupFeedbackObserver(feedbackFor) {
const form = this.el.closest("form");
if (!form)
return;
this._feedbackObserver = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.attributeName === "class") {
const hasNoFeedback = form.classList.contains("phx-no-feedback");
this.el.dispatchEvent(new CustomEvent("dm-feedback-change", {
detail: { showFeedback: !hasNoFeedback, field: feedbackFor }
}));
}
});
});
this._feedbackObserver.observe(form, { attributes: true, attributeFilter: ["class"] });
}
};
if (typeof window !== "undefined") {
window.__WebComponentHook__ = WebComponentHook;
window.__FormElementHook__ = FormElementHook;
}
export {
WebComponentHook,
FormElementHook
};