ash_admin/priv/static/assets/app.js
2024-03-19 09:53:33 -04:00

6654 lines
235 KiB
JavaScript

(() => {
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __objRest = (source, exclude) => {
var target = {};
for (var prop in source)
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
target[prop] = source[prop];
if (source != null && __getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(source)) {
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
target[prop] = source[prop];
}
return target;
};
var __commonJS = (cb, mod) => function __require() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
// vendor/topbar.js
var require_topbar = __commonJS({
"vendor/topbar.js"(exports, module) {
(function(window2, document2) {
"use strict";
(function() {
var lastTime = 0;
var vendors = ["ms", "moz", "webkit", "o"];
for (var x = 0; x < vendors.length && !window2.requestAnimationFrame; ++x) {
window2.requestAnimationFrame = window2[vendors[x] + "RequestAnimationFrame"];
window2.cancelAnimationFrame = window2[vendors[x] + "CancelAnimationFrame"] || window2[vendors[x] + "CancelRequestAnimationFrame"];
}
if (!window2.requestAnimationFrame)
window2.requestAnimationFrame = function(callback, element) {
var currTime = (/* @__PURE__ */ new Date()).getTime();
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
var id = window2.setTimeout(function() {
callback(currTime + timeToCall);
}, timeToCall);
lastTime = currTime + timeToCall;
return id;
};
if (!window2.cancelAnimationFrame)
window2.cancelAnimationFrame = function(id) {
clearTimeout(id);
};
})();
var canvas, currentProgress, showing, progressTimerId = null, fadeTimerId = null, delayTimerId = null, addEvent = function(elem, type, handler) {
if (elem.addEventListener)
elem.addEventListener(type, handler, false);
else if (elem.attachEvent)
elem.attachEvent("on" + type, handler);
else
elem["on" + type] = handler;
}, options = {
autoRun: true,
barThickness: 3,
barColors: {
0: "rgba(26, 188, 156, .9)",
".25": "rgba(52, 152, 219, .9)",
".50": "rgba(241, 196, 15, .9)",
".75": "rgba(230, 126, 34, .9)",
"1.0": "rgba(211, 84, 0, .9)"
},
shadowBlur: 10,
shadowColor: "rgba(0, 0, 0, .6)",
className: null
}, repaint = function() {
canvas.width = window2.innerWidth;
canvas.height = options.barThickness * 5;
var ctx = canvas.getContext("2d");
ctx.shadowBlur = options.shadowBlur;
ctx.shadowColor = options.shadowColor;
var lineGradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
for (var stop in options.barColors)
lineGradient.addColorStop(stop, options.barColors[stop]);
ctx.lineWidth = options.barThickness;
ctx.beginPath();
ctx.moveTo(0, options.barThickness / 2);
ctx.lineTo(
Math.ceil(currentProgress * canvas.width),
options.barThickness / 2
);
ctx.strokeStyle = lineGradient;
ctx.stroke();
}, createCanvas = function() {
canvas = document2.createElement("canvas");
var style = canvas.style;
style.position = "fixed";
style.top = style.left = style.right = style.margin = style.padding = 0;
style.zIndex = 100001;
style.display = "none";
if (options.className)
canvas.classList.add(options.className);
document2.body.appendChild(canvas);
addEvent(window2, "resize", repaint);
}, topbar2 = {
config: function(opts) {
for (var key in opts)
if (options.hasOwnProperty(key))
options[key] = opts[key];
},
show: function(delay) {
if (showing)
return;
if (delay) {
if (delayTimerId)
return;
delayTimerId = setTimeout(() => topbar2.show(), delay);
} else {
showing = true;
if (fadeTimerId !== null)
window2.cancelAnimationFrame(fadeTimerId);
if (!canvas)
createCanvas();
canvas.style.opacity = 1;
canvas.style.display = "block";
topbar2.progress(0);
if (options.autoRun) {
(function loop() {
progressTimerId = window2.requestAnimationFrame(loop);
topbar2.progress(
"+" + 0.05 * Math.pow(1 - Math.sqrt(currentProgress), 2)
);
})();
}
}
},
progress: function(to) {
if (typeof to === "undefined")
return currentProgress;
if (typeof to === "string") {
to = (to.indexOf("+") >= 0 || to.indexOf("-") >= 0 ? currentProgress : 0) + parseFloat(to);
}
currentProgress = to > 1 ? 1 : to;
repaint();
return currentProgress;
},
hide: function() {
clearTimeout(delayTimerId);
delayTimerId = null;
if (!showing)
return;
showing = false;
if (progressTimerId != null) {
window2.cancelAnimationFrame(progressTimerId);
progressTimerId = null;
}
(function loop() {
if (topbar2.progress("+.1") >= 1) {
canvas.style.opacity -= 0.05;
if (canvas.style.opacity <= 0.05) {
canvas.style.display = "none";
fadeTimerId = null;
return;
}
}
fadeTimerId = window2.requestAnimationFrame(loop);
})();
}
};
if (typeof module === "object" && typeof module.exports === "object") {
module.exports = topbar2;
} else if (typeof define === "function" && define.amd) {
define(function() {
return topbar2;
});
} else {
this.topbar = topbar2;
}
}).call(exports, window, document);
}
});
// ../deps/phoenix_html/priv/static/phoenix_html.js
(function() {
var PolyfillEvent = eventConstructor();
function eventConstructor() {
if (typeof window.CustomEvent === "function")
return window.CustomEvent;
function CustomEvent2(event, params2) {
params2 = params2 || { bubbles: false, cancelable: false, detail: void 0 };
var evt = document.createEvent("CustomEvent");
evt.initCustomEvent(event, params2.bubbles, params2.cancelable, params2.detail);
return evt;
}
CustomEvent2.prototype = window.Event.prototype;
return CustomEvent2;
}
function buildHiddenInput(name, value) {
var input = document.createElement("input");
input.type = "hidden";
input.name = name;
input.value = value;
return input;
}
function handleClick(element, targetModifierKey) {
var to = element.getAttribute("data-to"), method = buildHiddenInput("_method", element.getAttribute("data-method")), csrf = buildHiddenInput("_csrf_token", element.getAttribute("data-csrf")), form = document.createElement("form"), submit = document.createElement("input"), target = element.getAttribute("target");
form.method = element.getAttribute("data-method") === "get" ? "get" : "post";
form.action = to;
form.style.display = "none";
if (target)
form.target = target;
else if (targetModifierKey)
form.target = "_blank";
form.appendChild(csrf);
form.appendChild(method);
document.body.appendChild(form);
submit.type = "submit";
form.appendChild(submit);
submit.click();
}
window.addEventListener("click", function(e) {
var element = e.target;
if (e.defaultPrevented)
return;
while (element && element.getAttribute) {
var phoenixLinkEvent = new PolyfillEvent("phoenix.link.click", {
"bubbles": true,
"cancelable": true
});
if (!element.dispatchEvent(phoenixLinkEvent)) {
e.preventDefault();
e.stopImmediatePropagation();
return false;
}
if (element.getAttribute("data-method") && element.getAttribute("data-to")) {
handleClick(element, e.metaKey || e.shiftKey);
e.preventDefault();
return false;
} else {
element = element.parentNode;
}
}
}, false);
window.addEventListener("phoenix.link.click", function(e) {
var message = e.target.getAttribute("data-confirm");
if (message && !window.confirm(message)) {
e.preventDefault();
}
}, false);
})();
// ../deps/phoenix/priv/static/phoenix.mjs
var closure = (value) => {
if (typeof value === "function") {
return value;
} else {
let closure22 = function() {
return value;
};
return closure22;
}
};
var globalSelf = typeof self !== "undefined" ? self : null;
var phxWindow = typeof window !== "undefined" ? window : null;
var global = globalSelf || phxWindow || global;
var DEFAULT_VSN = "2.0.0";
var SOCKET_STATES = { connecting: 0, open: 1, closing: 2, closed: 3 };
var DEFAULT_TIMEOUT = 1e4;
var WS_CLOSE_NORMAL = 1e3;
var CHANNEL_STATES = {
closed: "closed",
errored: "errored",
joined: "joined",
joining: "joining",
leaving: "leaving"
};
var CHANNEL_EVENTS = {
close: "phx_close",
error: "phx_error",
join: "phx_join",
reply: "phx_reply",
leave: "phx_leave"
};
var TRANSPORTS = {
longpoll: "longpoll",
websocket: "websocket"
};
var XHR_STATES = {
complete: 4
};
var Push = class {
constructor(channel, event, payload, timeout) {
this.channel = channel;
this.event = event;
this.payload = payload || function() {
return {};
};
this.receivedResp = null;
this.timeout = timeout;
this.timeoutTimer = null;
this.recHooks = [];
this.sent = false;
}
/**
*
* @param {number} timeout
*/
resend(timeout) {
this.timeout = timeout;
this.reset();
this.send();
}
/**
*
*/
send() {
if (this.hasReceived("timeout")) {
return;
}
this.startTimeout();
this.sent = true;
this.channel.socket.push({
topic: this.channel.topic,
event: this.event,
payload: this.payload(),
ref: this.ref,
join_ref: this.channel.joinRef()
});
}
/**
*
* @param {*} status
* @param {*} callback
*/
receive(status, callback) {
if (this.hasReceived(status)) {
callback(this.receivedResp.response);
}
this.recHooks.push({ status, callback });
return this;
}
/**
* @private
*/
reset() {
this.cancelRefEvent();
this.ref = null;
this.refEvent = null;
this.receivedResp = null;
this.sent = false;
}
/**
* @private
*/
matchReceive({ status, response, _ref }) {
this.recHooks.filter((h) => h.status === status).forEach((h) => h.callback(response));
}
/**
* @private
*/
cancelRefEvent() {
if (!this.refEvent) {
return;
}
this.channel.off(this.refEvent);
}
/**
* @private
*/
cancelTimeout() {
clearTimeout(this.timeoutTimer);
this.timeoutTimer = null;
}
/**
* @private
*/
startTimeout() {
if (this.timeoutTimer) {
this.cancelTimeout();
}
this.ref = this.channel.socket.makeRef();
this.refEvent = this.channel.replyEventName(this.ref);
this.channel.on(this.refEvent, (payload) => {
this.cancelRefEvent();
this.cancelTimeout();
this.receivedResp = payload;
this.matchReceive(payload);
});
this.timeoutTimer = setTimeout(() => {
this.trigger("timeout", {});
}, this.timeout);
}
/**
* @private
*/
hasReceived(status) {
return this.receivedResp && this.receivedResp.status === status;
}
/**
* @private
*/
trigger(status, response) {
this.channel.trigger(this.refEvent, { status, response });
}
};
var Timer = class {
constructor(callback, timerCalc) {
this.callback = callback;
this.timerCalc = timerCalc;
this.timer = null;
this.tries = 0;
}
reset() {
this.tries = 0;
clearTimeout(this.timer);
}
/**
* Cancels any previous scheduleTimeout and schedules callback
*/
scheduleTimeout() {
clearTimeout(this.timer);
this.timer = setTimeout(() => {
this.tries = this.tries + 1;
this.callback();
}, this.timerCalc(this.tries + 1));
}
};
var Channel = class {
constructor(topic, params2, socket) {
this.state = CHANNEL_STATES.closed;
this.topic = topic;
this.params = closure(params2 || {});
this.socket = socket;
this.bindings = [];
this.bindingRef = 0;
this.timeout = this.socket.timeout;
this.joinedOnce = false;
this.joinPush = new Push(this, CHANNEL_EVENTS.join, this.params, this.timeout);
this.pushBuffer = [];
this.stateChangeRefs = [];
this.rejoinTimer = new Timer(() => {
if (this.socket.isConnected()) {
this.rejoin();
}
}, this.socket.rejoinAfterMs);
this.stateChangeRefs.push(this.socket.onError(() => this.rejoinTimer.reset()));
this.stateChangeRefs.push(
this.socket.onOpen(() => {
this.rejoinTimer.reset();
if (this.isErrored()) {
this.rejoin();
}
})
);
this.joinPush.receive("ok", () => {
this.state = CHANNEL_STATES.joined;
this.rejoinTimer.reset();
this.pushBuffer.forEach((pushEvent) => pushEvent.send());
this.pushBuffer = [];
});
this.joinPush.receive("error", () => {
this.state = CHANNEL_STATES.errored;
if (this.socket.isConnected()) {
this.rejoinTimer.scheduleTimeout();
}
});
this.onClose(() => {
this.rejoinTimer.reset();
if (this.socket.hasLogger())
this.socket.log("channel", `close ${this.topic} ${this.joinRef()}`);
this.state = CHANNEL_STATES.closed;
this.socket.remove(this);
});
this.onError((reason) => {
if (this.socket.hasLogger())
this.socket.log("channel", `error ${this.topic}`, reason);
if (this.isJoining()) {
this.joinPush.reset();
}
this.state = CHANNEL_STATES.errored;
if (this.socket.isConnected()) {
this.rejoinTimer.scheduleTimeout();
}
});
this.joinPush.receive("timeout", () => {
if (this.socket.hasLogger())
this.socket.log("channel", `timeout ${this.topic} (${this.joinRef()})`, this.joinPush.timeout);
let leavePush = new Push(this, CHANNEL_EVENTS.leave, closure({}), this.timeout);
leavePush.send();
this.state = CHANNEL_STATES.errored;
this.joinPush.reset();
if (this.socket.isConnected()) {
this.rejoinTimer.scheduleTimeout();
}
});
this.on(CHANNEL_EVENTS.reply, (payload, ref) => {
this.trigger(this.replyEventName(ref), payload);
});
}
/**
* Join the channel
* @param {integer} timeout
* @returns {Push}
*/
join(timeout = this.timeout) {
if (this.joinedOnce) {
throw new Error("tried to join multiple times. 'join' can only be called a single time per channel instance");
} else {
this.timeout = timeout;
this.joinedOnce = true;
this.rejoin();
return this.joinPush;
}
}
/**
* Hook into channel close
* @param {Function} callback
*/
onClose(callback) {
this.on(CHANNEL_EVENTS.close, callback);
}
/**
* Hook into channel errors
* @param {Function} callback
*/
onError(callback) {
return this.on(CHANNEL_EVENTS.error, (reason) => callback(reason));
}
/**
* Subscribes on channel events
*
* Subscription returns a ref counter, which can be used later to
* unsubscribe the exact event listener
*
* @example
* const ref1 = channel.on("event", do_stuff)
* const ref2 = channel.on("event", do_other_stuff)
* channel.off("event", ref1)
* // Since unsubscription, do_stuff won't fire,
* // while do_other_stuff will keep firing on the "event"
*
* @param {string} event
* @param {Function} callback
* @returns {integer} ref
*/
on(event, callback) {
let ref = this.bindingRef++;
this.bindings.push({ event, ref, callback });
return ref;
}
/**
* Unsubscribes off of channel events
*
* Use the ref returned from a channel.on() to unsubscribe one
* handler, or pass nothing for the ref to unsubscribe all
* handlers for the given event.
*
* @example
* // Unsubscribe the do_stuff handler
* const ref1 = channel.on("event", do_stuff)
* channel.off("event", ref1)
*
* // Unsubscribe all handlers from event
* channel.off("event")
*
* @param {string} event
* @param {integer} ref
*/
off(event, ref) {
this.bindings = this.bindings.filter((bind) => {
return !(bind.event === event && (typeof ref === "undefined" || ref === bind.ref));
});
}
/**
* @private
*/
canPush() {
return this.socket.isConnected() && this.isJoined();
}
/**
* Sends a message `event` to phoenix with the payload `payload`.
* Phoenix receives this in the `handle_in(event, payload, socket)`
* function. if phoenix replies or it times out (default 10000ms),
* then optionally the reply can be received.
*
* @example
* channel.push("event")
* .receive("ok", payload => console.log("phoenix replied:", payload))
* .receive("error", err => console.log("phoenix errored", err))
* .receive("timeout", () => console.log("timed out pushing"))
* @param {string} event
* @param {Object} payload
* @param {number} [timeout]
* @returns {Push}
*/
push(event, payload, timeout = this.timeout) {
payload = payload || {};
if (!this.joinedOnce) {
throw new Error(`tried to push '${event}' to '${this.topic}' before joining. Use channel.join() before pushing events`);
}
let pushEvent = new Push(this, event, function() {
return payload;
}, timeout);
if (this.canPush()) {
pushEvent.send();
} else {
pushEvent.startTimeout();
this.pushBuffer.push(pushEvent);
}
return pushEvent;
}
/** Leaves the channel
*
* Unsubscribes from server events, and
* instructs channel to terminate on server
*
* Triggers onClose() hooks
*
* To receive leave acknowledgements, use the `receive`
* hook to bind to the server ack, ie:
*
* @example
* channel.leave().receive("ok", () => alert("left!") )
*
* @param {integer} timeout
* @returns {Push}
*/
leave(timeout = this.timeout) {
this.rejoinTimer.reset();
this.joinPush.cancelTimeout();
this.state = CHANNEL_STATES.leaving;
let onClose = () => {
if (this.socket.hasLogger())
this.socket.log("channel", `leave ${this.topic}`);
this.trigger(CHANNEL_EVENTS.close, "leave");
};
let leavePush = new Push(this, CHANNEL_EVENTS.leave, closure({}), timeout);
leavePush.receive("ok", () => onClose()).receive("timeout", () => onClose());
leavePush.send();
if (!this.canPush()) {
leavePush.trigger("ok", {});
}
return leavePush;
}
/**
* Overridable message hook
*
* Receives all events for specialized message handling
* before dispatching to the channel callbacks.
*
* Must return the payload, modified or unmodified
* @param {string} event
* @param {Object} payload
* @param {integer} ref
* @returns {Object}
*/
onMessage(_event, payload, _ref) {
return payload;
}
/**
* @private
*/
isMember(topic, event, payload, joinRef) {
if (this.topic !== topic) {
return false;
}
if (joinRef && joinRef !== this.joinRef()) {
if (this.socket.hasLogger())
this.socket.log("channel", "dropping outdated message", { topic, event, payload, joinRef });
return false;
} else {
return true;
}
}
/**
* @private
*/
joinRef() {
return this.joinPush.ref;
}
/**
* @private
*/
rejoin(timeout = this.timeout) {
if (this.isLeaving()) {
return;
}
this.socket.leaveOpenTopic(this.topic);
this.state = CHANNEL_STATES.joining;
this.joinPush.resend(timeout);
}
/**
* @private
*/
trigger(event, payload, ref, joinRef) {
let handledPayload = this.onMessage(event, payload, ref, joinRef);
if (payload && !handledPayload) {
throw new Error("channel onMessage callbacks must return the payload, modified or unmodified");
}
let eventBindings = this.bindings.filter((bind) => bind.event === event);
for (let i = 0; i < eventBindings.length; i++) {
let bind = eventBindings[i];
bind.callback(handledPayload, ref, joinRef || this.joinRef());
}
}
/**
* @private
*/
replyEventName(ref) {
return `chan_reply_${ref}`;
}
/**
* @private
*/
isClosed() {
return this.state === CHANNEL_STATES.closed;
}
/**
* @private
*/
isErrored() {
return this.state === CHANNEL_STATES.errored;
}
/**
* @private
*/
isJoined() {
return this.state === CHANNEL_STATES.joined;
}
/**
* @private
*/
isJoining() {
return this.state === CHANNEL_STATES.joining;
}
/**
* @private
*/
isLeaving() {
return this.state === CHANNEL_STATES.leaving;
}
};
var Ajax = class {
static request(method, endPoint, accept, body, timeout, ontimeout, callback) {
if (global.XDomainRequest) {
let req = new global.XDomainRequest();
return this.xdomainRequest(req, method, endPoint, body, timeout, ontimeout, callback);
} else {
let req = new global.XMLHttpRequest();
return this.xhrRequest(req, method, endPoint, accept, body, timeout, ontimeout, callback);
}
}
static xdomainRequest(req, method, endPoint, body, timeout, ontimeout, callback) {
req.timeout = timeout;
req.open(method, endPoint);
req.onload = () => {
let response = this.parseJSON(req.responseText);
callback && callback(response);
};
if (ontimeout) {
req.ontimeout = ontimeout;
}
req.onprogress = () => {
};
req.send(body);
return req;
}
static xhrRequest(req, method, endPoint, accept, body, timeout, ontimeout, callback) {
req.open(method, endPoint, true);
req.timeout = timeout;
req.setRequestHeader("Content-Type", accept);
req.onerror = () => callback && callback(null);
req.onreadystatechange = () => {
if (req.readyState === XHR_STATES.complete && callback) {
let response = this.parseJSON(req.responseText);
callback(response);
}
};
if (ontimeout) {
req.ontimeout = ontimeout;
}
req.send(body);
return req;
}
static parseJSON(resp) {
if (!resp || resp === "") {
return null;
}
try {
return JSON.parse(resp);
} catch (e) {
console && console.log("failed to parse JSON response", resp);
return null;
}
}
static serialize(obj, parentKey) {
let queryStr = [];
for (var key in obj) {
if (!Object.prototype.hasOwnProperty.call(obj, key)) {
continue;
}
let paramKey = parentKey ? `${parentKey}[${key}]` : key;
let paramVal = obj[key];
if (typeof paramVal === "object") {
queryStr.push(this.serialize(paramVal, paramKey));
} else {
queryStr.push(encodeURIComponent(paramKey) + "=" + encodeURIComponent(paramVal));
}
}
return queryStr.join("&");
}
static appendParams(url, params2) {
if (Object.keys(params2).length === 0) {
return url;
}
let prefix = url.match(/\?/) ? "&" : "?";
return `${url}${prefix}${this.serialize(params2)}`;
}
};
var arrayBufferToBase64 = (buffer) => {
let binary = "";
let bytes = new Uint8Array(buffer);
let len = bytes.byteLength;
for (let i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return btoa(binary);
};
var LongPoll = class {
constructor(endPoint) {
this.endPoint = null;
this.token = null;
this.skipHeartbeat = true;
this.reqs = /* @__PURE__ */ new Set();
this.awaitingBatchAck = false;
this.currentBatch = null;
this.currentBatchTimer = null;
this.batchBuffer = [];
this.onopen = function() {
};
this.onerror = function() {
};
this.onmessage = function() {
};
this.onclose = function() {
};
this.pollEndpoint = this.normalizeEndpoint(endPoint);
this.readyState = SOCKET_STATES.connecting;
setTimeout(() => this.poll(), 0);
}
normalizeEndpoint(endPoint) {
return endPoint.replace("ws://", "http://").replace("wss://", "https://").replace(new RegExp("(.*)/" + TRANSPORTS.websocket), "$1/" + TRANSPORTS.longpoll);
}
endpointURL() {
return Ajax.appendParams(this.pollEndpoint, { token: this.token });
}
closeAndRetry(code, reason, wasClean) {
this.close(code, reason, wasClean);
this.readyState = SOCKET_STATES.connecting;
}
ontimeout() {
this.onerror("timeout");
this.closeAndRetry(1005, "timeout", false);
}
isActive() {
return this.readyState === SOCKET_STATES.open || this.readyState === SOCKET_STATES.connecting;
}
poll() {
this.ajax("GET", "application/json", null, () => this.ontimeout(), (resp) => {
if (resp) {
var { status, token, messages } = resp;
this.token = token;
} else {
status = 0;
}
switch (status) {
case 200:
messages.forEach((msg) => {
setTimeout(() => this.onmessage({ data: msg }), 0);
});
this.poll();
break;
case 204:
this.poll();
break;
case 410:
this.readyState = SOCKET_STATES.open;
this.onopen({});
this.poll();
break;
case 403:
this.onerror(403);
this.close(1008, "forbidden", false);
break;
case 0:
case 500:
this.onerror(500);
this.closeAndRetry(1011, "internal server error", 500);
break;
default:
throw new Error(`unhandled poll status ${status}`);
}
});
}
// we collect all pushes within the current event loop by
// setTimeout 0, which optimizes back-to-back procedural
// pushes against an empty buffer
send(body) {
if (typeof body !== "string") {
body = arrayBufferToBase64(body);
}
if (this.currentBatch) {
this.currentBatch.push(body);
} else if (this.awaitingBatchAck) {
this.batchBuffer.push(body);
} else {
this.currentBatch = [body];
this.currentBatchTimer = setTimeout(() => {
this.batchSend(this.currentBatch);
this.currentBatch = null;
}, 0);
}
}
batchSend(messages) {
this.awaitingBatchAck = true;
this.ajax("POST", "application/x-ndjson", messages.join("\n"), () => this.onerror("timeout"), (resp) => {
this.awaitingBatchAck = false;
if (!resp || resp.status !== 200) {
this.onerror(resp && resp.status);
this.closeAndRetry(1011, "internal server error", false);
} else if (this.batchBuffer.length > 0) {
this.batchSend(this.batchBuffer);
this.batchBuffer = [];
}
});
}
close(code, reason, wasClean) {
for (let req of this.reqs) {
req.abort();
}
this.readyState = SOCKET_STATES.closed;
let opts = Object.assign({ code: 1e3, reason: void 0, wasClean: true }, { code, reason, wasClean });
this.batchBuffer = [];
clearTimeout(this.currentBatchTimer);
this.currentBatchTimer = null;
if (typeof CloseEvent !== "undefined") {
this.onclose(new CloseEvent("close", opts));
} else {
this.onclose(opts);
}
}
ajax(method, contentType, body, onCallerTimeout, callback) {
let req;
let ontimeout = () => {
this.reqs.delete(req);
onCallerTimeout();
};
req = Ajax.request(method, this.endpointURL(), contentType, body, this.timeout, ontimeout, (resp) => {
this.reqs.delete(req);
if (this.isActive()) {
callback(resp);
}
});
this.reqs.add(req);
}
};
var serializer_default = {
HEADER_LENGTH: 1,
META_LENGTH: 4,
KINDS: { push: 0, reply: 1, broadcast: 2 },
encode(msg, callback) {
if (msg.payload.constructor === ArrayBuffer) {
return callback(this.binaryEncode(msg));
} else {
let payload = [msg.join_ref, msg.ref, msg.topic, msg.event, msg.payload];
return callback(JSON.stringify(payload));
}
},
decode(rawPayload, callback) {
if (rawPayload.constructor === ArrayBuffer) {
return callback(this.binaryDecode(rawPayload));
} else {
let [join_ref, ref, topic, event, payload] = JSON.parse(rawPayload);
return callback({ join_ref, ref, topic, event, payload });
}
},
// private
binaryEncode(message) {
let { join_ref, ref, event, topic, payload } = message;
let metaLength = this.META_LENGTH + join_ref.length + ref.length + topic.length + event.length;
let header = new ArrayBuffer(this.HEADER_LENGTH + metaLength);
let view = new DataView(header);
let offset = 0;
view.setUint8(offset++, this.KINDS.push);
view.setUint8(offset++, join_ref.length);
view.setUint8(offset++, ref.length);
view.setUint8(offset++, topic.length);
view.setUint8(offset++, event.length);
Array.from(join_ref, (char) => view.setUint8(offset++, char.charCodeAt(0)));
Array.from(ref, (char) => view.setUint8(offset++, char.charCodeAt(0)));
Array.from(topic, (char) => view.setUint8(offset++, char.charCodeAt(0)));
Array.from(event, (char) => view.setUint8(offset++, char.charCodeAt(0)));
var combined = new Uint8Array(header.byteLength + payload.byteLength);
combined.set(new Uint8Array(header), 0);
combined.set(new Uint8Array(payload), header.byteLength);
return combined.buffer;
},
binaryDecode(buffer) {
let view = new DataView(buffer);
let kind = view.getUint8(0);
let decoder = new TextDecoder();
switch (kind) {
case this.KINDS.push:
return this.decodePush(buffer, view, decoder);
case this.KINDS.reply:
return this.decodeReply(buffer, view, decoder);
case this.KINDS.broadcast:
return this.decodeBroadcast(buffer, view, decoder);
}
},
decodePush(buffer, view, decoder) {
let joinRefSize = view.getUint8(1);
let topicSize = view.getUint8(2);
let eventSize = view.getUint8(3);
let offset = this.HEADER_LENGTH + this.META_LENGTH - 1;
let joinRef = decoder.decode(buffer.slice(offset, offset + joinRefSize));
offset = offset + joinRefSize;
let topic = decoder.decode(buffer.slice(offset, offset + topicSize));
offset = offset + topicSize;
let event = decoder.decode(buffer.slice(offset, offset + eventSize));
offset = offset + eventSize;
let data = buffer.slice(offset, buffer.byteLength);
return { join_ref: joinRef, ref: null, topic, event, payload: data };
},
decodeReply(buffer, view, decoder) {
let joinRefSize = view.getUint8(1);
let refSize = view.getUint8(2);
let topicSize = view.getUint8(3);
let eventSize = view.getUint8(4);
let offset = this.HEADER_LENGTH + this.META_LENGTH;
let joinRef = decoder.decode(buffer.slice(offset, offset + joinRefSize));
offset = offset + joinRefSize;
let ref = decoder.decode(buffer.slice(offset, offset + refSize));
offset = offset + refSize;
let topic = decoder.decode(buffer.slice(offset, offset + topicSize));
offset = offset + topicSize;
let event = decoder.decode(buffer.slice(offset, offset + eventSize));
offset = offset + eventSize;
let data = buffer.slice(offset, buffer.byteLength);
let payload = { status: event, response: data };
return { join_ref: joinRef, ref, topic, event: CHANNEL_EVENTS.reply, payload };
},
decodeBroadcast(buffer, view, decoder) {
let topicSize = view.getUint8(1);
let eventSize = view.getUint8(2);
let offset = this.HEADER_LENGTH + 2;
let topic = decoder.decode(buffer.slice(offset, offset + topicSize));
offset = offset + topicSize;
let event = decoder.decode(buffer.slice(offset, offset + eventSize));
offset = offset + eventSize;
let data = buffer.slice(offset, buffer.byteLength);
return { join_ref: null, ref: null, topic, event, payload: data };
}
};
var Socket = class {
constructor(endPoint, opts = {}) {
this.stateChangeCallbacks = { open: [], close: [], error: [], message: [] };
this.channels = [];
this.sendBuffer = [];
this.ref = 0;
this.timeout = opts.timeout || DEFAULT_TIMEOUT;
this.transport = opts.transport || global.WebSocket || LongPoll;
this.longPollFallbackMs = opts.longPollFallbackMs;
this.fallbackTimer = null;
this.sessionStore = opts.sessionStorage || global.sessionStorage;
this.establishedConnections = 0;
this.defaultEncoder = serializer_default.encode.bind(serializer_default);
this.defaultDecoder = serializer_default.decode.bind(serializer_default);
this.closeWasClean = false;
this.binaryType = opts.binaryType || "arraybuffer";
this.connectClock = 1;
if (this.transport !== LongPoll) {
this.encode = opts.encode || this.defaultEncoder;
this.decode = opts.decode || this.defaultDecoder;
} else {
this.encode = this.defaultEncoder;
this.decode = this.defaultDecoder;
}
let awaitingConnectionOnPageShow = null;
if (phxWindow && phxWindow.addEventListener) {
phxWindow.addEventListener("pagehide", (_e) => {
if (this.conn) {
this.disconnect();
awaitingConnectionOnPageShow = this.connectClock;
}
});
phxWindow.addEventListener("pageshow", (_e) => {
if (awaitingConnectionOnPageShow === this.connectClock) {
awaitingConnectionOnPageShow = null;
this.connect();
}
});
}
this.heartbeatIntervalMs = opts.heartbeatIntervalMs || 3e4;
this.rejoinAfterMs = (tries) => {
if (opts.rejoinAfterMs) {
return opts.rejoinAfterMs(tries);
} else {
return [1e3, 2e3, 5e3][tries - 1] || 1e4;
}
};
this.reconnectAfterMs = (tries) => {
if (opts.reconnectAfterMs) {
return opts.reconnectAfterMs(tries);
} else {
return [10, 50, 100, 150, 200, 250, 500, 1e3, 2e3][tries - 1] || 5e3;
}
};
this.logger = opts.logger || null;
if (!this.logger && opts.debug) {
this.logger = (kind, msg, data) => {
console.log(`${kind}: ${msg}`, data);
};
}
this.longpollerTimeout = opts.longpollerTimeout || 2e4;
this.params = closure(opts.params || {});
this.endPoint = `${endPoint}/${TRANSPORTS.websocket}`;
this.vsn = opts.vsn || DEFAULT_VSN;
this.heartbeatTimeoutTimer = null;
this.heartbeatTimer = null;
this.pendingHeartbeatRef = null;
this.reconnectTimer = new Timer(() => {
this.teardown(() => this.connect());
}, this.reconnectAfterMs);
}
/**
* Returns the LongPoll transport reference
*/
getLongPollTransport() {
return LongPoll;
}
/**
* Disconnects and replaces the active transport
*
* @param {Function} newTransport - The new transport class to instantiate
*
*/
replaceTransport(newTransport) {
this.connectClock++;
this.closeWasClean = true;
clearTimeout(this.fallbackTimer);
this.reconnectTimer.reset();
if (this.conn) {
this.conn.close();
this.conn = null;
}
this.transport = newTransport;
}
/**
* Returns the socket protocol
*
* @returns {string}
*/
protocol() {
return location.protocol.match(/^https/) ? "wss" : "ws";
}
/**
* The fully qualified socket url
*
* @returns {string}
*/
endPointURL() {
let uri = Ajax.appendParams(
Ajax.appendParams(this.endPoint, this.params()),
{ vsn: this.vsn }
);
if (uri.charAt(0) !== "/") {
return uri;
}
if (uri.charAt(1) === "/") {
return `${this.protocol()}:${uri}`;
}
return `${this.protocol()}://${location.host}${uri}`;
}
/**
* Disconnects the socket
*
* See https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes for valid status codes.
*
* @param {Function} callback - Optional callback which is called after socket is disconnected.
* @param {integer} code - A status code for disconnection (Optional).
* @param {string} reason - A textual description of the reason to disconnect. (Optional)
*/
disconnect(callback, code, reason) {
this.connectClock++;
this.closeWasClean = true;
clearTimeout(this.fallbackTimer);
this.reconnectTimer.reset();
this.teardown(callback, code, reason);
}
/**
*
* @param {Object} params - The params to send when connecting, for example `{user_id: userToken}`
*
* Passing params to connect is deprecated; pass them in the Socket constructor instead:
* `new Socket("/socket", {params: {user_id: userToken}})`.
*/
connect(params2) {
if (params2) {
console && console.log("passing params to connect is deprecated. Instead pass :params to the Socket constructor");
this.params = closure(params2);
}
if (this.conn) {
return;
}
if (this.longPollFallbackMs && this.transport !== LongPoll) {
this.connectWithFallback(LongPoll, this.longPollFallbackMs);
} else {
this.transportConnect();
}
}
/**
* Logs the message. Override `this.logger` for specialized logging. noops by default
* @param {string} kind
* @param {string} msg
* @param {Object} data
*/
log(kind, msg, data) {
this.logger && this.logger(kind, msg, data);
}
/**
* Returns true if a logger has been set on this socket.
*/
hasLogger() {
return this.logger !== null;
}
/**
* Registers callbacks for connection open events
*
* @example socket.onOpen(function(){ console.info("the socket was opened") })
*
* @param {Function} callback
*/
onOpen(callback) {
let ref = this.makeRef();
this.stateChangeCallbacks.open.push([ref, callback]);
return ref;
}
/**
* Registers callbacks for connection close events
* @param {Function} callback
*/
onClose(callback) {
let ref = this.makeRef();
this.stateChangeCallbacks.close.push([ref, callback]);
return ref;
}
/**
* Registers callbacks for connection error events
*
* @example socket.onError(function(error){ alert("An error occurred") })
*
* @param {Function} callback
*/
onError(callback) {
let ref = this.makeRef();
this.stateChangeCallbacks.error.push([ref, callback]);
return ref;
}
/**
* Registers callbacks for connection message events
* @param {Function} callback
*/
onMessage(callback) {
let ref = this.makeRef();
this.stateChangeCallbacks.message.push([ref, callback]);
return ref;
}
/**
* Pings the server and invokes the callback with the RTT in milliseconds
* @param {Function} callback
*
* Returns true if the ping was pushed or false if unable to be pushed.
*/
ping(callback) {
if (!this.isConnected()) {
return false;
}
let ref = this.makeRef();
let startTime = Date.now();
this.push({ topic: "phoenix", event: "heartbeat", payload: {}, ref });
let onMsgRef = this.onMessage((msg) => {
if (msg.ref === ref) {
this.off([onMsgRef]);
callback(Date.now() - startTime);
}
});
return true;
}
/**
* @private
*/
transportConnect() {
this.connectClock++;
this.closeWasClean = false;
this.conn = new this.transport(this.endPointURL());
this.conn.binaryType = this.binaryType;
this.conn.timeout = this.longpollerTimeout;
this.conn.onopen = () => this.onConnOpen();
this.conn.onerror = (error) => this.onConnError(error);
this.conn.onmessage = (event) => this.onConnMessage(event);
this.conn.onclose = (event) => this.onConnClose(event);
}
getSession(key) {
return this.sessionStore && this.sessionStore.getItem(key);
}
storeSession(key, val) {
this.sessionStore && this.sessionStore.setItem(key, val);
}
connectWithFallback(fallbackTransport, fallbackThreshold = 2500) {
clearTimeout(this.fallbackTimer);
let established = false;
let primaryTransport = true;
let openRef, errorRef;
let fallback = (reason) => {
this.log("transport", `falling back to ${fallbackTransport.name}...`, reason);
this.off([openRef, errorRef]);
primaryTransport = false;
this.storeSession("phx:longpoll", "true");
this.replaceTransport(fallbackTransport);
this.transportConnect();
};
if (this.getSession("phx:longpoll")) {
return fallback("memorized");
}
this.fallbackTimer = setTimeout(fallback, fallbackThreshold);
errorRef = this.onError((reason) => {
this.log("transport", "error", reason);
if (primaryTransport && !established) {
clearTimeout(this.fallbackTimer);
fallback(reason);
}
});
this.onOpen(() => {
established = true;
if (!primaryTransport) {
return console.log("transport", `established ${fallbackTransport.name} fallback`);
}
clearTimeout(this.fallbackTimer);
this.fallbackTimer = setTimeout(fallback, fallbackThreshold);
this.ping((rtt) => {
this.log("transport", "connected to primary after", rtt);
clearTimeout(this.fallbackTimer);
});
});
this.transportConnect();
}
clearHeartbeats() {
clearTimeout(this.heartbeatTimer);
clearTimeout(this.heartbeatTimeoutTimer);
}
onConnOpen() {
if (this.hasLogger())
this.log("transport", `${this.transport.name} connected to ${this.endPointURL()}`);
this.closeWasClean = false;
this.establishedConnections++;
this.flushSendBuffer();
this.reconnectTimer.reset();
this.resetHeartbeat();
this.stateChangeCallbacks.open.forEach(([, callback]) => callback());
}
/**
* @private
*/
heartbeatTimeout() {
if (this.pendingHeartbeatRef) {
this.pendingHeartbeatRef = null;
if (this.hasLogger()) {
this.log("transport", "heartbeat timeout. Attempting to re-establish connection");
}
this.triggerChanError();
this.closeWasClean = false;
this.teardown(() => this.reconnectTimer.scheduleTimeout(), WS_CLOSE_NORMAL, "heartbeat timeout");
}
}
resetHeartbeat() {
if (this.conn && this.conn.skipHeartbeat) {
return;
}
this.pendingHeartbeatRef = null;
this.clearHeartbeats();
this.heartbeatTimer = setTimeout(() => this.sendHeartbeat(), this.heartbeatIntervalMs);
}
teardown(callback, code, reason) {
if (!this.conn) {
return callback && callback();
}
this.waitForBufferDone(() => {
if (this.conn) {
if (code) {
this.conn.close(code, reason || "");
} else {
this.conn.close();
}
}
this.waitForSocketClosed(() => {
if (this.conn) {
this.conn.onopen = function() {
};
this.conn.onerror = function() {
};
this.conn.onmessage = function() {
};
this.conn.onclose = function() {
};
this.conn = null;
}
callback && callback();
});
});
}
waitForBufferDone(callback, tries = 1) {
if (tries === 5 || !this.conn || !this.conn.bufferedAmount) {
callback();
return;
}
setTimeout(() => {
this.waitForBufferDone(callback, tries + 1);
}, 150 * tries);
}
waitForSocketClosed(callback, tries = 1) {
if (tries === 5 || !this.conn || this.conn.readyState === SOCKET_STATES.closed) {
callback();
return;
}
setTimeout(() => {
this.waitForSocketClosed(callback, tries + 1);
}, 150 * tries);
}
onConnClose(event) {
let closeCode = event && event.code;
if (this.hasLogger())
this.log("transport", "close", event);
this.triggerChanError();
this.clearHeartbeats();
if (!this.closeWasClean && closeCode !== 1e3) {
this.reconnectTimer.scheduleTimeout();
}
this.stateChangeCallbacks.close.forEach(([, callback]) => callback(event));
}
/**
* @private
*/
onConnError(error) {
if (this.hasLogger())
this.log("transport", error);
let transportBefore = this.transport;
let establishedBefore = this.establishedConnections;
this.stateChangeCallbacks.error.forEach(([, callback]) => {
callback(error, transportBefore, establishedBefore);
});
if (transportBefore === this.transport || establishedBefore > 0) {
this.triggerChanError();
}
}
/**
* @private
*/
triggerChanError() {
this.channels.forEach((channel) => {
if (!(channel.isErrored() || channel.isLeaving() || channel.isClosed())) {
channel.trigger(CHANNEL_EVENTS.error);
}
});
}
/**
* @returns {string}
*/
connectionState() {
switch (this.conn && this.conn.readyState) {
case SOCKET_STATES.connecting:
return "connecting";
case SOCKET_STATES.open:
return "open";
case SOCKET_STATES.closing:
return "closing";
default:
return "closed";
}
}
/**
* @returns {boolean}
*/
isConnected() {
return this.connectionState() === "open";
}
/**
* @private
*
* @param {Channel}
*/
remove(channel) {
this.off(channel.stateChangeRefs);
this.channels = this.channels.filter((c) => c.joinRef() !== channel.joinRef());
}
/**
* Removes `onOpen`, `onClose`, `onError,` and `onMessage` registrations.
*
* @param {refs} - list of refs returned by calls to
* `onOpen`, `onClose`, `onError,` and `onMessage`
*/
off(refs) {
for (let key in this.stateChangeCallbacks) {
this.stateChangeCallbacks[key] = this.stateChangeCallbacks[key].filter(([ref]) => {
return refs.indexOf(ref) === -1;
});
}
}
/**
* Initiates a new channel for the given topic
*
* @param {string} topic
* @param {Object} chanParams - Parameters for the channel
* @returns {Channel}
*/
channel(topic, chanParams = {}) {
let chan = new Channel(topic, chanParams, this);
this.channels.push(chan);
return chan;
}
/**
* @param {Object} data
*/
push(data) {
if (this.hasLogger()) {
let { topic, event, payload, ref, join_ref } = data;
this.log("push", `${topic} ${event} (${join_ref}, ${ref})`, payload);
}
if (this.isConnected()) {
this.encode(data, (result) => this.conn.send(result));
} else {
this.sendBuffer.push(() => this.encode(data, (result) => this.conn.send(result)));
}
}
/**
* Return the next message ref, accounting for overflows
* @returns {string}
*/
makeRef() {
let newRef = this.ref + 1;
if (newRef === this.ref) {
this.ref = 0;
} else {
this.ref = newRef;
}
return this.ref.toString();
}
sendHeartbeat() {
if (this.pendingHeartbeatRef && !this.isConnected()) {
return;
}
this.pendingHeartbeatRef = this.makeRef();
this.push({ topic: "phoenix", event: "heartbeat", payload: {}, ref: this.pendingHeartbeatRef });
this.heartbeatTimeoutTimer = setTimeout(() => this.heartbeatTimeout(), this.heartbeatIntervalMs);
}
flushSendBuffer() {
if (this.isConnected() && this.sendBuffer.length > 0) {
this.sendBuffer.forEach((callback) => callback());
this.sendBuffer = [];
}
}
onConnMessage(rawMessage) {
this.decode(rawMessage.data, (msg) => {
let { topic, event, payload, ref, join_ref } = msg;
if (ref && ref === this.pendingHeartbeatRef) {
this.clearHeartbeats();
this.pendingHeartbeatRef = null;
this.heartbeatTimer = setTimeout(() => this.sendHeartbeat(), this.heartbeatIntervalMs);
}
if (this.hasLogger())
this.log("receive", `${payload.status || ""} ${topic} ${event} ${ref && "(" + ref + ")" || ""}`, payload);
for (let i = 0; i < this.channels.length; i++) {
const channel = this.channels[i];
if (!channel.isMember(topic, event, payload, join_ref)) {
continue;
}
channel.trigger(event, payload, ref, join_ref);
}
for (let i = 0; i < this.stateChangeCallbacks.message.length; i++) {
let [, callback] = this.stateChangeCallbacks.message[i];
callback(msg);
}
});
}
leaveOpenTopic(topic) {
let dupChannel = this.channels.find((c) => c.topic === topic && (c.isJoined() || c.isJoining()));
if (dupChannel) {
if (this.hasLogger())
this.log("transport", `leaving duplicate topic "${topic}"`);
dupChannel.leave();
}
}
};
// js/app.js
var import_topbar = __toESM(require_topbar());
// ../deps/phoenix_live_view/priv/static/phoenix_live_view.esm.js
var CONSECUTIVE_RELOADS = "consecutive-reloads";
var MAX_RELOADS = 10;
var RELOAD_JITTER_MIN = 5e3;
var RELOAD_JITTER_MAX = 1e4;
var FAILSAFE_JITTER = 3e4;
var PHX_EVENT_CLASSES = [
"phx-click-loading",
"phx-change-loading",
"phx-submit-loading",
"phx-keydown-loading",
"phx-keyup-loading",
"phx-blur-loading",
"phx-focus-loading",
"phx-hook-loading"
];
var PHX_COMPONENT = "data-phx-component";
var PHX_LIVE_LINK = "data-phx-link";
var PHX_TRACK_STATIC = "track-static";
var PHX_LINK_STATE = "data-phx-link-state";
var PHX_REF = "data-phx-ref";
var PHX_REF_SRC = "data-phx-ref-src";
var PHX_TRACK_UPLOADS = "track-uploads";
var PHX_UPLOAD_REF = "data-phx-upload-ref";
var PHX_PREFLIGHTED_REFS = "data-phx-preflighted-refs";
var PHX_DONE_REFS = "data-phx-done-refs";
var PHX_DROP_TARGET = "drop-target";
var PHX_ACTIVE_ENTRY_REFS = "data-phx-active-refs";
var PHX_LIVE_FILE_UPDATED = "phx:live-file:updated";
var PHX_SKIP = "data-phx-skip";
var PHX_MAGIC_ID = "data-phx-id";
var PHX_PRUNE = "data-phx-prune";
var PHX_PAGE_LOADING = "page-loading";
var PHX_CONNECTED_CLASS = "phx-connected";
var PHX_LOADING_CLASS = "phx-loading";
var PHX_NO_FEEDBACK_CLASS = "phx-no-feedback";
var PHX_ERROR_CLASS = "phx-error";
var PHX_CLIENT_ERROR_CLASS = "phx-client-error";
var PHX_SERVER_ERROR_CLASS = "phx-server-error";
var PHX_PARENT_ID = "data-phx-parent-id";
var PHX_MAIN = "data-phx-main";
var PHX_ROOT_ID = "data-phx-root-id";
var PHX_VIEWPORT_TOP = "viewport-top";
var PHX_VIEWPORT_BOTTOM = "viewport-bottom";
var PHX_TRIGGER_ACTION = "trigger-action";
var PHX_FEEDBACK_FOR = "feedback-for";
var PHX_FEEDBACK_GROUP = "feedback-group";
var PHX_HAS_FOCUSED = "phx-has-focused";
var FOCUSABLE_INPUTS = ["text", "textarea", "number", "email", "password", "search", "tel", "url", "date", "time", "datetime-local", "color", "range"];
var CHECKABLE_INPUTS = ["checkbox", "radio"];
var PHX_HAS_SUBMITTED = "phx-has-submitted";
var PHX_SESSION = "data-phx-session";
var PHX_VIEW_SELECTOR = `[${PHX_SESSION}]`;
var PHX_STICKY = "data-phx-sticky";
var PHX_STATIC = "data-phx-static";
var PHX_READONLY = "data-phx-readonly";
var PHX_DISABLED = "data-phx-disabled";
var PHX_DISABLE_WITH = "disable-with";
var PHX_DISABLE_WITH_RESTORE = "data-phx-disable-with-restore";
var PHX_HOOK = "hook";
var PHX_DEBOUNCE = "debounce";
var PHX_THROTTLE = "throttle";
var PHX_UPDATE = "update";
var PHX_STREAM = "stream";
var PHX_STREAM_REF = "data-phx-stream";
var PHX_KEY = "key";
var PHX_PRIVATE = "phxPrivate";
var PHX_AUTO_RECOVER = "auto-recover";
var PHX_LV_DEBUG = "phx:live-socket:debug";
var PHX_LV_PROFILE = "phx:live-socket:profiling";
var PHX_LV_LATENCY_SIM = "phx:live-socket:latency-sim";
var PHX_PROGRESS = "progress";
var PHX_MOUNTED = "mounted";
var LOADER_TIMEOUT = 1;
var BEFORE_UNLOAD_LOADER_TIMEOUT = 200;
var BINDING_PREFIX = "phx-";
var PUSH_TIMEOUT = 3e4;
var DEBOUNCE_TRIGGER = "debounce-trigger";
var THROTTLED = "throttled";
var DEBOUNCE_PREV_KEY = "debounce-prev-key";
var DEFAULTS = {
debounce: 300,
throttle: 300
};
var DYNAMICS = "d";
var STATIC = "s";
var ROOT = "r";
var COMPONENTS = "c";
var EVENTS = "e";
var REPLY = "r";
var TITLE = "t";
var TEMPLATES = "p";
var STREAM = "stream";
var EntryUploader = class {
constructor(entry, chunkSize, liveSocket2) {
this.liveSocket = liveSocket2;
this.entry = entry;
this.offset = 0;
this.chunkSize = chunkSize;
this.chunkTimer = null;
this.errored = false;
this.uploadChannel = liveSocket2.channel(`lvu:${entry.ref}`, { token: entry.metadata() });
}
error(reason) {
if (this.errored) {
return;
}
this.uploadChannel.leave();
this.errored = true;
clearTimeout(this.chunkTimer);
this.entry.error(reason);
}
upload() {
this.uploadChannel.onError((reason) => this.error(reason));
this.uploadChannel.join().receive("ok", (_data) => this.readNextChunk()).receive("error", (reason) => this.error(reason));
}
isDone() {
return this.offset >= this.entry.file.size;
}
readNextChunk() {
let reader = new window.FileReader();
let blob = this.entry.file.slice(this.offset, this.chunkSize + this.offset);
reader.onload = (e) => {
if (e.target.error === null) {
this.offset += e.target.result.byteLength;
this.pushChunk(e.target.result);
} else {
return logError("Read error: " + e.target.error);
}
};
reader.readAsArrayBuffer(blob);
}
pushChunk(chunk) {
if (!this.uploadChannel.isJoined()) {
return;
}
this.uploadChannel.push("chunk", chunk).receive("ok", () => {
this.entry.progress(this.offset / this.entry.file.size * 100);
if (!this.isDone()) {
this.chunkTimer = setTimeout(() => this.readNextChunk(), this.liveSocket.getLatencySim() || 0);
}
}).receive("error", ({ reason }) => this.error(reason));
}
};
var logError = (msg, obj) => console.error && console.error(msg, obj);
var isCid = (cid) => {
let type = typeof cid;
return type === "number" || type === "string" && /^(0|[1-9]\d*)$/.test(cid);
};
function detectDuplicateIds() {
let ids = /* @__PURE__ */ new Set();
let elems = document.querySelectorAll("*[id]");
for (let i = 0, len = elems.length; i < len; i++) {
if (ids.has(elems[i].id)) {
console.error(`Multiple IDs detected: ${elems[i].id}. Ensure unique element ids.`);
} else {
ids.add(elems[i].id);
}
}
}
var debug = (view, kind, msg, obj) => {
if (view.liveSocket.isDebugEnabled()) {
console.log(`${view.id} ${kind}: ${msg} - `, obj);
}
};
var closure2 = (val) => typeof val === "function" ? val : function() {
return val;
};
var clone = (obj) => {
return JSON.parse(JSON.stringify(obj));
};
var closestPhxBinding = (el, binding, borderEl) => {
do {
if (el.matches(`[${binding}]`) && !el.disabled) {
return el;
}
el = el.parentElement || el.parentNode;
} while (el !== null && el.nodeType === 1 && !(borderEl && borderEl.isSameNode(el) || el.matches(PHX_VIEW_SELECTOR)));
return null;
};
var isObject = (obj) => {
return obj !== null && typeof obj === "object" && !(obj instanceof Array);
};
var isEqualObj = (obj1, obj2) => JSON.stringify(obj1) === JSON.stringify(obj2);
var isEmpty = (obj) => {
for (let x in obj) {
return false;
}
return true;
};
var maybe = (el, callback) => el && callback(el);
var channelUploader = function(entries, onError, resp, liveSocket2) {
entries.forEach((entry) => {
let entryUploader = new EntryUploader(entry, resp.config.chunk_size, liveSocket2);
entryUploader.upload();
});
};
var Browser = {
canPushState() {
return typeof history.pushState !== "undefined";
},
dropLocal(localStorage, namespace, subkey) {
return localStorage.removeItem(this.localKey(namespace, subkey));
},
updateLocal(localStorage, namespace, subkey, initial, func) {
let current = this.getLocal(localStorage, namespace, subkey);
let key = this.localKey(namespace, subkey);
let newVal = current === null ? initial : func(current);
localStorage.setItem(key, JSON.stringify(newVal));
return newVal;
},
getLocal(localStorage, namespace, subkey) {
return JSON.parse(localStorage.getItem(this.localKey(namespace, subkey)));
},
updateCurrentState(callback) {
if (!this.canPushState()) {
return;
}
history.replaceState(callback(history.state || {}), "", window.location.href);
},
pushState(kind, meta, to) {
if (this.canPushState()) {
if (to !== window.location.href) {
if (meta.type == "redirect" && meta.scroll) {
let currentState = history.state || {};
currentState.scroll = meta.scroll;
history.replaceState(currentState, "", window.location.href);
}
delete meta.scroll;
history[kind + "State"](meta, "", to || null);
let hashEl = this.getHashTargetEl(window.location.hash);
if (hashEl) {
hashEl.scrollIntoView();
} else if (meta.type === "redirect") {
window.scroll(0, 0);
}
}
} else {
this.redirect(to);
}
},
setCookie(name, value) {
document.cookie = `${name}=${value}`;
},
getCookie(name) {
return document.cookie.replace(new RegExp(`(?:(?:^|.*;s*)${name}s*=s*([^;]*).*$)|^.*$`), "$1");
},
redirect(toURL, flash) {
if (flash) {
Browser.setCookie("__phoenix_flash__", flash + "; max-age=60000; path=/");
}
window.location = toURL;
},
localKey(namespace, subkey) {
return `${namespace}-${subkey}`;
},
getHashTargetEl(maybeHash) {
let hash = maybeHash.toString().substring(1);
if (hash === "") {
return;
}
return document.getElementById(hash) || document.querySelector(`a[name="${hash}"]`);
}
};
var browser_default = Browser;
var ARIA = {
focusMain() {
let target = document.querySelector("main h1, main, h1");
if (target) {
let origTabIndex = target.tabIndex;
target.tabIndex = -1;
target.focus();
target.tabIndex = origTabIndex;
}
},
anyOf(instance, classes) {
return classes.find((name) => instance instanceof name);
},
isFocusable(el, interactiveOnly) {
return el instanceof HTMLAnchorElement && el.rel !== "ignore" || el instanceof HTMLAreaElement && el.href !== void 0 || !el.disabled && this.anyOf(el, [HTMLInputElement, HTMLSelectElement, HTMLTextAreaElement, HTMLButtonElement]) || el instanceof HTMLIFrameElement || (el.tabIndex > 0 || !interactiveOnly && el.getAttribute("tabindex") !== null && el.getAttribute("aria-hidden") !== "true");
},
attemptFocus(el, interactiveOnly) {
if (this.isFocusable(el, interactiveOnly)) {
try {
el.focus();
} catch (e) {
}
}
return !!document.activeElement && document.activeElement.isSameNode(el);
},
focusFirstInteractive(el) {
let child = el.firstElementChild;
while (child) {
if (this.attemptFocus(child, true) || this.focusFirstInteractive(child, true)) {
return true;
}
child = child.nextElementSibling;
}
},
focusFirst(el) {
let child = el.firstElementChild;
while (child) {
if (this.attemptFocus(child) || this.focusFirst(child)) {
return true;
}
child = child.nextElementSibling;
}
},
focusLast(el) {
let child = el.lastElementChild;
while (child) {
if (this.attemptFocus(child) || this.focusLast(child)) {
return true;
}
child = child.previousElementSibling;
}
}
};
var aria_default = ARIA;
var focusStack = null;
var default_transition_time = 200;
var JS = {
exec(eventType, phxEvent, view, sourceEl, defaults) {
let [defaultKind, defaultArgs] = defaults || [null, { callback: defaults && defaults.callback }];
let commands = phxEvent.charAt(0) === "[" ? JSON.parse(phxEvent) : [[defaultKind, defaultArgs]];
commands.forEach(([kind, args]) => {
if (kind === defaultKind && defaultArgs.data) {
args.data = Object.assign(args.data || {}, defaultArgs.data);
args.callback = args.callback || defaultArgs.callback;
}
this.filterToEls(sourceEl, args).forEach((el) => {
this[`exec_${kind}`](eventType, phxEvent, view, sourceEl, el, args);
});
});
},
isVisible(el) {
return !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length > 0);
},
isInViewport(el) {
const rect = el.getBoundingClientRect();
const windowHeight = window.innerHeight || document.documentElement.clientHeight;
const windowWidth = window.innerWidth || document.documentElement.clientWidth;
return rect.right > 0 && rect.bottom > 0 && rect.left < windowWidth && rect.top < windowHeight;
},
exec_exec(eventType, phxEvent, view, sourceEl, el, { attr, to }) {
let nodes = to ? dom_default.all(document, to) : [sourceEl];
nodes.forEach((node) => {
let encodedJS = node.getAttribute(attr);
if (!encodedJS) {
throw new Error(`expected ${attr} to contain JS command on "${to}"`);
}
view.liveSocket.execJS(node, encodedJS, eventType);
});
},
exec_dispatch(eventType, phxEvent, view, sourceEl, el, { to, event, detail, bubbles }) {
detail = detail || {};
detail.dispatcher = sourceEl;
dom_default.dispatchEvent(el, event, { detail, bubbles });
},
exec_push(eventType, phxEvent, view, sourceEl, el, args) {
let { event, data, target, page_loading, loading, value, dispatcher, callback } = args;
let pushOpts = { loading, value, target, page_loading: !!page_loading };
let targetSrc = eventType === "change" && dispatcher ? dispatcher : sourceEl;
let phxTarget = target || targetSrc.getAttribute(view.binding("target")) || targetSrc;
view.withinTargets(phxTarget, (targetView, targetCtx) => {
if (!targetView.isConnected()) {
return;
}
if (eventType === "change") {
let { newCid, _target } = args;
_target = _target || (dom_default.isFormInput(sourceEl) ? sourceEl.name : void 0);
if (_target) {
pushOpts._target = _target;
}
targetView.pushInput(sourceEl, targetCtx, newCid, event || phxEvent, pushOpts, callback);
} else if (eventType === "submit") {
let { submitter } = args;
targetView.submitForm(sourceEl, targetCtx, event || phxEvent, submitter, pushOpts, callback);
} else {
targetView.pushEvent(eventType, sourceEl, targetCtx, event || phxEvent, data, pushOpts, callback);
}
});
},
exec_navigate(eventType, phxEvent, view, sourceEl, el, { href, replace }) {
view.liveSocket.historyRedirect(href, replace ? "replace" : "push");
},
exec_patch(eventType, phxEvent, view, sourceEl, el, { href, replace }) {
view.liveSocket.pushHistoryPatch(href, replace ? "replace" : "push", sourceEl);
},
exec_focus(eventType, phxEvent, view, sourceEl, el) {
window.requestAnimationFrame(() => aria_default.attemptFocus(el));
},
exec_focus_first(eventType, phxEvent, view, sourceEl, el) {
window.requestAnimationFrame(() => aria_default.focusFirstInteractive(el) || aria_default.focusFirst(el));
},
exec_push_focus(eventType, phxEvent, view, sourceEl, el) {
window.requestAnimationFrame(() => focusStack = el || sourceEl);
},
exec_pop_focus(eventType, phxEvent, view, sourceEl, el) {
window.requestAnimationFrame(() => {
if (focusStack) {
focusStack.focus();
}
focusStack = null;
});
},
exec_add_class(eventType, phxEvent, view, sourceEl, el, { names, transition, time }) {
this.addOrRemoveClasses(el, names, [], transition, time, view);
},
exec_remove_class(eventType, phxEvent, view, sourceEl, el, { names, transition, time }) {
this.addOrRemoveClasses(el, [], names, transition, time, view);
},
exec_toggle_class(eventType, phxEvent, view, sourceEl, el, { to, names, transition, time }) {
this.toggleClasses(el, names, transition, view);
},
exec_toggle_attr(eventType, phxEvent, view, sourceEl, el, { attr: [attr, val1, val2] }) {
if (el.hasAttribute(attr)) {
if (val2 !== void 0) {
if (el.getAttribute(attr) === val1) {
this.setOrRemoveAttrs(el, [[attr, val2]], []);
} else {
this.setOrRemoveAttrs(el, [[attr, val1]], []);
}
} else {
this.setOrRemoveAttrs(el, [], [attr]);
}
} else {
this.setOrRemoveAttrs(el, [[attr, val1]], []);
}
},
exec_transition(eventType, phxEvent, view, sourceEl, el, { time, transition }) {
this.addOrRemoveClasses(el, [], [], transition, time, view);
},
exec_toggle(eventType, phxEvent, view, sourceEl, el, { display, ins, outs, time }) {
this.toggle(eventType, view, el, display, ins, outs, time);
},
exec_show(eventType, phxEvent, view, sourceEl, el, { display, transition, time }) {
this.show(eventType, view, el, display, transition, time);
},
exec_hide(eventType, phxEvent, view, sourceEl, el, { display, transition, time }) {
this.hide(eventType, view, el, display, transition, time);
},
exec_set_attr(eventType, phxEvent, view, sourceEl, el, { attr: [attr, val] }) {
this.setOrRemoveAttrs(el, [[attr, val]], []);
},
exec_remove_attr(eventType, phxEvent, view, sourceEl, el, { attr }) {
this.setOrRemoveAttrs(el, [], [attr]);
},
show(eventType, view, el, display, transition, time) {
if (!this.isVisible(el)) {
this.toggle(eventType, view, el, display, transition, null, time);
}
},
hide(eventType, view, el, display, transition, time) {
if (this.isVisible(el)) {
this.toggle(eventType, view, el, display, null, transition, time);
}
},
toggle(eventType, view, el, display, ins, outs, time) {
time = time || default_transition_time;
let [inClasses, inStartClasses, inEndClasses] = ins || [[], [], []];
let [outClasses, outStartClasses, outEndClasses] = outs || [[], [], []];
if (inClasses.length > 0 || outClasses.length > 0) {
if (this.isVisible(el)) {
let onStart = () => {
this.addOrRemoveClasses(el, outStartClasses, inClasses.concat(inStartClasses).concat(inEndClasses));
window.requestAnimationFrame(() => {
this.addOrRemoveClasses(el, outClasses, []);
window.requestAnimationFrame(() => this.addOrRemoveClasses(el, outEndClasses, outStartClasses));
});
};
el.dispatchEvent(new Event("phx:hide-start"));
view.transition(time, onStart, () => {
this.addOrRemoveClasses(el, [], outClasses.concat(outEndClasses));
dom_default.putSticky(el, "toggle", (currentEl) => currentEl.style.display = "none");
el.dispatchEvent(new Event("phx:hide-end"));
});
} else {
if (eventType === "remove") {
return;
}
let onStart = () => {
this.addOrRemoveClasses(el, inStartClasses, outClasses.concat(outStartClasses).concat(outEndClasses));
let stickyDisplay = display || this.defaultDisplay(el);
dom_default.putSticky(el, "toggle", (currentEl) => currentEl.style.display = stickyDisplay);
window.requestAnimationFrame(() => {
this.addOrRemoveClasses(el, inClasses, []);
window.requestAnimationFrame(() => this.addOrRemoveClasses(el, inEndClasses, inStartClasses));
});
};
el.dispatchEvent(new Event("phx:show-start"));
view.transition(time, onStart, () => {
this.addOrRemoveClasses(el, [], inClasses.concat(inEndClasses));
el.dispatchEvent(new Event("phx:show-end"));
});
}
} else {
if (this.isVisible(el)) {
window.requestAnimationFrame(() => {
el.dispatchEvent(new Event("phx:hide-start"));
dom_default.putSticky(el, "toggle", (currentEl) => currentEl.style.display = "none");
el.dispatchEvent(new Event("phx:hide-end"));
});
} else {
window.requestAnimationFrame(() => {
el.dispatchEvent(new Event("phx:show-start"));
let stickyDisplay = display || this.defaultDisplay(el);
dom_default.putSticky(el, "toggle", (currentEl) => currentEl.style.display = stickyDisplay);
el.dispatchEvent(new Event("phx:show-end"));
});
}
}
},
toggleClasses(el, classes, transition, time, view) {
window.requestAnimationFrame(() => {
let [prevAdds, prevRemoves] = dom_default.getSticky(el, "classes", [[], []]);
let newAdds = classes.filter((name) => prevAdds.indexOf(name) < 0 && !el.classList.contains(name));
let newRemoves = classes.filter((name) => prevRemoves.indexOf(name) < 0 && el.classList.contains(name));
this.addOrRemoveClasses(el, newAdds, newRemoves, transition, time, view);
});
},
addOrRemoveClasses(el, adds, removes, transition, time, view) {
time = time || default_transition_time;
let [transitionRun, transitionStart, transitionEnd] = transition || [[], [], []];
if (transitionRun.length > 0) {
let onStart = () => {
this.addOrRemoveClasses(el, transitionStart, [].concat(transitionRun).concat(transitionEnd));
window.requestAnimationFrame(() => {
this.addOrRemoveClasses(el, transitionRun, []);
window.requestAnimationFrame(() => this.addOrRemoveClasses(el, transitionEnd, transitionStart));
});
};
let onDone = () => this.addOrRemoveClasses(el, adds.concat(transitionEnd), removes.concat(transitionRun).concat(transitionStart));
return view.transition(time, onStart, onDone);
}
window.requestAnimationFrame(() => {
let [prevAdds, prevRemoves] = dom_default.getSticky(el, "classes", [[], []]);
let keepAdds = adds.filter((name) => prevAdds.indexOf(name) < 0 && !el.classList.contains(name));
let keepRemoves = removes.filter((name) => prevRemoves.indexOf(name) < 0 && el.classList.contains(name));
let newAdds = prevAdds.filter((name) => removes.indexOf(name) < 0).concat(keepAdds);
let newRemoves = prevRemoves.filter((name) => adds.indexOf(name) < 0).concat(keepRemoves);
dom_default.putSticky(el, "classes", (currentEl) => {
currentEl.classList.remove(...newRemoves);
currentEl.classList.add(...newAdds);
return [newAdds, newRemoves];
});
});
},
setOrRemoveAttrs(el, sets, removes) {
let [prevSets, prevRemoves] = dom_default.getSticky(el, "attrs", [[], []]);
let alteredAttrs = sets.map(([attr, _val]) => attr).concat(removes);
let newSets = prevSets.filter(([attr, _val]) => !alteredAttrs.includes(attr)).concat(sets);
let newRemoves = prevRemoves.filter((attr) => !alteredAttrs.includes(attr)).concat(removes);
dom_default.putSticky(el, "attrs", (currentEl) => {
newRemoves.forEach((attr) => currentEl.removeAttribute(attr));
newSets.forEach(([attr, val]) => currentEl.setAttribute(attr, val));
return [newSets, newRemoves];
});
},
hasAllClasses(el, classes) {
return classes.every((name) => el.classList.contains(name));
},
isToggledOut(el, outClasses) {
return !this.isVisible(el) || this.hasAllClasses(el, outClasses);
},
filterToEls(sourceEl, { to }) {
return to ? dom_default.all(document, to) : [sourceEl];
},
defaultDisplay(el) {
return { tr: "table-row", td: "table-cell" }[el.tagName.toLowerCase()] || "block";
}
};
var js_default = JS;
var DOM = {
byId(id) {
return document.getElementById(id) || logError(`no id found for ${id}`);
},
removeClass(el, className) {
el.classList.remove(className);
if (el.classList.length === 0) {
el.removeAttribute("class");
}
},
all(node, query, callback) {
if (!node) {
return [];
}
let array = Array.from(node.querySelectorAll(query));
return callback ? array.forEach(callback) : array;
},
childNodeLength(html) {
let template = document.createElement("template");
template.innerHTML = html;
return template.content.childElementCount;
},
isUploadInput(el) {
return el.type === "file" && el.getAttribute(PHX_UPLOAD_REF) !== null;
},
isAutoUpload(inputEl) {
return inputEl.hasAttribute("data-phx-auto-upload");
},
findUploadInputs(node) {
const formId = node.id;
const inputsOutsideForm = this.all(document, `input[type="file"][${PHX_UPLOAD_REF}][form="${formId}"]`);
return this.all(node, `input[type="file"][${PHX_UPLOAD_REF}]`).concat(inputsOutsideForm);
},
findComponentNodeList(node, cid) {
return this.filterWithinSameLiveView(this.all(node, `[${PHX_COMPONENT}="${cid}"]`), node);
},
isPhxDestroyed(node) {
return node.id && DOM.private(node, "destroyed") ? true : false;
},
wantsNewTab(e) {
let wantsNewTab = e.ctrlKey || e.shiftKey || e.metaKey || e.button && e.button === 1;
let isDownload = e.target instanceof HTMLAnchorElement && e.target.hasAttribute("download");
let isTargetBlank = e.target.hasAttribute("target") && e.target.getAttribute("target").toLowerCase() === "_blank";
return wantsNewTab || isTargetBlank || isDownload;
},
isUnloadableFormSubmit(e) {
let isDialogSubmit = e.target && e.target.getAttribute("method") === "dialog" || e.submitter && e.submitter.getAttribute("formmethod") === "dialog";
if (isDialogSubmit) {
return false;
} else {
return !e.defaultPrevented && !this.wantsNewTab(e);
}
},
isNewPageClick(e, currentLocation) {
let href = e.target instanceof HTMLAnchorElement ? e.target.getAttribute("href") : null;
let url;
if (e.defaultPrevented || href === null || this.wantsNewTab(e)) {
return false;
}
if (href.startsWith("mailto:") || href.startsWith("tel:")) {
return false;
}
if (e.target.isContentEditable) {
return false;
}
try {
url = new URL(href);
} catch (e2) {
try {
url = new URL(href, currentLocation);
} catch (e3) {
return true;
}
}
if (url.host === currentLocation.host && url.protocol === currentLocation.protocol) {
if (url.pathname === currentLocation.pathname && url.search === currentLocation.search) {
return url.hash === "" && !url.href.endsWith("#");
}
}
return url.protocol.startsWith("http");
},
markPhxChildDestroyed(el) {
if (this.isPhxChild(el)) {
el.setAttribute(PHX_SESSION, "");
}
this.putPrivate(el, "destroyed", true);
},
findPhxChildrenInFragment(html, parentId) {
let template = document.createElement("template");
template.innerHTML = html;
return this.findPhxChildren(template.content, parentId);
},
isIgnored(el, phxUpdate) {
return (el.getAttribute(phxUpdate) || el.getAttribute("data-phx-update")) === "ignore";
},
isPhxUpdate(el, phxUpdate, updateTypes) {
return el.getAttribute && updateTypes.indexOf(el.getAttribute(phxUpdate)) >= 0;
},
findPhxSticky(el) {
return this.all(el, `[${PHX_STICKY}]`);
},
findPhxChildren(el, parentId) {
return this.all(el, `${PHX_VIEW_SELECTOR}[${PHX_PARENT_ID}="${parentId}"]`);
},
findParentCIDs(node, cids) {
let initial = new Set(cids);
let parentCids = cids.reduce((acc, cid) => {
let selector = `[${PHX_COMPONENT}="${cid}"] [${PHX_COMPONENT}]`;
this.filterWithinSameLiveView(this.all(node, selector), node).map((el) => parseInt(el.getAttribute(PHX_COMPONENT))).forEach((childCID) => acc.delete(childCID));
return acc;
}, initial);
return parentCids.size === 0 ? new Set(cids) : parentCids;
},
filterWithinSameLiveView(nodes, parent) {
if (parent.querySelector(PHX_VIEW_SELECTOR)) {
return nodes.filter((el) => this.withinSameLiveView(el, parent));
} else {
return nodes;
}
},
withinSameLiveView(node, parent) {
while (node = node.parentNode) {
if (node.isSameNode(parent)) {
return true;
}
if (node.getAttribute(PHX_SESSION) !== null) {
return false;
}
}
},
private(el, key) {
return el[PHX_PRIVATE] && el[PHX_PRIVATE][key];
},
deletePrivate(el, key) {
el[PHX_PRIVATE] && delete el[PHX_PRIVATE][key];
},
putPrivate(el, key, value) {
if (!el[PHX_PRIVATE]) {
el[PHX_PRIVATE] = {};
}
el[PHX_PRIVATE][key] = value;
},
updatePrivate(el, key, defaultVal, updateFunc) {
let existing = this.private(el, key);
if (existing === void 0) {
this.putPrivate(el, key, updateFunc(defaultVal));
} else {
this.putPrivate(el, key, updateFunc(existing));
}
},
copyPrivates(target, source) {
if (source[PHX_PRIVATE]) {
target[PHX_PRIVATE] = source[PHX_PRIVATE];
}
},
putTitle(str) {
let titleEl = document.querySelector("title");
if (titleEl) {
let { prefix, suffix } = titleEl.dataset;
document.title = `${prefix || ""}${str}${suffix || ""}`;
} else {
document.title = str;
}
},
debounce(el, event, phxDebounce, defaultDebounce, phxThrottle, defaultThrottle, asyncFilter, callback) {
let debounce = el.getAttribute(phxDebounce);
let throttle = el.getAttribute(phxThrottle);
if (debounce === "") {
debounce = defaultDebounce;
}
if (throttle === "") {
throttle = defaultThrottle;
}
let value = debounce || throttle;
switch (value) {
case null:
return callback();
case "blur":
if (this.once(el, "debounce-blur")) {
el.addEventListener("blur", () => callback());
}
return;
default:
let timeout = parseInt(value);
let trigger = () => throttle ? this.deletePrivate(el, THROTTLED) : callback();
let currentCycle = this.incCycle(el, DEBOUNCE_TRIGGER, trigger);
if (isNaN(timeout)) {
return logError(`invalid throttle/debounce value: ${value}`);
}
if (throttle) {
let newKeyDown = false;
if (event.type === "keydown") {
let prevKey = this.private(el, DEBOUNCE_PREV_KEY);
this.putPrivate(el, DEBOUNCE_PREV_KEY, event.key);
newKeyDown = prevKey !== event.key;
}
if (!newKeyDown && this.private(el, THROTTLED)) {
return false;
} else {
callback();
const t = setTimeout(() => {
if (asyncFilter()) {
this.triggerCycle(el, DEBOUNCE_TRIGGER);
}
}, timeout);
this.putPrivate(el, THROTTLED, t);
}
} else {
setTimeout(() => {
if (asyncFilter()) {
this.triggerCycle(el, DEBOUNCE_TRIGGER, currentCycle);
}
}, timeout);
}
let form = el.form;
if (form && this.once(form, "bind-debounce")) {
form.addEventListener("submit", () => {
Array.from(new FormData(form).entries(), ([name]) => {
let input = form.querySelector(`[name="${name}"]`);
this.incCycle(input, DEBOUNCE_TRIGGER);
this.deletePrivate(input, THROTTLED);
});
});
}
if (this.once(el, "bind-debounce")) {
el.addEventListener("blur", () => {
clearTimeout(this.private(el, THROTTLED));
this.triggerCycle(el, DEBOUNCE_TRIGGER);
});
}
}
},
triggerCycle(el, key, currentCycle) {
let [cycle, trigger] = this.private(el, key);
if (!currentCycle) {
currentCycle = cycle;
}
if (currentCycle === cycle) {
this.incCycle(el, key);
trigger();
}
},
once(el, key) {
if (this.private(el, key) === true) {
return false;
}
this.putPrivate(el, key, true);
return true;
},
incCycle(el, key, trigger = function() {
}) {
let [currentCycle] = this.private(el, key) || [0, trigger];
currentCycle++;
this.putPrivate(el, key, [currentCycle, trigger]);
return currentCycle;
},
maybeAddPrivateHooks(el, phxViewportTop, phxViewportBottom) {
if (el.hasAttribute && (el.hasAttribute(phxViewportTop) || el.hasAttribute(phxViewportBottom))) {
el.setAttribute("data-phx-hook", "Phoenix.InfiniteScroll");
}
},
isFeedbackContainer(el, phxFeedbackFor) {
return el.hasAttribute && el.hasAttribute(phxFeedbackFor);
},
maybeHideFeedback(container, feedbackContainers, phxFeedbackFor, phxFeedbackGroup) {
const feedbackResults = {};
feedbackContainers.forEach((el) => {
if (!container.contains(el))
return;
const feedback = el.getAttribute(phxFeedbackFor);
if (!feedback) {
js_default.addOrRemoveClasses(el, [], [PHX_NO_FEEDBACK_CLASS]);
return;
}
if (feedbackResults[feedback] === true) {
this.hideFeedback(el);
return;
}
feedbackResults[feedback] = this.shouldHideFeedback(container, feedback, phxFeedbackGroup);
if (feedbackResults[feedback] === true) {
this.hideFeedback(el);
}
});
},
hideFeedback(container) {
js_default.addOrRemoveClasses(container, [PHX_NO_FEEDBACK_CLASS], []);
},
shouldHideFeedback(container, nameOrGroup, phxFeedbackGroup) {
const query = `[name="${nameOrGroup}"],
[name="${nameOrGroup}[]"],
[${phxFeedbackGroup}="${nameOrGroup}"]`;
let focused = false;
DOM.all(container, query, (input) => {
if (this.private(input, PHX_HAS_FOCUSED) || this.private(input, PHX_HAS_SUBMITTED)) {
focused = true;
}
});
return !focused;
},
feedbackSelector(input, phxFeedbackFor, phxFeedbackGroup) {
let query = `[${phxFeedbackFor}="${input.name}"],
[${phxFeedbackFor}="${input.name.replace(/\[\]$/, "")}"]`;
if (input.getAttribute(phxFeedbackGroup)) {
query += `,[${phxFeedbackFor}="${input.getAttribute(phxFeedbackGroup)}"]`;
}
return query;
},
resetForm(form, phxFeedbackFor, phxFeedbackGroup) {
Array.from(form.elements).forEach((input) => {
let query = this.feedbackSelector(input, phxFeedbackFor, phxFeedbackGroup);
this.deletePrivate(input, PHX_HAS_FOCUSED);
this.deletePrivate(input, PHX_HAS_SUBMITTED);
this.all(document, query, (feedbackEl) => {
js_default.addOrRemoveClasses(feedbackEl, [PHX_NO_FEEDBACK_CLASS], []);
});
});
},
showError(inputEl, phxFeedbackFor, phxFeedbackGroup) {
if (inputEl.name) {
let query = this.feedbackSelector(inputEl, phxFeedbackFor, phxFeedbackGroup);
this.all(document, query, (el) => {
js_default.addOrRemoveClasses(el, [], [PHX_NO_FEEDBACK_CLASS]);
});
}
},
isPhxChild(node) {
return node.getAttribute && node.getAttribute(PHX_PARENT_ID);
},
isPhxSticky(node) {
return node.getAttribute && node.getAttribute(PHX_STICKY) !== null;
},
isChildOfAny(el, parents) {
return !!parents.find((parent) => parent.contains(el));
},
firstPhxChild(el) {
return this.isPhxChild(el) ? el : this.all(el, `[${PHX_PARENT_ID}]`)[0];
},
dispatchEvent(target, name, opts = {}) {
let defaultBubble = true;
let isUploadTarget = target.nodeName === "INPUT" && target.type === "file";
if (isUploadTarget && name === "click") {
defaultBubble = false;
}
let bubbles = opts.bubbles === void 0 ? defaultBubble : !!opts.bubbles;
let eventOpts = { bubbles, cancelable: true, detail: opts.detail || {} };
let event = name === "click" ? new MouseEvent("click", eventOpts) : new CustomEvent(name, eventOpts);
target.dispatchEvent(event);
},
cloneNode(node, html) {
if (typeof html === "undefined") {
return node.cloneNode(true);
} else {
let cloned = node.cloneNode(false);
cloned.innerHTML = html;
return cloned;
}
},
mergeAttrs(target, source, opts = {}) {
let exclude = new Set(opts.exclude || []);
let isIgnored = opts.isIgnored;
let sourceAttrs = source.attributes;
for (let i = sourceAttrs.length - 1; i >= 0; i--) {
let name = sourceAttrs[i].name;
if (!exclude.has(name)) {
const sourceValue = source.getAttribute(name);
if (target.getAttribute(name) !== sourceValue && (!isIgnored || isIgnored && name.startsWith("data-"))) {
target.setAttribute(name, sourceValue);
}
} else {
if (name === "value" && target.value === source.value) {
target.setAttribute("value", source.getAttribute(name));
}
}
}
let targetAttrs = target.attributes;
for (let i = targetAttrs.length - 1; i >= 0; i--) {
let name = targetAttrs[i].name;
if (isIgnored) {
if (name.startsWith("data-") && !source.hasAttribute(name) && ![PHX_REF, PHX_REF_SRC].includes(name)) {
target.removeAttribute(name);
}
} else {
if (!source.hasAttribute(name)) {
target.removeAttribute(name);
}
}
}
},
mergeFocusedInput(target, source) {
if (!(target instanceof HTMLSelectElement)) {
DOM.mergeAttrs(target, source, { exclude: ["value"] });
}
if (source.readOnly) {
target.setAttribute("readonly", true);
} else {
target.removeAttribute("readonly");
}
},
hasSelectionRange(el) {
return el.setSelectionRange && (el.type === "text" || el.type === "textarea");
},
restoreFocus(focused, selectionStart, selectionEnd) {
if (focused instanceof HTMLSelectElement) {
focused.focus();
}
if (!DOM.isTextualInput(focused)) {
return;
}
let wasFocused = focused.matches(":focus");
if (focused.readOnly) {
focused.blur();
}
if (!wasFocused) {
focused.focus();
}
if (this.hasSelectionRange(focused)) {
focused.setSelectionRange(selectionStart, selectionEnd);
}
},
isFormInput(el) {
return /^(?:input|select|textarea)$/i.test(el.tagName) && el.type !== "button";
},
syncAttrsToProps(el) {
if (el instanceof HTMLInputElement && CHECKABLE_INPUTS.indexOf(el.type.toLocaleLowerCase()) >= 0) {
el.checked = el.getAttribute("checked") !== null;
}
},
isTextualInput(el) {
return FOCUSABLE_INPUTS.indexOf(el.type) >= 0;
},
isNowTriggerFormExternal(el, phxTriggerExternal) {
return el.getAttribute && el.getAttribute(phxTriggerExternal) !== null;
},
syncPendingRef(fromEl, toEl, disableWith) {
let ref = fromEl.getAttribute(PHX_REF);
if (ref === null) {
return true;
}
let refSrc = fromEl.getAttribute(PHX_REF_SRC);
if (DOM.isFormInput(fromEl) || fromEl.getAttribute(disableWith) !== null) {
if (DOM.isUploadInput(fromEl)) {
DOM.mergeAttrs(fromEl, toEl, { isIgnored: true });
}
DOM.putPrivate(fromEl, PHX_REF, toEl);
return false;
} else {
PHX_EVENT_CLASSES.forEach((className) => {
fromEl.classList.contains(className) && toEl.classList.add(className);
});
toEl.setAttribute(PHX_REF, ref);
toEl.setAttribute(PHX_REF_SRC, refSrc);
return true;
}
},
cleanChildNodes(container, phxUpdate) {
if (DOM.isPhxUpdate(container, phxUpdate, ["append", "prepend"])) {
let toRemove = [];
container.childNodes.forEach((childNode) => {
if (!childNode.id) {
let isEmptyTextNode = childNode.nodeType === Node.TEXT_NODE && childNode.nodeValue.trim() === "";
if (!isEmptyTextNode) {
logError(`only HTML element tags with an id are allowed inside containers with phx-update.
removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
`);
}
toRemove.push(childNode);
}
});
toRemove.forEach((childNode) => childNode.remove());
}
},
replaceRootContainer(container, tagName, attrs) {
let retainedAttrs = /* @__PURE__ */ new Set(["id", PHX_SESSION, PHX_STATIC, PHX_MAIN, PHX_ROOT_ID]);
if (container.tagName.toLowerCase() === tagName.toLowerCase()) {
Array.from(container.attributes).filter((attr) => !retainedAttrs.has(attr.name.toLowerCase())).forEach((attr) => container.removeAttribute(attr.name));
Object.keys(attrs).filter((name) => !retainedAttrs.has(name.toLowerCase())).forEach((attr) => container.setAttribute(attr, attrs[attr]));
return container;
} else {
let newContainer = document.createElement(tagName);
Object.keys(attrs).forEach((attr) => newContainer.setAttribute(attr, attrs[attr]));
retainedAttrs.forEach((attr) => newContainer.setAttribute(attr, container.getAttribute(attr)));
newContainer.innerHTML = container.innerHTML;
container.replaceWith(newContainer);
return newContainer;
}
},
getSticky(el, name, defaultVal) {
let op = (DOM.private(el, "sticky") || []).find(([existingName]) => name === existingName);
if (op) {
let [_name, _op, stashedResult] = op;
return stashedResult;
} else {
return typeof defaultVal === "function" ? defaultVal() : defaultVal;
}
},
deleteSticky(el, name) {
this.updatePrivate(el, "sticky", [], (ops) => {
return ops.filter(([existingName, _]) => existingName !== name);
});
},
putSticky(el, name, op) {
let stashedResult = op(el);
this.updatePrivate(el, "sticky", [], (ops) => {
let existingIndex = ops.findIndex(([existingName]) => name === existingName);
if (existingIndex >= 0) {
ops[existingIndex] = [name, op, stashedResult];
} else {
ops.push([name, op, stashedResult]);
}
return ops;
});
},
applyStickyOperations(el) {
let ops = DOM.private(el, "sticky");
if (!ops) {
return;
}
ops.forEach(([name, op, _stashed]) => this.putSticky(el, name, op));
}
};
var dom_default = DOM;
var UploadEntry = class {
static isActive(fileEl, file) {
let isNew = file._phxRef === void 0;
let activeRefs = fileEl.getAttribute(PHX_ACTIVE_ENTRY_REFS).split(",");
let isActive = activeRefs.indexOf(LiveUploader.genFileRef(file)) >= 0;
return file.size > 0 && (isNew || isActive);
}
static isPreflighted(fileEl, file) {
let preflightedRefs = fileEl.getAttribute(PHX_PREFLIGHTED_REFS).split(",");
let isPreflighted = preflightedRefs.indexOf(LiveUploader.genFileRef(file)) >= 0;
return isPreflighted && this.isActive(fileEl, file);
}
static isPreflightInProgress(file) {
return file._preflightInProgress === true;
}
static markPreflightInProgress(file) {
file._preflightInProgress = true;
}
constructor(fileEl, file, view, autoUpload) {
this.ref = LiveUploader.genFileRef(file);
this.fileEl = fileEl;
this.file = file;
this.view = view;
this.meta = null;
this._isCancelled = false;
this._isDone = false;
this._progress = 0;
this._lastProgressSent = -1;
this._onDone = function() {
};
this._onElUpdated = this.onElUpdated.bind(this);
this.fileEl.addEventListener(PHX_LIVE_FILE_UPDATED, this._onElUpdated);
this.autoUpload = autoUpload;
}
metadata() {
return this.meta;
}
progress(progress) {
this._progress = Math.floor(progress);
if (this._progress > this._lastProgressSent) {
if (this._progress >= 100) {
this._progress = 100;
this._lastProgressSent = 100;
this._isDone = true;
this.view.pushFileProgress(this.fileEl, this.ref, 100, () => {
LiveUploader.untrackFile(this.fileEl, this.file);
this._onDone();
});
} else {
this._lastProgressSent = this._progress;
this.view.pushFileProgress(this.fileEl, this.ref, this._progress);
}
}
}
isCancelled() {
return this._isCancelled;
}
cancel() {
this.file._preflightInProgress = false;
this._isCancelled = true;
this._isDone = true;
this._onDone();
}
isDone() {
return this._isDone;
}
error(reason = "failed") {
this.fileEl.removeEventListener(PHX_LIVE_FILE_UPDATED, this._onElUpdated);
this.view.pushFileProgress(this.fileEl, this.ref, { error: reason });
if (!this.isAutoUpload()) {
LiveUploader.clearFiles(this.fileEl);
}
}
isAutoUpload() {
return this.autoUpload;
}
onDone(callback) {
this._onDone = () => {
this.fileEl.removeEventListener(PHX_LIVE_FILE_UPDATED, this._onElUpdated);
callback();
};
}
onElUpdated() {
let activeRefs = this.fileEl.getAttribute(PHX_ACTIVE_ENTRY_REFS).split(",");
if (activeRefs.indexOf(this.ref) === -1) {
LiveUploader.untrackFile(this.fileEl, this.file);
this.cancel();
}
}
toPreflightPayload() {
return {
last_modified: this.file.lastModified,
name: this.file.name,
relative_path: this.file.webkitRelativePath,
size: this.file.size,
type: this.file.type,
ref: this.ref,
meta: typeof this.file.meta === "function" ? this.file.meta() : void 0
};
}
uploader(uploaders) {
if (this.meta.uploader) {
let callback = uploaders[this.meta.uploader] || logError(`no uploader configured for ${this.meta.uploader}`);
return { name: this.meta.uploader, callback };
} else {
return { name: "channel", callback: channelUploader };
}
}
zipPostFlight(resp) {
this.meta = resp.entries[this.ref];
if (!this.meta) {
logError(`no preflight upload response returned with ref ${this.ref}`, { input: this.fileEl, response: resp });
}
}
};
var liveUploaderFileRef = 0;
var LiveUploader = class {
static genFileRef(file) {
let ref = file._phxRef;
if (ref !== void 0) {
return ref;
} else {
file._phxRef = (liveUploaderFileRef++).toString();
return file._phxRef;
}
}
static getEntryDataURL(inputEl, ref, callback) {
let file = this.activeFiles(inputEl).find((file2) => this.genFileRef(file2) === ref);
callback(URL.createObjectURL(file));
}
static hasUploadsInProgress(formEl) {
let active = 0;
dom_default.findUploadInputs(formEl).forEach((input) => {
if (input.getAttribute(PHX_PREFLIGHTED_REFS) !== input.getAttribute(PHX_DONE_REFS)) {
active++;
}
});
return active > 0;
}
static serializeUploads(inputEl) {
let files = this.activeFiles(inputEl);
let fileData = {};
files.forEach((file) => {
let entry = { path: inputEl.name };
let uploadRef = inputEl.getAttribute(PHX_UPLOAD_REF);
fileData[uploadRef] = fileData[uploadRef] || [];
entry.ref = this.genFileRef(file);
entry.last_modified = file.lastModified;
entry.name = file.name || entry.ref;
entry.relative_path = file.webkitRelativePath;
entry.type = file.type;
entry.size = file.size;
if (typeof file.meta === "function") {
entry.meta = file.meta();
}
fileData[uploadRef].push(entry);
});
return fileData;
}
static clearFiles(inputEl) {
inputEl.value = null;
inputEl.removeAttribute(PHX_UPLOAD_REF);
dom_default.putPrivate(inputEl, "files", []);
}
static untrackFile(inputEl, file) {
dom_default.putPrivate(inputEl, "files", dom_default.private(inputEl, "files").filter((f) => !Object.is(f, file)));
}
static trackFiles(inputEl, files, dataTransfer) {
if (inputEl.getAttribute("multiple") !== null) {
let newFiles = files.filter((file) => !this.activeFiles(inputEl).find((f) => Object.is(f, file)));
dom_default.updatePrivate(inputEl, "files", [], (existing) => existing.concat(newFiles));
inputEl.value = null;
} else {
if (dataTransfer && dataTransfer.files.length > 0) {
inputEl.files = dataTransfer.files;
}
dom_default.putPrivate(inputEl, "files", files);
}
}
static activeFileInputs(formEl) {
let fileInputs = dom_default.findUploadInputs(formEl);
return Array.from(fileInputs).filter((el) => el.files && this.activeFiles(el).length > 0);
}
static activeFiles(input) {
return (dom_default.private(input, "files") || []).filter((f) => UploadEntry.isActive(input, f));
}
static inputsAwaitingPreflight(formEl) {
let fileInputs = dom_default.findUploadInputs(formEl);
return Array.from(fileInputs).filter((input) => this.filesAwaitingPreflight(input).length > 0);
}
static filesAwaitingPreflight(input) {
return this.activeFiles(input).filter((f) => !UploadEntry.isPreflighted(input, f) && !UploadEntry.isPreflightInProgress(f));
}
static markPreflightInProgress(entries) {
entries.forEach((entry) => UploadEntry.markPreflightInProgress(entry.file));
}
constructor(inputEl, view, onComplete) {
this.autoUpload = dom_default.isAutoUpload(inputEl);
this.view = view;
this.onComplete = onComplete;
this._entries = Array.from(LiveUploader.filesAwaitingPreflight(inputEl) || []).map((file) => new UploadEntry(inputEl, file, view, this.autoUpload));
LiveUploader.markPreflightInProgress(this._entries);
this.numEntriesInProgress = this._entries.length;
}
isAutoUpload() {
return this.autoUpload;
}
entries() {
return this._entries;
}
initAdapterUpload(resp, onError, liveSocket2) {
this._entries = this._entries.map((entry) => {
if (entry.isCancelled()) {
this.numEntriesInProgress--;
if (this.numEntriesInProgress === 0) {
this.onComplete();
}
} else {
entry.zipPostFlight(resp);
entry.onDone(() => {
this.numEntriesInProgress--;
if (this.numEntriesInProgress === 0) {
this.onComplete();
}
});
}
return entry;
});
let groupedEntries = this._entries.reduce((acc, entry) => {
if (!entry.meta) {
return acc;
}
let { name, callback } = entry.uploader(liveSocket2.uploaders);
acc[name] = acc[name] || { callback, entries: [] };
acc[name].entries.push(entry);
return acc;
}, {});
for (let name in groupedEntries) {
let { callback, entries } = groupedEntries[name];
callback(entries, onError, resp, liveSocket2);
}
}
};
var Hooks = {
LiveFileUpload: {
activeRefs() {
return this.el.getAttribute(PHX_ACTIVE_ENTRY_REFS);
},
preflightedRefs() {
return this.el.getAttribute(PHX_PREFLIGHTED_REFS);
},
mounted() {
this.preflightedWas = this.preflightedRefs();
},
updated() {
let newPreflights = this.preflightedRefs();
if (this.preflightedWas !== newPreflights) {
this.preflightedWas = newPreflights;
if (newPreflights === "") {
this.__view.cancelSubmit(this.el.form);
}
}
if (this.activeRefs() === "") {
this.el.value = null;
}
this.el.dispatchEvent(new CustomEvent(PHX_LIVE_FILE_UPDATED));
}
},
LiveImgPreview: {
mounted() {
this.ref = this.el.getAttribute("data-phx-entry-ref");
this.inputEl = document.getElementById(this.el.getAttribute(PHX_UPLOAD_REF));
LiveUploader.getEntryDataURL(this.inputEl, this.ref, (url) => {
this.url = url;
this.el.src = url;
});
},
destroyed() {
URL.revokeObjectURL(this.url);
}
},
FocusWrap: {
mounted() {
this.focusStart = this.el.firstElementChild;
this.focusEnd = this.el.lastElementChild;
this.focusStart.addEventListener("focus", () => aria_default.focusLast(this.el));
this.focusEnd.addEventListener("focus", () => aria_default.focusFirst(this.el));
this.el.addEventListener("phx:show-end", () => this.el.focus());
if (window.getComputedStyle(this.el).display !== "none") {
aria_default.focusFirst(this.el);
}
}
}
};
var findScrollContainer = (el) => {
if (["scroll", "auto"].indexOf(getComputedStyle(el).overflowY) >= 0)
return el;
if (document.documentElement === el)
return null;
return findScrollContainer(el.parentElement);
};
var scrollTop = (scrollContainer) => {
if (scrollContainer) {
return scrollContainer.scrollTop;
} else {
return document.documentElement.scrollTop || document.body.scrollTop;
}
};
var bottom = (scrollContainer) => {
if (scrollContainer) {
return scrollContainer.getBoundingClientRect().bottom;
} else {
return window.innerHeight || document.documentElement.clientHeight;
}
};
var top = (scrollContainer) => {
if (scrollContainer) {
return scrollContainer.getBoundingClientRect().top;
} else {
return 0;
}
};
var isAtViewportTop = (el, scrollContainer) => {
let rect = el.getBoundingClientRect();
return rect.top >= top(scrollContainer) && rect.left >= 0 && rect.top <= bottom(scrollContainer);
};
var isAtViewportBottom = (el, scrollContainer) => {
let rect = el.getBoundingClientRect();
return rect.right >= top(scrollContainer) && rect.left >= 0 && rect.bottom <= bottom(scrollContainer);
};
var isWithinViewport = (el, scrollContainer) => {
let rect = el.getBoundingClientRect();
return rect.top >= top(scrollContainer) && rect.left >= 0 && rect.top <= bottom(scrollContainer);
};
Hooks.InfiniteScroll = {
mounted() {
this.scrollContainer = findScrollContainer(this.el);
let scrollBefore = scrollTop(this.scrollContainer);
let topOverran = false;
let throttleInterval = 500;
let pendingOp = null;
let onTopOverrun = this.throttle(throttleInterval, (topEvent, firstChild) => {
pendingOp = () => true;
this.liveSocket.execJSHookPush(this.el, topEvent, { id: firstChild.id, _overran: true }, () => {
pendingOp = null;
});
});
let onFirstChildAtTop = this.throttle(throttleInterval, (topEvent, firstChild) => {
pendingOp = () => firstChild.scrollIntoView({ block: "start" });
this.liveSocket.execJSHookPush(this.el, topEvent, { id: firstChild.id }, () => {
pendingOp = null;
window.requestAnimationFrame(() => {
if (!isWithinViewport(firstChild, this.scrollContainer)) {
firstChild.scrollIntoView({ block: "start" });
}
});
});
});
let onLastChildAtBottom = this.throttle(throttleInterval, (bottomEvent, lastChild) => {
pendingOp = () => lastChild.scrollIntoView({ block: "end" });
this.liveSocket.execJSHookPush(this.el, bottomEvent, { id: lastChild.id }, () => {
pendingOp = null;
window.requestAnimationFrame(() => {
if (!isWithinViewport(lastChild, this.scrollContainer)) {
lastChild.scrollIntoView({ block: "end" });
}
});
});
});
this.onScroll = (_e) => {
let scrollNow = scrollTop(this.scrollContainer);
if (pendingOp) {
scrollBefore = scrollNow;
return pendingOp();
}
let rect = this.el.getBoundingClientRect();
let topEvent = this.el.getAttribute(this.liveSocket.binding("viewport-top"));
let bottomEvent = this.el.getAttribute(this.liveSocket.binding("viewport-bottom"));
let lastChild = this.el.lastElementChild;
let firstChild = this.el.firstElementChild;
let isScrollingUp = scrollNow < scrollBefore;
let isScrollingDown = scrollNow > scrollBefore;
if (isScrollingUp && topEvent && !topOverran && rect.top >= 0) {
topOverran = true;
onTopOverrun(topEvent, firstChild);
} else if (isScrollingDown && topOverran && rect.top <= 0) {
topOverran = false;
}
if (topEvent && isScrollingUp && isAtViewportTop(firstChild, this.scrollContainer)) {
onFirstChildAtTop(topEvent, firstChild);
} else if (bottomEvent && isScrollingDown && isAtViewportBottom(lastChild, this.scrollContainer)) {
onLastChildAtBottom(bottomEvent, lastChild);
}
scrollBefore = scrollNow;
};
if (this.scrollContainer) {
this.scrollContainer.addEventListener("scroll", this.onScroll);
} else {
window.addEventListener("scroll", this.onScroll);
}
},
destroyed() {
if (this.scrollContainer) {
this.scrollContainer.removeEventListener("scroll", this.onScroll);
} else {
window.removeEventListener("scroll", this.onScroll);
}
},
throttle(interval, callback) {
let lastCallAt = 0;
let timer;
return (...args) => {
let now = Date.now();
let remainingTime = interval - (now - lastCallAt);
if (remainingTime <= 0 || remainingTime > interval) {
if (timer) {
clearTimeout(timer);
timer = null;
}
lastCallAt = now;
callback(...args);
} else if (!timer) {
timer = setTimeout(() => {
lastCallAt = Date.now();
timer = null;
callback(...args);
}, remainingTime);
}
};
}
};
var hooks_default = Hooks;
var DOMPostMorphRestorer = class {
constructor(containerBefore, containerAfter, updateType) {
let idsBefore = /* @__PURE__ */ new Set();
let idsAfter = new Set([...containerAfter.children].map((child) => child.id));
let elementsToModify = [];
Array.from(containerBefore.children).forEach((child) => {
if (child.id) {
idsBefore.add(child.id);
if (idsAfter.has(child.id)) {
let previousElementId = child.previousElementSibling && child.previousElementSibling.id;
elementsToModify.push({ elementId: child.id, previousElementId });
}
}
});
this.containerId = containerAfter.id;
this.updateType = updateType;
this.elementsToModify = elementsToModify;
this.elementIdsToAdd = [...idsAfter].filter((id) => !idsBefore.has(id));
}
perform() {
let container = dom_default.byId(this.containerId);
this.elementsToModify.forEach((elementToModify) => {
if (elementToModify.previousElementId) {
maybe(document.getElementById(elementToModify.previousElementId), (previousElem) => {
maybe(document.getElementById(elementToModify.elementId), (elem) => {
let isInRightPlace = elem.previousElementSibling && elem.previousElementSibling.id == previousElem.id;
if (!isInRightPlace) {
previousElem.insertAdjacentElement("afterend", elem);
}
});
});
} else {
maybe(document.getElementById(elementToModify.elementId), (elem) => {
let isInRightPlace = elem.previousElementSibling == null;
if (!isInRightPlace) {
container.insertAdjacentElement("afterbegin", elem);
}
});
}
});
if (this.updateType == "prepend") {
this.elementIdsToAdd.reverse().forEach((elemId) => {
maybe(document.getElementById(elemId), (elem) => container.insertAdjacentElement("afterbegin", elem));
});
}
}
};
var DOCUMENT_FRAGMENT_NODE = 11;
function morphAttrs(fromNode, toNode) {
var toNodeAttrs = toNode.attributes;
var attr;
var attrName;
var attrNamespaceURI;
var attrValue;
var fromValue;
if (toNode.nodeType === DOCUMENT_FRAGMENT_NODE || fromNode.nodeType === DOCUMENT_FRAGMENT_NODE) {
return;
}
for (var i = toNodeAttrs.length - 1; i >= 0; i--) {
attr = toNodeAttrs[i];
attrName = attr.name;
attrNamespaceURI = attr.namespaceURI;
attrValue = attr.value;
if (attrNamespaceURI) {
attrName = attr.localName || attrName;
fromValue = fromNode.getAttributeNS(attrNamespaceURI, attrName);
if (fromValue !== attrValue) {
if (attr.prefix === "xmlns") {
attrName = attr.name;
}
fromNode.setAttributeNS(attrNamespaceURI, attrName, attrValue);
}
} else {
fromValue = fromNode.getAttribute(attrName);
if (fromValue !== attrValue) {
fromNode.setAttribute(attrName, attrValue);
}
}
}
var fromNodeAttrs = fromNode.attributes;
for (var d = fromNodeAttrs.length - 1; d >= 0; d--) {
attr = fromNodeAttrs[d];
attrName = attr.name;
attrNamespaceURI = attr.namespaceURI;
if (attrNamespaceURI) {
attrName = attr.localName || attrName;
if (!toNode.hasAttributeNS(attrNamespaceURI, attrName)) {
fromNode.removeAttributeNS(attrNamespaceURI, attrName);
}
} else {
if (!toNode.hasAttribute(attrName)) {
fromNode.removeAttribute(attrName);
}
}
}
}
var range;
var NS_XHTML = "http://www.w3.org/1999/xhtml";
var doc = typeof document === "undefined" ? void 0 : document;
var HAS_TEMPLATE_SUPPORT = !!doc && "content" in doc.createElement("template");
var HAS_RANGE_SUPPORT = !!doc && doc.createRange && "createContextualFragment" in doc.createRange();
function createFragmentFromTemplate(str) {
var template = doc.createElement("template");
template.innerHTML = str;
return template.content.childNodes[0];
}
function createFragmentFromRange(str) {
if (!range) {
range = doc.createRange();
range.selectNode(doc.body);
}
var fragment = range.createContextualFragment(str);
return fragment.childNodes[0];
}
function createFragmentFromWrap(str) {
var fragment = doc.createElement("body");
fragment.innerHTML = str;
return fragment.childNodes[0];
}
function toElement(str) {
str = str.trim();
if (HAS_TEMPLATE_SUPPORT) {
return createFragmentFromTemplate(str);
} else if (HAS_RANGE_SUPPORT) {
return createFragmentFromRange(str);
}
return createFragmentFromWrap(str);
}
function compareNodeNames(fromEl, toEl) {
var fromNodeName = fromEl.nodeName;
var toNodeName = toEl.nodeName;
var fromCodeStart, toCodeStart;
if (fromNodeName === toNodeName) {
return true;
}
fromCodeStart = fromNodeName.charCodeAt(0);
toCodeStart = toNodeName.charCodeAt(0);
if (fromCodeStart <= 90 && toCodeStart >= 97) {
return fromNodeName === toNodeName.toUpperCase();
} else if (toCodeStart <= 90 && fromCodeStart >= 97) {
return toNodeName === fromNodeName.toUpperCase();
} else {
return false;
}
}
function createElementNS(name, namespaceURI) {
return !namespaceURI || namespaceURI === NS_XHTML ? doc.createElement(name) : doc.createElementNS(namespaceURI, name);
}
function moveChildren(fromEl, toEl) {
var curChild = fromEl.firstChild;
while (curChild) {
var nextChild = curChild.nextSibling;
toEl.appendChild(curChild);
curChild = nextChild;
}
return toEl;
}
function syncBooleanAttrProp(fromEl, toEl, name) {
if (fromEl[name] !== toEl[name]) {
fromEl[name] = toEl[name];
if (fromEl[name]) {
fromEl.setAttribute(name, "");
} else {
fromEl.removeAttribute(name);
}
}
}
var specialElHandlers = {
OPTION: function(fromEl, toEl) {
var parentNode = fromEl.parentNode;
if (parentNode) {
var parentName = parentNode.nodeName.toUpperCase();
if (parentName === "OPTGROUP") {
parentNode = parentNode.parentNode;
parentName = parentNode && parentNode.nodeName.toUpperCase();
}
if (parentName === "SELECT" && !parentNode.hasAttribute("multiple")) {
if (fromEl.hasAttribute("selected") && !toEl.selected) {
fromEl.setAttribute("selected", "selected");
fromEl.removeAttribute("selected");
}
parentNode.selectedIndex = -1;
}
}
syncBooleanAttrProp(fromEl, toEl, "selected");
},
INPUT: function(fromEl, toEl) {
syncBooleanAttrProp(fromEl, toEl, "checked");
syncBooleanAttrProp(fromEl, toEl, "disabled");
if (fromEl.value !== toEl.value) {
fromEl.value = toEl.value;
}
if (!toEl.hasAttribute("value")) {
fromEl.removeAttribute("value");
}
},
TEXTAREA: function(fromEl, toEl) {
var newValue = toEl.value;
if (fromEl.value !== newValue) {
fromEl.value = newValue;
}
var firstChild = fromEl.firstChild;
if (firstChild) {
var oldValue = firstChild.nodeValue;
if (oldValue == newValue || !newValue && oldValue == fromEl.placeholder) {
return;
}
firstChild.nodeValue = newValue;
}
},
SELECT: function(fromEl, toEl) {
if (!toEl.hasAttribute("multiple")) {
var selectedIndex = -1;
var i = 0;
var curChild = fromEl.firstChild;
var optgroup;
var nodeName;
while (curChild) {
nodeName = curChild.nodeName && curChild.nodeName.toUpperCase();
if (nodeName === "OPTGROUP") {
optgroup = curChild;
curChild = optgroup.firstChild;
} else {
if (nodeName === "OPTION") {
if (curChild.hasAttribute("selected")) {
selectedIndex = i;
break;
}
i++;
}
curChild = curChild.nextSibling;
if (!curChild && optgroup) {
curChild = optgroup.nextSibling;
optgroup = null;
}
}
}
fromEl.selectedIndex = selectedIndex;
}
}
};
var ELEMENT_NODE = 1;
var DOCUMENT_FRAGMENT_NODE$1 = 11;
var TEXT_NODE = 3;
var COMMENT_NODE = 8;
function noop() {
}
function defaultGetNodeKey(node) {
if (node) {
return node.getAttribute && node.getAttribute("id") || node.id;
}
}
function morphdomFactory(morphAttrs2) {
return function morphdom2(fromNode, toNode, options) {
if (!options) {
options = {};
}
if (typeof toNode === "string") {
if (fromNode.nodeName === "#document" || fromNode.nodeName === "HTML" || fromNode.nodeName === "BODY") {
var toNodeHtml = toNode;
toNode = doc.createElement("html");
toNode.innerHTML = toNodeHtml;
} else {
toNode = toElement(toNode);
}
} else if (toNode.nodeType === DOCUMENT_FRAGMENT_NODE$1) {
toNode = toNode.firstElementChild;
}
var getNodeKey = options.getNodeKey || defaultGetNodeKey;
var onBeforeNodeAdded = options.onBeforeNodeAdded || noop;
var onNodeAdded = options.onNodeAdded || noop;
var onBeforeElUpdated = options.onBeforeElUpdated || noop;
var onElUpdated = options.onElUpdated || noop;
var onBeforeNodeDiscarded = options.onBeforeNodeDiscarded || noop;
var onNodeDiscarded = options.onNodeDiscarded || noop;
var onBeforeElChildrenUpdated = options.onBeforeElChildrenUpdated || noop;
var skipFromChildren = options.skipFromChildren || noop;
var addChild = options.addChild || function(parent, child) {
return parent.appendChild(child);
};
var childrenOnly = options.childrenOnly === true;
var fromNodesLookup = /* @__PURE__ */ Object.create(null);
var keyedRemovalList = [];
function addKeyedRemoval(key) {
keyedRemovalList.push(key);
}
function walkDiscardedChildNodes(node, skipKeyedNodes) {
if (node.nodeType === ELEMENT_NODE) {
var curChild = node.firstChild;
while (curChild) {
var key = void 0;
if (skipKeyedNodes && (key = getNodeKey(curChild))) {
addKeyedRemoval(key);
} else {
onNodeDiscarded(curChild);
if (curChild.firstChild) {
walkDiscardedChildNodes(curChild, skipKeyedNodes);
}
}
curChild = curChild.nextSibling;
}
}
}
function removeNode(node, parentNode, skipKeyedNodes) {
if (onBeforeNodeDiscarded(node) === false) {
return;
}
if (parentNode) {
parentNode.removeChild(node);
}
onNodeDiscarded(node);
walkDiscardedChildNodes(node, skipKeyedNodes);
}
function indexTree(node) {
if (node.nodeType === ELEMENT_NODE || node.nodeType === DOCUMENT_FRAGMENT_NODE$1) {
var curChild = node.firstChild;
while (curChild) {
var key = getNodeKey(curChild);
if (key) {
fromNodesLookup[key] = curChild;
}
indexTree(curChild);
curChild = curChild.nextSibling;
}
}
}
indexTree(fromNode);
function handleNodeAdded(el) {
onNodeAdded(el);
var curChild = el.firstChild;
while (curChild) {
var nextSibling = curChild.nextSibling;
var key = getNodeKey(curChild);
if (key) {
var unmatchedFromEl = fromNodesLookup[key];
if (unmatchedFromEl && compareNodeNames(curChild, unmatchedFromEl)) {
curChild.parentNode.replaceChild(unmatchedFromEl, curChild);
morphEl(unmatchedFromEl, curChild);
} else {
handleNodeAdded(curChild);
}
} else {
handleNodeAdded(curChild);
}
curChild = nextSibling;
}
}
function cleanupFromEl(fromEl, curFromNodeChild, curFromNodeKey) {
while (curFromNodeChild) {
var fromNextSibling = curFromNodeChild.nextSibling;
if (curFromNodeKey = getNodeKey(curFromNodeChild)) {
addKeyedRemoval(curFromNodeKey);
} else {
removeNode(curFromNodeChild, fromEl, true);
}
curFromNodeChild = fromNextSibling;
}
}
function morphEl(fromEl, toEl, childrenOnly2) {
var toElKey = getNodeKey(toEl);
if (toElKey) {
delete fromNodesLookup[toElKey];
}
if (!childrenOnly2) {
if (onBeforeElUpdated(fromEl, toEl) === false) {
return;
}
morphAttrs2(fromEl, toEl);
onElUpdated(fromEl);
if (onBeforeElChildrenUpdated(fromEl, toEl) === false) {
return;
}
}
if (fromEl.nodeName !== "TEXTAREA") {
morphChildren(fromEl, toEl);
} else {
specialElHandlers.TEXTAREA(fromEl, toEl);
}
}
function morphChildren(fromEl, toEl) {
var skipFrom = skipFromChildren(fromEl, toEl);
var curToNodeChild = toEl.firstChild;
var curFromNodeChild = fromEl.firstChild;
var curToNodeKey;
var curFromNodeKey;
var fromNextSibling;
var toNextSibling;
var matchingFromEl;
outer:
while (curToNodeChild) {
toNextSibling = curToNodeChild.nextSibling;
curToNodeKey = getNodeKey(curToNodeChild);
while (!skipFrom && curFromNodeChild) {
fromNextSibling = curFromNodeChild.nextSibling;
if (curToNodeChild.isSameNode && curToNodeChild.isSameNode(curFromNodeChild)) {
curToNodeChild = toNextSibling;
curFromNodeChild = fromNextSibling;
continue outer;
}
curFromNodeKey = getNodeKey(curFromNodeChild);
var curFromNodeType = curFromNodeChild.nodeType;
var isCompatible = void 0;
if (curFromNodeType === curToNodeChild.nodeType) {
if (curFromNodeType === ELEMENT_NODE) {
if (curToNodeKey) {
if (curToNodeKey !== curFromNodeKey) {
if (matchingFromEl = fromNodesLookup[curToNodeKey]) {
if (fromNextSibling === matchingFromEl) {
isCompatible = false;
} else {
fromEl.insertBefore(matchingFromEl, curFromNodeChild);
if (curFromNodeKey) {
addKeyedRemoval(curFromNodeKey);
} else {
removeNode(curFromNodeChild, fromEl, true);
}
curFromNodeChild = matchingFromEl;
curFromNodeKey = getNodeKey(curFromNodeChild);
}
} else {
isCompatible = false;
}
}
} else if (curFromNodeKey) {
isCompatible = false;
}
isCompatible = isCompatible !== false && compareNodeNames(curFromNodeChild, curToNodeChild);
if (isCompatible) {
morphEl(curFromNodeChild, curToNodeChild);
}
} else if (curFromNodeType === TEXT_NODE || curFromNodeType == COMMENT_NODE) {
isCompatible = true;
if (curFromNodeChild.nodeValue !== curToNodeChild.nodeValue) {
curFromNodeChild.nodeValue = curToNodeChild.nodeValue;
}
}
}
if (isCompatible) {
curToNodeChild = toNextSibling;
curFromNodeChild = fromNextSibling;
continue outer;
}
if (curFromNodeKey) {
addKeyedRemoval(curFromNodeKey);
} else {
removeNode(curFromNodeChild, fromEl, true);
}
curFromNodeChild = fromNextSibling;
}
if (curToNodeKey && (matchingFromEl = fromNodesLookup[curToNodeKey]) && compareNodeNames(matchingFromEl, curToNodeChild)) {
if (!skipFrom) {
addChild(fromEl, matchingFromEl);
}
morphEl(matchingFromEl, curToNodeChild);
} else {
var onBeforeNodeAddedResult = onBeforeNodeAdded(curToNodeChild);
if (onBeforeNodeAddedResult !== false) {
if (onBeforeNodeAddedResult) {
curToNodeChild = onBeforeNodeAddedResult;
}
if (curToNodeChild.actualize) {
curToNodeChild = curToNodeChild.actualize(fromEl.ownerDocument || doc);
}
addChild(fromEl, curToNodeChild);
handleNodeAdded(curToNodeChild);
}
}
curToNodeChild = toNextSibling;
curFromNodeChild = fromNextSibling;
}
cleanupFromEl(fromEl, curFromNodeChild, curFromNodeKey);
var specialElHandler = specialElHandlers[fromEl.nodeName];
if (specialElHandler) {
specialElHandler(fromEl, toEl);
}
}
var morphedNode = fromNode;
var morphedNodeType = morphedNode.nodeType;
var toNodeType = toNode.nodeType;
if (!childrenOnly) {
if (morphedNodeType === ELEMENT_NODE) {
if (toNodeType === ELEMENT_NODE) {
if (!compareNodeNames(fromNode, toNode)) {
onNodeDiscarded(fromNode);
morphedNode = moveChildren(fromNode, createElementNS(toNode.nodeName, toNode.namespaceURI));
}
} else {
morphedNode = toNode;
}
} else if (morphedNodeType === TEXT_NODE || morphedNodeType === COMMENT_NODE) {
if (toNodeType === morphedNodeType) {
if (morphedNode.nodeValue !== toNode.nodeValue) {
morphedNode.nodeValue = toNode.nodeValue;
}
return morphedNode;
} else {
morphedNode = toNode;
}
}
}
if (morphedNode === toNode) {
onNodeDiscarded(fromNode);
} else {
if (toNode.isSameNode && toNode.isSameNode(morphedNode)) {
return;
}
morphEl(morphedNode, toNode, childrenOnly);
if (keyedRemovalList) {
for (var i = 0, len = keyedRemovalList.length; i < len; i++) {
var elToRemove = fromNodesLookup[keyedRemovalList[i]];
if (elToRemove) {
removeNode(elToRemove, elToRemove.parentNode, false);
}
}
}
}
if (!childrenOnly && morphedNode !== fromNode && fromNode.parentNode) {
if (morphedNode.actualize) {
morphedNode = morphedNode.actualize(fromNode.ownerDocument || doc);
}
fromNode.parentNode.replaceChild(morphedNode, fromNode);
}
return morphedNode;
};
}
var morphdom = morphdomFactory(morphAttrs);
var morphdom_esm_default = morphdom;
var DOMPatch = class {
static patchEl(fromEl, toEl, activeElement) {
morphdom_esm_default(fromEl, toEl, {
childrenOnly: false,
onBeforeElUpdated: (fromEl2, toEl2) => {
if (activeElement && activeElement.isSameNode(fromEl2) && dom_default.isFormInput(fromEl2)) {
dom_default.mergeFocusedInput(fromEl2, toEl2);
return false;
}
}
});
}
constructor(view, container, id, html, streams, targetCID) {
this.view = view;
this.liveSocket = view.liveSocket;
this.container = container;
this.id = id;
this.rootID = view.root.id;
this.html = html;
this.streams = streams;
this.streamInserts = {};
this.streamComponentRestore = {};
this.targetCID = targetCID;
this.cidPatch = isCid(this.targetCID);
this.pendingRemoves = [];
this.phxRemove = this.liveSocket.binding("remove");
this.callbacks = {
beforeadded: [],
beforeupdated: [],
beforephxChildAdded: [],
afteradded: [],
afterupdated: [],
afterdiscarded: [],
afterphxChildAdded: [],
aftertransitionsDiscarded: []
};
}
before(kind, callback) {
this.callbacks[`before${kind}`].push(callback);
}
after(kind, callback) {
this.callbacks[`after${kind}`].push(callback);
}
trackBefore(kind, ...args) {
this.callbacks[`before${kind}`].forEach((callback) => callback(...args));
}
trackAfter(kind, ...args) {
this.callbacks[`after${kind}`].forEach((callback) => callback(...args));
}
markPrunableContentForRemoval() {
let phxUpdate = this.liveSocket.binding(PHX_UPDATE);
dom_default.all(this.container, `[${phxUpdate}=append] > *, [${phxUpdate}=prepend] > *`, (el) => {
el.setAttribute(PHX_PRUNE, "");
});
}
perform(isJoinPatch) {
let { view, liveSocket: liveSocket2, container, html } = this;
let targetContainer = this.isCIDPatch() ? this.targetCIDContainer(html) : container;
if (this.isCIDPatch() && !targetContainer) {
return;
}
let focused = liveSocket2.getActiveElement();
let { selectionStart, selectionEnd } = focused && dom_default.hasSelectionRange(focused) ? focused : {};
let phxUpdate = liveSocket2.binding(PHX_UPDATE);
let phxFeedbackFor = liveSocket2.binding(PHX_FEEDBACK_FOR);
let phxFeedbackGroup = liveSocket2.binding(PHX_FEEDBACK_GROUP);
let disableWith = liveSocket2.binding(PHX_DISABLE_WITH);
let phxViewportTop = liveSocket2.binding(PHX_VIEWPORT_TOP);
let phxViewportBottom = liveSocket2.binding(PHX_VIEWPORT_BOTTOM);
let phxTriggerExternal = liveSocket2.binding(PHX_TRIGGER_ACTION);
let added = [];
let feedbackContainers = [];
let updates = [];
let appendPrependUpdates = [];
let externalFormTriggered = null;
function morph(targetContainer2, source) {
morphdom_esm_default(targetContainer2, source, {
childrenOnly: targetContainer2.getAttribute(PHX_COMPONENT) === null,
getNodeKey: (node) => {
if (dom_default.isPhxDestroyed(node)) {
return null;
}
if (isJoinPatch) {
return node.id;
}
return node.id || node.getAttribute && node.getAttribute(PHX_MAGIC_ID);
},
skipFromChildren: (from) => {
return from.getAttribute(phxUpdate) === PHX_STREAM;
},
addChild: (parent, child) => {
let { ref, streamAt } = this.getStreamInsert(child);
if (ref === void 0) {
return parent.appendChild(child);
}
this.setStreamRef(child, ref);
if (streamAt === 0) {
parent.insertAdjacentElement("afterbegin", child);
} else if (streamAt === -1) {
parent.appendChild(child);
} else if (streamAt > 0) {
let sibling = Array.from(parent.children)[streamAt];
parent.insertBefore(child, sibling);
}
},
onBeforeNodeAdded: (el) => {
dom_default.maybeAddPrivateHooks(el, phxViewportTop, phxViewportBottom);
this.trackBefore("added", el);
let morphedEl = el;
if (!isJoinPatch && this.streamComponentRestore[el.id]) {
morphedEl = this.streamComponentRestore[el.id];
delete this.streamComponentRestore[el.id];
morph.bind(this)(morphedEl, el);
}
return morphedEl;
},
onNodeAdded: (el) => {
if (el.getAttribute) {
this.maybeReOrderStream(el, true);
}
if (dom_default.isFeedbackContainer(el, phxFeedbackFor))
feedbackContainers.push(el);
if (el instanceof HTMLImageElement && el.srcset) {
el.srcset = el.srcset;
} else if (el instanceof HTMLVideoElement && el.autoplay) {
el.play();
}
if (dom_default.isNowTriggerFormExternal(el, phxTriggerExternal)) {
externalFormTriggered = el;
}
if (dom_default.isPhxChild(el) && view.ownsElement(el) || dom_default.isPhxSticky(el) && view.ownsElement(el.parentNode)) {
this.trackAfter("phxChildAdded", el);
}
added.push(el);
},
onNodeDiscarded: (el) => this.onNodeDiscarded(el),
onBeforeNodeDiscarded: (el) => {
if (el.getAttribute && el.getAttribute(PHX_PRUNE) !== null) {
return true;
}
if (el.parentElement !== null && el.id && dom_default.isPhxUpdate(el.parentElement, phxUpdate, [PHX_STREAM, "append", "prepend"])) {
return false;
}
if (this.maybePendingRemove(el)) {
return false;
}
if (this.skipCIDSibling(el)) {
return false;
}
return true;
},
onElUpdated: (el) => {
if (dom_default.isNowTriggerFormExternal(el, phxTriggerExternal)) {
externalFormTriggered = el;
}
updates.push(el);
this.maybeReOrderStream(el, false);
},
onBeforeElUpdated: (fromEl, toEl) => {
dom_default.maybeAddPrivateHooks(toEl, phxViewportTop, phxViewportBottom);
if (dom_default.isFeedbackContainer(fromEl, phxFeedbackFor) || dom_default.isFeedbackContainer(toEl, phxFeedbackFor)) {
feedbackContainers.push(fromEl);
feedbackContainers.push(toEl);
}
dom_default.cleanChildNodes(toEl, phxUpdate);
if (this.skipCIDSibling(toEl)) {
this.maybeReOrderStream(fromEl);
return false;
}
if (dom_default.isPhxSticky(fromEl)) {
return false;
}
if (dom_default.isIgnored(fromEl, phxUpdate) || fromEl.form && fromEl.form.isSameNode(externalFormTriggered)) {
this.trackBefore("updated", fromEl, toEl);
dom_default.mergeAttrs(fromEl, toEl, { isIgnored: true });
updates.push(fromEl);
dom_default.applyStickyOperations(fromEl);
return false;
}
if (fromEl.type === "number" && (fromEl.validity && fromEl.validity.badInput)) {
return false;
}
if (!dom_default.syncPendingRef(fromEl, toEl, disableWith)) {
if (dom_default.isUploadInput(fromEl)) {
this.trackBefore("updated", fromEl, toEl);
updates.push(fromEl);
}
dom_default.applyStickyOperations(fromEl);
return false;
}
if (dom_default.isPhxChild(toEl)) {
let prevSession = fromEl.getAttribute(PHX_SESSION);
dom_default.mergeAttrs(fromEl, toEl, { exclude: [PHX_STATIC] });
if (prevSession !== "") {
fromEl.setAttribute(PHX_SESSION, prevSession);
}
fromEl.setAttribute(PHX_ROOT_ID, this.rootID);
dom_default.applyStickyOperations(fromEl);
return false;
}
dom_default.copyPrivates(toEl, fromEl);
let isFocusedFormEl = focused && fromEl.isSameNode(focused) && dom_default.isFormInput(fromEl);
let focusedSelectChanged = isFocusedFormEl && this.isChangedSelect(fromEl, toEl);
if (isFocusedFormEl && fromEl.type !== "hidden" && !focusedSelectChanged) {
this.trackBefore("updated", fromEl, toEl);
dom_default.mergeFocusedInput(fromEl, toEl);
dom_default.syncAttrsToProps(fromEl);
updates.push(fromEl);
dom_default.applyStickyOperations(fromEl);
return false;
} else {
if (focusedSelectChanged) {
fromEl.blur();
}
if (dom_default.isPhxUpdate(toEl, phxUpdate, ["append", "prepend"])) {
appendPrependUpdates.push(new DOMPostMorphRestorer(fromEl, toEl, toEl.getAttribute(phxUpdate)));
}
dom_default.syncAttrsToProps(toEl);
dom_default.applyStickyOperations(toEl);
this.trackBefore("updated", fromEl, toEl);
return true;
}
}
});
}
this.trackBefore("added", container);
this.trackBefore("updated", container, container);
liveSocket2.time("morphdom", () => {
this.streams.forEach(([ref, inserts, deleteIds, reset]) => {
inserts.forEach(([key, streamAt, limit]) => {
this.streamInserts[key] = { ref, streamAt, limit, reset };
});
if (reset !== void 0) {
dom_default.all(container, `[${PHX_STREAM_REF}="${ref}"]`, (child) => {
this.removeStreamChildElement(child);
});
}
deleteIds.forEach((id) => {
let child = container.querySelector(`[id="${id}"]`);
if (child) {
this.removeStreamChildElement(child);
}
});
});
if (isJoinPatch) {
dom_default.all(this.container, `[${phxUpdate}=${PHX_STREAM}]`, (el) => {
this.liveSocket.owner(el, (view2) => {
if (view2 === this.view) {
Array.from(el.children).forEach((child) => {
this.removeStreamChildElement(child);
});
}
});
});
}
morph.bind(this)(targetContainer, html);
});
if (liveSocket2.isDebugEnabled()) {
detectDuplicateIds();
}
if (appendPrependUpdates.length > 0) {
liveSocket2.time("post-morph append/prepend restoration", () => {
appendPrependUpdates.forEach((update) => update.perform());
});
}
dom_default.maybeHideFeedback(targetContainer, feedbackContainers, phxFeedbackFor, phxFeedbackGroup);
liveSocket2.silenceEvents(() => dom_default.restoreFocus(focused, selectionStart, selectionEnd));
dom_default.dispatchEvent(document, "phx:update");
added.forEach((el) => this.trackAfter("added", el));
updates.forEach((el) => this.trackAfter("updated", el));
this.transitionPendingRemoves();
if (externalFormTriggered) {
liveSocket2.unload();
Object.getPrototypeOf(externalFormTriggered).submit.call(externalFormTriggered);
}
return true;
}
onNodeDiscarded(el) {
if (dom_default.isPhxChild(el) || dom_default.isPhxSticky(el)) {
this.liveSocket.destroyViewByEl(el);
}
this.trackAfter("discarded", el);
}
maybePendingRemove(node) {
if (node.getAttribute && node.getAttribute(this.phxRemove) !== null) {
this.pendingRemoves.push(node);
return true;
} else {
return false;
}
}
removeStreamChildElement(child) {
if (this.streamInserts[child.id]) {
this.streamComponentRestore[child.id] = child;
child.remove();
} else {
if (!this.maybePendingRemove(child)) {
child.remove();
this.onNodeDiscarded(child);
}
}
}
getStreamInsert(el) {
let insert = el.id ? this.streamInserts[el.id] : {};
return insert || {};
}
setStreamRef(el, ref) {
dom_default.putSticky(el, PHX_STREAM_REF, (el2) => el2.setAttribute(PHX_STREAM_REF, ref));
}
maybeReOrderStream(el, isNew) {
let { ref, streamAt, reset } = this.getStreamInsert(el);
if (streamAt === void 0) {
return;
}
this.setStreamRef(el, ref);
if (!reset && !isNew) {
return;
}
if (!el.parentElement) {
return;
}
if (streamAt === 0) {
el.parentElement.insertBefore(el, el.parentElement.firstElementChild);
} else if (streamAt > 0) {
let children = Array.from(el.parentElement.children);
let oldIndex = children.indexOf(el);
if (streamAt >= children.length - 1) {
el.parentElement.appendChild(el);
} else {
let sibling = children[streamAt];
if (oldIndex > streamAt) {
el.parentElement.insertBefore(el, sibling);
} else {
el.parentElement.insertBefore(el, sibling.nextElementSibling);
}
}
}
this.maybeLimitStream(el);
}
maybeLimitStream(el) {
let { limit } = this.getStreamInsert(el);
let children = limit !== null && Array.from(el.parentElement.children);
if (limit && limit < 0 && children.length > limit * -1) {
children.slice(0, children.length + limit).forEach((child) => this.removeStreamChildElement(child));
} else if (limit && limit >= 0 && children.length > limit) {
children.slice(limit).forEach((child) => this.removeStreamChildElement(child));
}
}
transitionPendingRemoves() {
let { pendingRemoves, liveSocket: liveSocket2 } = this;
if (pendingRemoves.length > 0) {
liveSocket2.transitionRemoves(pendingRemoves);
liveSocket2.requestDOMUpdate(() => {
pendingRemoves.forEach((el) => {
let child = dom_default.firstPhxChild(el);
if (child) {
liveSocket2.destroyViewByEl(child);
}
el.remove();
});
this.trackAfter("transitionsDiscarded", pendingRemoves);
});
}
}
isChangedSelect(fromEl, toEl) {
if (!(fromEl instanceof HTMLSelectElement) || fromEl.multiple) {
return false;
}
if (fromEl.options.length !== toEl.options.length) {
return true;
}
let fromSelected = fromEl.selectedOptions[0];
let toSelected = toEl.selectedOptions[0];
if (fromSelected && fromSelected.hasAttribute("selected")) {
toSelected.setAttribute("selected", fromSelected.getAttribute("selected"));
}
return !fromEl.isEqualNode(toEl);
}
isCIDPatch() {
return this.cidPatch;
}
skipCIDSibling(el) {
return el.nodeType === Node.ELEMENT_NODE && el.hasAttribute(PHX_SKIP);
}
targetCIDContainer(html) {
if (!this.isCIDPatch()) {
return;
}
let [first, ...rest] = dom_default.findComponentNodeList(this.container, this.targetCID);
if (rest.length === 0 && dom_default.childNodeLength(html) === 1) {
return first;
} else {
return first && first.parentNode;
}
}
indexOf(parent, child) {
return Array.from(parent.children).indexOf(child);
}
};
var VOID_TAGS = /* @__PURE__ */ new Set([
"area",
"base",
"br",
"col",
"command",
"embed",
"hr",
"img",
"input",
"keygen",
"link",
"meta",
"param",
"source",
"track",
"wbr"
]);
var quoteChars = /* @__PURE__ */ new Set(["'", '"']);
var modifyRoot = (html, attrs, clearInnerHTML) => {
let i = 0;
let insideComment = false;
let beforeTag, afterTag, tag, tagNameEndsAt, id, newHTML;
let lookahead = html.match(/^(\s*(?:<!--.*?-->\s*)*)<([^\s\/>]+)/);
if (lookahead === null) {
throw new Error(`malformed html ${html}`);
}
i = lookahead[0].length;
beforeTag = lookahead[1];
tag = lookahead[2];
tagNameEndsAt = i;
for (i; i < html.length; i++) {
if (html.charAt(i) === ">") {
break;
}
if (html.charAt(i) === "=") {
let isId = html.slice(i - 3, i) === " id";
i++;
let char = html.charAt(i);
if (quoteChars.has(char)) {
let attrStartsAt = i;
i++;
for (i; i < html.length; i++) {
if (html.charAt(i) === char) {
break;
}
}
if (isId) {
id = html.slice(attrStartsAt + 1, i);
break;
}
}
}
}
let closeAt = html.length - 1;
insideComment = false;
while (closeAt >= beforeTag.length + tag.length) {
let char = html.charAt(closeAt);
if (insideComment) {
if (char === "-" && html.slice(closeAt - 3, closeAt) === "<!-") {
insideComment = false;
closeAt -= 4;
} else {
closeAt -= 1;
}
} else if (char === ">" && html.slice(closeAt - 2, closeAt) === "--") {
insideComment = true;
closeAt -= 3;
} else if (char === ">") {
break;
} else {
closeAt -= 1;
}
}
afterTag = html.slice(closeAt + 1, html.length);
let attrsStr = Object.keys(attrs).map((attr) => attrs[attr] === true ? attr : `${attr}="${attrs[attr]}"`).join(" ");
if (clearInnerHTML) {
let idAttrStr = id ? ` id="${id}"` : "";
if (VOID_TAGS.has(tag)) {
newHTML = `<${tag}${idAttrStr}${attrsStr === "" ? "" : " "}${attrsStr}/>`;
} else {
newHTML = `<${tag}${idAttrStr}${attrsStr === "" ? "" : " "}${attrsStr}></${tag}>`;
}
} else {
let rest = html.slice(tagNameEndsAt, closeAt + 1);
newHTML = `<${tag}${attrsStr === "" ? "" : " "}${attrsStr}${rest}`;
}
return [newHTML, beforeTag, afterTag];
};
var Rendered = class {
static extract(diff) {
let { [REPLY]: reply, [EVENTS]: events, [TITLE]: title } = diff;
delete diff[REPLY];
delete diff[EVENTS];
delete diff[TITLE];
return { diff, title, reply: reply || null, events: events || [] };
}
constructor(viewId, rendered) {
this.viewId = viewId;
this.rendered = {};
this.magicId = 0;
this.mergeDiff(rendered);
}
parentViewId() {
return this.viewId;
}
toString(onlyCids) {
let [str, streams] = this.recursiveToString(this.rendered, this.rendered[COMPONENTS], onlyCids, true, {});
return [str, streams];
}
recursiveToString(rendered, components = rendered[COMPONENTS], onlyCids, changeTracking, rootAttrs) {
onlyCids = onlyCids ? new Set(onlyCids) : null;
let output = { buffer: "", components, onlyCids, streams: /* @__PURE__ */ new Set() };
this.toOutputBuffer(rendered, null, output, changeTracking, rootAttrs);
return [output.buffer, output.streams];
}
componentCIDs(diff) {
return Object.keys(diff[COMPONENTS] || {}).map((i) => parseInt(i));
}
isComponentOnlyDiff(diff) {
if (!diff[COMPONENTS]) {
return false;
}
return Object.keys(diff).length === 1;
}
getComponent(diff, cid) {
return diff[COMPONENTS][cid];
}
resetRender(cid) {
if (this.rendered[COMPONENTS][cid]) {
this.rendered[COMPONENTS][cid].reset = true;
}
}
mergeDiff(diff) {
let newc = diff[COMPONENTS];
let cache = {};
delete diff[COMPONENTS];
this.rendered = this.mutableMerge(this.rendered, diff);
this.rendered[COMPONENTS] = this.rendered[COMPONENTS] || {};
if (newc) {
let oldc = this.rendered[COMPONENTS];
for (let cid in newc) {
newc[cid] = this.cachedFindComponent(cid, newc[cid], oldc, newc, cache);
}
for (let cid in newc) {
oldc[cid] = newc[cid];
}
diff[COMPONENTS] = newc;
}
}
cachedFindComponent(cid, cdiff, oldc, newc, cache) {
if (cache[cid]) {
return cache[cid];
} else {
let ndiff, stat, scid = cdiff[STATIC];
if (isCid(scid)) {
let tdiff;
if (scid > 0) {
tdiff = this.cachedFindComponent(scid, newc[scid], oldc, newc, cache);
} else {
tdiff = oldc[-scid];
}
stat = tdiff[STATIC];
ndiff = this.cloneMerge(tdiff, cdiff, true);
ndiff[STATIC] = stat;
} else {
ndiff = cdiff[STATIC] !== void 0 || oldc[cid] === void 0 ? cdiff : this.cloneMerge(oldc[cid], cdiff, false);
}
cache[cid] = ndiff;
return ndiff;
}
}
mutableMerge(target, source) {
if (source[STATIC] !== void 0) {
return source;
} else {
this.doMutableMerge(target, source);
return target;
}
}
doMutableMerge(target, source) {
for (let key in source) {
let val = source[key];
let targetVal = target[key];
let isObjVal = isObject(val);
if (isObjVal && val[STATIC] === void 0 && isObject(targetVal)) {
this.doMutableMerge(targetVal, val);
} else {
target[key] = val;
}
}
if (target[ROOT]) {
target.newRender = true;
}
}
cloneMerge(target, source, pruneMagicId) {
let merged = __spreadValues(__spreadValues({}, target), source);
for (let key in merged) {
let val = source[key];
let targetVal = target[key];
if (isObject(val) && val[STATIC] === void 0 && isObject(targetVal)) {
merged[key] = this.cloneMerge(targetVal, val, pruneMagicId);
} else if (val === void 0 && isObject(targetVal)) {
merged[key] = this.cloneMerge(targetVal, {}, pruneMagicId);
}
}
if (pruneMagicId) {
delete merged.magicId;
delete merged.newRender;
} else if (target[ROOT]) {
merged.newRender = true;
}
return merged;
}
componentToString(cid) {
let [str, streams] = this.recursiveCIDToString(this.rendered[COMPONENTS], cid, null);
let [strippedHTML, _before, _after] = modifyRoot(str, {});
return [strippedHTML, streams];
}
pruneCIDs(cids) {
cids.forEach((cid) => delete this.rendered[COMPONENTS][cid]);
}
get() {
return this.rendered;
}
isNewFingerprint(diff = {}) {
return !!diff[STATIC];
}
templateStatic(part, templates) {
if (typeof part === "number") {
return templates[part];
} else {
return part;
}
}
nextMagicID() {
this.magicId++;
return `m${this.magicId}-${this.parentViewId()}`;
}
toOutputBuffer(rendered, templates, output, changeTracking, rootAttrs = {}) {
if (rendered[DYNAMICS]) {
return this.comprehensionToBuffer(rendered, templates, output);
}
let { [STATIC]: statics } = rendered;
statics = this.templateStatic(statics, templates);
let isRoot = rendered[ROOT];
let prevBuffer = output.buffer;
if (isRoot) {
output.buffer = "";
}
if (changeTracking && isRoot && !rendered.magicId) {
rendered.newRender = true;
rendered.magicId = this.nextMagicID();
}
output.buffer += statics[0];
for (let i = 1; i < statics.length; i++) {
this.dynamicToBuffer(rendered[i - 1], templates, output, changeTracking);
output.buffer += statics[i];
}
if (isRoot) {
let skip = false;
let attrs;
if (changeTracking || rendered.magicId) {
skip = changeTracking && !rendered.newRender;
attrs = __spreadValues({ [PHX_MAGIC_ID]: rendered.magicId }, rootAttrs);
} else {
attrs = rootAttrs;
}
if (skip) {
attrs[PHX_SKIP] = true;
}
let [newRoot, commentBefore, commentAfter] = modifyRoot(output.buffer, attrs, skip);
rendered.newRender = false;
output.buffer = prevBuffer + commentBefore + newRoot + commentAfter;
}
}
comprehensionToBuffer(rendered, templates, output) {
let { [DYNAMICS]: dynamics, [STATIC]: statics, [STREAM]: stream } = rendered;
let [_ref, _inserts, deleteIds, reset] = stream || [null, {}, [], null];
statics = this.templateStatic(statics, templates);
let compTemplates = templates || rendered[TEMPLATES];
for (let d = 0; d < dynamics.length; d++) {
let dynamic = dynamics[d];
output.buffer += statics[0];
for (let i = 1; i < statics.length; i++) {
let changeTracking = false;
this.dynamicToBuffer(dynamic[i - 1], compTemplates, output, changeTracking);
output.buffer += statics[i];
}
}
if (stream !== void 0 && (rendered[DYNAMICS].length > 0 || deleteIds.length > 0 || reset)) {
delete rendered[STREAM];
rendered[DYNAMICS] = [];
output.streams.add(stream);
}
}
dynamicToBuffer(rendered, templates, output, changeTracking) {
if (typeof rendered === "number") {
let [str, streams] = this.recursiveCIDToString(output.components, rendered, output.onlyCids);
output.buffer += str;
output.streams = /* @__PURE__ */ new Set([...output.streams, ...streams]);
} else if (isObject(rendered)) {
this.toOutputBuffer(rendered, templates, output, changeTracking, {});
} else {
output.buffer += rendered;
}
}
recursiveCIDToString(components, cid, onlyCids) {
let component = components[cid] || logError(`no component for CID ${cid}`, components);
let attrs = { [PHX_COMPONENT]: cid };
let skip = onlyCids && !onlyCids.has(cid);
component.newRender = !skip;
component.magicId = `c${cid}-${this.parentViewId()}`;
let changeTracking = !component.reset;
let [html, streams] = this.recursiveToString(component, components, onlyCids, changeTracking, attrs);
delete component.reset;
return [html, streams];
}
};
var viewHookID = 1;
var ViewHook = class {
static makeID() {
return viewHookID++;
}
static elementID(el) {
return el.phxHookId;
}
constructor(view, el, callbacks) {
this.__view = view;
this.liveSocket = view.liveSocket;
this.__callbacks = callbacks;
this.__listeners = /* @__PURE__ */ new Set();
this.__isDisconnected = false;
this.el = el;
this.el.phxHookId = this.constructor.makeID();
for (let key in this.__callbacks) {
this[key] = this.__callbacks[key];
}
}
__mounted() {
this.mounted && this.mounted();
}
__updated() {
this.updated && this.updated();
}
__beforeUpdate() {
this.beforeUpdate && this.beforeUpdate();
}
__destroyed() {
this.destroyed && this.destroyed();
}
__reconnected() {
if (this.__isDisconnected) {
this.__isDisconnected = false;
this.reconnected && this.reconnected();
}
}
__disconnected() {
this.__isDisconnected = true;
this.disconnected && this.disconnected();
}
pushEvent(event, payload = {}, onReply = function() {
}) {
return this.__view.pushHookEvent(this.el, null, event, payload, onReply);
}
pushEventTo(phxTarget, event, payload = {}, onReply = function() {
}) {
return this.__view.withinTargets(phxTarget, (view, targetCtx) => {
return view.pushHookEvent(this.el, targetCtx, event, payload, onReply);
});
}
handleEvent(event, callback) {
let callbackRef = (customEvent, bypass) => bypass ? event : callback(customEvent.detail);
window.addEventListener(`phx:${event}`, callbackRef);
this.__listeners.add(callbackRef);
return callbackRef;
}
removeHandleEvent(callbackRef) {
let event = callbackRef(null, true);
window.removeEventListener(`phx:${event}`, callbackRef);
this.__listeners.delete(callbackRef);
}
upload(name, files) {
return this.__view.dispatchUploads(null, name, files);
}
uploadTo(phxTarget, name, files) {
return this.__view.withinTargets(phxTarget, (view, targetCtx) => {
view.dispatchUploads(targetCtx, name, files);
});
}
__cleanup__() {
this.__listeners.forEach((callbackRef) => this.removeHandleEvent(callbackRef));
}
};
var serializeForm = (form, metadata, onlyNames = []) => {
const _a = metadata, { submitter } = _a, meta = __objRest(_a, ["submitter"]);
let injectedElement;
if (submitter && submitter.name) {
const input = document.createElement("input");
input.type = "hidden";
const formId = submitter.getAttribute("form");
if (formId) {
input.setAttribute("form", formId);
}
input.name = submitter.name;
input.value = submitter.value;
submitter.parentElement.insertBefore(input, submitter);
injectedElement = input;
}
const formData = new FormData(form);
const toRemove = [];
formData.forEach((val, key, _index) => {
if (val instanceof File) {
toRemove.push(key);
}
});
toRemove.forEach((key) => formData.delete(key));
const params2 = new URLSearchParams();
for (let [key, val] of formData.entries()) {
if (onlyNames.length === 0 || onlyNames.indexOf(key) >= 0) {
params2.append(key, val);
}
}
if (submitter && injectedElement) {
submitter.parentElement.removeChild(injectedElement);
}
for (let metaKey in meta) {
params2.append(metaKey, meta[metaKey]);
}
return params2.toString();
};
var View = class {
constructor(el, liveSocket2, parentView, flash, liveReferer) {
this.isDead = false;
this.liveSocket = liveSocket2;
this.flash = flash;
this.parent = parentView;
this.root = parentView ? parentView.root : this;
this.el = el;
this.id = this.el.id;
this.ref = 0;
this.childJoins = 0;
this.loaderTimer = null;
this.pendingDiffs = [];
this.pendingForms = /* @__PURE__ */ new Set();
this.redirect = false;
this.href = null;
this.joinCount = this.parent ? this.parent.joinCount - 1 : 0;
this.joinPending = true;
this.destroyed = false;
this.joinCallback = function(onDone) {
onDone && onDone();
};
this.stopCallback = function() {
};
this.pendingJoinOps = this.parent ? null : [];
this.viewHooks = {};
this.formSubmits = [];
this.children = this.parent ? null : {};
this.root.children[this.id] = {};
this.channel = this.liveSocket.channel(`lv:${this.id}`, () => {
let url = this.href && this.expandURL(this.href);
return {
redirect: this.redirect ? url : void 0,
url: this.redirect ? void 0 : url || void 0,
params: this.connectParams(liveReferer),
session: this.getSession(),
static: this.getStatic(),
flash: this.flash
};
});
}
setHref(href) {
this.href = href;
}
setRedirect(href) {
this.redirect = true;
this.href = href;
}
isMain() {
return this.el.hasAttribute(PHX_MAIN);
}
connectParams(liveReferer) {
let params2 = this.liveSocket.params(this.el);
let manifest = dom_default.all(document, `[${this.binding(PHX_TRACK_STATIC)}]`).map((node) => node.src || node.href).filter((url) => typeof url === "string");
if (manifest.length > 0) {
params2["_track_static"] = manifest;
}
params2["_mounts"] = this.joinCount;
params2["_live_referer"] = liveReferer;
return params2;
}
isConnected() {
return this.channel.canPush();
}
getSession() {
return this.el.getAttribute(PHX_SESSION);
}
getStatic() {
let val = this.el.getAttribute(PHX_STATIC);
return val === "" ? null : val;
}
destroy(callback = function() {
}) {
this.destroyAllChildren();
this.destroyed = true;
delete this.root.children[this.id];
if (this.parent) {
delete this.root.children[this.parent.id][this.id];
}
clearTimeout(this.loaderTimer);
let onFinished = () => {
callback();
for (let id in this.viewHooks) {
this.destroyHook(this.viewHooks[id]);
}
};
dom_default.markPhxChildDestroyed(this.el);
this.log("destroyed", () => ["the child has been removed from the parent"]);
this.channel.leave().receive("ok", onFinished).receive("error", onFinished).receive("timeout", onFinished);
}
setContainerClasses(...classes) {
this.el.classList.remove(PHX_CONNECTED_CLASS, PHX_LOADING_CLASS, PHX_ERROR_CLASS, PHX_CLIENT_ERROR_CLASS, PHX_SERVER_ERROR_CLASS);
this.el.classList.add(...classes);
}
showLoader(timeout) {
clearTimeout(this.loaderTimer);
if (timeout) {
this.loaderTimer = setTimeout(() => this.showLoader(), timeout);
} else {
for (let id in this.viewHooks) {
this.viewHooks[id].__disconnected();
}
this.setContainerClasses(PHX_LOADING_CLASS);
}
}
execAll(binding) {
dom_default.all(this.el, `[${binding}]`, (el) => this.liveSocket.execJS(el, el.getAttribute(binding)));
}
hideLoader() {
clearTimeout(this.loaderTimer);
this.setContainerClasses(PHX_CONNECTED_CLASS);
this.execAll(this.binding("connected"));
}
triggerReconnected() {
for (let id in this.viewHooks) {
this.viewHooks[id].__reconnected();
}
}
log(kind, msgCallback) {
this.liveSocket.log(this, kind, msgCallback);
}
transition(time, onStart, onDone = function() {
}) {
this.liveSocket.transition(time, onStart, onDone);
}
withinTargets(phxTarget, callback) {
if (phxTarget instanceof HTMLElement || phxTarget instanceof SVGElement) {
return this.liveSocket.owner(phxTarget, (view) => callback(view, phxTarget));
}
if (isCid(phxTarget)) {
let targets = dom_default.findComponentNodeList(this.el, phxTarget);
if (targets.length === 0) {
logError(`no component found matching phx-target of ${phxTarget}`);
} else {
callback(this, parseInt(phxTarget));
}
} else {
let targets = Array.from(document.querySelectorAll(phxTarget));
if (targets.length === 0) {
logError(`nothing found matching the phx-target selector "${phxTarget}"`);
}
targets.forEach((target) => this.liveSocket.owner(target, (view) => callback(view, target)));
}
}
applyDiff(type, rawDiff, callback) {
this.log(type, () => ["", clone(rawDiff)]);
let { diff, reply, events, title } = Rendered.extract(rawDiff);
callback({ diff, reply, events });
if (title) {
window.requestAnimationFrame(() => dom_default.putTitle(title));
}
}
onJoin(resp) {
let { rendered, container } = resp;
if (container) {
let [tag, attrs] = container;
this.el = dom_default.replaceRootContainer(this.el, tag, attrs);
}
this.childJoins = 0;
this.joinPending = true;
this.flash = null;
browser_default.dropLocal(this.liveSocket.localStorage, window.location.pathname, CONSECUTIVE_RELOADS);
this.applyDiff("mount", rendered, ({ diff, events }) => {
this.rendered = new Rendered(this.id, diff);
let [html, streams] = this.renderContainer(null, "join");
this.dropPendingRefs();
let forms = this.formsForRecovery(html).filter(([form, newForm, newCid]) => {
return !this.pendingForms.has(form.id);
});
this.joinCount++;
if (forms.length > 0) {
forms.forEach(([form, newForm, newCid], i) => {
this.pendingForms.add(form.id);
this.pushFormRecovery(form, newCid, (resp2) => {
this.pendingForms.delete(form.id);
if (i === forms.length - 1) {
this.onJoinComplete(resp2, html, streams, events);
}
});
});
} else {
this.onJoinComplete(resp, html, streams, events);
}
});
}
dropPendingRefs() {
dom_default.all(document, `[${PHX_REF_SRC}="${this.id}"][${PHX_REF}]`, (el) => {
el.removeAttribute(PHX_REF);
el.removeAttribute(PHX_REF_SRC);
});
}
onJoinComplete({ live_patch }, html, streams, events) {
this.pendingForms.clear();
if (this.joinCount > 1 || this.parent && !this.parent.isJoinPending()) {
return this.applyJoinPatch(live_patch, html, streams, events);
}
let newChildren = dom_default.findPhxChildrenInFragment(html, this.id).filter((toEl) => {
let fromEl = toEl.id && this.el.querySelector(`[id="${toEl.id}"]`);
let phxStatic = fromEl && fromEl.getAttribute(PHX_STATIC);
if (phxStatic) {
toEl.setAttribute(PHX_STATIC, phxStatic);
}
if (fromEl) {
fromEl.setAttribute(PHX_ROOT_ID, this.root.id);
}
return this.joinChild(toEl);
});
if (newChildren.length === 0) {
if (this.parent) {
this.root.pendingJoinOps.push([this, () => this.applyJoinPatch(live_patch, html, streams, events)]);
this.parent.ackJoin(this);
} else {
this.onAllChildJoinsComplete();
this.applyJoinPatch(live_patch, html, streams, events);
}
} else {
this.root.pendingJoinOps.push([this, () => this.applyJoinPatch(live_patch, html, streams, events)]);
}
}
attachTrueDocEl() {
this.el = dom_default.byId(this.id);
this.el.setAttribute(PHX_ROOT_ID, this.root.id);
}
execNewMounted() {
let phxViewportTop = this.binding(PHX_VIEWPORT_TOP);
let phxViewportBottom = this.binding(PHX_VIEWPORT_BOTTOM);
dom_default.all(this.el, `[${phxViewportTop}], [${phxViewportBottom}]`, (hookEl) => {
dom_default.maybeAddPrivateHooks(hookEl, phxViewportTop, phxViewportBottom);
this.maybeAddNewHook(hookEl);
});
dom_default.all(this.el, `[${this.binding(PHX_HOOK)}], [data-phx-${PHX_HOOK}]`, (hookEl) => {
this.maybeAddNewHook(hookEl);
});
dom_default.all(this.el, `[${this.binding(PHX_MOUNTED)}]`, (el) => this.maybeMounted(el));
}
applyJoinPatch(live_patch, html, streams, events) {
this.attachTrueDocEl();
let patch = new DOMPatch(this, this.el, this.id, html, streams, null);
patch.markPrunableContentForRemoval();
this.performPatch(patch, false, true);
this.joinNewChildren();
this.execNewMounted();
this.joinPending = false;
this.liveSocket.dispatchEvents(events);
this.applyPendingUpdates();
if (live_patch) {
let { kind, to } = live_patch;
this.liveSocket.historyPatch(to, kind);
}
this.hideLoader();
if (this.joinCount > 1) {
this.triggerReconnected();
}
this.stopCallback();
}
triggerBeforeUpdateHook(fromEl, toEl) {
this.liveSocket.triggerDOM("onBeforeElUpdated", [fromEl, toEl]);
let hook = this.getHook(fromEl);
let isIgnored = hook && dom_default.isIgnored(fromEl, this.binding(PHX_UPDATE));
if (hook && !fromEl.isEqualNode(toEl) && !(isIgnored && isEqualObj(fromEl.dataset, toEl.dataset))) {
hook.__beforeUpdate();
return hook;
}
}
maybeMounted(el) {
let phxMounted = el.getAttribute(this.binding(PHX_MOUNTED));
let hasBeenInvoked = phxMounted && dom_default.private(el, "mounted");
if (phxMounted && !hasBeenInvoked) {
this.liveSocket.execJS(el, phxMounted);
dom_default.putPrivate(el, "mounted", true);
}
}
maybeAddNewHook(el, force) {
let newHook = this.addHook(el);
if (newHook) {
newHook.__mounted();
}
}
performPatch(patch, pruneCids, isJoinPatch = false) {
let removedEls = [];
let phxChildrenAdded = false;
let updatedHookIds = /* @__PURE__ */ new Set();
patch.after("added", (el) => {
this.liveSocket.triggerDOM("onNodeAdded", [el]);
let phxViewportTop = this.binding(PHX_VIEWPORT_TOP);
let phxViewportBottom = this.binding(PHX_VIEWPORT_BOTTOM);
dom_default.maybeAddPrivateHooks(el, phxViewportTop, phxViewportBottom);
this.maybeAddNewHook(el);
if (el.getAttribute) {
this.maybeMounted(el);
}
});
patch.after("phxChildAdded", (el) => {
if (dom_default.isPhxSticky(el)) {
this.liveSocket.joinRootViews();
} else {
phxChildrenAdded = true;
}
});
patch.before("updated", (fromEl, toEl) => {
let hook = this.triggerBeforeUpdateHook(fromEl, toEl);
if (hook) {
updatedHookIds.add(fromEl.id);
}
});
patch.after("updated", (el) => {
if (updatedHookIds.has(el.id)) {
this.getHook(el).__updated();
}
});
patch.after("discarded", (el) => {
if (el.nodeType === Node.ELEMENT_NODE) {
removedEls.push(el);
}
});
patch.after("transitionsDiscarded", (els) => this.afterElementsRemoved(els, pruneCids));
patch.perform(isJoinPatch);
this.afterElementsRemoved(removedEls, pruneCids);
return phxChildrenAdded;
}
afterElementsRemoved(elements, pruneCids) {
let destroyedCIDs = [];
elements.forEach((parent) => {
let components = dom_default.all(parent, `[${PHX_COMPONENT}]`);
let hooks = dom_default.all(parent, `[${this.binding(PHX_HOOK)}]`);
components.concat(parent).forEach((el) => {
let cid = this.componentID(el);
if (isCid(cid) && destroyedCIDs.indexOf(cid) === -1) {
destroyedCIDs.push(cid);
}
});
hooks.concat(parent).forEach((hookEl) => {
let hook = this.getHook(hookEl);
hook && this.destroyHook(hook);
});
});
if (pruneCids) {
this.maybePushComponentsDestroyed(destroyedCIDs);
}
}
joinNewChildren() {
dom_default.findPhxChildren(this.el, this.id).forEach((el) => this.joinChild(el));
}
getChildById(id) {
return this.root.children[this.id][id];
}
getDescendentByEl(el) {
if (el.id === this.id) {
return this;
} else {
return this.children[el.getAttribute(PHX_PARENT_ID)][el.id];
}
}
destroyDescendent(id) {
for (let parentId in this.root.children) {
for (let childId in this.root.children[parentId]) {
if (childId === id) {
return this.root.children[parentId][childId].destroy();
}
}
}
}
joinChild(el) {
let child = this.getChildById(el.id);
if (!child) {
let view = new View(el, this.liveSocket, this);
this.root.children[this.id][view.id] = view;
view.join();
this.childJoins++;
return true;
}
}
isJoinPending() {
return this.joinPending;
}
ackJoin(_child) {
this.childJoins--;
if (this.childJoins === 0) {
if (this.parent) {
this.parent.ackJoin(this);
} else {
this.onAllChildJoinsComplete();
}
}
}
onAllChildJoinsComplete() {
this.joinCallback(() => {
this.pendingJoinOps.forEach(([view, op]) => {
if (!view.isDestroyed()) {
op();
}
});
this.pendingJoinOps = [];
});
}
update(diff, events) {
if (this.isJoinPending() || this.liveSocket.hasPendingLink() && this.root.isMain()) {
return this.pendingDiffs.push({ diff, events });
}
this.rendered.mergeDiff(diff);
let phxChildrenAdded = false;
if (this.rendered.isComponentOnlyDiff(diff)) {
this.liveSocket.time("component patch complete", () => {
let parentCids = dom_default.findParentCIDs(this.el, this.rendered.componentCIDs(diff));
parentCids.forEach((parentCID) => {
if (this.componentPatch(this.rendered.getComponent(diff, parentCID), parentCID)) {
phxChildrenAdded = true;
}
});
});
} else if (!isEmpty(diff)) {
this.liveSocket.time("full patch complete", () => {
let [html, streams] = this.renderContainer(diff, "update");
let patch = new DOMPatch(this, this.el, this.id, html, streams, null);
phxChildrenAdded = this.performPatch(patch, true);
});
}
this.liveSocket.dispatchEvents(events);
if (phxChildrenAdded) {
this.joinNewChildren();
}
}
renderContainer(diff, kind) {
return this.liveSocket.time(`toString diff (${kind})`, () => {
let tag = this.el.tagName;
let cids = diff ? this.rendered.componentCIDs(diff) : null;
let [html, streams] = this.rendered.toString(cids);
return [`<${tag}>${html}</${tag}>`, streams];
});
}
componentPatch(diff, cid) {
if (isEmpty(diff))
return false;
let [html, streams] = this.rendered.componentToString(cid);
let patch = new DOMPatch(this, this.el, this.id, html, streams, cid);
let childrenAdded = this.performPatch(patch, true);
return childrenAdded;
}
getHook(el) {
return this.viewHooks[ViewHook.elementID(el)];
}
addHook(el) {
if (ViewHook.elementID(el) || !el.getAttribute) {
return;
}
let hookName = el.getAttribute(`data-phx-${PHX_HOOK}`) || el.getAttribute(this.binding(PHX_HOOK));
if (hookName && !this.ownsElement(el)) {
return;
}
let callbacks = this.liveSocket.getHookCallbacks(hookName);
if (callbacks) {
if (!el.id) {
logError(`no DOM ID for hook "${hookName}". Hooks require a unique ID on each element.`, el);
}
let hook = new ViewHook(this, el, callbacks);
this.viewHooks[ViewHook.elementID(hook.el)] = hook;
return hook;
} else if (hookName !== null) {
logError(`unknown hook found for "${hookName}"`, el);
}
}
destroyHook(hook) {
hook.__destroyed();
hook.__cleanup__();
delete this.viewHooks[ViewHook.elementID(hook.el)];
}
applyPendingUpdates() {
this.pendingDiffs.forEach(({ diff, events }) => this.update(diff, events));
this.pendingDiffs = [];
this.eachChild((child) => child.applyPendingUpdates());
}
eachChild(callback) {
let children = this.root.children[this.id] || {};
for (let id in children) {
callback(this.getChildById(id));
}
}
onChannel(event, cb) {
this.liveSocket.onChannel(this.channel, event, (resp) => {
if (this.isJoinPending()) {
this.root.pendingJoinOps.push([this, () => cb(resp)]);
} else {
this.liveSocket.requestDOMUpdate(() => cb(resp));
}
});
}
bindChannel() {
this.liveSocket.onChannel(this.channel, "diff", (rawDiff) => {
this.liveSocket.requestDOMUpdate(() => {
this.applyDiff("update", rawDiff, ({ diff, events }) => this.update(diff, events));
});
});
this.onChannel("redirect", ({ to, flash }) => this.onRedirect({ to, flash }));
this.onChannel("live_patch", (redir) => this.onLivePatch(redir));
this.onChannel("live_redirect", (redir) => this.onLiveRedirect(redir));
this.channel.onError((reason) => this.onError(reason));
this.channel.onClose((reason) => this.onClose(reason));
}
destroyAllChildren() {
this.eachChild((child) => child.destroy());
}
onLiveRedirect(redir) {
let { to, kind, flash } = redir;
let url = this.expandURL(to);
this.liveSocket.historyRedirect(url, kind, flash);
}
onLivePatch(redir) {
let { to, kind } = redir;
this.href = this.expandURL(to);
this.liveSocket.historyPatch(to, kind);
}
expandURL(to) {
return to.startsWith("/") ? `${window.location.protocol}//${window.location.host}${to}` : to;
}
onRedirect({ to, flash }) {
this.liveSocket.redirect(to, flash);
}
isDestroyed() {
return this.destroyed;
}
joinDead() {
this.isDead = true;
}
join(callback) {
this.showLoader(this.liveSocket.loaderTimeout);
this.bindChannel();
if (this.isMain()) {
this.stopCallback = this.liveSocket.withPageLoading({ to: this.href, kind: "initial" });
}
this.joinCallback = (onDone) => {
onDone = onDone || function() {
};
callback ? callback(this.joinCount, onDone) : onDone();
};
this.liveSocket.wrapPush(this, { timeout: false }, () => {
return this.channel.join().receive("ok", (data) => {
if (!this.isDestroyed()) {
this.liveSocket.requestDOMUpdate(() => this.onJoin(data));
}
}).receive("error", (resp) => !this.isDestroyed() && this.onJoinError(resp)).receive("timeout", () => !this.isDestroyed() && this.onJoinError({ reason: "timeout" }));
});
}
onJoinError(resp) {
if (resp.reason === "reload") {
this.log("error", () => [`failed mount with ${resp.status}. Falling back to page request`, resp]);
if (this.isMain()) {
this.onRedirect({ to: this.href });
}
return;
} else if (resp.reason === "unauthorized" || resp.reason === "stale") {
this.log("error", () => ["unauthorized live_redirect. Falling back to page request", resp]);
if (this.isMain()) {
this.onRedirect({ to: this.href });
}
return;
}
if (resp.redirect || resp.live_redirect) {
this.joinPending = false;
this.channel.leave();
}
if (resp.redirect) {
return this.onRedirect(resp.redirect);
}
if (resp.live_redirect) {
return this.onLiveRedirect(resp.live_redirect);
}
this.displayError([PHX_LOADING_CLASS, PHX_ERROR_CLASS, PHX_SERVER_ERROR_CLASS]);
this.log("error", () => ["unable to join", resp]);
if (this.liveSocket.isConnected()) {
this.liveSocket.reloadWithJitter(this);
}
}
onClose(reason) {
if (this.isDestroyed()) {
return;
}
if (this.liveSocket.hasPendingLink() && reason !== "leave") {
return this.liveSocket.reloadWithJitter(this);
}
this.destroyAllChildren();
this.liveSocket.dropActiveElement(this);
if (document.activeElement) {
document.activeElement.blur();
}
if (this.liveSocket.isUnloaded()) {
this.showLoader(BEFORE_UNLOAD_LOADER_TIMEOUT);
}
}
onError(reason) {
this.onClose(reason);
if (this.liveSocket.isConnected()) {
this.log("error", () => ["view crashed", reason]);
}
if (!this.liveSocket.isUnloaded()) {
if (this.liveSocket.isConnected()) {
this.displayError([PHX_LOADING_CLASS, PHX_ERROR_CLASS, PHX_SERVER_ERROR_CLASS]);
} else {
this.displayError([PHX_LOADING_CLASS, PHX_ERROR_CLASS, PHX_CLIENT_ERROR_CLASS]);
}
}
}
displayError(classes) {
if (this.isMain()) {
dom_default.dispatchEvent(window, "phx:page-loading-start", { detail: { to: this.href, kind: "error" } });
}
this.showLoader();
this.setContainerClasses(...classes);
this.execAll(this.binding("disconnected"));
}
pushWithReply(refGenerator, event, payload, onReply = function() {
}) {
if (!this.isConnected()) {
return;
}
let [ref, [el], opts] = refGenerator ? refGenerator() : [null, [], {}];
let onLoadingDone = function() {
};
if (opts.page_loading || el && el.getAttribute(this.binding(PHX_PAGE_LOADING)) !== null) {
onLoadingDone = this.liveSocket.withPageLoading({ kind: "element", target: el });
}
if (typeof payload.cid !== "number") {
delete payload.cid;
}
return this.liveSocket.wrapPush(this, { timeout: true }, () => {
return this.channel.push(event, payload, PUSH_TIMEOUT).receive("ok", (resp) => {
let finish = (hookReply) => {
if (resp.redirect) {
this.onRedirect(resp.redirect);
}
if (resp.live_patch) {
this.onLivePatch(resp.live_patch);
}
if (resp.live_redirect) {
this.onLiveRedirect(resp.live_redirect);
}
onLoadingDone();
onReply(resp, hookReply);
};
if (resp.diff) {
this.liveSocket.requestDOMUpdate(() => {
this.applyDiff("update", resp.diff, ({ diff, reply, events }) => {
if (ref !== null) {
this.undoRefs(ref);
}
this.update(diff, events);
finish(reply);
});
});
} else {
if (ref !== null) {
this.undoRefs(ref);
}
finish(null);
}
});
});
}
undoRefs(ref) {
if (!this.isConnected()) {
return;
}
dom_default.all(document, `[${PHX_REF_SRC}="${this.id}"][${PHX_REF}="${ref}"]`, (el) => {
let disabledVal = el.getAttribute(PHX_DISABLED);
let readOnlyVal = el.getAttribute(PHX_READONLY);
el.removeAttribute(PHX_REF);
el.removeAttribute(PHX_REF_SRC);
if (readOnlyVal !== null) {
el.readOnly = readOnlyVal === "true" ? true : false;
el.removeAttribute(PHX_READONLY);
}
if (disabledVal !== null) {
el.disabled = disabledVal === "true" ? true : false;
el.removeAttribute(PHX_DISABLED);
}
PHX_EVENT_CLASSES.forEach((className) => dom_default.removeClass(el, className));
let disableRestore = el.getAttribute(PHX_DISABLE_WITH_RESTORE);
if (disableRestore !== null) {
el.innerText = disableRestore;
el.removeAttribute(PHX_DISABLE_WITH_RESTORE);
}
let toEl = dom_default.private(el, PHX_REF);
if (toEl) {
let hook = this.triggerBeforeUpdateHook(el, toEl);
DOMPatch.patchEl(el, toEl, this.liveSocket.getActiveElement());
if (hook) {
hook.__updated();
}
dom_default.deletePrivate(el, PHX_REF);
}
});
}
putRef(elements, event, opts = {}) {
let newRef = this.ref++;
let disableWith = this.binding(PHX_DISABLE_WITH);
if (opts.loading) {
elements = elements.concat(dom_default.all(document, opts.loading));
}
elements.forEach((el) => {
el.classList.add(`phx-${event}-loading`);
el.setAttribute(PHX_REF, newRef);
el.setAttribute(PHX_REF_SRC, this.el.id);
let disableText = el.getAttribute(disableWith);
if (disableText !== null) {
if (!el.getAttribute(PHX_DISABLE_WITH_RESTORE)) {
el.setAttribute(PHX_DISABLE_WITH_RESTORE, el.innerText);
}
if (disableText !== "") {
el.innerText = disableText;
}
el.setAttribute(PHX_DISABLED, el.getAttribute(PHX_DISABLED) || el.disabled);
el.setAttribute("disabled", "");
}
});
return [newRef, elements, opts];
}
componentID(el) {
let cid = el.getAttribute && el.getAttribute(PHX_COMPONENT);
return cid ? parseInt(cid) : null;
}
targetComponentID(target, targetCtx, opts = {}) {
if (isCid(targetCtx)) {
return targetCtx;
}
let cidOrSelector = opts.target || target.getAttribute(this.binding("target"));
if (isCid(cidOrSelector)) {
return parseInt(cidOrSelector);
} else if (targetCtx && (cidOrSelector !== null || opts.target)) {
return this.closestComponentID(targetCtx);
} else {
return null;
}
}
closestComponentID(targetCtx) {
if (isCid(targetCtx)) {
return targetCtx;
} else if (targetCtx) {
return maybe(targetCtx.closest(`[${PHX_COMPONENT}]`), (el) => this.ownsElement(el) && this.componentID(el));
} else {
return null;
}
}
pushHookEvent(el, targetCtx, event, payload, onReply) {
if (!this.isConnected()) {
this.log("hook", () => ["unable to push hook event. LiveView not connected", event, payload]);
return false;
}
let [ref, els, opts] = this.putRef([el], "hook");
this.pushWithReply(() => [ref, els, opts], "event", {
type: "hook",
event,
value: payload,
cid: this.closestComponentID(targetCtx)
}, (resp, reply) => onReply(reply, ref));
return ref;
}
extractMeta(el, meta, value) {
let prefix = this.binding("value-");
for (let i = 0; i < el.attributes.length; i++) {
if (!meta) {
meta = {};
}
let name = el.attributes[i].name;
if (name.startsWith(prefix)) {
meta[name.replace(prefix, "")] = el.getAttribute(name);
}
}
if (el.value !== void 0 && !(el instanceof HTMLFormElement)) {
if (!meta) {
meta = {};
}
meta.value = el.value;
if (el.tagName === "INPUT" && CHECKABLE_INPUTS.indexOf(el.type) >= 0 && !el.checked) {
delete meta.value;
}
}
if (value) {
if (!meta) {
meta = {};
}
for (let key in value) {
meta[key] = value[key];
}
}
return meta;
}
pushEvent(type, el, targetCtx, phxEvent, meta, opts = {}, onReply) {
this.pushWithReply(() => this.putRef([el], type, opts), "event", {
type,
event: phxEvent,
value: this.extractMeta(el, meta, opts.value),
cid: this.targetComponentID(el, targetCtx, opts)
}, (resp, reply) => onReply && onReply(reply));
}
pushFileProgress(fileEl, entryRef, progress, onReply = function() {
}) {
this.liveSocket.withinOwners(fileEl.form, (view, targetCtx) => {
view.pushWithReply(null, "progress", {
event: fileEl.getAttribute(view.binding(PHX_PROGRESS)),
ref: fileEl.getAttribute(PHX_UPLOAD_REF),
entry_ref: entryRef,
progress,
cid: view.targetComponentID(fileEl.form, targetCtx)
}, onReply);
});
}
pushInput(inputEl, targetCtx, forceCid, phxEvent, opts, callback) {
let uploads;
let cid = isCid(forceCid) ? forceCid : this.targetComponentID(inputEl.form, targetCtx, opts);
let refGenerator = () => this.putRef([inputEl, inputEl.form], "change", opts);
let formData;
let meta = this.extractMeta(inputEl.form);
if (inputEl instanceof HTMLButtonElement) {
meta.submitter = inputEl;
}
if (inputEl.getAttribute(this.binding("change"))) {
formData = serializeForm(inputEl.form, __spreadValues({ _target: opts._target }, meta), [inputEl.name]);
} else {
formData = serializeForm(inputEl.form, __spreadValues({ _target: opts._target }, meta));
}
if (dom_default.isUploadInput(inputEl) && inputEl.files && inputEl.files.length > 0) {
LiveUploader.trackFiles(inputEl, Array.from(inputEl.files));
}
uploads = LiveUploader.serializeUploads(inputEl);
let event = {
type: "form",
event: phxEvent,
value: formData,
uploads,
cid
};
this.pushWithReply(refGenerator, "event", event, (resp) => {
dom_default.showError(inputEl, this.liveSocket.binding(PHX_FEEDBACK_FOR), this.liveSocket.binding(PHX_FEEDBACK_GROUP));
if (dom_default.isUploadInput(inputEl) && dom_default.isAutoUpload(inputEl)) {
if (LiveUploader.filesAwaitingPreflight(inputEl).length > 0) {
let [ref, _els] = refGenerator();
this.uploadFiles(inputEl.form, targetCtx, ref, cid, (_uploads) => {
callback && callback(resp);
this.triggerAwaitingSubmit(inputEl.form);
this.undoRefs(ref);
});
}
} else {
callback && callback(resp);
}
});
}
triggerAwaitingSubmit(formEl) {
let awaitingSubmit = this.getScheduledSubmit(formEl);
if (awaitingSubmit) {
let [_el, _ref, _opts, callback] = awaitingSubmit;
this.cancelSubmit(formEl);
callback();
}
}
getScheduledSubmit(formEl) {
return this.formSubmits.find(([el, _ref, _opts, _callback]) => el.isSameNode(formEl));
}
scheduleSubmit(formEl, ref, opts, callback) {
if (this.getScheduledSubmit(formEl)) {
return true;
}
this.formSubmits.push([formEl, ref, opts, callback]);
}
cancelSubmit(formEl) {
this.formSubmits = this.formSubmits.filter(([el, ref, _callback]) => {
if (el.isSameNode(formEl)) {
this.undoRefs(ref);
return false;
} else {
return true;
}
});
}
disableForm(formEl, opts = {}) {
let filterIgnored = (el) => {
let userIgnored = closestPhxBinding(el, `${this.binding(PHX_UPDATE)}=ignore`, el.form);
return !(userIgnored || closestPhxBinding(el, "data-phx-update=ignore", el.form));
};
let filterDisables = (el) => {
return el.hasAttribute(this.binding(PHX_DISABLE_WITH));
};
let filterButton = (el) => el.tagName == "BUTTON";
let filterInput = (el) => ["INPUT", "TEXTAREA", "SELECT"].includes(el.tagName);
let formElements = Array.from(formEl.elements);
let disables = formElements.filter(filterDisables);
let buttons = formElements.filter(filterButton).filter(filterIgnored);
let inputs = formElements.filter(filterInput).filter(filterIgnored);
buttons.forEach((button) => {
button.setAttribute(PHX_DISABLED, button.disabled);
button.disabled = true;
});
inputs.forEach((input) => {
input.setAttribute(PHX_READONLY, input.readOnly);
input.readOnly = true;
if (input.files) {
input.setAttribute(PHX_DISABLED, input.disabled);
input.disabled = true;
}
});
formEl.setAttribute(this.binding(PHX_PAGE_LOADING), "");
return this.putRef([formEl].concat(disables).concat(buttons).concat(inputs), "submit", opts);
}
pushFormSubmit(formEl, targetCtx, phxEvent, submitter, opts, onReply) {
let refGenerator = () => this.disableForm(formEl, opts);
let cid = this.targetComponentID(formEl, targetCtx);
if (LiveUploader.hasUploadsInProgress(formEl)) {
let [ref, _els] = refGenerator();
let push = () => this.pushFormSubmit(formEl, targetCtx, phxEvent, submitter, opts, onReply);
return this.scheduleSubmit(formEl, ref, opts, push);
} else if (LiveUploader.inputsAwaitingPreflight(formEl).length > 0) {
let [ref, els] = refGenerator();
let proxyRefGen = () => [ref, els, opts];
this.uploadFiles(formEl, targetCtx, ref, cid, (uploads) => {
if (LiveUploader.inputsAwaitingPreflight(formEl).length > 0) {
return this.undoRefs(ref);
}
let meta = this.extractMeta(formEl);
let formData = serializeForm(formEl, __spreadValues({ submitter }, meta));
this.pushWithReply(proxyRefGen, "event", {
type: "form",
event: phxEvent,
value: formData,
cid
}, onReply);
});
} else if (!(formEl.hasAttribute(PHX_REF) && formEl.classList.contains("phx-submit-loading"))) {
let meta = this.extractMeta(formEl);
let formData = serializeForm(formEl, __spreadValues({ submitter }, meta));
this.pushWithReply(refGenerator, "event", {
type: "form",
event: phxEvent,
value: formData,
cid
}, onReply);
}
}
uploadFiles(formEl, targetCtx, ref, cid, onComplete) {
let joinCountAtUpload = this.joinCount;
let inputEls = LiveUploader.activeFileInputs(formEl);
let numFileInputsInProgress = inputEls.length;
inputEls.forEach((inputEl) => {
let uploader = new LiveUploader(inputEl, this, () => {
numFileInputsInProgress--;
if (numFileInputsInProgress === 0) {
onComplete();
}
});
let entries = uploader.entries().map((entry) => entry.toPreflightPayload());
if (entries.length === 0) {
numFileInputsInProgress--;
return;
}
let payload = {
ref: inputEl.getAttribute(PHX_UPLOAD_REF),
entries,
cid: this.targetComponentID(inputEl.form, targetCtx)
};
this.log("upload", () => ["sending preflight request", payload]);
this.pushWithReply(null, "allow_upload", payload, (resp) => {
this.log("upload", () => ["got preflight response", resp]);
uploader.entries().forEach((entry) => {
if (resp.entries && !resp.entries[entry.ref]) {
this.handleFailedEntryPreflight(entry.ref, "failed preflight", uploader);
}
});
if (resp.error || Object.keys(resp.entries).length === 0) {
this.undoRefs(ref);
let errors = resp.error || [];
errors.map(([entry_ref, reason]) => {
this.handleFailedEntryPreflight(entry_ref, reason, uploader);
});
} else {
let onError = (callback) => {
this.channel.onError(() => {
if (this.joinCount === joinCountAtUpload) {
callback();
}
});
};
uploader.initAdapterUpload(resp, onError, this.liveSocket);
}
});
});
}
handleFailedEntryPreflight(uploadRef, reason, uploader) {
if (uploader.isAutoUpload()) {
let entry = uploader.entries().find((entry2) => entry2.ref === uploadRef.toString());
if (entry) {
entry.cancel();
}
} else {
uploader.entries().map((entry) => entry.cancel());
}
this.log("upload", () => [`error for entry ${uploadRef}`, reason]);
}
dispatchUploads(targetCtx, name, filesOrBlobs) {
let targetElement = this.targetCtxElement(targetCtx) || this.el;
let inputs = dom_default.findUploadInputs(targetElement).filter((el) => el.name === name);
if (inputs.length === 0) {
logError(`no live file inputs found matching the name "${name}"`);
} else if (inputs.length > 1) {
logError(`duplicate live file inputs found matching the name "${name}"`);
} else {
dom_default.dispatchEvent(inputs[0], PHX_TRACK_UPLOADS, { detail: { files: filesOrBlobs } });
}
}
targetCtxElement(targetCtx) {
if (isCid(targetCtx)) {
let [target] = dom_default.findComponentNodeList(this.el, targetCtx);
return target;
} else if (targetCtx) {
return targetCtx;
} else {
return null;
}
}
pushFormRecovery(form, newCid, callback) {
this.liveSocket.withinOwners(form, (view, targetCtx) => {
let phxChange = this.binding("change");
let inputs = Array.from(form.elements).filter((el) => dom_default.isFormInput(el) && el.name && !el.hasAttribute(phxChange));
if (inputs.length === 0) {
return;
}
inputs.forEach((input2) => input2.hasAttribute(PHX_UPLOAD_REF) && LiveUploader.clearFiles(input2));
let input = inputs.find((el) => el.type !== "hidden") || inputs[0];
let phxEvent = form.getAttribute(this.binding(PHX_AUTO_RECOVER)) || form.getAttribute(this.binding("change"));
js_default.exec("change", phxEvent, view, input, ["push", { _target: input.name, newCid, callback }]);
});
}
pushLinkPatch(href, targetEl, callback) {
let linkRef = this.liveSocket.setPendingLink(href);
let refGen = targetEl ? () => this.putRef([targetEl], "click") : null;
let fallback = () => this.liveSocket.redirect(window.location.href);
let url = href.startsWith("/") ? `${location.protocol}//${location.host}${href}` : href;
let push = this.pushWithReply(refGen, "live_patch", { url }, (resp) => {
this.liveSocket.requestDOMUpdate(() => {
if (resp.link_redirect) {
this.liveSocket.replaceMain(href, null, callback, linkRef);
} else {
if (this.liveSocket.commitPendingLink(linkRef)) {
this.href = href;
}
this.applyPendingUpdates();
callback && callback(linkRef);
}
});
});
if (push) {
push.receive("timeout", fallback);
} else {
fallback();
}
}
formsForRecovery(html) {
if (this.joinCount === 0) {
return [];
}
let phxChange = this.binding("change");
let template = document.createElement("template");
template.innerHTML = html;
return dom_default.all(this.el, `form[${phxChange}]`).filter((form) => form.id && this.ownsElement(form)).filter((form) => form.elements.length > 0).filter((form) => form.getAttribute(this.binding(PHX_AUTO_RECOVER)) !== "ignore").map((form) => {
const phxChangeValue = CSS.escape(form.getAttribute(phxChange));
let newForm = template.content.querySelector(`form[id="${form.id}"][${phxChange}="${phxChangeValue}"]`);
if (newForm) {
return [form, newForm, this.targetComponentID(newForm)];
} else {
return [form, form, this.targetComponentID(form)];
}
}).filter(([form, newForm, newCid]) => newForm);
}
maybePushComponentsDestroyed(destroyedCIDs) {
let willDestroyCIDs = destroyedCIDs.filter((cid) => {
return dom_default.findComponentNodeList(this.el, cid).length === 0;
});
if (willDestroyCIDs.length > 0) {
willDestroyCIDs.forEach((cid) => this.rendered.resetRender(cid));
this.pushWithReply(null, "cids_will_destroy", { cids: willDestroyCIDs }, () => {
let completelyDestroyCIDs = willDestroyCIDs.filter((cid) => {
return dom_default.findComponentNodeList(this.el, cid).length === 0;
});
if (completelyDestroyCIDs.length > 0) {
this.pushWithReply(null, "cids_destroyed", { cids: completelyDestroyCIDs }, (resp) => {
this.rendered.pruneCIDs(resp.cids);
});
}
});
}
}
ownsElement(el) {
let parentViewEl = el.closest(PHX_VIEW_SELECTOR);
return el.getAttribute(PHX_PARENT_ID) === this.id || parentViewEl && parentViewEl.id === this.id || !parentViewEl && this.isDead;
}
submitForm(form, targetCtx, phxEvent, submitter, opts = {}) {
dom_default.putPrivate(form, PHX_HAS_SUBMITTED, true);
const phxFeedbackFor = this.liveSocket.binding(PHX_FEEDBACK_FOR);
const phxFeedbackGroup = this.liveSocket.binding(PHX_FEEDBACK_GROUP);
const inputs = Array.from(form.elements);
inputs.forEach((input) => dom_default.putPrivate(input, PHX_HAS_SUBMITTED, true));
this.liveSocket.blurActiveElement(this);
this.pushFormSubmit(form, targetCtx, phxEvent, submitter, opts, () => {
inputs.forEach((input) => dom_default.showError(input, phxFeedbackFor, phxFeedbackGroup));
this.liveSocket.restorePreviouslyActiveFocus();
});
}
binding(kind) {
return this.liveSocket.binding(kind);
}
};
var LiveSocket = class {
constructor(url, phxSocket, opts = {}) {
this.unloaded = false;
if (!phxSocket || phxSocket.constructor.name === "Object") {
throw new Error(`
a phoenix Socket must be provided as the second argument to the LiveSocket constructor. For example:
import {Socket} from "phoenix"
import {LiveSocket} from "phoenix_live_view"
let liveSocket = new LiveSocket("/live", Socket, {...})
`);
}
this.socket = new phxSocket(url, opts);
this.bindingPrefix = opts.bindingPrefix || BINDING_PREFIX;
this.opts = opts;
this.params = closure2(opts.params || {});
this.viewLogger = opts.viewLogger;
this.metadataCallbacks = opts.metadata || {};
this.defaults = Object.assign(clone(DEFAULTS), opts.defaults || {});
this.activeElement = null;
this.prevActive = null;
this.silenced = false;
this.main = null;
this.outgoingMainEl = null;
this.clickStartedAtTarget = null;
this.linkRef = 1;
this.roots = {};
this.href = window.location.href;
this.pendingLink = null;
this.currentLocation = clone(window.location);
this.hooks = opts.hooks || {};
this.uploaders = opts.uploaders || {};
this.loaderTimeout = opts.loaderTimeout || LOADER_TIMEOUT;
this.reloadWithJitterTimer = null;
this.maxReloads = opts.maxReloads || MAX_RELOADS;
this.reloadJitterMin = opts.reloadJitterMin || RELOAD_JITTER_MIN;
this.reloadJitterMax = opts.reloadJitterMax || RELOAD_JITTER_MAX;
this.failsafeJitter = opts.failsafeJitter || FAILSAFE_JITTER;
this.localStorage = opts.localStorage || window.localStorage;
this.sessionStorage = opts.sessionStorage || window.sessionStorage;
this.boundTopLevelEvents = false;
this.domCallbacks = Object.assign({ onNodeAdded: closure2(), onBeforeElUpdated: closure2() }, opts.dom || {});
this.transitions = new TransitionSet();
window.addEventListener("pagehide", (_e) => {
this.unloaded = true;
});
this.socket.onOpen(() => {
if (this.isUnloaded()) {
window.location.reload();
}
});
}
isProfileEnabled() {
return this.sessionStorage.getItem(PHX_LV_PROFILE) === "true";
}
isDebugEnabled() {
return this.sessionStorage.getItem(PHX_LV_DEBUG) === "true";
}
isDebugDisabled() {
return this.sessionStorage.getItem(PHX_LV_DEBUG) === "false";
}
enableDebug() {
this.sessionStorage.setItem(PHX_LV_DEBUG, "true");
}
enableProfiling() {
this.sessionStorage.setItem(PHX_LV_PROFILE, "true");
}
disableDebug() {
this.sessionStorage.setItem(PHX_LV_DEBUG, "false");
}
disableProfiling() {
this.sessionStorage.removeItem(PHX_LV_PROFILE);
}
enableLatencySim(upperBoundMs) {
this.enableDebug();
console.log("latency simulator enabled for the duration of this browser session. Call disableLatencySim() to disable");
this.sessionStorage.setItem(PHX_LV_LATENCY_SIM, upperBoundMs);
}
disableLatencySim() {
this.sessionStorage.removeItem(PHX_LV_LATENCY_SIM);
}
getLatencySim() {
let str = this.sessionStorage.getItem(PHX_LV_LATENCY_SIM);
return str ? parseInt(str) : null;
}
getSocket() {
return this.socket;
}
connect() {
if (window.location.hostname === "localhost" && !this.isDebugDisabled()) {
this.enableDebug();
}
let doConnect = () => {
if (this.joinRootViews()) {
this.bindTopLevelEvents();
this.socket.connect();
} else if (this.main) {
this.socket.connect();
} else {
this.bindTopLevelEvents({ dead: true });
}
this.joinDeadView();
};
if (["complete", "loaded", "interactive"].indexOf(document.readyState) >= 0) {
doConnect();
} else {
document.addEventListener("DOMContentLoaded", () => doConnect());
}
}
disconnect(callback) {
clearTimeout(this.reloadWithJitterTimer);
this.socket.disconnect(callback);
}
replaceTransport(transport) {
clearTimeout(this.reloadWithJitterTimer);
this.socket.replaceTransport(transport);
this.connect();
}
execJS(el, encodedJS, eventType = null) {
this.owner(el, (view) => js_default.exec(eventType, encodedJS, view, el));
}
execJSHookPush(el, phxEvent, data, callback) {
this.withinOwners(el, (view) => {
js_default.exec("hook", phxEvent, view, el, ["push", { data, callback }]);
});
}
unload() {
if (this.unloaded) {
return;
}
if (this.main && this.isConnected()) {
this.log(this.main, "socket", () => ["disconnect for page nav"]);
}
this.unloaded = true;
this.destroyAllViews();
this.disconnect();
}
triggerDOM(kind, args) {
this.domCallbacks[kind](...args);
}
time(name, func) {
if (!this.isProfileEnabled() || !console.time) {
return func();
}
console.time(name);
let result = func();
console.timeEnd(name);
return result;
}
log(view, kind, msgCallback) {
if (this.viewLogger) {
let [msg, obj] = msgCallback();
this.viewLogger(view, kind, msg, obj);
} else if (this.isDebugEnabled()) {
let [msg, obj] = msgCallback();
debug(view, kind, msg, obj);
}
}
requestDOMUpdate(callback) {
this.transitions.after(callback);
}
transition(time, onStart, onDone = function() {
}) {
this.transitions.addTransition(time, onStart, onDone);
}
onChannel(channel, event, cb) {
channel.on(event, (data) => {
let latency = this.getLatencySim();
if (!latency) {
cb(data);
} else {
setTimeout(() => cb(data), latency);
}
});
}
wrapPush(view, opts, push) {
let latency = this.getLatencySim();
let oldJoinCount = view.joinCount;
if (!latency) {
if (this.isConnected() && opts.timeout) {
return push().receive("timeout", () => {
if (view.joinCount === oldJoinCount && !view.isDestroyed()) {
this.reloadWithJitter(view, () => {
this.log(view, "timeout", () => ["received timeout while communicating with server. Falling back to hard refresh for recovery"]);
});
}
});
} else {
return push();
}
}
let fakePush = {
receives: [],
receive(kind, cb) {
this.receives.push([kind, cb]);
}
};
setTimeout(() => {
if (view.isDestroyed()) {
return;
}
fakePush.receives.reduce((acc, [kind, cb]) => acc.receive(kind, cb), push());
}, latency);
return fakePush;
}
reloadWithJitter(view, log) {
clearTimeout(this.reloadWithJitterTimer);
this.disconnect();
let minMs = this.reloadJitterMin;
let maxMs = this.reloadJitterMax;
let afterMs = Math.floor(Math.random() * (maxMs - minMs + 1)) + minMs;
let tries = browser_default.updateLocal(this.localStorage, window.location.pathname, CONSECUTIVE_RELOADS, 0, (count) => count + 1);
if (tries > this.maxReloads) {
afterMs = this.failsafeJitter;
}
this.reloadWithJitterTimer = setTimeout(() => {
if (view.isDestroyed() || view.isConnected()) {
return;
}
view.destroy();
log ? log() : this.log(view, "join", () => [`encountered ${tries} consecutive reloads`]);
if (tries > this.maxReloads) {
this.log(view, "join", () => [`exceeded ${this.maxReloads} consecutive reloads. Entering failsafe mode`]);
}
if (this.hasPendingLink()) {
window.location = this.pendingLink;
} else {
window.location.reload();
}
}, afterMs);
}
getHookCallbacks(name) {
return name && name.startsWith("Phoenix.") ? hooks_default[name.split(".")[1]] : this.hooks[name];
}
isUnloaded() {
return this.unloaded;
}
isConnected() {
return this.socket.isConnected();
}
getBindingPrefix() {
return this.bindingPrefix;
}
binding(kind) {
return `${this.getBindingPrefix()}${kind}`;
}
channel(topic, params2) {
return this.socket.channel(topic, params2);
}
joinDeadView() {
let body = document.body;
if (body && !this.isPhxView(body) && !this.isPhxView(document.firstElementChild)) {
let view = this.newRootView(body);
view.setHref(this.getHref());
view.joinDead();
if (!this.main) {
this.main = view;
}
window.requestAnimationFrame(() => view.execNewMounted());
}
}
joinRootViews() {
let rootsFound = false;
dom_default.all(document, `${PHX_VIEW_SELECTOR}:not([${PHX_PARENT_ID}])`, (rootEl) => {
if (!this.getRootById(rootEl.id)) {
let view = this.newRootView(rootEl);
view.setHref(this.getHref());
view.join();
if (rootEl.hasAttribute(PHX_MAIN)) {
this.main = view;
}
}
rootsFound = true;
});
return rootsFound;
}
redirect(to, flash) {
this.unload();
browser_default.redirect(to, flash);
}
replaceMain(href, flash, callback = null, linkRef = this.setPendingLink(href)) {
let liveReferer = this.currentLocation.href;
this.outgoingMainEl = this.outgoingMainEl || this.main.el;
let newMainEl = dom_default.cloneNode(this.outgoingMainEl, "");
this.main.showLoader(this.loaderTimeout);
this.main.destroy();
this.main = this.newRootView(newMainEl, flash, liveReferer);
this.main.setRedirect(href);
this.transitionRemoves(null, true);
this.main.join((joinCount, onDone) => {
if (joinCount === 1 && this.commitPendingLink(linkRef)) {
this.requestDOMUpdate(() => {
dom_default.findPhxSticky(document).forEach((el) => newMainEl.appendChild(el));
this.outgoingMainEl.replaceWith(newMainEl);
this.outgoingMainEl = null;
callback && callback(linkRef);
onDone();
});
}
});
}
transitionRemoves(elements, skipSticky) {
let removeAttr = this.binding("remove");
elements = elements || dom_default.all(document, `[${removeAttr}]`);
if (skipSticky) {
const stickies = dom_default.findPhxSticky(document) || [];
elements = elements.filter((el) => !dom_default.isChildOfAny(el, stickies));
}
elements.forEach((el) => {
this.execJS(el, el.getAttribute(removeAttr), "remove");
});
}
isPhxView(el) {
return el.getAttribute && el.getAttribute(PHX_SESSION) !== null;
}
newRootView(el, flash, liveReferer) {
let view = new View(el, this, null, flash, liveReferer);
this.roots[view.id] = view;
return view;
}
owner(childEl, callback) {
let view = maybe(childEl.closest(PHX_VIEW_SELECTOR), (el) => this.getViewByEl(el)) || this.main;
if (view) {
callback(view);
}
}
withinOwners(childEl, callback) {
this.owner(childEl, (view) => callback(view, childEl));
}
getViewByEl(el) {
let rootId = el.getAttribute(PHX_ROOT_ID);
return maybe(this.getRootById(rootId), (root) => root.getDescendentByEl(el));
}
getRootById(id) {
return this.roots[id];
}
destroyAllViews() {
for (let id in this.roots) {
this.roots[id].destroy();
delete this.roots[id];
}
this.main = null;
}
destroyViewByEl(el) {
let root = this.getRootById(el.getAttribute(PHX_ROOT_ID));
if (root && root.id === el.id) {
root.destroy();
delete this.roots[root.id];
} else if (root) {
root.destroyDescendent(el.id);
}
}
setActiveElement(target) {
if (this.activeElement === target) {
return;
}
this.activeElement = target;
let cancel = () => {
if (target === this.activeElement) {
this.activeElement = null;
}
target.removeEventListener("mouseup", this);
target.removeEventListener("touchend", this);
};
target.addEventListener("mouseup", cancel);
target.addEventListener("touchend", cancel);
}
getActiveElement() {
if (document.activeElement === document.body) {
return this.activeElement || document.activeElement;
} else {
return document.activeElement || document.body;
}
}
dropActiveElement(view) {
if (this.prevActive && view.ownsElement(this.prevActive)) {
this.prevActive = null;
}
}
restorePreviouslyActiveFocus() {
if (this.prevActive && this.prevActive !== document.body) {
this.prevActive.focus();
}
}
blurActiveElement() {
this.prevActive = this.getActiveElement();
if (this.prevActive !== document.body) {
this.prevActive.blur();
}
}
bindTopLevelEvents({ dead } = {}) {
if (this.boundTopLevelEvents) {
return;
}
this.boundTopLevelEvents = true;
this.socket.onClose((event) => {
if (event && event.code === 1e3 && this.main) {
return this.reloadWithJitter(this.main);
}
});
document.body.addEventListener("click", function() {
});
window.addEventListener("pageshow", (e) => {
if (e.persisted) {
this.getSocket().disconnect();
this.withPageLoading({ to: window.location.href, kind: "redirect" });
window.location.reload();
}
}, true);
if (!dead) {
this.bindNav();
}
this.bindClicks();
if (!dead) {
this.bindForms();
}
this.bind({ keyup: "keyup", keydown: "keydown" }, (e, type, view, targetEl, phxEvent, phxTarget) => {
let matchKey = targetEl.getAttribute(this.binding(PHX_KEY));
let pressedKey = e.key && e.key.toLowerCase();
if (matchKey && matchKey.toLowerCase() !== pressedKey) {
return;
}
let data = __spreadValues({ key: e.key }, this.eventMeta(type, e, targetEl));
js_default.exec(type, phxEvent, view, targetEl, ["push", { data }]);
});
this.bind({ blur: "focusout", focus: "focusin" }, (e, type, view, targetEl, phxEvent, phxTarget) => {
if (!phxTarget) {
let data = __spreadValues({ key: e.key }, this.eventMeta(type, e, targetEl));
js_default.exec(type, phxEvent, view, targetEl, ["push", { data }]);
}
});
this.bind({ blur: "blur", focus: "focus" }, (e, type, view, targetEl, phxEvent, phxTarget) => {
if (phxTarget === "window") {
let data = this.eventMeta(type, e, targetEl);
js_default.exec(type, phxEvent, view, targetEl, ["push", { data }]);
}
});
window.addEventListener("dragover", (e) => e.preventDefault());
window.addEventListener("drop", (e) => {
e.preventDefault();
let dropTargetId = maybe(closestPhxBinding(e.target, this.binding(PHX_DROP_TARGET)), (trueTarget) => {
return trueTarget.getAttribute(this.binding(PHX_DROP_TARGET));
});
let dropTarget = dropTargetId && document.getElementById(dropTargetId);
let files = Array.from(e.dataTransfer.files || []);
if (!dropTarget || dropTarget.disabled || files.length === 0 || !(dropTarget.files instanceof FileList)) {
return;
}
LiveUploader.trackFiles(dropTarget, files, e.dataTransfer);
dropTarget.dispatchEvent(new Event("input", { bubbles: true }));
});
this.on(PHX_TRACK_UPLOADS, (e) => {
let uploadTarget = e.target;
if (!dom_default.isUploadInput(uploadTarget)) {
return;
}
let files = Array.from(e.detail.files || []).filter((f) => f instanceof File || f instanceof Blob);
LiveUploader.trackFiles(uploadTarget, files);
uploadTarget.dispatchEvent(new Event("input", { bubbles: true }));
});
}
eventMeta(eventName, e, targetEl) {
let callback = this.metadataCallbacks[eventName];
return callback ? callback(e, targetEl) : {};
}
setPendingLink(href) {
this.linkRef++;
this.pendingLink = href;
return this.linkRef;
}
commitPendingLink(linkRef) {
if (this.linkRef !== linkRef) {
return false;
} else {
this.href = this.pendingLink;
this.pendingLink = null;
return true;
}
}
getHref() {
return this.href;
}
hasPendingLink() {
return !!this.pendingLink;
}
bind(events, callback) {
for (let event in events) {
let browserEventName = events[event];
this.on(browserEventName, (e) => {
let binding = this.binding(event);
let windowBinding = this.binding(`window-${event}`);
let targetPhxEvent = e.target.getAttribute && e.target.getAttribute(binding);
if (targetPhxEvent) {
this.debounce(e.target, e, browserEventName, () => {
this.withinOwners(e.target, (view) => {
callback(e, event, view, e.target, targetPhxEvent, null);
});
});
} else {
dom_default.all(document, `[${windowBinding}]`, (el) => {
let phxEvent = el.getAttribute(windowBinding);
this.debounce(el, e, browserEventName, () => {
this.withinOwners(el, (view) => {
callback(e, event, view, el, phxEvent, "window");
});
});
});
}
});
}
}
bindClicks() {
window.addEventListener("mousedown", (e) => this.clickStartedAtTarget = e.target);
this.bindClick("click", "click", false);
this.bindClick("mousedown", "capture-click", true);
}
bindClick(eventName, bindingName, capture) {
let click = this.binding(bindingName);
window.addEventListener(eventName, (e) => {
let target = null;
if (capture) {
target = e.target.matches(`[${click}]`) ? e.target : e.target.querySelector(`[${click}]`);
} else {
if (e.detail === 0)
this.clickStartedAtTarget = e.target;
let clickStartedAtTarget = this.clickStartedAtTarget || e.target;
target = closestPhxBinding(clickStartedAtTarget, click);
this.dispatchClickAway(e, clickStartedAtTarget);
this.clickStartedAtTarget = null;
}
let phxEvent = target && target.getAttribute(click);
if (!phxEvent) {
if (!capture && dom_default.isNewPageClick(e, window.location)) {
this.unload();
}
return;
}
if (target.getAttribute("href") === "#") {
e.preventDefault();
}
if (target.hasAttribute(PHX_REF)) {
return;
}
this.debounce(target, e, "click", () => {
this.withinOwners(target, (view) => {
js_default.exec("click", phxEvent, view, target, ["push", { data: this.eventMeta("click", e, target) }]);
});
});
}, capture);
}
dispatchClickAway(e, clickStartedAt) {
let phxClickAway = this.binding("click-away");
dom_default.all(document, `[${phxClickAway}]`, (el) => {
if (!(el.isSameNode(clickStartedAt) || el.contains(clickStartedAt))) {
this.withinOwners(el, (view) => {
let phxEvent = el.getAttribute(phxClickAway);
if (js_default.isVisible(el) && js_default.isInViewport(el)) {
js_default.exec("click", phxEvent, view, el, ["push", { data: this.eventMeta("click", e, e.target) }]);
}
});
}
});
}
bindNav() {
if (!browser_default.canPushState()) {
return;
}
if (history.scrollRestoration) {
history.scrollRestoration = "manual";
}
let scrollTimer = null;
window.addEventListener("scroll", (_e) => {
clearTimeout(scrollTimer);
scrollTimer = setTimeout(() => {
browser_default.updateCurrentState((state) => Object.assign(state, { scroll: window.scrollY }));
}, 100);
});
window.addEventListener("popstate", (event) => {
if (!this.registerNewLocation(window.location)) {
return;
}
let { type, id, root, scroll } = event.state || {};
let href = window.location.href;
dom_default.dispatchEvent(window, "phx:navigate", { detail: { href, patch: type === "patch", pop: true } });
this.requestDOMUpdate(() => {
if (this.main.isConnected() && (type === "patch" && id === this.main.id)) {
this.main.pushLinkPatch(href, null, () => {
this.maybeScroll(scroll);
});
} else {
this.replaceMain(href, null, () => {
if (root) {
this.replaceRootHistory();
}
this.maybeScroll(scroll);
});
}
});
}, false);
window.addEventListener("click", (e) => {
let target = closestPhxBinding(e.target, PHX_LIVE_LINK);
let type = target && target.getAttribute(PHX_LIVE_LINK);
if (!type || !this.isConnected() || !this.main || dom_default.wantsNewTab(e)) {
return;
}
let href = target.href instanceof SVGAnimatedString ? target.href.baseVal : target.href;
let linkState = target.getAttribute(PHX_LINK_STATE);
e.preventDefault();
e.stopImmediatePropagation();
if (this.pendingLink === href) {
return;
}
this.requestDOMUpdate(() => {
if (type === "patch") {
this.pushHistoryPatch(href, linkState, target);
} else if (type === "redirect") {
this.historyRedirect(href, linkState);
} else {
throw new Error(`expected ${PHX_LIVE_LINK} to be "patch" or "redirect", got: ${type}`);
}
let phxClick = target.getAttribute(this.binding("click"));
if (phxClick) {
this.requestDOMUpdate(() => this.execJS(target, phxClick, "click"));
}
});
}, false);
}
maybeScroll(scroll) {
if (typeof scroll === "number") {
requestAnimationFrame(() => {
window.scrollTo(0, scroll);
});
}
}
dispatchEvent(event, payload = {}) {
dom_default.dispatchEvent(window, `phx:${event}`, { detail: payload });
}
dispatchEvents(events) {
events.forEach(([event, payload]) => this.dispatchEvent(event, payload));
}
withPageLoading(info, callback) {
dom_default.dispatchEvent(window, "phx:page-loading-start", { detail: info });
let done = () => dom_default.dispatchEvent(window, "phx:page-loading-stop", { detail: info });
return callback ? callback(done) : done;
}
pushHistoryPatch(href, linkState, targetEl) {
if (!this.isConnected() || !this.main.isMain()) {
return browser_default.redirect(href);
}
this.withPageLoading({ to: href, kind: "patch" }, (done) => {
this.main.pushLinkPatch(href, targetEl, (linkRef) => {
this.historyPatch(href, linkState, linkRef);
done();
});
});
}
historyPatch(href, linkState, linkRef = this.setPendingLink(href)) {
if (!this.commitPendingLink(linkRef)) {
return;
}
browser_default.pushState(linkState, { type: "patch", id: this.main.id }, href);
dom_default.dispatchEvent(window, "phx:navigate", { detail: { patch: true, href, pop: false } });
this.registerNewLocation(window.location);
}
historyRedirect(href, linkState, flash) {
if (!this.isConnected() || !this.main.isMain()) {
return browser_default.redirect(href, flash);
}
if (/^\/$|^\/[^\/]+.*$/.test(href)) {
let { protocol, host } = window.location;
href = `${protocol}//${host}${href}`;
}
let scroll = window.scrollY;
this.withPageLoading({ to: href, kind: "redirect" }, (done) => {
this.replaceMain(href, flash, (linkRef) => {
if (linkRef === this.linkRef) {
browser_default.pushState(linkState, { type: "redirect", id: this.main.id, scroll }, href);
dom_default.dispatchEvent(window, "phx:navigate", { detail: { href, patch: false, pop: false } });
this.registerNewLocation(window.location);
}
done();
});
});
}
replaceRootHistory() {
browser_default.pushState("replace", { root: true, type: "patch", id: this.main.id });
}
registerNewLocation(newLocation) {
let { pathname, search } = this.currentLocation;
if (pathname + search === newLocation.pathname + newLocation.search) {
return false;
} else {
this.currentLocation = clone(newLocation);
return true;
}
}
bindForms() {
let iterations = 0;
let externalFormSubmitted = false;
this.on("submit", (e) => {
let phxSubmit = e.target.getAttribute(this.binding("submit"));
let phxChange = e.target.getAttribute(this.binding("change"));
if (!externalFormSubmitted && phxChange && !phxSubmit) {
externalFormSubmitted = true;
e.preventDefault();
this.withinOwners(e.target, (view) => {
view.disableForm(e.target);
window.requestAnimationFrame(() => {
if (dom_default.isUnloadableFormSubmit(e)) {
this.unload();
}
e.target.submit();
});
});
}
}, true);
this.on("submit", (e) => {
let phxEvent = e.target.getAttribute(this.binding("submit"));
if (!phxEvent) {
if (dom_default.isUnloadableFormSubmit(e)) {
this.unload();
}
return;
}
e.preventDefault();
e.target.disabled = true;
this.withinOwners(e.target, (view) => {
js_default.exec("submit", phxEvent, view, e.target, ["push", { submitter: e.submitter }]);
});
}, false);
for (let type of ["change", "input"]) {
this.on(type, (e) => {
let phxChange = this.binding("change");
let input = e.target;
let inputEvent = input.getAttribute(phxChange);
let formEvent = input.form && input.form.getAttribute(phxChange);
let phxEvent = inputEvent || formEvent;
if (!phxEvent) {
return;
}
if (input.type === "number" && input.validity && input.validity.badInput) {
return;
}
let dispatcher = inputEvent ? input : input.form;
let currentIterations = iterations;
iterations++;
let { at, type: lastType } = dom_default.private(input, "prev-iteration") || {};
if (at === currentIterations - 1 && type === "change" && lastType === "input") {
return;
}
dom_default.putPrivate(input, "prev-iteration", { at: currentIterations, type });
this.debounce(input, e, type, () => {
this.withinOwners(dispatcher, (view) => {
dom_default.putPrivate(input, PHX_HAS_FOCUSED, true);
if (!dom_default.isTextualInput(input)) {
this.setActiveElement(input);
}
js_default.exec("change", phxEvent, view, input, ["push", { _target: e.target.name, dispatcher }]);
});
});
}, false);
}
this.on("reset", (e) => {
let form = e.target;
dom_default.resetForm(form, this.binding(PHX_FEEDBACK_FOR), this.binding(PHX_FEEDBACK_GROUP));
let input = Array.from(form.elements).find((el) => el.type === "reset");
if (input) {
window.requestAnimationFrame(() => {
input.dispatchEvent(new Event("input", { bubbles: true, cancelable: false }));
});
}
});
}
debounce(el, event, eventType, callback) {
if (eventType === "blur" || eventType === "focusout") {
return callback();
}
let phxDebounce = this.binding(PHX_DEBOUNCE);
let phxThrottle = this.binding(PHX_THROTTLE);
let defaultDebounce = this.defaults.debounce.toString();
let defaultThrottle = this.defaults.throttle.toString();
this.withinOwners(el, (view) => {
let asyncFilter = () => !view.isDestroyed() && document.body.contains(el);
dom_default.debounce(el, event, phxDebounce, defaultDebounce, phxThrottle, defaultThrottle, asyncFilter, () => {
callback();
});
});
}
silenceEvents(callback) {
this.silenced = true;
callback();
this.silenced = false;
}
on(event, callback) {
window.addEventListener(event, (e) => {
if (!this.silenced) {
callback(e);
}
});
}
};
var TransitionSet = class {
constructor() {
this.transitions = /* @__PURE__ */ new Set();
this.pendingOps = [];
}
reset() {
this.transitions.forEach((timer) => {
clearTimeout(timer);
this.transitions.delete(timer);
});
this.flushPendingOps();
}
after(callback) {
if (this.size() === 0) {
callback();
} else {
this.pushPendingOp(callback);
}
}
addTransition(time, onStart, onDone) {
onStart();
let timer = setTimeout(() => {
this.transitions.delete(timer);
onDone();
this.flushPendingOps();
}, time);
this.transitions.add(timer);
}
pushPendingOp(op) {
this.pendingOps.push(op);
}
size() {
return this.transitions.size;
}
flushPendingOps() {
if (this.size() > 0) {
return;
}
let op = this.pendingOps.shift();
if (op) {
op();
this.flushPendingOps();
}
}
};
// js/app.js
var socketPath = document.querySelector("html").getAttribute("phx-socket") || "/live";
var csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content");
var Hooks2 = {};
var editors = {};
Hooks2.JsonEditor = {
mounted() {
const inputId = this.el.getAttribute("data-input-id");
const hook = this;
this.editor = new JSONEditor(
this.el,
{
onChangeText: (json2) => {
const target = document.getElementById(inputId);
try {
JSON.parse(json2);
target.value = json2;
target.dispatchEvent(new Event("change", { bubbles: true }));
} catch (_e) {
}
},
onChange: () => {
try {
const target = document.getElementById(inputId);
json = hook.editor.get();
target.value = JSON.stringify(json);
target.dispatchEvent(new Event("change", { bubbles: true }));
} catch (_e) {
}
},
onModeChange: (newMode) => {
hook.mode = newMode;
},
modes: ["text", "tree"]
},
JSON.parse(document.getElementById(inputId).value)
);
editors[this.el.id] = this.editor;
}
};
Hooks2.JsonEditorSource = {
updated() {
try {
let editor = editors[this.el.getAttribute("data-editor-id")];
if (editor.getMode() === "tree") {
editor.update(JSON.parse(this.el.value));
} else {
if (editor.get() !== JSON.parse(this.el.value)) {
editor.setText(this.el.value);
} else {
}
}
} catch (_e) {
}
}
};
Hooks2.JsonView = {
updated() {
const json2 = JSON.parse(this.el.getAttribute("data-json"));
this.editor = new JSONEditor(
this.el,
{
mode: "preview"
},
json2
);
},
mounted() {
const json2 = JSON.parse(this.el.getAttribute("data-json"));
this.editor = new JSONEditor(
this.el,
{
mode: "preview"
},
json2
);
}
};
var init = (element) => new EasyMDE({
element,
initialValue: element.getAttribute("value")
});
Hooks2.MarkdownEditor = {
mounted() {
const id = this.el.getAttribute("data-target-id");
const el = document.getElementById(id);
const easyMDE = init(el);
easyMDE.codemirror.on("change", () => {
el.value = easyMDE.value();
el.dispatchEvent(new Event("change", { bubbles: true }));
});
}
};
Hooks2.Actor = {
mounted() {
this.handleEvent("set_actor", (payload) => {
document.cookie = "actor_resource=" + payload.resource + ";path=/";
document.cookie = "actor_primary_key=" + payload.primary_key + ";path=/";
document.cookie = "actor_action=" + payload.action + ";path=/";
document.cookie = "actor_api=" + payload.api + ";path=/";
});
this.handleEvent("clear_actor", () => {
document.cookie = "actor_resource=;path=/";
document.cookie = "actor_primary_key=;path=/";
document.cookie = "actor_action;path=/";
document.cookie = "actor_api=;path=/";
document.cookie = "actor_authorizing=false;path=/";
document.cookie = "actor_paused=true;path=/";
});
this.handleEvent("toggle_authorizing", (payload) => {
document.cookie = "actor_authorizing=" + payload.authorizing + ";path=/";
});
this.handleEvent("toggle_actor_paused", (payload) => {
document.cookie = "actor_paused=" + payload.actor_paused + ";path=/";
});
}
};
Hooks2.Tenant = {
mounted() {
this.handleEvent("set_tenant", (payload) => {
document.cookie = "tenant=" + payload.tenant + ";path=/";
});
this.handleEvent("clear_tenant", () => {
document.cookie = "tenant=;path=/";
});
}
};
Hooks2.MaintainAttrs = {
attrs() {
return this.el.getAttribute("data-attrs").split(", ");
},
beforeUpdate() {
this.prevAttrs = this.attrs().map((name) => [
name,
this.el.getAttribute(name)
]);
},
updated() {
this.prevAttrs.forEach(([name, val]) => this.el.setAttribute(name, val));
}
};
function getCookie(name) {
var re = new RegExp(name + "=([^;]+)");
var value = re.exec(document.cookie);
return value != null ? unescape(value[1]) : null;
}
var params = () => {
return {
_csrf_token: csrfToken,
tenant: getCookie("tenant"),
actor_resource: getCookie("actor_resource"),
actor_primary_key: getCookie("actor_primary_key"),
actor_action: getCookie("actor_action"),
actor_api: getCookie("actor_api"),
actor_authorizing: getCookie("actor_authorizing"),
actor_paused: getCookie("actor_paused")
};
};
var liveSocket = new LiveSocket(socketPath, Socket, {
params,
hooks: Hooks2,
dom: {
onBeforeElUpdated(from, to) {
if (from._x_dataStack) {
window.Alpine.clone(from, to);
}
}
}
});
import_topbar.default.config({ barColors: { 0: "#29d" }, shadowColor: "rgba(0, 0, 0, .3)" });
window.addEventListener("phx:page-loading-start", (_info) => import_topbar.default.show(300));
window.addEventListener("phx:page-loading-stop", (_info) => import_topbar.default.hide());
liveSocket.connect();
liveSocket.enableDebug();
window.liveSocket = liveSocket;
})();
/**
* @license MIT
* topbar 2.0.0, 2023-02-04
* https://buunguyen.github.io/topbar
* Copyright (c) 2021 Buu Nguyen
*/