phoenix_live_view 1.2.1 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,279 @@
1
+ import { HookJSCommands } from "./js_commands";
2
+ import LiveSocket from "./live_socket";
3
+ export type OnReply = (reply: any, ref: number) => any;
4
+ export type CallbackRef = {
5
+ event: string;
6
+ callback: (payload: any) => any;
7
+ };
8
+ export type PhxTarget = string | number | HTMLElement;
9
+ /**
10
+ * Defines the lifecycle callbacks and custom methods for a LiveView hook.
11
+ *
12
+ * @category JavaScript Hooks
13
+ */
14
+ export interface HookInterface<E extends HTMLElement = HTMLElement> {
15
+ /**
16
+ * The DOM element that the hook is attached to.
17
+ */
18
+ el: E;
19
+ /**
20
+ * The LiveSocket instance that the hook is attached to.
21
+ */
22
+ liveSocket: LiveSocket;
23
+ /**
24
+ * The mounted callback.
25
+ *
26
+ * Called when the element has been added to the DOM and its server LiveView has finished mounting.
27
+ */
28
+ mounted?: () => void;
29
+ /**
30
+ * The beforeUpdate callback.
31
+ *
32
+ * Called when the element is about to be updated in the DOM.
33
+ * Note: any call here must be synchronous as the operation cannot be deferred or cancelled.
34
+ */
35
+ beforeUpdate?: () => void;
36
+ /**
37
+ * The updated callback.
38
+ *
39
+ * Called when the element has been updated in the DOM by the server.
40
+ */
41
+ updated?: () => void;
42
+ /**
43
+ * The destroyed callback.
44
+ *
45
+ * Called when the element has been removed from the page, either by a parent update, or by the parent being removed entirely.
46
+ */
47
+ destroyed?: () => void;
48
+ /**
49
+ * The disconnected callback.
50
+ *
51
+ * Called when the element's parent LiveView has disconnected from the server.
52
+ */
53
+ disconnected?: () => void;
54
+ /**
55
+ * The reconnected callback.
56
+ *
57
+ * Called when the element's parent LiveView has reconnected to the server.
58
+ */
59
+ reconnected?: () => void;
60
+ /**
61
+ * Returns an object with methods to manipulate the DOM and execute JavaScript.
62
+ * The applied changes integrate with server DOM patching.
63
+ */
64
+ js(): HookJSCommands;
65
+ /**
66
+ * Pushes an event to the server and invokes a callback with the server's reply.
67
+ *
68
+ * **Note:** this version silently ignores push errors.
69
+ * Use the {@link pushEvent | promise-returning version} to handle errors.
70
+ *
71
+ * @param event - The event name.
72
+ * @param payload - The payload to send to the server. Must be a serializable
73
+ * value (typically JSON-serializable, depends on the Socket configuration).
74
+ * Defaults to an empty object.
75
+ * @param onReply - A callback to handle the server's reply.
76
+ */
77
+ pushEvent(event: string, payload: unknown, onReply: OnReply): void;
78
+ /**
79
+ * Pushes an event to the server and returns a Promise that resolves with the server's reply.
80
+ *
81
+ * The promise will be rejected in case of errors
82
+ * such as a disconnected state, timeout, or the server rejecting the event.
83
+ *
84
+ * @param event - The event name.
85
+ * @param [payload] - The payload to send to the server. Must be a serializable
86
+ * value (typically JSON-serializable, depends on the Socket configuration).
87
+ * Defaults to an empty object.
88
+ * @returns A promise that fulfills or rejects with the server's reply.
89
+ */
90
+ pushEvent(event: string, payload?: unknown): Promise<any>;
91
+ /**
92
+ * Pushes a targeted event to the server and invokes a callback with the server's reply.
93
+ *
94
+ * It sends the event to the LiveComponent or LiveView the `selectorOrTarget` is defined in,
95
+ * where its value can be either a query selector, an actual DOM element, or a CID (component id)
96
+ * returned by the `@myself` assign.
97
+ *
98
+ * If the selector matches multiple elements, the event is sent to all of them,
99
+ * even if they belong to the same LiveComponent or LiveView.
100
+ *
101
+ * **Note:** this version silently ignores push errors.
102
+ * Use the {@link pushEventTo | promise-returning version} to handle errors.
103
+ *
104
+ * @param selectorOrTarget - The selector, element, or CID to target.
105
+ * @param event - The event name.
106
+ * @param payload - The payload to send to the server. Must be a serializable
107
+ * value (typically JSON-serializable, depends on the Socket configuration).
108
+ * Defaults to an empty object.
109
+ * @param onReply - A callback to handle the server's reply.
110
+ */
111
+ pushEventTo(selectorOrTarget: PhxTarget, event: string, payload: unknown, onReply: OnReply): void;
112
+ /**
113
+ * Pushes a targeted event to the server and returns a Promise that resolves with the server's reply.
114
+ *
115
+ * It sends the event to the LiveComponent or LiveView the `selectorOrTarget` is defined in,
116
+ * where its value can be either a query selector, an actual DOM element, or a CID (component id)
117
+ * returned by the `@myself` assign.
118
+ *
119
+ * If the selector matches multiple elements, the event is sent to all of them,
120
+ * even if they belong to the same LiveComponent or LiveView.
121
+ * Because of this, it returns a single promise that matches the return value of
122
+ * [`Promise.allSettled()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled#return_value).
123
+ * Individual fulfilled values are of the format `{ reply, ref }`, where `reply` is the server's reply.
124
+ *
125
+ * The individual promises will be rejected in case of errors
126
+ * such as a disconnected state, timeout, or the server rejecting the event.
127
+ *
128
+ * @param selectorOrTarget - The selector, element, or CID to target.
129
+ * @param event - The event name.
130
+ * @param [payload] - The payload to send to the server. Must be a serializable
131
+ * value (typically JSON-serializable, depends on the Socket configuration).
132
+ * Defaults to an empty object.
133
+ * @returns A promise that resolves when the event has been handled by all targets.
134
+ */
135
+ pushEventTo(selectorOrTarget: PhxTarget, event: string, payload?: unknown): Promise<PromiseSettledResult<{
136
+ reply: any;
137
+ ref: number;
138
+ }>[]>;
139
+ /**
140
+ * Allows to register a callback to be called when an event is received from the server.
141
+ *
142
+ * This is used to handle `pushEvent` calls from the server. The callback is called with the payload from the server.
143
+ *
144
+ * @param event - The event name.
145
+ * @param callback - The callback to call when the event is received.
146
+ *
147
+ * @returns A reference to the callback, which can be used in `removeHandleEvent` to remove the callback.
148
+ */
149
+ handleEvent(event: string, callback: (payload: any) => any): CallbackRef;
150
+ /**
151
+ * Removes a callback registered with `handleEvent`.
152
+ *
153
+ * @param ref - The reference to the callback to remove.
154
+ */
155
+ removeHandleEvent(ref: CallbackRef): void;
156
+ /**
157
+ * Allows to trigger a live file upload.
158
+ *
159
+ * @param name - The upload name corresponding to the `Phoenix.LiveView.allow_upload/3` call.
160
+ * @param files - The files to upload.
161
+ */
162
+ upload(name: any, files: any): any;
163
+ /**
164
+ * Allows to trigger a live file upload to a specific target.
165
+ *
166
+ * @param selectorOrTarget - The target to upload the files to.
167
+ * @param name - The upload name corresponding to the `Phoenix.LiveView.allow_upload/3` call.
168
+ * @param files - The files to upload.
169
+ */
170
+ uploadTo(selectorOrTarget: PhxTarget, name: any, files: any): any;
171
+ [key: PropertyKey]: any;
172
+ }
173
+ /**
174
+ * Defines the lifecycle callbacks and custom methods for a LiveView hook.
175
+ *
176
+ * @category JavaScript Hooks
177
+ */
178
+ export interface Hook<T = object, E extends HTMLElement = HTMLElement> {
179
+ /**
180
+ * The mounted callback.
181
+ *
182
+ * Called when the element has been added to the DOM and its server LiveView has finished mounting.
183
+ */
184
+ mounted?: (this: T & HookInterface<E>) => void;
185
+ /**
186
+ * The beforeUpdate callback.
187
+ *
188
+ * Called when the element is about to be updated in the DOM.
189
+ * Note: any call here must be synchronous as the operation cannot be deferred or cancelled.
190
+ */
191
+ beforeUpdate?: (this: T & HookInterface<E>) => void;
192
+ /**
193
+ * The updated callback.
194
+ *
195
+ * Called when the element has been updated in the DOM by the server.
196
+ */
197
+ updated?: (this: T & HookInterface<E>) => void;
198
+ /**
199
+ * The destroyed callback.
200
+ *
201
+ * Called when the element has been removed from the page, either by a parent update, or by the parent being removed entirely.
202
+ */
203
+ destroyed?: (this: T & HookInterface<E>) => void;
204
+ /**
205
+ * The disconnected callback.
206
+ *
207
+ * Called when the element's parent LiveView has disconnected from the server.
208
+ */
209
+ disconnected?: (this: T & HookInterface<E>) => void;
210
+ /**
211
+ * The reconnected callback.
212
+ *
213
+ * Called when the element's parent LiveView has reconnected to the server.
214
+ */
215
+ reconnected?: (this: T & HookInterface<E>) => void;
216
+ [key: PropertyKey]: any;
217
+ }
218
+ /**
219
+ * Base class for LiveView hooks. Users extend this class to define their hooks.
220
+ *
221
+ * Example:
222
+ * ```typescript
223
+ * class MyCustomHook extends ViewHook {
224
+ * myState = "initial";
225
+ *
226
+ * mounted() {
227
+ * console.log("Hook mounted on element:", this.el);
228
+ * this.el.addEventListener("click", () => {
229
+ * this.pushEvent("element-clicked", { state: this.myState });
230
+ * });
231
+ * }
232
+ *
233
+ * updated() {
234
+ * console.log("Hook updated", this.el.id);
235
+ * }
236
+ *
237
+ * myCustomMethod(someArg: string) {
238
+ * console.log("myCustomMethod called with:", someArg, "Current state:", this.myState);
239
+ * }
240
+ * }
241
+ * ```
242
+ *
243
+ * The `this` context within the hook methods (mounted, updated, custom methods, etc.)
244
+ * will refer to the hook instance, providing access to `this.el`, `this.liveSocket`,
245
+ * `this.pushEvent()`, etc., as well as any properties or methods defined on the subclass.
246
+ *
247
+ * @category JavaScript Hooks
248
+ */
249
+ export declare class ViewHook<E extends HTMLElement = HTMLElement> implements HookInterface<E> {
250
+ el: E;
251
+ private __listeners;
252
+ private __isDisconnected;
253
+ private __view;
254
+ private __liveSocket;
255
+ get liveSocket(): LiveSocket;
256
+ mounted(): void;
257
+ beforeUpdate(): void;
258
+ updated(): void;
259
+ destroyed(): void;
260
+ disconnected(): void;
261
+ reconnected(): void;
262
+ js(): HookJSCommands;
263
+ pushEvent(event: string, payload: unknown, onReply: OnReply): void;
264
+ pushEvent(event: string, payload?: unknown): Promise<any>;
265
+ pushEventTo(selectorOrTarget: PhxTarget, event: string, payload: unknown, onReply: OnReply): void;
266
+ pushEventTo(selectorOrTarget: PhxTarget, event: string, payload?: unknown): Promise<PromiseSettledResult<{
267
+ reply: any;
268
+ ref: number;
269
+ }>[]>;
270
+ handleEvent(event: string, callback: (payload: any) => any): CallbackRef;
271
+ removeHandleEvent(ref: CallbackRef): void;
272
+ upload(name: string, files: FileList): any;
273
+ uploadTo(selectorOrTarget: PhxTarget, name: string, files: FileList): any;
274
+ }
275
+ /**
276
+ * @category JavaScript Hooks
277
+ */
278
+ export type HooksOptions = Record<string, typeof ViewHook | Hook<any, any>>;
279
+ export default ViewHook;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "phoenix_live_view",
3
- "version": "1.2.1",
3
+ "version": "1.2.3",
4
4
  "description": "The Phoenix LiveView JavaScript client.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -33,7 +33,7 @@
33
33
  },
34
34
  "devDependencies": {
35
35
  "@babel/cli": "7.27.2",
36
- "@babel/core": "7.27.4",
36
+ "@babel/core": "7.29.6",
37
37
  "@babel/preset-env": "7.27.2",
38
38
  "@babel/preset-typescript": "^7.27.1",
39
39
  "@eslint/js": "^9.29.0",
@@ -58,7 +58,6 @@
58
58
  "typescript-eslint": "^8.34.0"
59
59
  },
60
60
  "scripts": {
61
- "setup": "mix deps.get && npm install",
62
61
  "build": "tsc",
63
62
  "e2e:server": "MIX_ENV=e2e mix test --cover --export-coverage e2e test/e2e/test_helper.exs",
64
63
  "e2e:test": "mix assets.build && cd test/e2e && npx playwright install && npx playwright test",
@@ -71,7 +70,7 @@
71
70
  "test": "npm run js:test && npm run e2e:test",
72
71
  "typecheck:tests": "tsc -p assets/test/tsconfig.json",
73
72
  "cover:merge": "node test/e2e/merge-coverage.js",
74
- "cover": "npm run test && npm run cover:merge",
73
+ "cover": "npm test && npm run cover:merge",
75
74
  "cover:report": "npx monocart show-report cover/merged-js/index.html",
76
75
  "docs": "typedoc assets/js/phoenix_live_view/index.ts --readme assets/js/phoenix_live_view/README.md --html doc/js"
77
76
  }
@@ -6094,7 +6094,7 @@ var LiveSocket = class {
6094
6094
  * Returns the version of the LiveView client.
6095
6095
  */
6096
6096
  version() {
6097
- return "1.2.1";
6097
+ return "1.2.3";
6098
6098
  }
6099
6099
  /**
6100
6100
  * Returns true if profiling is enabled. See {@link enableProfiling} and {@link disableProfiling}.
@@ -6065,7 +6065,7 @@ var LiveSocket = class {
6065
6065
  * Returns the version of the LiveView client.
6066
6066
  */
6067
6067
  version() {
6068
- return "1.2.1";
6068
+ return "1.2.3";
6069
6069
  }
6070
6070
  /**
6071
6071
  * Returns true if profiling is enabled. See {@link enableProfiling} and {@link disableProfiling}.
@@ -6117,7 +6117,7 @@ removing illegal node: "${("outerHTML" in childNode && childNode.outerHTML || ch
6117
6117
  * Returns the version of the LiveView client.
6118
6118
  */
6119
6119
  version() {
6120
- return "1.2.1";
6120
+ return "1.2.3";
6121
6121
  }
6122
6122
  /**
6123
6123
  * Returns true if profiling is enabled. See {@link enableProfiling} and {@link disableProfiling}.
@@ -18,4 +18,4 @@ removing illegal node: "${("outerHTML"in i&&i.outerHTML||i.nodeValue||"").trim()
18
18
  import {Socket} from "phoenix"
19
19
  import {LiveSocket} from "phoenix_live_view"
20
20
  let liveSocket = new LiveSocket("/live", Socket, {...})
21
- `);this.socket=new t(e,i),this.bindingPrefix=i.bindingPrefix||pi,this.params=je(i.params||{}),this.viewLogger=i.viewLogger,this.metadataCallbacks=i.metadata||{},this.defaults=Object.assign(We(gi),i.defaults||{}),this.prevActive=null,this.silenced=!1,this.main=null,this.outgoingMainEl=null,this.clickStartedAtTarget=null,this.linkRef=1,this.roots={},this.href=window.location.href,this.pendingLink=null,this.currentLocation=We(window.location),this.hooks=i.hooks||{},this.uploaders=i.uploaders||{},this.loaderTimeout=i.loaderTimeout||hi,this.disconnectedTimeout=i.disconnectedTimeout||fi,this.reloadWithJitterTimer=null,this.maxReloads=i.maxReloads||10,this.reloadJitterMin=i.reloadJitterMin||5e3,this.reloadJitterMax=i.reloadJitterMax||1e4,this.failsafeJitter=i.failsafeJitter||3e4,this.localStorage=i.localStorage||window.localStorage,this.sessionStorage=i.sessionStorage||window.sessionStorage,this.boundTopLevelEvents=!1,this.boundEventNames=new Set,this.blockPhxChangeWhileComposing=i.blockPhxChangeWhileComposing||!1,this.serverCloseRef=null,this.domCallbacks=Object.assign({jsQuerySelectorAll:null,onPatchStart:je(),onPatchEnd:je(),onNodeAdded:je(),onBeforeElUpdated:je()},i.dom||{}),this.transitions=new Gt,this.currentHistoryPosition=parseInt(this.sessionStorage.getItem(it)||"0")||0,window.addEventListener("pagehide",n=>{this.unloaded=!0}),this.socket.onOpen(()=>{this.isUnloaded()&&window.location.reload()})}version(){return"1.2.1"}isProfileEnabled(){return this.sessionStorage.getItem(Et)==="true"}isDebugEnabled(){return this.sessionStorage.getItem(tt)==="true"}isDebugDisabled(){return this.sessionStorage.getItem(tt)==="false"}enableDebug(){this.sessionStorage.setItem(tt,"true")}enableProfiling(){this.sessionStorage.setItem(Et,"true")}disableDebug(){this.sessionStorage.setItem(tt,"false")}disableProfiling(){this.sessionStorage.removeItem(Et)}enableLatencySim(e){this.enableDebug(),console.log("latency simulator enabled for the duration of this browser session. Call disableLatencySim() to disable"),this.sessionStorage.setItem(bt,e.toString())}disableLatencySim(){this.sessionStorage.removeItem(bt)}getLatencySim(){let e=this.sessionStorage.getItem(bt);return e?parseInt(e):null}getSocket(){return this.socket}connect(){window.location.hostname==="localhost"&&!this.isDebugDisabled()&&this.enableDebug();let e=()=>{this.resetReloadStatus(),this.joinRootViews()?(this.bindTopLevelEvents(),this.socket.connect()):this.main?this.socket.connect():this.bindTopLevelEvents({dead:!0}),this.joinDeadView()};["complete","loaded","interactive"].indexOf(document.readyState)>=0?e():document.addEventListener("DOMContentLoaded",()=>e())}disconnect(e){this.reloadWithJitterTimer!=null&&clearTimeout(this.reloadWithJitterTimer),this.serverCloseRef&&(this.socket.off([this.serverCloseRef]),this.serverCloseRef=null),this.socket.disconnect(e)}replaceTransport(e){this.reloadWithJitterTimer!=null&&clearTimeout(this.reloadWithJitterTimer),this.socket.replaceTransport(e),this.connect()}execJS(e,t,i=null){let n=new CustomEvent("phx:exec",{detail:{sourceElement:e}});this.owner(e,r=>k.exec(n,i,t,r,e))}js(){return kt(this,"js")}unload(){this.unloaded||(this.main&&this.isConnected()&&this.log(this.main,"socket",()=>["disconnect for page nav"]),this.unloaded=!0,this.destroyAllViews(),this.disconnect())}triggerDOM(e,t){this.domCallbacks[e](...t)}time(e,t){if(!this.isProfileEnabled()||!console.time)return t();console.time(e);let i=t();return console.timeEnd(e),i}log(e,t,i){if(this.viewLogger){let[n,r]=i();this.viewLogger(e,t,n,r)}else if(this.isDebugEnabled()){let[n,r]=i();bi(e,t,n,r)}}requestDOMUpdate(e){this.transitions.after(e)}asyncTransition(e){this.transitions.addAsyncTransition(e)}transition(e,t,i=function(){}){this.transitions.addTransition(e,t,i)}onChannel(e,t,i){e.on(t,n=>{let r=this.getLatencySim();r?setTimeout(()=>i(n),r):i(n)})}reloadWithJitter(e,t){this.reloadWithJitterTimer!=null&&clearTimeout(this.reloadWithJitterTimer),this.disconnect();let i=this.reloadJitterMin,n=this.reloadJitterMax,r=Math.floor(Math.random()*(n-i+1))+i,o=V.updateLocal(this.localStorage,window.location.pathname,ht,0,a=>a+1);o>=this.maxReloads&&(r=this.failsafeJitter),this.reloadWithJitterTimer=setTimeout(()=>{e.isDestroyed()||e.isConnected()||(e.destroy(),t?t():this.log(e,"join",()=>[`encountered ${o} consecutive reloads`]),o>=this.maxReloads&&this.log(e,"join",()=>[`exceeded ${this.maxReloads} consecutive reloads. Entering failsafe mode`]),this.pendingLink!==null?window.location.href=this.pendingLink:window.location.reload())},r)}getHookDefinition(e){if(e)return this.maybeInternalHook(e)||this.hooks[e]||this.maybeRuntimeHook(e)}maybeInternalHook(e){return e&&e.startsWith("Phoenix.")&&_i[e.split(".")[1]]}maybeRuntimeHook(e){let t=document.querySelector(`script[${Ve}="${CSS.escape(e)}"]`);if(!t)return;let i=window[`phx_hook_${e}`];if(!i||typeof i!="function"){w("a runtime hook must be a function",t);return}let n=i();if(n&&(typeof n=="object"||typeof n=="function"))return n;w("runtime hook must return an object with hook callbacks or an instance of ViewHook",t)}isUnloaded(){return this.unloaded}isConnected(){return this.socket.isConnected()}getBindingPrefix(){return this.bindingPrefix}binding(e){return`${this.getBindingPrefix()}${e}`}channel(e,t){return this.socket.channel(e,t)}joinDeadView(){let e=document.body;if(e&&!this.isPhxView(e)&&!this.isPhxView(document.firstElementChild)){let t=this.newRootView(e);t.setHref(this.getHref()),t.joinDead(),this.main||(this.main=t),window.requestAnimationFrame(()=>{var i;t.execNewMounted(),this.maybeScroll((i=history.state)==null?void 0:i.scroll)})}}joinRootViews(){let e=!1;return d.all(document,`${ce}:not([${ne}])`,t=>{if(!this.getRootById(t.id)){let i=this.newRootView(t);d.isPhxSticky(t)||i.setHref(this.getHref()),i.join(),t.hasAttribute(De)&&(this.main=i)}e=!0}),e}redirect(e,t,i){i&&V.setCookie(Mt,i,60),this.unload(),V.redirect(e,t)}replaceMain(e,t,i=null,n=this.setPendingLink(e)){if(!this.main)return;let r=this.currentLocation.href;this.outgoingMainEl=this.outgoingMainEl||this.main.el;let o=d.findPhxSticky(document)||[],a=d.all(this.outgoingMainEl,`[${this.binding("remove")}]`).filter(u=>!d.isChildOfAny(u,o)),l=d.cloneNode(this.outgoingMainEl,""),c=this.main;c.showLoader(this.loaderTimeout),c.destroy(),this.main=this.newRootView(l,t,r),this.main.setRedirect(e),this.transitionRemoves(a,c),this.main.join((u,p)=>{u===1&&this.commitPendingLink(n)&&this.requestDOMUpdate(()=>{a.forEach(m=>m.remove()),o.forEach(m=>l.appendChild(m)),this.outgoingMainEl.replaceWith(l),this.outgoingMainEl=null,i&&i(n),p()})})}transitionRemoves(e,t,i){let n=this.binding("remove"),r=o=>{o.preventDefault(),o.stopImmediatePropagation()};e.forEach(o=>{for(let l of this.boundEventNames)o.addEventListener(l,r,!0);let a=new CustomEvent("phx:exec",{detail:{sourceElement:o}});k.exec(a,"remove",o.getAttribute(n),t,o)}),this.requestDOMUpdate(()=>{e.forEach(o=>{for(let a of this.boundEventNames)o.removeEventListener(a,r,!0)}),i&&i()})}isPhxView(e){return e.getAttribute&&e.getAttribute(q)!==null}newRootView(e,t,i){let n=new Re(e,this,null,t,i);return this.roots[n.id]=n,n}owner(e,t){let i,n=d.closestViewEl(e);if(n)i=d.private(n,"view");else{if(!e.isConnected)return null;i=this.main}return i&&t?t(i):i}withinOwners(e,t){this.owner(e,i=>t(i,e))}getViewByEl(e){let t=e.getAttribute(z);return fe(this.getRootById(t),i=>i.getDescendentByEl(e))}getRootById(e){return this.roots[e]}destroyAllViews(){for(let e in this.roots)this.roots[e].destroy(),delete this.roots[e];this.main=null}destroyViewByEl(e){let t=this.getRootById(e.getAttribute(z));t&&t.id===e.id?(t.destroy(),delete this.roots[t.id]):t&&t.destroyDescendent(e.id)}getActiveElement(){return document.activeElement}dropActiveElement(e){this.prevActive&&e.ownsElement(this.prevActive)&&(this.prevActive=null)}restorePreviouslyActiveFocus(){this.prevActive&&this.prevActive!==document.body&&this.prevActive instanceof HTMLElement&&this.prevActive.focus()}blurActiveElement(){this.prevActive=this.getActiveElement(),this.prevActive!==document.body&&this.prevActive instanceof HTMLElement&&this.prevActive.blur()}bindTopLevelEvents({dead:e}={}){this.boundTopLevelEvents||(this.boundTopLevelEvents=!0,this.serverCloseRef=this.socket.onClose(t=>{if(t&&t.code===1e3&&this.main)return this.reloadWithJitter(this.main)}),document.body.addEventListener("click",function(){}),window.addEventListener("pageshow",t=>{t.persisted&&(this.getSocket().disconnect(),this.withPageLoading({to:window.location.href,kind:"redirect"}),window.location.reload())},!0),e||this.bindNav(),this.bindClicks(),e||this.bindForms(),this.bind({keyup:"keyup",keydown:"keydown"},(t,i,n,r,o,a)=>{let l=r.getAttribute(this.binding(di)),c=t.key&&t.key.toLowerCase();if(l&&l.toLowerCase()!==c)return;let u=D({key:t.key},this.eventMeta(i,t,r));k.exec(t,i,o,n,r,["push",{data:u}])}),this.bind({blur:"focusout",focus:"focusin"},(t,i,n,r,o,a)=>{if(!a){let l=D({},this.eventMeta(i,t,r));k.exec(t,i,o,n,r,["push",{data:l}])}}),this.bind({blur:"blur",focus:"focus"},(t,i,n,r,o,a)=>{if(a==="window"){let l=this.eventMeta(i,t,r);k.exec(t,i,o,n,r,["push",{data:l}])}}),this.on("dragover",t=>t.preventDefault()),this.on("dragenter",t=>{let i=t.target&&d.elementFromTarget(t.target);if(!i)return;let n=ue(i,this.binding(qe));!n||!(n instanceof HTMLElement)||Si(t)&&this.js().addClass(n,ft)}),this.on("dragleave",t=>{let i=t.target&&d.elementFromTarget(t.target);if(!i)return;let n=ue(i,this.binding(qe));if(!n||!(n instanceof HTMLElement))return;let r=n.getBoundingClientRect();(t.clientX<=r.left||t.clientX>=r.right||t.clientY<=r.top||t.clientY>=r.bottom)&&this.js().removeClass(n,ft)}),this.on("drop",t=>{let i=t.target&&d.elementFromTarget(t.target);if(!i)return;t.preventDefault();let n=ue(i,this.binding(qe));if(!n||!(n instanceof HTMLElement)||(this.js().removeClass(n,ft),!t.dataTransfer))return;let r=n.getAttribute(this.binding(qe)),o=r&&document.getElementById(r),a=Array.from(t.dataTransfer.files||[]);!o||!(o instanceof HTMLInputElement)||o.disabled||a.length===0||!(o.files instanceof FileList)||(R.trackFiles(o,a,t.dataTransfer),o.dispatchEvent(new Event("input",{bubbles:!0})))}),this.on(mt,t=>{let i=t.target&&d.elementFromTarget(t.target);if(!d.isUploadInput(i))return;let n=Array.from(t.detail.files||[]).filter(r=>r instanceof File||r instanceof Blob);R.trackFiles(i,n),i.dispatchEvent(new Event("input",{bubbles:!0}))}))}eventMeta(e,t,i){let n=this.metadataCallbacks[e];return n?n(t,i):{}}setPendingLink(e){return this.linkRef++,this.pendingLink=e,this.resetReloadStatus(),this.linkRef}resetReloadStatus(){V.deleteCookie(Mt)}commitPendingLink(e){return this.linkRef!==e?!1:(this.pendingLink!==null&&(this.href=this.pendingLink,this.pendingLink=null),!0)}getHref(){return this.href}hasPendingLink(){return!!this.pendingLink}bind(e,t){for(let i in e){let n=e[i];this.on(n,r=>{let o=this.binding(i),a=this.binding(`window-${i}`),l=r.target instanceof Element&&r.target.getAttribute(o);r.target instanceof Element&&(l?this.debounce(r.target,r,n,()=>{this.withinOwners(r.target,c=>{t(r,i,c,r.target,l,null)})}):d.all(document,`[${a}]`,c=>{let u=c.getAttribute(a);this.debounce(c,r,n,()=>{this.withinOwners(c,p=>{t(r,i,p,c,u,"window")})})}))})}}bindClicks(){this.on("mousedown",e=>this.clickStartedAtTarget=e.target),this.bindClick()}bindClick(){let e=this.binding("click");window.addEventListener("click",t=>{let i=t.target&&d.elementFromTarget(t.target);if(!i)return;t.detail===0&&(this.clickStartedAtTarget=i);let n=this.clickStartedAtTarget||i;if(i=ue(i,e),this.dispatchClickAway(t,n),this.clickStartedAtTarget=null,!i)return;let r=i.getAttribute(e);if(!r){d.isNewPageClick(t,window.location)&&this.unload();return}i.getAttribute("href")==="#"&&t.preventDefault(),!i.hasAttribute(U)&&this.debounce(i,t,"click",()=>{this.withinOwners(i,o=>{k.exec(t,"click",r,o,i,["push",{data:this.eventMeta("click",t,i)}])})})},!1)}dispatchClickAway(e,t){let i=this.binding("click-away"),n=t.closest(`[${Z}]`),r=n&&d.byId(n.getAttribute(Z));d.all(document,`[${i}]`,o=>{let a=t;n&&!n.contains(o)&&(a=r),o.isSameNode(a)||o.contains(a)||!k.isVisible(t)||this.withinOwners(o,l=>{let c=o.getAttribute(i);k.isVisible(o)&&k.isInViewport(o)&&k.exec(e,"click",c,l,o,["push",{data:this.eventMeta("click",e,e.target)}])})})}bindNav(){if(!V.canPushState())return;history.scrollRestoration&&(history.scrollRestoration="manual");let e=null;window.addEventListener("scroll",t=>{e!=null&&clearTimeout(e),e=setTimeout(()=>{V.updateCurrentState(i=>Object.assign(i,{scroll:window.scrollY}))},100)}),window.addEventListener("popstate",t=>{if(!this.registerNewLocation(window.location))return;let{type:i,backType:n,id:r,scroll:o,position:a}=t.state||{},l=window.location.href,c=a>this.currentHistoryPosition,u=c?i:n||i;this.currentHistoryPosition=a||0,this.sessionStorage.setItem(it,this.currentHistoryPosition.toString()),d.dispatchEvent(window,"phx:navigate",{detail:{href:l,patch:u==="patch",pop:!0,direction:c?"forward":"backward"}}),this.requestDOMUpdate(()=>{let p=()=>{this.maybeScroll(o)};this.main&&this.main.isConnected()&&u==="patch"&&r===this.main.id?this.main.pushLinkPatch(t,l,null,p):this.replaceMain(l,null,p)})},!1),window.addEventListener("click",t=>{let i=t.target&&d.elementFromTarget(t.target);if(!i)return;let n=ue(i,pt),r=n&&n.getAttribute(pt);if(!r||!this.isConnected()||!this.main||d.wantsNewTab(t))return;let o=n.href instanceof SVGAnimatedString?n.href.baseVal:n.href,a=n.getAttribute(Pt);if(a!=="replace"&&a!=="push")throw new Error(`expected ${Pt} to be "replace" or "push", got: ${a}`);t.preventDefault(),t.stopImmediatePropagation(),this.pendingLink!==o&&this.requestDOMUpdate(()=>{if(r==="patch")this.pushHistoryPatch(t,o,a,n);else if(r==="redirect")this.historyRedirect(t,o,a,null,n);else throw new Error(`expected ${pt} to be "patch" or "redirect", got: ${r}`);let l=n.getAttribute(this.binding("click"));l&&this.requestDOMUpdate(()=>this.execJS(n,l,"click"))})},!1)}maybeScroll(e){typeof e=="number"&&requestAnimationFrame(()=>{window.scrollTo(0,e)})}dispatchEvent(e,t={}){d.dispatchEvent(window,`phx:${e}`,{detail:t})}dispatchEvents(e){e.forEach(([t,i])=>this.dispatchEvent(t,i))}withPageLoading(e,t){d.dispatchEvent(window,"phx:page-loading-start",{detail:e});let i=()=>d.dispatchEvent(window,"phx:page-loading-stop",{detail:e});return t?t(i):i}pushHistoryPatch(e,t,i,n){if(!this.isConnected()||!(this.main&&this.main.isMain()))return V.redirect(t);this.withPageLoading({to:t,kind:"patch"},r=>{this.main.pushLinkPatch(e,t,n,o=>{this.historyPatch(t,i,o),r()})})}historyPatch(e,t,i=this.setPendingLink(e)){this.commitPendingLink(i)&&(this.currentHistoryPosition++,this.sessionStorage.setItem(it,this.currentHistoryPosition.toString()),V.updateCurrentState(n=>le(D({},n),{backType:"patch"})),V.pushState(t,{type:"patch",id:this.main.id,position:this.currentHistoryPosition},e),d.dispatchEvent(window,"phx:navigate",{detail:{patch:!0,href:e,pop:!1,direction:"forward"}}),this.registerNewLocation(window.location))}historyRedirect(e,t,i,n,r){let o=r&&e.isTrusted&&e.type!=="popstate";if(o&&r.classList.add("phx-click-loading"),!this.isConnected()||!(this.main&&this.main.isMain()))return V.redirect(t,n);if(/^\/$|^\/[^\/]+.*$/.test(t)){let{protocol:l,host:c}=window.location;t=`${l}//${c}${t}`}let a=window.scrollY;this.withPageLoading({to:t,kind:"redirect"},l=>{this.replaceMain(t,n,c=>{c===this.linkRef&&(this.currentHistoryPosition++,this.sessionStorage.setItem(it,this.currentHistoryPosition.toString()),V.updateCurrentState(u=>le(D({},u),{backType:"redirect"})),V.pushState(i,{type:"redirect",id:this.main.id,scroll:a,position:this.currentHistoryPosition},t),d.dispatchEvent(window,"phx:navigate",{detail:{href:t,patch:!1,pop:!1,direction:"forward"}}),this.registerNewLocation(window.location)),o&&r.classList.remove("phx-click-loading"),l()})})}registerNewLocation(e){let{pathname:t,search:i}=this.currentLocation;return t+i===e.pathname+e.search?!1:(this.currentLocation=We(e),!0)}bindForms(){let e=0,t=!1;this.on("submit",i=>{if(!(i.target instanceof HTMLFormElement))return;let n=i.target.getAttribute(this.binding("submit")),r=i.target.getAttribute(this.binding("change"));!t&&r&&!n&&(t=!0,i.preventDefault(),this.withinOwners(i.target,o=>{o.disableForm(i.target),window.requestAnimationFrame(()=>{d.isUnloadableFormSubmit(i)&&this.unload(),i.target.submit()})}))}),this.on("submit",i=>{if(!(i.target instanceof HTMLFormElement))return;let n=i.target.getAttribute(this.binding("submit"));if(!n){d.isUnloadableFormSubmit(i)&&this.unload();return}i.preventDefault(),i.target.disabled=!0,this.withinOwners(i.target,r=>{k.exec(i,"submit",n,r,i.target,["push",{submitter:i.submitter}])})});for(let i of["change","input"])this.on(i,n=>{if(!d.isFormAssociated(n.target))return;if(n instanceof CustomEvent&&n.target.form===void 0){if(n.detail&&n.detail.dispatcher)throw new Error(`dispatching a custom ${i} event is only supported on input elements inside a form`);return}let r=n.target,o=this.binding("change");if(this.blockPhxChangeWhileComposing&&n instanceof InputEvent&&n.isComposing){let h=`composition-listener-${i}`;d.private(r,h)||(d.putPrivate(r,h,!0),r.addEventListener("compositionend",()=>{r.dispatchEvent(new Event(i,{bubbles:!0})),d.deletePrivate(r,h)},{once:!0}));return}let a=r.getAttribute(o),l=r.form&&r.form.getAttribute(o),c=a||l;if(!c||r.type==="number"&&r.validity&&r.validity.badInput)return;let u=a?r:r.form,p=e;e++;let{at:m,type:g}=d.private(r,"prev-iteration")||{};m===p-1&&i==="change"&&g==="input"||(d.putPrivate(r,"prev-iteration",{at:p,type:i}),this.debounce(r,n,i,()=>{this.withinOwners(u,h=>{d.putPrivate(r,we,!0),k.exec(n,"change",c,h,r,["push",{_target:r.name,dispatcher:u}])})}))});this.on("reset",i=>{let n=i.target;d.resetForm(n);let r=Array.from(n.elements).find(o=>"type"in o&&o.type==="reset");r&&window.requestAnimationFrame(()=>{r.dispatchEvent(new Event("input",{bubbles:!0,cancelable:!1}))})})}debounce(e,t,i,n){if(i==="blur"||i==="focusout")return n();let r=this.binding(oi),o=this.binding(ai),a=this.defaults.debounce.toString(),l=this.defaults.throttle.toString();this.withinOwners(e,c=>{let u=()=>!c.isDestroyed()&&document.body.contains(e);d.debounce(e,t,r,a,o,l,u,()=>{n()})})}silenceEvents(e){this.silenced=!0,e(),this.silenced=!1}on(e,t){this.boundEventNames.add(e),window.addEventListener(e,i=>{this.silenced||t(i)})}jsQuerySelectorAll(e,t,i){let n=this.domCallbacks.jsQuerySelectorAll;return n?n(e,t,i):i()}},Gt=class{constructor(){this.transitions=new Set,this.promises=new Set,this.pendingOps=[]}reset(){this.transitions.forEach(e=>{clearTimeout(e),this.transitions.delete(e)}),this.promises.clear(),this.flushPendingOps()}after(e){this.size()===0?e():this.pushPendingOp(e)}addTransition(e,t,i){t();let n=setTimeout(()=>{this.transitions.delete(n),i(),this.flushPendingOps()},e);this.transitions.add(n)}addAsyncTransition(e){this.promises.add(e),e.then(()=>{this.promises.delete(e),this.flushPendingOps()})}pushPendingOp(e){this.pendingOps.push(e)}size(){return this.transitions.size+this.promises.size}flushPendingOps(){if(this.size()>0)return;let e=this.pendingOps.shift();e&&(e(),this.flushPendingOps())}};function wn(s,e){let t=d.getCustomElHook(s);if(t)return t;s.hasAttribute("id")||w("Elements passed to createHook need to have a unique id attribute",s);let i=new Q(Re.closestView(s),s,e);return d.putCustomElHook(s,i),i}function Tn(s,e){return R.getEntryDataURL(s,e)}return ji(_n);})();
21
+ `);this.socket=new t(e,i),this.bindingPrefix=i.bindingPrefix||pi,this.params=je(i.params||{}),this.viewLogger=i.viewLogger,this.metadataCallbacks=i.metadata||{},this.defaults=Object.assign(We(gi),i.defaults||{}),this.prevActive=null,this.silenced=!1,this.main=null,this.outgoingMainEl=null,this.clickStartedAtTarget=null,this.linkRef=1,this.roots={},this.href=window.location.href,this.pendingLink=null,this.currentLocation=We(window.location),this.hooks=i.hooks||{},this.uploaders=i.uploaders||{},this.loaderTimeout=i.loaderTimeout||hi,this.disconnectedTimeout=i.disconnectedTimeout||fi,this.reloadWithJitterTimer=null,this.maxReloads=i.maxReloads||10,this.reloadJitterMin=i.reloadJitterMin||5e3,this.reloadJitterMax=i.reloadJitterMax||1e4,this.failsafeJitter=i.failsafeJitter||3e4,this.localStorage=i.localStorage||window.localStorage,this.sessionStorage=i.sessionStorage||window.sessionStorage,this.boundTopLevelEvents=!1,this.boundEventNames=new Set,this.blockPhxChangeWhileComposing=i.blockPhxChangeWhileComposing||!1,this.serverCloseRef=null,this.domCallbacks=Object.assign({jsQuerySelectorAll:null,onPatchStart:je(),onPatchEnd:je(),onNodeAdded:je(),onBeforeElUpdated:je()},i.dom||{}),this.transitions=new Gt,this.currentHistoryPosition=parseInt(this.sessionStorage.getItem(it)||"0")||0,window.addEventListener("pagehide",n=>{this.unloaded=!0}),this.socket.onOpen(()=>{this.isUnloaded()&&window.location.reload()})}version(){return"1.2.3"}isProfileEnabled(){return this.sessionStorage.getItem(Et)==="true"}isDebugEnabled(){return this.sessionStorage.getItem(tt)==="true"}isDebugDisabled(){return this.sessionStorage.getItem(tt)==="false"}enableDebug(){this.sessionStorage.setItem(tt,"true")}enableProfiling(){this.sessionStorage.setItem(Et,"true")}disableDebug(){this.sessionStorage.setItem(tt,"false")}disableProfiling(){this.sessionStorage.removeItem(Et)}enableLatencySim(e){this.enableDebug(),console.log("latency simulator enabled for the duration of this browser session. Call disableLatencySim() to disable"),this.sessionStorage.setItem(bt,e.toString())}disableLatencySim(){this.sessionStorage.removeItem(bt)}getLatencySim(){let e=this.sessionStorage.getItem(bt);return e?parseInt(e):null}getSocket(){return this.socket}connect(){window.location.hostname==="localhost"&&!this.isDebugDisabled()&&this.enableDebug();let e=()=>{this.resetReloadStatus(),this.joinRootViews()?(this.bindTopLevelEvents(),this.socket.connect()):this.main?this.socket.connect():this.bindTopLevelEvents({dead:!0}),this.joinDeadView()};["complete","loaded","interactive"].indexOf(document.readyState)>=0?e():document.addEventListener("DOMContentLoaded",()=>e())}disconnect(e){this.reloadWithJitterTimer!=null&&clearTimeout(this.reloadWithJitterTimer),this.serverCloseRef&&(this.socket.off([this.serverCloseRef]),this.serverCloseRef=null),this.socket.disconnect(e)}replaceTransport(e){this.reloadWithJitterTimer!=null&&clearTimeout(this.reloadWithJitterTimer),this.socket.replaceTransport(e),this.connect()}execJS(e,t,i=null){let n=new CustomEvent("phx:exec",{detail:{sourceElement:e}});this.owner(e,r=>k.exec(n,i,t,r,e))}js(){return kt(this,"js")}unload(){this.unloaded||(this.main&&this.isConnected()&&this.log(this.main,"socket",()=>["disconnect for page nav"]),this.unloaded=!0,this.destroyAllViews(),this.disconnect())}triggerDOM(e,t){this.domCallbacks[e](...t)}time(e,t){if(!this.isProfileEnabled()||!console.time)return t();console.time(e);let i=t();return console.timeEnd(e),i}log(e,t,i){if(this.viewLogger){let[n,r]=i();this.viewLogger(e,t,n,r)}else if(this.isDebugEnabled()){let[n,r]=i();bi(e,t,n,r)}}requestDOMUpdate(e){this.transitions.after(e)}asyncTransition(e){this.transitions.addAsyncTransition(e)}transition(e,t,i=function(){}){this.transitions.addTransition(e,t,i)}onChannel(e,t,i){e.on(t,n=>{let r=this.getLatencySim();r?setTimeout(()=>i(n),r):i(n)})}reloadWithJitter(e,t){this.reloadWithJitterTimer!=null&&clearTimeout(this.reloadWithJitterTimer),this.disconnect();let i=this.reloadJitterMin,n=this.reloadJitterMax,r=Math.floor(Math.random()*(n-i+1))+i,o=V.updateLocal(this.localStorage,window.location.pathname,ht,0,a=>a+1);o>=this.maxReloads&&(r=this.failsafeJitter),this.reloadWithJitterTimer=setTimeout(()=>{e.isDestroyed()||e.isConnected()||(e.destroy(),t?t():this.log(e,"join",()=>[`encountered ${o} consecutive reloads`]),o>=this.maxReloads&&this.log(e,"join",()=>[`exceeded ${this.maxReloads} consecutive reloads. Entering failsafe mode`]),this.pendingLink!==null?window.location.href=this.pendingLink:window.location.reload())},r)}getHookDefinition(e){if(e)return this.maybeInternalHook(e)||this.hooks[e]||this.maybeRuntimeHook(e)}maybeInternalHook(e){return e&&e.startsWith("Phoenix.")&&_i[e.split(".")[1]]}maybeRuntimeHook(e){let t=document.querySelector(`script[${Ve}="${CSS.escape(e)}"]`);if(!t)return;let i=window[`phx_hook_${e}`];if(!i||typeof i!="function"){w("a runtime hook must be a function",t);return}let n=i();if(n&&(typeof n=="object"||typeof n=="function"))return n;w("runtime hook must return an object with hook callbacks or an instance of ViewHook",t)}isUnloaded(){return this.unloaded}isConnected(){return this.socket.isConnected()}getBindingPrefix(){return this.bindingPrefix}binding(e){return`${this.getBindingPrefix()}${e}`}channel(e,t){return this.socket.channel(e,t)}joinDeadView(){let e=document.body;if(e&&!this.isPhxView(e)&&!this.isPhxView(document.firstElementChild)){let t=this.newRootView(e);t.setHref(this.getHref()),t.joinDead(),this.main||(this.main=t),window.requestAnimationFrame(()=>{var i;t.execNewMounted(),this.maybeScroll((i=history.state)==null?void 0:i.scroll)})}}joinRootViews(){let e=!1;return d.all(document,`${ce}:not([${ne}])`,t=>{if(!this.getRootById(t.id)){let i=this.newRootView(t);d.isPhxSticky(t)||i.setHref(this.getHref()),i.join(),t.hasAttribute(De)&&(this.main=i)}e=!0}),e}redirect(e,t,i){i&&V.setCookie(Mt,i,60),this.unload(),V.redirect(e,t)}replaceMain(e,t,i=null,n=this.setPendingLink(e)){if(!this.main)return;let r=this.currentLocation.href;this.outgoingMainEl=this.outgoingMainEl||this.main.el;let o=d.findPhxSticky(document)||[],a=d.all(this.outgoingMainEl,`[${this.binding("remove")}]`).filter(u=>!d.isChildOfAny(u,o)),l=d.cloneNode(this.outgoingMainEl,""),c=this.main;c.showLoader(this.loaderTimeout),c.destroy(),this.main=this.newRootView(l,t,r),this.main.setRedirect(e),this.transitionRemoves(a,c),this.main.join((u,p)=>{u===1&&this.commitPendingLink(n)&&this.requestDOMUpdate(()=>{a.forEach(m=>m.remove()),o.forEach(m=>l.appendChild(m)),this.outgoingMainEl.replaceWith(l),this.outgoingMainEl=null,i&&i(n),p()})})}transitionRemoves(e,t,i){let n=this.binding("remove"),r=o=>{o.preventDefault(),o.stopImmediatePropagation()};e.forEach(o=>{for(let l of this.boundEventNames)o.addEventListener(l,r,!0);let a=new CustomEvent("phx:exec",{detail:{sourceElement:o}});k.exec(a,"remove",o.getAttribute(n),t,o)}),this.requestDOMUpdate(()=>{e.forEach(o=>{for(let a of this.boundEventNames)o.removeEventListener(a,r,!0)}),i&&i()})}isPhxView(e){return e.getAttribute&&e.getAttribute(q)!==null}newRootView(e,t,i){let n=new Re(e,this,null,t,i);return this.roots[n.id]=n,n}owner(e,t){let i,n=d.closestViewEl(e);if(n)i=d.private(n,"view");else{if(!e.isConnected)return null;i=this.main}return i&&t?t(i):i}withinOwners(e,t){this.owner(e,i=>t(i,e))}getViewByEl(e){let t=e.getAttribute(z);return fe(this.getRootById(t),i=>i.getDescendentByEl(e))}getRootById(e){return this.roots[e]}destroyAllViews(){for(let e in this.roots)this.roots[e].destroy(),delete this.roots[e];this.main=null}destroyViewByEl(e){let t=this.getRootById(e.getAttribute(z));t&&t.id===e.id?(t.destroy(),delete this.roots[t.id]):t&&t.destroyDescendent(e.id)}getActiveElement(){return document.activeElement}dropActiveElement(e){this.prevActive&&e.ownsElement(this.prevActive)&&(this.prevActive=null)}restorePreviouslyActiveFocus(){this.prevActive&&this.prevActive!==document.body&&this.prevActive instanceof HTMLElement&&this.prevActive.focus()}blurActiveElement(){this.prevActive=this.getActiveElement(),this.prevActive!==document.body&&this.prevActive instanceof HTMLElement&&this.prevActive.blur()}bindTopLevelEvents({dead:e}={}){this.boundTopLevelEvents||(this.boundTopLevelEvents=!0,this.serverCloseRef=this.socket.onClose(t=>{if(t&&t.code===1e3&&this.main)return this.reloadWithJitter(this.main)}),document.body.addEventListener("click",function(){}),window.addEventListener("pageshow",t=>{t.persisted&&(this.getSocket().disconnect(),this.withPageLoading({to:window.location.href,kind:"redirect"}),window.location.reload())},!0),e||this.bindNav(),this.bindClicks(),e||this.bindForms(),this.bind({keyup:"keyup",keydown:"keydown"},(t,i,n,r,o,a)=>{let l=r.getAttribute(this.binding(di)),c=t.key&&t.key.toLowerCase();if(l&&l.toLowerCase()!==c)return;let u=D({key:t.key},this.eventMeta(i,t,r));k.exec(t,i,o,n,r,["push",{data:u}])}),this.bind({blur:"focusout",focus:"focusin"},(t,i,n,r,o,a)=>{if(!a){let l=D({},this.eventMeta(i,t,r));k.exec(t,i,o,n,r,["push",{data:l}])}}),this.bind({blur:"blur",focus:"focus"},(t,i,n,r,o,a)=>{if(a==="window"){let l=this.eventMeta(i,t,r);k.exec(t,i,o,n,r,["push",{data:l}])}}),this.on("dragover",t=>t.preventDefault()),this.on("dragenter",t=>{let i=t.target&&d.elementFromTarget(t.target);if(!i)return;let n=ue(i,this.binding(qe));!n||!(n instanceof HTMLElement)||Si(t)&&this.js().addClass(n,ft)}),this.on("dragleave",t=>{let i=t.target&&d.elementFromTarget(t.target);if(!i)return;let n=ue(i,this.binding(qe));if(!n||!(n instanceof HTMLElement))return;let r=n.getBoundingClientRect();(t.clientX<=r.left||t.clientX>=r.right||t.clientY<=r.top||t.clientY>=r.bottom)&&this.js().removeClass(n,ft)}),this.on("drop",t=>{let i=t.target&&d.elementFromTarget(t.target);if(!i)return;t.preventDefault();let n=ue(i,this.binding(qe));if(!n||!(n instanceof HTMLElement)||(this.js().removeClass(n,ft),!t.dataTransfer))return;let r=n.getAttribute(this.binding(qe)),o=r&&document.getElementById(r),a=Array.from(t.dataTransfer.files||[]);!o||!(o instanceof HTMLInputElement)||o.disabled||a.length===0||!(o.files instanceof FileList)||(R.trackFiles(o,a,t.dataTransfer),o.dispatchEvent(new Event("input",{bubbles:!0})))}),this.on(mt,t=>{let i=t.target&&d.elementFromTarget(t.target);if(!d.isUploadInput(i))return;let n=Array.from(t.detail.files||[]).filter(r=>r instanceof File||r instanceof Blob);R.trackFiles(i,n),i.dispatchEvent(new Event("input",{bubbles:!0}))}))}eventMeta(e,t,i){let n=this.metadataCallbacks[e];return n?n(t,i):{}}setPendingLink(e){return this.linkRef++,this.pendingLink=e,this.resetReloadStatus(),this.linkRef}resetReloadStatus(){V.deleteCookie(Mt)}commitPendingLink(e){return this.linkRef!==e?!1:(this.pendingLink!==null&&(this.href=this.pendingLink,this.pendingLink=null),!0)}getHref(){return this.href}hasPendingLink(){return!!this.pendingLink}bind(e,t){for(let i in e){let n=e[i];this.on(n,r=>{let o=this.binding(i),a=this.binding(`window-${i}`),l=r.target instanceof Element&&r.target.getAttribute(o);r.target instanceof Element&&(l?this.debounce(r.target,r,n,()=>{this.withinOwners(r.target,c=>{t(r,i,c,r.target,l,null)})}):d.all(document,`[${a}]`,c=>{let u=c.getAttribute(a);this.debounce(c,r,n,()=>{this.withinOwners(c,p=>{t(r,i,p,c,u,"window")})})}))})}}bindClicks(){this.on("mousedown",e=>this.clickStartedAtTarget=e.target),this.bindClick()}bindClick(){let e=this.binding("click");window.addEventListener("click",t=>{let i=t.target&&d.elementFromTarget(t.target);if(!i)return;t.detail===0&&(this.clickStartedAtTarget=i);let n=this.clickStartedAtTarget||i;if(i=ue(i,e),this.dispatchClickAway(t,n),this.clickStartedAtTarget=null,!i)return;let r=i.getAttribute(e);if(!r){d.isNewPageClick(t,window.location)&&this.unload();return}i.getAttribute("href")==="#"&&t.preventDefault(),!i.hasAttribute(U)&&this.debounce(i,t,"click",()=>{this.withinOwners(i,o=>{k.exec(t,"click",r,o,i,["push",{data:this.eventMeta("click",t,i)}])})})},!1)}dispatchClickAway(e,t){let i=this.binding("click-away"),n=t.closest(`[${Z}]`),r=n&&d.byId(n.getAttribute(Z));d.all(document,`[${i}]`,o=>{let a=t;n&&!n.contains(o)&&(a=r),o.isSameNode(a)||o.contains(a)||!k.isVisible(t)||this.withinOwners(o,l=>{let c=o.getAttribute(i);k.isVisible(o)&&k.isInViewport(o)&&k.exec(e,"click",c,l,o,["push",{data:this.eventMeta("click",e,e.target)}])})})}bindNav(){if(!V.canPushState())return;history.scrollRestoration&&(history.scrollRestoration="manual");let e=null;window.addEventListener("scroll",t=>{e!=null&&clearTimeout(e),e=setTimeout(()=>{V.updateCurrentState(i=>Object.assign(i,{scroll:window.scrollY}))},100)}),window.addEventListener("popstate",t=>{if(!this.registerNewLocation(window.location))return;let{type:i,backType:n,id:r,scroll:o,position:a}=t.state||{},l=window.location.href,c=a>this.currentHistoryPosition,u=c?i:n||i;this.currentHistoryPosition=a||0,this.sessionStorage.setItem(it,this.currentHistoryPosition.toString()),d.dispatchEvent(window,"phx:navigate",{detail:{href:l,patch:u==="patch",pop:!0,direction:c?"forward":"backward"}}),this.requestDOMUpdate(()=>{let p=()=>{this.maybeScroll(o)};this.main&&this.main.isConnected()&&u==="patch"&&r===this.main.id?this.main.pushLinkPatch(t,l,null,p):this.replaceMain(l,null,p)})},!1),window.addEventListener("click",t=>{let i=t.target&&d.elementFromTarget(t.target);if(!i)return;let n=ue(i,pt),r=n&&n.getAttribute(pt);if(!r||!this.isConnected()||!this.main||d.wantsNewTab(t))return;let o=n.href instanceof SVGAnimatedString?n.href.baseVal:n.href,a=n.getAttribute(Pt);if(a!=="replace"&&a!=="push")throw new Error(`expected ${Pt} to be "replace" or "push", got: ${a}`);t.preventDefault(),t.stopImmediatePropagation(),this.pendingLink!==o&&this.requestDOMUpdate(()=>{if(r==="patch")this.pushHistoryPatch(t,o,a,n);else if(r==="redirect")this.historyRedirect(t,o,a,null,n);else throw new Error(`expected ${pt} to be "patch" or "redirect", got: ${r}`);let l=n.getAttribute(this.binding("click"));l&&this.requestDOMUpdate(()=>this.execJS(n,l,"click"))})},!1)}maybeScroll(e){typeof e=="number"&&requestAnimationFrame(()=>{window.scrollTo(0,e)})}dispatchEvent(e,t={}){d.dispatchEvent(window,`phx:${e}`,{detail:t})}dispatchEvents(e){e.forEach(([t,i])=>this.dispatchEvent(t,i))}withPageLoading(e,t){d.dispatchEvent(window,"phx:page-loading-start",{detail:e});let i=()=>d.dispatchEvent(window,"phx:page-loading-stop",{detail:e});return t?t(i):i}pushHistoryPatch(e,t,i,n){if(!this.isConnected()||!(this.main&&this.main.isMain()))return V.redirect(t);this.withPageLoading({to:t,kind:"patch"},r=>{this.main.pushLinkPatch(e,t,n,o=>{this.historyPatch(t,i,o),r()})})}historyPatch(e,t,i=this.setPendingLink(e)){this.commitPendingLink(i)&&(this.currentHistoryPosition++,this.sessionStorage.setItem(it,this.currentHistoryPosition.toString()),V.updateCurrentState(n=>le(D({},n),{backType:"patch"})),V.pushState(t,{type:"patch",id:this.main.id,position:this.currentHistoryPosition},e),d.dispatchEvent(window,"phx:navigate",{detail:{patch:!0,href:e,pop:!1,direction:"forward"}}),this.registerNewLocation(window.location))}historyRedirect(e,t,i,n,r){let o=r&&e.isTrusted&&e.type!=="popstate";if(o&&r.classList.add("phx-click-loading"),!this.isConnected()||!(this.main&&this.main.isMain()))return V.redirect(t,n);if(/^\/$|^\/[^\/]+.*$/.test(t)){let{protocol:l,host:c}=window.location;t=`${l}//${c}${t}`}let a=window.scrollY;this.withPageLoading({to:t,kind:"redirect"},l=>{this.replaceMain(t,n,c=>{c===this.linkRef&&(this.currentHistoryPosition++,this.sessionStorage.setItem(it,this.currentHistoryPosition.toString()),V.updateCurrentState(u=>le(D({},u),{backType:"redirect"})),V.pushState(i,{type:"redirect",id:this.main.id,scroll:a,position:this.currentHistoryPosition},t),d.dispatchEvent(window,"phx:navigate",{detail:{href:t,patch:!1,pop:!1,direction:"forward"}}),this.registerNewLocation(window.location)),o&&r.classList.remove("phx-click-loading"),l()})})}registerNewLocation(e){let{pathname:t,search:i}=this.currentLocation;return t+i===e.pathname+e.search?!1:(this.currentLocation=We(e),!0)}bindForms(){let e=0,t=!1;this.on("submit",i=>{if(!(i.target instanceof HTMLFormElement))return;let n=i.target.getAttribute(this.binding("submit")),r=i.target.getAttribute(this.binding("change"));!t&&r&&!n&&(t=!0,i.preventDefault(),this.withinOwners(i.target,o=>{o.disableForm(i.target),window.requestAnimationFrame(()=>{d.isUnloadableFormSubmit(i)&&this.unload(),i.target.submit()})}))}),this.on("submit",i=>{if(!(i.target instanceof HTMLFormElement))return;let n=i.target.getAttribute(this.binding("submit"));if(!n){d.isUnloadableFormSubmit(i)&&this.unload();return}i.preventDefault(),i.target.disabled=!0,this.withinOwners(i.target,r=>{k.exec(i,"submit",n,r,i.target,["push",{submitter:i.submitter}])})});for(let i of["change","input"])this.on(i,n=>{if(!d.isFormAssociated(n.target))return;if(n instanceof CustomEvent&&n.target.form===void 0){if(n.detail&&n.detail.dispatcher)throw new Error(`dispatching a custom ${i} event is only supported on input elements inside a form`);return}let r=n.target,o=this.binding("change");if(this.blockPhxChangeWhileComposing&&n instanceof InputEvent&&n.isComposing){let h=`composition-listener-${i}`;d.private(r,h)||(d.putPrivate(r,h,!0),r.addEventListener("compositionend",()=>{r.dispatchEvent(new Event(i,{bubbles:!0})),d.deletePrivate(r,h)},{once:!0}));return}let a=r.getAttribute(o),l=r.form&&r.form.getAttribute(o),c=a||l;if(!c||r.type==="number"&&r.validity&&r.validity.badInput)return;let u=a?r:r.form,p=e;e++;let{at:m,type:g}=d.private(r,"prev-iteration")||{};m===p-1&&i==="change"&&g==="input"||(d.putPrivate(r,"prev-iteration",{at:p,type:i}),this.debounce(r,n,i,()=>{this.withinOwners(u,h=>{d.putPrivate(r,we,!0),k.exec(n,"change",c,h,r,["push",{_target:r.name,dispatcher:u}])})}))});this.on("reset",i=>{let n=i.target;d.resetForm(n);let r=Array.from(n.elements).find(o=>"type"in o&&o.type==="reset");r&&window.requestAnimationFrame(()=>{r.dispatchEvent(new Event("input",{bubbles:!0,cancelable:!1}))})})}debounce(e,t,i,n){if(i==="blur"||i==="focusout")return n();let r=this.binding(oi),o=this.binding(ai),a=this.defaults.debounce.toString(),l=this.defaults.throttle.toString();this.withinOwners(e,c=>{let u=()=>!c.isDestroyed()&&document.body.contains(e);d.debounce(e,t,r,a,o,l,u,()=>{n()})})}silenceEvents(e){this.silenced=!0,e(),this.silenced=!1}on(e,t){this.boundEventNames.add(e),window.addEventListener(e,i=>{this.silenced||t(i)})}jsQuerySelectorAll(e,t,i){let n=this.domCallbacks.jsQuerySelectorAll;return n?n(e,t,i):i()}},Gt=class{constructor(){this.transitions=new Set,this.promises=new Set,this.pendingOps=[]}reset(){this.transitions.forEach(e=>{clearTimeout(e),this.transitions.delete(e)}),this.promises.clear(),this.flushPendingOps()}after(e){this.size()===0?e():this.pushPendingOp(e)}addTransition(e,t,i){t();let n=setTimeout(()=>{this.transitions.delete(n),i(),this.flushPendingOps()},e);this.transitions.add(n)}addAsyncTransition(e){this.promises.add(e),e.then(()=>{this.promises.delete(e),this.flushPendingOps()})}pushPendingOp(e){this.pendingOps.push(e)}size(){return this.transitions.size+this.promises.size}flushPendingOps(){if(this.size()>0)return;let e=this.pendingOps.shift();e&&(e(),this.flushPendingOps())}};function wn(s,e){let t=d.getCustomElHook(s);if(t)return t;s.hasAttribute("id")||w("Elements passed to createHook need to have a unique id attribute",s);let i=new Q(Re.closestView(s),s,e);return d.putCustomElHook(s,i),i}function Tn(s,e){return R.getEntryDataURL(s,e)}return ji(_n);})();