vendor: 1,934 bytes, lines 1-39
1var __create = Object.create; 2var __defProp = Object.defineProperty; 3var __getOwnPropDesc = Object.getOwnPropertyDescriptor; 4var __getOwnPropNames = Object.getOwnPropertyNames; 5var __getProtoOf = Object.getPrototypeOf; 6var __hasOwnProp = Object.prototype.hasOwnProperty; 7var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { 8 get: (a, b) => (typeof require !== "undefined" ? require : a)[b] 9}) : x)(function(x) { 10 if (typeof require !== "undefined") return require.apply(this, arguments); 11 throw Error('Dynamic require of "' + x + '" is not supported'); 12}); 13var __esm = (fn, res) => function __init() { 14 return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res; 15}; 16var __commonJS = (cb, mod) => function __require2() { 17 return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; 18}; 19var __export = (target, all) => { 20 for (var name in all) 21 __defProp(target, name, { get: all[name], enumerable: true }); 22}; 23var __copyProps = (to, from, except, desc) => { 24 if (from && typeof from === "object" || typeof from === "function") { 25 for (let key of __getOwnPropNames(from)) 26 if (!__hasOwnProp.call(to, key) && key !== except) 27 __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); 28 } 29 return to; 30}; 31var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( 32 // If the importer is in node compatibility mode or this is not an ESM 33 // file that has been converted to a CommonJS file using a Babel- 34 // compatible transform (i.e. "__esModule" has not been set), then set 35 // "default" to the CommonJS "module.exports" for node compatibility. 36 isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, 37 mod 38)); 39
vendor: 334 bytes, lines 40-50
40// node_modules/@rails/actioncable/src/adapters.js 41var adapters_default; 42var init_adapters = __esm({ 43 "node_modules/@rails/actioncable/src/adapters.js"() { 44 adapters_default = { 45 logger: typeof console !== "undefined" ? console : void 0, 46 WebSocket: typeof WebSocket !== "undefined" ? WebSocket : void 0 47 }; 48 } 49}); 50
vendor: 386 bytes, lines 51-66
51// node_modules/@rails/actioncable/src/logger.js 52var logger_default; 53var init_logger = __esm({ 54 "node_modules/@rails/actioncable/src/logger.js"() { 55 init_adapters(); 56 logger_default = { 57 log(...messages) { 58 if (this.enabled) { 59 messages.push(Date.now()); 60 adapters_default.logger.log("[ActionCable]", ...messages); 61 } 62 } 63 }; 64 } 65}); 66
vendor: 4,101 bytes, lines 67-176
67// node_modules/@rails/actioncable/src/connection_monitor.js 68var now, secondsSince, ConnectionMonitor, connection_monitor_default; 69var init_connection_monitor = __esm({ 70 "node_modules/@rails/actioncable/src/connection_monitor.js"() { 71 init_logger(); 72 now = () => (/* @__PURE__ */ new Date()).getTime(); 73 secondsSince = (time) => (now() - time) / 1e3; 74 ConnectionMonitor = class { 75 constructor(connection) { 76 this.visibilityDidChange = this.visibilityDidChange.bind(this); 77 this.connection = connection; 78 this.reconnectAttempts = 0; 79 } 80 start() { 81 if (!this.isRunning()) { 82 this.startedAt = now(); 83 delete this.stoppedAt; 84 this.startPolling(); 85 addEventListener("visibilitychange", this.visibilityDidChange); 86 logger_default.log(`ConnectionMonitor started. stale threshold = ${this.constructor.staleThreshold} s`); 87 } 88 } 89 stop() { 90 if (this.isRunning()) { 91 this.stoppedAt = now(); 92 this.stopPolling(); 93 removeEventListener("visibilitychange", this.visibilityDidChange); 94 logger_default.log("ConnectionMonitor stopped"); 95 } 96 } 97 isRunning() { 98 return this.startedAt && !this.stoppedAt; 99 } 100 recordMessage() { 101 this.pingedAt = now(); 102 } 103 recordConnect() { 104 this.reconnectAttempts = 0; 105 delete this.disconnectedAt; 106 logger_default.log("ConnectionMonitor recorded connect"); 107 } 108 recordDisconnect() { 109 this.disconnectedAt = now(); 110 logger_default.log("ConnectionMonitor recorded disconnect"); 111 } 112 // Private 113 startPolling() { 114 this.stopPolling(); 115 this.poll(); 116 } 117 stopPolling() { 118 clearTimeout(this.pollTimeout); 119 } 120 poll() { 121 this.pollTimeout = setTimeout( 122 () => { 123 this.reconnectIfStale(); 124 this.poll(); 125 }, 126 this.getPollInterval() 127 ); 128 } 129 getPollInterval() { 130 const { staleThreshold, reconnectionBackoffRate } = this.constructor; 131 const backoff = Math.pow(1 + reconnectionBackoffRate, Math.min(this.reconnectAttempts, 10)); 132 const jitterMax = this.reconnectAttempts === 0 ? 1 : reconnectionBackoffRate; 133 const jitter = jitterMax * Math.random(); 134 return staleThreshold * 1e3 * backoff * (1 + jitter); 135 } 136 reconnectIfStale() { 137 if (this.connectionIsStale()) { 138 logger_default.log(`ConnectionMonitor detected stale connection. reconnectAttempts = ${this.reconnectAttempts}, time stale = ${secondsSince(this.refreshedAt)} s, stale threshold = ${this.constructor.staleThreshold} s`); 139 this.reconnectAttempts++; 140 if (this.disconnectedRecently()) { 141 logger_default.log(`ConnectionMonitor skipping reopening recent disconnect. time disconnected = ${secondsSince(this.disconnectedAt)} s`); 142 } else { 143 logger_default.log("ConnectionMonitor reopening"); 144 this.connection.reopen(); 145 } 146 } 147 } 148 get refreshedAt() { 149 return this.pingedAt ? this.pingedAt : this.startedAt; 150 } 151 connectionIsStale() { 152 return secondsSince(this.refreshedAt) > this.constructor.staleThreshold; 153 } 154 disconnectedRecently() { 155 return this.disconnectedAt && secondsSince(this.disconnectedAt) < this.constructor.staleThreshold; 156 } 157 visibilityDidChange() { 158 if (document.visibilityState === "visible") { 159 setTimeout( 160 () => { 161 if (this.connectionIsStale() || !this.connection.isOpen()) { 162 logger_default.log(`ConnectionMonitor reopening stale connection on visibilitychange. visibilityState = ${document.visibilityState}`); 163 this.connection.reopen(); 164 } 165 }, 166 200 167 ); 168 } 169 } 170 }; 171 ConnectionMonitor.staleThreshold = 6; 172 ConnectionMonitor.reconnectionBackoffRate = 0.15; 173 connection_monitor_default = ConnectionMonitor; 174 } 175}); 176
vendor: 741 bytes, lines 177-203
177// node_modules/@rails/actioncable/src/internal.js 178var internal_default; 179var init_internal = __esm({ 180 "node_modules/@rails/actioncable/src/internal.js"() { 181 internal_default = { 182 "message_types": { 183 "welcome": "welcome", 184 "disconnect": "disconnect", 185 "ping": "ping", 186 "confirmation": "confirm_subscription", 187 "rejection": "reject_subscription" 188 }, 189 "disconnect_reasons": { 190 "unauthorized": "unauthorized", 191 "invalid_request": "invalid_request", 192 "server_restart": "server_restart", 193 "remote": "remote" 194 }, 195 "default_mount_path": "/cable", 196 "protocols": [ 197 "actioncable-v1-json", 198 "actioncable-unsupported" 199 ] 200 }; 201 } 202}); 203
vendor: 5,887 bytes, lines 204-372
204// node_modules/@rails/actioncable/src/connection.js 205var message_types, protocols, supportedProtocols, indexOf, Connection, connection_default; 206var init_connection = __esm({ 207 "node_modules/@rails/actioncable/src/connection.js"() { 208 init_adapters(); 209 init_connection_monitor(); 210 init_internal(); 211 init_logger(); 212 ({ message_types, protocols } = internal_default); 213 supportedProtocols = protocols.slice(0, protocols.length - 1); 214 indexOf = [].indexOf; 215 Connection = class { 216 constructor(consumer2) { 217 this.open = this.open.bind(this); 218 this.consumer = consumer2; 219 this.subscriptions = this.consumer.subscriptions; 220 this.monitor = new connection_monitor_default(this); 221 this.disconnected = true; 222 } 223 send(data) { 224 if (this.isOpen()) { 225 this.webSocket.send(JSON.stringify(data)); 226 return true; 227 } else { 228 return false; 229 } 230 } 231 open() { 232 if (this.isActive()) { 233 logger_default.log(`Attempted to open WebSocket, but existing socket is ${this.getState()}`); 234 return false; 235 } else { 236 const socketProtocols = [...protocols, ...this.consumer.subprotocols || []]; 237 logger_default.log(`Opening WebSocket, current state is ${this.getState()}, subprotocols: ${socketProtocols}`); 238 if (this.webSocket) { 239 this.uninstallEventHandlers(); 240 } 241 this.webSocket = new adapters_default.WebSocket(this.consumer.url, socketProtocols); 242 this.installEventHandlers(); 243 this.monitor.start(); 244 return true; 245 } 246 } 247 close({ allowReconnect } = { allowReconnect: true }) { 248 if (!allowReconnect) { 249 this.monitor.stop(); 250 } 251 if (this.isOpen()) { 252 return this.webSocket.close(); 253 } 254 } 255 reopen() { 256 logger_default.log(`Reopening WebSocket, current state is ${this.getState()}`); 257 if (this.isActive()) { 258 try { 259 return this.close(); 260 } catch (error2) { 261 logger_default.log("Failed to reopen WebSocket", error2); 262 } finally { 263 logger_default.log(`Reopening WebSocket in ${this.constructor.reopenDelay}ms`); 264 setTimeout(this.open, this.constructor.reopenDelay); 265 } 266 } else { 267 return this.open(); 268 } 269 } 270 getProtocol() { 271 if (this.webSocket) { 272 return this.webSocket.protocol; 273 } 274 } 275 isOpen() { 276 return this.isState("open"); 277 } 278 isActive() { 279 return this.isState("open", "connecting"); 280 } 281 triedToReconnect() { 282 return this.monitor.reconnectAttempts > 0; 283 } 284 // Private 285 isProtocolSupported() { 286 return indexOf.call(supportedProtocols, this.getProtocol()) >= 0; 287 } 288 isState(...states) { 289 return indexOf.call(states, this.getState()) >= 0; 290 } 291 getState() { 292 if (this.webSocket) { 293 for (let state in adapters_default.WebSocket) { 294 if (adapters_default.WebSocket[state] === this.webSocket.readyState) { 295 return state.toLowerCase(); 296 } 297 } 298 } 299 return null; 300 } 301 installEventHandlers() { 302 for (let eventName in this.events) { 303 const handler = this.events[eventName].bind(this); 304 this.webSocket[`on${eventName}`] = handler; 305 } 306 } 307 uninstallEventHandlers() { 308 for (let eventName in this.events) { 309 this.webSocket[`on${eventName}`] = function() { 310 }; 311 } 312 } 313 }; 314 Connection.reopenDelay = 500; 315 Connection.prototype.events = { 316 message(event) { 317 if (!this.isProtocolSupported()) { 318 return; 319 } 320 const { identifier, message, reason, reconnect, type } = JSON.parse(event.data); 321 this.monitor.recordMessage(); 322 switch (type) { 323 case message_types.welcome: 324 if (this.triedToReconnect()) { 325 this.reconnectAttempted = true; 326 } 327 this.monitor.recordConnect(); 328 return this.subscriptions.reload(); 329 case message_types.disconnect: 330 logger_default.log(`Disconnecting. Reason: ${reason}`); 331 return this.close({ allowReconnect: reconnect }); 332 case message_types.ping: 333 return null; 334 case message_types.confirmation: 335 this.subscriptions.confirmSubscription(identifier); 336 if (this.reconnectAttempted) { 337 this.reconnectAttempted = false; 338 return this.subscriptions.notify(identifier, "connected", { reconnected: true }); 339 } else { 340 return this.subscriptions.notify(identifier, "connected", { reconnected: false }); 341 } 342 case message_types.rejection: 343 return this.subscriptions.reject(identifier); 344 default: 345 return this.subscriptions.notify(identifier, "received", message); 346 } 347 }, 348 open() { 349 logger_default.log(`WebSocket onopen event, using '${this.getProtocol()}' subprotocol`); 350 this.disconnected = false; 351 if (!this.isProtocolSupported()) { 352 logger_default.log("Protocol is unsupported. Stopping monitor and disconnecting."); 353 return this.close({ allowReconnect: false }); 354 } 355 }, 356 close(event) { 357 logger_default.log("WebSocket onclose event"); 358 if (this.disconnected) { 359 return; 360 } 361 this.disconnected = true; 362 this.monitor.recordDisconnect(); 363 return this.subscriptions.notifyAll("disconnected", { willAttemptReconnect: this.monitor.isRunning() }); 364 }, 365 error() { 366 logger_default.log("WebSocket onerror event"); 367 } 368 }; 369 connection_default = Connection; 370 } 371}); 372
vendor: 1,036 bytes, lines 373-406
373// node_modules/@rails/actioncable/src/subscription.js 374var extend, Subscription; 375var init_subscription = __esm({ 376 "node_modules/@rails/actioncable/src/subscription.js"() { 377 extend = function(object, properties) { 378 if (properties != null) { 379 for (let key in properties) { 380 const value = properties[key]; 381 object[key] = value; 382 } 383 } 384 return object; 385 }; 386 Subscription = class { 387 constructor(consumer2, params = {}, mixin) { 388 this.consumer = consumer2; 389 this.identifier = JSON.stringify(params); 390 extend(this, mixin); 391 } 392 // Perform a channel action with the optional data passed as an attribute 393 perform(action, data = {}) { 394 data.action = action; 395 return this.send(data); 396 } 397 send(data) { 398 return this.consumer.send({ command: "message", identifier: this.identifier, data: JSON.stringify(data) }); 399 } 400 unsubscribe() { 401 return this.consumer.subscriptions.remove(this); 402 } 403 }; 404 } 405}); 406
vendor: 1,802 bytes, lines 407-454
407// node_modules/@rails/actioncable/src/subscription_guarantor.js 408var SubscriptionGuarantor, subscription_guarantor_default; 409var init_subscription_guarantor = __esm({ 410 "node_modules/@rails/actioncable/src/subscription_guarantor.js"() { 411 init_logger(); 412 SubscriptionGuarantor = class { 413 constructor(subscriptions) { 414 this.subscriptions = subscriptions; 415 this.pendingSubscriptions = []; 416 } 417 guarantee(subscription) { 418 if (this.pendingSubscriptions.indexOf(subscription) == -1) { 419 logger_default.log(`SubscriptionGuarantor guaranteeing ${subscription.identifier}`); 420 this.pendingSubscriptions.push(subscription); 421 } else { 422 logger_default.log(`SubscriptionGuarantor already guaranteeing ${subscription.identifier}`); 423 } 424 this.startGuaranteeing(); 425 } 426 forget(subscription) { 427 logger_default.log(`SubscriptionGuarantor forgetting ${subscription.identifier}`); 428 this.pendingSubscriptions = this.pendingSubscriptions.filter((s) => s !== subscription); 429 } 430 startGuaranteeing() { 431 this.stopGuaranteeing(); 432 this.retrySubscribing(); 433 } 434 stopGuaranteeing() { 435 clearTimeout(this.retryTimeout); 436 } 437 retrySubscribing() { 438 this.retryTimeout = setTimeout( 439 () => { 440 if (this.subscriptions && typeof this.subscriptions.subscribe === "function") { 441 this.pendingSubscriptions.map((subscription) => { 442 logger_default.log(`SubscriptionGuarantor resubscribing ${subscription.identifier}`); 443 this.subscriptions.subscribe(subscription); 444 }); 445 } 446 }, 447 500 448 ); 449 } 450 }; 451 subscription_guarantor_default = SubscriptionGuarantor; 452 } 453}); 454
vendor: 2,968 bytes, lines 455-535
455// node_modules/@rails/actioncable/src/subscriptions.js 456var Subscriptions; 457var init_subscriptions = __esm({ 458 "node_modules/@rails/actioncable/src/subscriptions.js"() { 459 init_subscription(); 460 init_subscription_guarantor(); 461 init_logger(); 462 Subscriptions = class { 463 constructor(consumer2) { 464 this.consumer = consumer2; 465 this.guarantor = new subscription_guarantor_default(this); 466 this.subscriptions = []; 467 } 468 create(channelName, mixin) { 469 const channel = channelName; 470 const params = typeof channel === "object" ? channel : { channel }; 471 const subscription = new Subscription(this.consumer, params, mixin); 472 return this.add(subscription); 473 } 474 // Private 475 add(subscription) { 476 this.subscriptions.push(subscription); 477 this.consumer.ensureActiveConnection(); 478 this.notify(subscription, "initialized"); 479 this.subscribe(subscription); 480 return subscription; 481 } 482 remove(subscription) { 483 this.forget(subscription); 484 if (!this.findAll(subscription.identifier).length) { 485 this.sendCommand(subscription, "unsubscribe"); 486 } 487 return subscription; 488 } 489 reject(identifier) { 490 return this.findAll(identifier).map((subscription) => { 491 this.forget(subscription); 492 this.notify(subscription, "rejected"); 493 return subscription; 494 }); 495 } 496 forget(subscription) { 497 this.guarantor.forget(subscription); 498 this.subscriptions = this.subscriptions.filter((s) => s !== subscription); 499 return subscription; 500 } 501 findAll(identifier) { 502 return this.subscriptions.filter((s) => s.identifier === identifier); 503 } 504 reload() { 505 return this.subscriptions.map((subscription) => this.subscribe(subscription)); 506 } 507 notifyAll(callbackName, ...args) { 508 return this.subscriptions.map((subscription) => this.notify(subscription, callbackName, ...args)); 509 } 510 notify(subscription, callbackName, ...args) { 511 let subscriptions; 512 if (typeof subscription === "string") { 513 subscriptions = this.findAll(subscription); 514 } else { 515 subscriptions = [subscription]; 516 } 517 return subscriptions.map((subscription2) => typeof subscription2[callbackName] === "function" ? subscription2[callbackName](...args) : void 0); 518 } 519 subscribe(subscription) { 520 if (this.sendCommand(subscription, "subscribe")) { 521 this.guarantor.guarantee(subscription); 522 } 523 } 524 confirmSubscription(identifier) { 525 logger_default.log(`Subscription confirmed ${identifier}`); 526 this.findAll(identifier).map((subscription) => this.guarantor.forget(subscription)); 527 } 528 sendCommand(subscription, command) { 529 const { identifier } = subscription; 530 return this.consumer.send({ command, identifier }); 531 } 532 }; 533 } 534}); 535
vendor: 1,295 bytes, lines 536-586
536// node_modules/@rails/actioncable/src/consumer.js 537function createWebSocketURL(url) { 538 if (typeof url === "function") { 539 url = url(); 540 } 541 if (url && !/^wss?:/i.test(url)) { 542 const a = document.createElement("a"); 543 a.href = url; 544 a.href = a.href; 545 a.protocol = a.protocol.replace("http", "ws"); 546 return a.href; 547 } else { 548 return url; 549 } 550} 551var Consumer; 552var init_consumer = __esm({ 553 "node_modules/@rails/actioncable/src/consumer.js"() { 554 init_connection(); 555 init_subscriptions(); 556 Consumer = class { 557 constructor(url) { 558 this._url = url; 559 this.subscriptions = new Subscriptions(this); 560 this.connection = new connection_default(this); 561 this.subprotocols = []; 562 } 563 get url() { 564 return createWebSocketURL(this._url); 565 } 566 send(data) { 567 return this.connection.send(data); 568 } 569 connect() { 570 return this.connection.open(); 571 } 572 disconnect() { 573 return this.connection.close({ allowReconnect: false }); 574 } 575 ensureActiveConnection() { 576 if (!this.connection.isActive()) { 577 return this.connection.open(); 578 } 579 } 580 addSubProtocol(subprotocol) { 581 this.subprotocols = [...this.subprotocols, subprotocol]; 582 } 583 }; 584 } 585}); 586
vendor: 1,183 bytes, lines 587-625
587// node_modules/@rails/actioncable/src/index.js 588var src_exports = {}; 589__export(src_exports, { 590 Connection: () => connection_default, 591 ConnectionMonitor: () => connection_monitor_default, 592 Consumer: () => Consumer, 593 INTERNAL: () => internal_default, 594 Subscription: () => Subscription, 595 SubscriptionGuarantor: () => subscription_guarantor_default, 596 Subscriptions: () => Subscriptions, 597 adapters: () => adapters_default, 598 createConsumer: () => createConsumer, 599 createWebSocketURL: () => createWebSocketURL, 600 getConfig: () => getConfig, 601 logger: () => logger_default 602}); 603function createConsumer(url = getConfig("url") || internal_default.default_mount_path) { 604 return new Consumer(url); 605} 606function getConfig(name) { 607 const element = document.head.querySelector(`meta[name='action-cable-${name}']`); 608 if (element) { 609 return element.getAttribute("content"); 610 } 611} 612var init_src = __esm({ 613 "node_modules/@rails/actioncable/src/index.js"() { 614 init_connection(); 615 init_connection_monitor(); 616 init_consumer(); 617 init_internal(); 618 init_subscription(); 619 init_subscriptions(); 620 init_subscription_guarantor(); 621 init_adapters(); 622 init_logger(); 623 } 624}); 625
vendor: 3,699 bytes, lines 626-722
626// node_modules/fetch-jsonp/build/fetch-jsonp.js 627var require_fetch_jsonp = __commonJS({ 628 "node_modules/fetch-jsonp/build/fetch-jsonp.js"(exports, module) { 629 (function(global, factory) { 630 if (typeof define === "function" && define.amd) { 631 define(["exports", "module"], factory); 632 } else if (typeof exports !== "undefined" && typeof module !== "undefined") { 633 factory(exports, module); 634 } else { 635 var mod = { 636 exports: {} 637 }; 638 factory(mod.exports, mod); 639 global.fetchJsonp = mod.exports; 640 } 641 })(exports, function(exports2, module2) { 642 "use strict"; 643 var defaultOptions2 = { 644 timeout: 5e3, 645 jsonpCallback: "callback", 646 jsonpCallbackFunction: null 647 }; 648 function generateCallbackFunction() { 649 return "jsonp_" + Date.now() + "_" + Math.ceil(Math.random() * 1e5); 650 } 651 function clearFunction(functionName) { 652 try { 653 delete window[functionName]; 654 } catch (e) { 655 window[functionName] = void 0; 656 } 657 } 658 function removeScript(scriptId) { 659 var script = document.getElementById(scriptId); 660 if (script) { 661 document.getElementsByTagName("head")[0].removeChild(script); 662 } 663 } 664 function fetchJsonp2(_url) { 665 var options = arguments.length <= 1 || arguments[1] === void 0 ? {} : arguments[1]; 666 var url = _url; 667 var timeout = options.timeout || defaultOptions2.timeout; 668 var jsonpCallback = options.jsonpCallback || defaultOptions2.jsonpCallback; 669 var timeoutId = void 0; 670 return new Promise(function(resolve, reject) { 671 var callbackFunction = options.jsonpCallbackFunction || generateCallbackFunction(); 672 var scriptId = jsonpCallback + "_" + callbackFunction; 673 window[callbackFunction] = function(response) { 674 resolve({ 675 ok: true, 676 // keep consistent with fetch API 677 json: function json() { 678 return Promise.resolve(response); 679 } 680 }); 681 if (timeoutId) clearTimeout(timeoutId); 682 removeScript(scriptId); 683 clearFunction(callbackFunction); 684 }; 685 url += url.indexOf("?") === -1 ? "?" : "&"; 686 var jsonpScript = document.createElement("script"); 687 jsonpScript.setAttribute("src", "" + url + jsonpCallback + "=" + callbackFunction); 688 if (options.charset) { 689 jsonpScript.setAttribute("charset", options.charset); 690 } 691 if (options.nonce) { 692 jsonpScript.setAttribute("nonce", options.nonce); 693 } 694 if (options.referrerPolicy) { 695 jsonpScript.setAttribute("referrerPolicy", options.referrerPolicy); 696 } 697 if (options.crossorigin) { 698 jsonpScript.setAttribute("crossorigin", "true"); 699 } 700 jsonpScript.id = scriptId; 701 document.getElementsByTagName("head")[0].appendChild(jsonpScript); 702 timeoutId = setTimeout(function() { 703 reject(new Error("JSONP request to " + _url + " timed out")); 704 clearFunction(callbackFunction); 705 removeScript(scriptId); 706 window[callbackFunction] = function() { 707 clearFunction(callbackFunction); 708 }; 709 }, timeout); 710 jsonpScript.onerror = function() { 711 reject(new Error("JSONP request to " + _url + " failed")); 712 clearFunction(callbackFunction); 713 removeScript(scriptId); 714 if (timeoutId) clearTimeout(timeoutId); 715 }; 716 }); 717 } 718 module2.exports = fetchJsonp2; 719 }); 720 } 721}); 722
vendor: 37,450 bytes, lines 723-1647
723// node_modules/pikaday/pikaday.js 724var require_pikaday = __commonJS({ 725 "node_modules/pikaday/pikaday.js"(exports, module) { 726 (function(root, factory) { 727 "use strict"; 728 var moment; 729 if (typeof exports === "object") { 730 try { 731 moment = __require("moment"); 732 } catch (e) { 733 } 734 module.exports = factory(moment); 735 } else if (typeof define === "function" && define.amd) { 736 define(function(req) { 737 var id = "moment"; 738 try { 739 moment = req(id); 740 } catch (e) { 741 } 742 return factory(moment); 743 }); 744 } else { 745 root.Pikaday = factory(root.moment); 746 } 747 })(exports, function(moment) { 748 "use strict"; 749 var hasMoment = typeof moment === "function", hasEventListeners = !!window.addEventListener, document2 = window.document, sto = window.setTimeout, addEvent = function(el, e, callback, capture) { 750 if (hasEventListeners) { 751 el.addEventListener(e, callback, !!capture); 752 } else { 753 el.attachEvent("on" + e, callback); 754 } 755 }, removeEvent = function(el, e, callback, capture) { 756 if (hasEventListeners) { 757 el.removeEventListener(e, callback, !!capture); 758 } else { 759 el.detachEvent("on" + e, callback); 760 } 761 }, trim = function(str) { 762 return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, ""); 763 }, hasClass = function(el, cn) { 764 return (" " + el.className + " ").indexOf(" " + cn + " ") !== -1; 765 }, addClass = function(el, cn) { 766 if (!hasClass(el, cn)) { 767 el.className = el.className === "" ? cn : el.className + " " + cn; 768 } 769 }, removeClass = function(el, cn) { 770 el.className = trim((" " + el.className + " ").replace(" " + cn + " ", " ")); 771 }, isArray = function(obj) { 772 return /Array/.test(Object.prototype.toString.call(obj)); 773 }, isDate = function(obj) { 774 return /Date/.test(Object.prototype.toString.call(obj)) && !isNaN(obj.getTime()); 775 }, isWeekend = function(date) { 776 var day = date.getDay(); 777 return day === 0 || day === 6; 778 }, isLeapYear = function(year) { 779 return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0; 780 }, getDaysInMonth = function(year, month) { 781 return [31, isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]; 782 }, setToStartOfDay = function(date) { 783 if (isDate(date)) date.setHours(0, 0, 0, 0); 784 }, compareDates = function(a, b) { 785 return a.getTime() === b.getTime(); 786 }, extend3 = function(to, from, overwrite) { 787 var prop, hasProp; 788 for (prop in from) { 789 hasProp = to[prop] !== void 0; 790 if (hasProp && typeof from[prop] === "object" && from[prop] !== null && from[prop].nodeName === void 0) { 791 if (isDate(from[prop])) { 792 if (overwrite) { 793 to[prop] = new Date(from[prop].getTime()); 794 } 795 } else if (isArray(from[prop])) { 796 if (overwrite) { 797 to[prop] = from[prop].slice(0); 798 } 799 } else { 800 to[prop] = extend3({}, from[prop], overwrite); 801 } 802 } else if (overwrite || !hasProp) { 803 to[prop] = from[prop]; 804 } 805 } 806 return to; 807 }, fireEvent = function(el, eventName, data) { 808 var ev; 809 if (document2.createEvent) { 810 ev = document2.createEvent("HTMLEvents"); 811 ev.initEvent(eventName, true, false); 812 ev = extend3(ev, data); 813 el.dispatchEvent(ev); 814 } else if (document2.createEventObject) { 815 ev = document2.createEventObject(); 816 ev = extend3(ev, data); 817 el.fireEvent("on" + eventName, ev); 818 } 819 }, adjustCalendar = function(calendar) { 820 if (calendar.month < 0) { 821 calendar.year -= Math.ceil(Math.abs(calendar.month) / 12); 822 calendar.month += 12; 823 } 824 if (calendar.month > 11) { 825 calendar.year += Math.floor(Math.abs(calendar.month) / 12); 826 calendar.month -= 12; 827 } 828 return calendar; 829 }, defaults = { 830 // bind the picker to a form field 831 field: null, 832 // automatically show/hide the picker on `field` focus (default `true` if `field` is set) 833 bound: void 0, 834 // data-attribute on the input field with an aria assistance text (only applied when `bound` is set) 835 ariaLabel: "Use the arrow keys to pick a date", 836 // position of the datepicker, relative to the field (default to bottom & left) 837 // ('bottom' & 'left' keywords are not used, 'top' & 'right' are modifier on the bottom/left position) 838 position: "bottom left", 839 // automatically fit in the viewport even if it means repositioning from the position option 840 reposition: true, 841 // the default output format for `.toString()` and `field` value 842 format: "YYYY-MM-DD", 843 // the toString function which gets passed a current date object and format 844 // and returns a string 845 toString: null, 846 // used to create date object from current input string 847 parse: null, 848 // the initial date to view when first opened 849 defaultDate: null, 850 // make the `defaultDate` the initial selected value 851 setDefaultDate: false, 852 // first day of week (0: Sunday, 1: Monday etc) 853 firstDay: 0, 854 // minimum number of days in the week that gets week number one 855 // default ISO 8601, week 01 is the week with the first Thursday (4) 856 firstWeekOfYearMinDays: 4, 857 // the default flag for moment's strict date parsing 858 formatStrict: false, 859 // the minimum/earliest date that can be selected 860 minDate: null, 861 // the maximum/latest date that can be selected 862 maxDate: null, 863 // number of years either side, or array of upper/lower range 864 yearRange: 10, 865 // show week numbers at head of row 866 showWeekNumber: false, 867 // Week picker mode 868 pickWholeWeek: false, 869 // used internally (don't config outside) 870 minYear: 0, 871 maxYear: 9999, 872 minMonth: void 0, 873 maxMonth: void 0, 874 startRange: null, 875 endRange: null, 876 isRTL: false, 877 // Additional text to append to the year in the calendar title 878 yearSuffix: "", 879 // Render the month after year in the calendar title 880 showMonthAfterYear: false, 881 // Render days of the calendar grid that fall in the next or previous month 882 showDaysInNextAndPreviousMonths: false, 883 // Allows user to select days that fall in the next or previous month 884 enableSelectionDaysInNextAndPreviousMonths: false, 885 // how many months are visible 886 numberOfMonths: 1, 887 // when numberOfMonths is used, this will help you to choose where the main calendar will be (default `left`, can be set to `right`) 888 // only used for the first display or when a selected date is not visible 889 mainCalendar: "left", 890 // Specify a DOM element to render the calendar in 891 container: void 0, 892 // Blur field when date is selected 893 blurFieldOnSelect: true, 894 // internationalization 895 i18n: { 896 previousMonth: "Previous Month", 897 nextMonth: "Next Month", 898 months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], 899 weekdays: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], 900 weekdaysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"] 901 }, 902 // Theme Classname 903 theme: null, 904 // events array 905 events: [], 906 // callback function 907 onSelect: null, 908 onOpen: null, 909 onClose: null, 910 onDraw: null, 911 // Enable keyboard input 912 keyboardInput: true 913 }, renderDayName = function(opts, day, abbr) { 914 day += opts.firstDay; 915 while (day >= 7) { 916 day -= 7; 917 } 918 return abbr ? opts.i18n.weekdaysShort[day] : opts.i18n.weekdays[day]; 919 }, renderDay = function(opts) { 920 var arr = []; 921 var ariaSelected = "false"; 922 if (opts.isEmpty) { 923 if (opts.showDaysInNextAndPreviousMonths) { 924 arr.push("is-outside-current-month"); 925 if (!opts.enableSelectionDaysInNextAndPreviousMonths) { 926 arr.push("is-selection-disabled"); 927 } 928 } else { 929 return '<td class="is-empty"></td>'; 930 } 931 } 932 if (opts.isDisabled) { 933 arr.push("is-disabled"); 934 } 935 if (opts.isToday) { 936 arr.push("is-today"); 937 } 938 if (opts.isSelected) { 939 arr.push("is-selected"); 940 ariaSelected = "true"; 941 } 942 if (opts.hasEvent) { 943 arr.push("has-event"); 944 } 945 if (opts.isInRange) { 946 arr.push("is-inrange"); 947 } 948 if (opts.isStartRange) { 949 arr.push("is-startrange"); 950 } 951 if (opts.isEndRange) { 952 arr.push("is-endrange"); 953 } 954 return '<td data-day="' + opts.day + '" class="' + arr.join(" ") + '" aria-selected="' + ariaSelected + '"><button class="pika-button pika-day" type="button" data-pika-year="' + opts.year + '" data-pika-month="' + opts.month + '" data-pika-day="' + opts.day + '">' + opts.day + "</button></td>"; 955 }, isoWeek = function(date, firstWeekOfYearMinDays) { 956 date.setHours(0, 0, 0, 0); 957 var yearDay = date.getDate(), weekDay = date.getDay(), dayInFirstWeek = firstWeekOfYearMinDays, dayShift = dayInFirstWeek - 1, daysPerWeek = 7, prevWeekDay = function(day) { 958 return (day + daysPerWeek - 1) % daysPerWeek; 959 }; 960 date.setDate(yearDay + dayShift - prevWeekDay(weekDay)); 961 var jan4th = new Date(date.getFullYear(), 0, dayInFirstWeek), msPerDay = 24 * 60 * 60 * 1e3, daysBetween = (date.getTime() - jan4th.getTime()) / msPerDay, weekNum = 1 + Math.round((daysBetween - dayShift + prevWeekDay(jan4th.getDay())) / daysPerWeek); 962 return weekNum; 963 }, renderWeek = function(d, m, y, firstWeekOfYearMinDays) { 964 var date = new Date(y, m, d), week = hasMoment ? moment(date).isoWeek() : isoWeek(date, firstWeekOfYearMinDays); 965 return '<td class="pika-week">' + week + "</td>"; 966 }, renderRow = function(days, isRTL, pickWholeWeek, isRowSelected) { 967 return '<tr class="pika-row' + (pickWholeWeek ? " pick-whole-week" : "") + (isRowSelected ? " is-selected" : "") + '">' + (isRTL ? days.reverse() : days).join("") + "</tr>"; 968 }, renderBody = function(rows) { 969 return "<tbody>" + rows.join("") + "</tbody>"; 970 }, renderHead = function(opts) { 971 var i, arr = []; 972 if (opts.showWeekNumber) { 973 arr.push("<th></th>"); 974 } 975 for (i = 0; i < 7; i++) { 976 arr.push('<th scope="col"><abbr title="' + renderDayName(opts, i) + '">' + renderDayName(opts, i, true) + "</abbr></th>"); 977 } 978 return "<thead><tr>" + (opts.isRTL ? arr.reverse() : arr).join("") + "</tr></thead>"; 979 }, renderTitle = function(instance, c, year, month, refYear, randId) { 980 var i, j, arr, opts = instance._o, isMinYear = year === opts.minYear, isMaxYear = year === opts.maxYear, html = '<div id="' + randId + '" class="pika-title" role="heading" aria-live="assertive">', monthHtml, yearHtml, prev = true, next = true; 981 for (arr = [], i = 0; i < 12; i++) { 982 arr.push('<option value="' + (year === refYear ? i - c : 12 + i - c) + '"' + (i === month ? ' selected="selected"' : "") + (isMinYear && i < opts.minMonth || isMaxYear && i > opts.maxMonth ? ' disabled="disabled"' : "") + ">" + opts.i18n.months[i] + "</option>"); 983 } 984 monthHtml = '<div class="pika-label">' + opts.i18n.months[month] + '<select class="pika-select pika-select-month" tabindex="-1">' + arr.join("") + "</select></div>"; 985 if (isArray(opts.yearRange)) { 986 i = opts.yearRange[0]; 987 j = opts.yearRange[1] + 1; 988 } else { 989 i = year - opts.yearRange; 990 j = 1 + year + opts.yearRange; 991 } 992 for (arr = []; i < j && i <= opts.maxYear; i++) { 993 if (i >= opts.minYear) { 994 arr.push('<option value="' + i + '"' + (i === year ? ' selected="selected"' : "") + ">" + i + "</option>"); 995 } 996 } 997 yearHtml = '<div class="pika-label">' + year + opts.yearSuffix + '<select class="pika-select pika-select-year" tabindex="-1">' + arr.join("") + "</select></div>"; 998 if (opts.showMonthAfterYear) { 999 html += yearHtml + monthHtml; 1000 } else { 1001 html += monthHtml + yearHtml; 1002 } 1003 if (isMinYear && (month === 0 || opts.minMonth >= month)) { 1004 prev = false; 1005 } 1006 if (isMaxYear && (month === 11 || opts.maxMonth <= month)) { 1007 next = false; 1008 } 1009 if (c === 0) { 1010 html += '<button class="pika-prev' + (prev ? "" : " is-disabled") + '" type="button">' + opts.i18n.previousMonth + "</button>"; 1011 } 1012 if (c === instance._o.numberOfMonths - 1) { 1013 html += '<button class="pika-next' + (next ? "" : " is-disabled") + '" type="button">' + opts.i18n.nextMonth + "</button>"; 1014 } 1015 return html += "</div>"; 1016 }, renderTable = function(opts, data, randId) { 1017 return '<table cellpadding="0" cellspacing="0" class="pika-table" role="grid" aria-labelledby="' + randId + '">' + renderHead(opts) + renderBody(data) + "</table>"; 1018 }, Pikaday2 = function(options) { 1019 var self = this, opts = self.config(options); 1020 self._onMouseDown = function(e) { 1021 if (!self._v) { 1022 return; 1023 } 1024 e = e || window.event; 1025 var target = e.target || e.srcElement; 1026 if (!target) { 1027 return; 1028 } 1029 if (!hasClass(target, "is-disabled")) { 1030 if (hasClass(target, "pika-button") && !hasClass(target, "is-empty") && !hasClass(target.parentNode, "is-disabled")) { 1031 self.setDate(new Date(target.getAttribute("data-pika-year"), target.getAttribute("data-pika-month"), target.getAttribute("data-pika-day"))); 1032 if (opts.bound) { 1033 sto(function() { 1034 self.hide(); 1035 if (opts.blurFieldOnSelect && opts.field) { 1036 opts.field.blur(); 1037 } 1038 }, 100); 1039 } 1040 } else if (hasClass(target, "pika-prev")) { 1041 self.prevMonth(); 1042 } else if (hasClass(target, "pika-next")) { 1043 self.nextMonth(); 1044 } 1045 } 1046 if (!hasClass(target, "pika-select")) { 1047 if (e.preventDefault) { 1048 e.preventDefault(); 1049 } else { 1050 e.returnValue = false; 1051 return false; 1052 } 1053 } else { 1054 self._c = true; 1055 } 1056 }; 1057 self._onChange = function(e) { 1058 e = e || window.event; 1059 var target = e.target || e.srcElement; 1060 if (!target) { 1061 return; 1062 } 1063 if (hasClass(target, "pika-select-month")) { 1064 self.gotoMonth(target.value); 1065 } else if (hasClass(target, "pika-select-year")) { 1066 self.gotoYear(target.value); 1067 } 1068 }; 1069 self._onKeyChange = function(e) { 1070 e = e || window.event; 1071 if (self.isVisible()) { 1072 switch (e.keyCode) { 1073 case 13: 1074 case 27: 1075 if (opts.field) { 1076 opts.field.blur(); 1077 } 1078 break; 1079 case 37: 1080 self.adjustDate("subtract", 1); 1081 break; 1082 case 38: 1083 self.adjustDate("subtract", 7); 1084 break; 1085 case 39: 1086 self.adjustDate("add", 1); 1087 break; 1088 case 40: 1089 self.adjustDate("add", 7); 1090 break; 1091 case 8: 1092 case 46: 1093 self.setDate(null); 1094 break; 1095 } 1096 } 1097 }; 1098 self._parseFieldValue = function() { 1099 if (opts.parse) { 1100 return opts.parse(opts.field.value, opts.format); 1101 } else if (hasMoment) { 1102 var date = moment(opts.field.value, opts.format, opts.formatStrict); 1103 return date && date.isValid() ? date.toDate() : null; 1104 } else { 1105 return new Date(Date.parse(opts.field.value)); 1106 } 1107 }; 1108 self._onInputChange = function(e) { 1109 var date; 1110 if (e.firedBy === self) { 1111 return; 1112 } 1113 date = self._parseFieldValue(); 1114 if (isDate(date)) { 1115 self.setDate(date); 1116 } 1117 if (!self._v) { 1118 self.show(); 1119 } 1120 }; 1121 self._onInputFocus = function() { 1122 self.show(); 1123 }; 1124 self._onInputClick = function() { 1125 self.show(); 1126 }; 1127 self._onInputBlur = function() { 1128 var pEl = document2.activeElement; 1129 do { 1130 if (hasClass(pEl, "pika-single")) { 1131 return; 1132 } 1133 } while (pEl = pEl.parentNode); 1134 if (!self._c) { 1135 self._b = sto(function() { 1136 self.hide(); 1137 }, 50); 1138 } 1139 self._c = false; 1140 }; 1141 self._onClick = function(e) { 1142 e = e || window.event; 1143 var target = e.target || e.srcElement, pEl = target; 1144 if (!target) { 1145 return; 1146 } 1147 if (!hasEventListeners && hasClass(target, "pika-select")) { 1148 if (!target.onchange) { 1149 target.setAttribute("onchange", "return;"); 1150 addEvent(target, "change", self._onChange); 1151 } 1152 } 1153 do { 1154 if (hasClass(pEl, "pika-single") || pEl === opts.trigger) { 1155 return; 1156 } 1157 } while (pEl = pEl.parentNode); 1158 if (self._v && target !== opts.trigger && pEl !== opts.trigger) { 1159 self.hide(); 1160 } 1161 }; 1162 self.el = document2.createElement("div"); 1163 self.el.className = "pika-single" + (opts.isRTL ? " is-rtl" : "") + (opts.theme ? " " + opts.theme : ""); 1164 addEvent(self.el, "mousedown", self._onMouseDown, true); 1165 addEvent(self.el, "touchend", self._onMouseDown, true); 1166 addEvent(self.el, "change", self._onChange); 1167 if (opts.keyboardInput) { 1168 addEvent(document2, "keydown", self._onKeyChange); 1169 } 1170 if (opts.field) { 1171 if (opts.container) { 1172 opts.container.appendChild(self.el); 1173 } else if (opts.bound) { 1174 document2.body.appendChild(self.el); 1175 } else { 1176 opts.field.parentNode.insertBefore(self.el, opts.field.nextSibling); 1177 } 1178 addEvent(opts.field, "change", self._onInputChange); 1179 if (!opts.defaultDate) { 1180 opts.defaultDate = self._parseFieldValue(); 1181 opts.setDefaultDate = true; 1182 } 1183 } 1184 var defDate = opts.defaultDate; 1185 if (isDate(defDate)) { 1186 if (opts.setDefaultDate) { 1187 self.setDate(defDate, true); 1188 } else { 1189 self.gotoDate(defDate); 1190 } 1191 } else { 1192 self.gotoDate(/* @__PURE__ */ new Date()); 1193 } 1194 if (opts.bound) { 1195 this.hide(); 1196 self.el.className += " is-bound"; 1197 addEvent(opts.trigger, "click", self._onInputClick); 1198 addEvent(opts.trigger, "focus", self._onInputFocus); 1199 addEvent(opts.trigger, "blur", self._onInputBlur); 1200 } else { 1201 this.show(); 1202 } 1203 }; 1204 Pikaday2.prototype = { 1205 /** 1206 * configure functionality 1207 */ 1208 config: function(options) { 1209 if (!this._o) { 1210 this._o = extend3({}, defaults, true); 1211 } 1212 var opts = extend3(this._o, options, true); 1213 opts.isRTL = !!opts.isRTL; 1214 opts.field = opts.field && opts.field.nodeName ? opts.field : null; 1215 opts.theme = typeof opts.theme === "string" && opts.theme ? opts.theme : null; 1216 opts.bound = !!(opts.bound !== void 0 ? opts.field && opts.bound : opts.field); 1217 opts.trigger = opts.trigger && opts.trigger.nodeName ? opts.trigger : opts.field; 1218 opts.disableWeekends = !!opts.disableWeekends; 1219 opts.disableDayFn = typeof opts.disableDayFn === "function" ? opts.disableDayFn : null; 1220 var nom = parseInt(opts.numberOfMonths, 10) || 1; 1221 opts.numberOfMonths = nom > 4 ? 4 : nom; 1222 if (!isDate(opts.minDate)) { 1223 opts.minDate = false; 1224 } 1225 if (!isDate(opts.maxDate)) { 1226 opts.maxDate = false; 1227 } 1228 if (opts.minDate && opts.maxDate && opts.maxDate < opts.minDate) { 1229 opts.maxDate = opts.minDate = false; 1230 } 1231 if (opts.minDate) { 1232 this.setMinDate(opts.minDate); 1233 } 1234 if (opts.maxDate) { 1235 this.setMaxDate(opts.maxDate); 1236 } 1237 if (isArray(opts.yearRange)) { 1238 var fallback = (/* @__PURE__ */ new Date()).getFullYear() - 10; 1239 opts.yearRange[0] = parseInt(opts.yearRange[0], 10) || fallback; 1240 opts.yearRange[1] = parseInt(opts.yearRange[1], 10) || fallback; 1241 } else { 1242 opts.yearRange = Math.abs(parseInt(opts.yearRange, 10)) || defaults.yearRange; 1243 if (opts.yearRange > 100) { 1244 opts.yearRange = 100; 1245 } 1246 } 1247 return opts; 1248 }, 1249 /** 1250 * return a formatted string of the current selection (using Moment.js if available) 1251 */ 1252 toString: function(format) { 1253 format = format || this._o.format; 1254 if (!isDate(this._d)) { 1255 return ""; 1256 } 1257 if (this._o.toString) { 1258 return this._o.toString(this._d, format); 1259 } 1260 if (hasMoment) { 1261 return moment(this._d).format(format); 1262 } 1263 return this._d.toDateString(); 1264 }, 1265 /** 1266 * return a Moment.js object of the current selection (if available) 1267 */ 1268 getMoment: function() { 1269 return hasMoment ? moment(this._d) : null; 1270 }, 1271 /** 1272 * set the current selection from a Moment.js object (if available) 1273 */ 1274 setMoment: function(date, preventOnSelect) { 1275 if (hasMoment && moment.isMoment(date)) { 1276 this.setDate(date.toDate(), preventOnSelect); 1277 } 1278 }, 1279 /** 1280 * return a Date object of the current selection 1281 */ 1282 getDate: function() { 1283 return isDate(this._d) ? new Date(this._d.getTime()) : null; 1284 }, 1285 /** 1286 * set the current selection 1287 */ 1288 setDate: function(date, preventOnSelect) { 1289 if (!date) { 1290 this._d = null; 1291 if (this._o.field) { 1292 this._o.field.value = ""; 1293 fireEvent(this._o.field, "change", { firedBy: this }); 1294 } 1295 return this.draw(); 1296 } 1297 if (typeof date === "string") { 1298 date = new Date(Date.parse(date)); 1299 } 1300 if (!isDate(date)) { 1301 return; 1302 } 1303 var min = this._o.minDate, max = this._o.maxDate; 1304 if (isDate(min) && date < min) { 1305 date = min; 1306 } else if (isDate(max) && date > max) { 1307 date = max; 1308 } 1309 this._d = new Date(date.getTime()); 1310 setToStartOfDay(this._d); 1311 this.gotoDate(this._d); 1312 if (this._o.field) { 1313 this._o.field.value = this.toString(); 1314 fireEvent(this._o.field, "change", { firedBy: this }); 1315 } 1316 if (!preventOnSelect && typeof this._o.onSelect === "function") { 1317 this._o.onSelect.call(this, this.getDate()); 1318 } 1319 }, 1320 /** 1321 * clear and reset the date 1322 */ 1323 clear: function() { 1324 this.setDate(null); 1325 }, 1326 /** 1327 * change view to a specific date 1328 */ 1329 gotoDate: function(date) { 1330 var newCalendar = true; 1331 if (!isDate(date)) { 1332 return; 1333 } 1334 if (this.calendars) { 1335 var firstVisibleDate = new Date(this.calendars[0].year, this.calendars[0].month, 1), lastVisibleDate = new Date(this.calendars[this.calendars.length - 1].year, this.calendars[this.calendars.length - 1].month, 1), visibleDate = date.getTime(); 1336 lastVisibleDate.setMonth(lastVisibleDate.getMonth() + 1); 1337 lastVisibleDate.setDate(lastVisibleDate.getDate() - 1); 1338 newCalendar = visibleDate < firstVisibleDate.getTime() || lastVisibleDate.getTime() < visibleDate; 1339 } 1340 if (newCalendar) { 1341 this.calendars = [{ 1342 month: date.getMonth(), 1343 year: date.getFullYear() 1344 }]; 1345 if (this._o.mainCalendar === "right") { 1346 this.calendars[0].month += 1 - this._o.numberOfMonths; 1347 } 1348 } 1349 this.adjustCalendars(); 1350 }, 1351 adjustDate: function(sign, days) { 1352 var day = this.getDate() || /* @__PURE__ */ new Date(); 1353 var difference = parseInt(days) * 24 * 60 * 60 * 1e3; 1354 var newDay; 1355 if (sign === "add") { 1356 newDay = new Date(day.valueOf() + difference); 1357 } else if (sign === "subtract") { 1358 newDay = new Date(day.valueOf() - difference); 1359 } 1360 this.setDate(newDay); 1361 }, 1362 adjustCalendars: function() { 1363 this.calendars[0] = adjustCalendar(this.calendars[0]); 1364 for (var c = 1; c < this._o.numberOfMonths; c++) { 1365 this.calendars[c] = adjustCalendar({ 1366 month: this.calendars[0].month + c, 1367 year: this.calendars[0].year 1368 }); 1369 } 1370 this.draw(); 1371 }, 1372 gotoToday: function() { 1373 this.gotoDate(/* @__PURE__ */ new Date()); 1374 }, 1375 /** 1376 * change view to a specific month (zero-index, e.g. 0: January) 1377 */ 1378 gotoMonth: function(month) { 1379 if (!isNaN(month)) { 1380 this.calendars[0].month = parseInt(month, 10); 1381 this.adjustCalendars(); 1382 } 1383 }, 1384 nextMonth: function() { 1385 this.calendars[0].month++; 1386 this.adjustCalendars(); 1387 }, 1388 prevMonth: function() { 1389 this.calendars[0].month--; 1390 this.adjustCalendars(); 1391 }, 1392 /** 1393 * change view to a specific full year (e.g. "2012") 1394 */ 1395 gotoYear: function(year) { 1396 if (!isNaN(year)) { 1397 this.calendars[0].year = parseInt(year, 10); 1398 this.adjustCalendars(); 1399 } 1400 }, 1401 /** 1402 * change the minDate 1403 */ 1404 setMinDate: function(value) { 1405 if (value instanceof Date) { 1406 setToStartOfDay(value); 1407 this._o.minDate = value; 1408 this._o.minYear = value.getFullYear(); 1409 this._o.minMonth = value.getMonth(); 1410 } else { 1411 this._o.minDate = defaults.minDate; 1412 this._o.minYear = defaults.minYear; 1413 this._o.minMonth = defaults.minMonth; 1414 this._o.startRange = defaults.startRange; 1415 } 1416 this.draw(); 1417 }, 1418 /** 1419 * change the maxDate 1420 */ 1421 setMaxDate: function(value) { 1422 if (value instanceof Date) { 1423 setToStartOfDay(value); 1424 this._o.maxDate = value; 1425 this._o.maxYear = value.getFullYear(); 1426 this._o.maxMonth = value.getMonth(); 1427 } else { 1428 this._o.maxDate = defaults.maxDate; 1429 this._o.maxYear = defaults.maxYear; 1430 this._o.maxMonth = defaults.maxMonth; 1431 this._o.endRange = defaults.endRange; 1432 } 1433 this.draw(); 1434 }, 1435 setStartRange: function(value) { 1436 this._o.startRange = value; 1437 }, 1438 setEndRange: function(value) { 1439 this._o.endRange = value; 1440 }, 1441 /** 1442 * refresh the HTML 1443 */ 1444 draw: function(force) { 1445 if (!this._v && !force) { 1446 return; 1447 } 1448 var opts = this._o, minYear = opts.minYear, maxYear = opts.maxYear, minMonth = opts.minMonth, maxMonth = opts.maxMonth, html = "", randId; 1449 if (this._y <= minYear) { 1450 this._y = minYear; 1451 if (!isNaN(minMonth) && this._m < minMonth) { 1452 this._m = minMonth; 1453 } 1454 } 1455 if (this._y >= maxYear) { 1456 this._y = maxYear; 1457 if (!isNaN(maxMonth) && this._m > maxMonth) { 1458 this._m = maxMonth; 1459 } 1460 } 1461 for (var c = 0; c < opts.numberOfMonths; c++) { 1462 randId = "pika-title-" + Math.random().toString(36).replace(/[^a-z]+/g, "").substr(0, 2); 1463 html += '<div class="pika-lendar">' + renderTitle(this, c, this.calendars[c].year, this.calendars[c].month, this.calendars[0].year, randId) + this.render(this.calendars[c].year, this.calendars[c].month, randId) + "</div>"; 1464 } 1465 this.el.innerHTML = html; 1466 if (opts.bound) { 1467 if (opts.field.type !== "hidden") { 1468 sto(function() { 1469 opts.trigger.focus(); 1470 }, 1); 1471 } 1472 } 1473 if (typeof this._o.onDraw === "function") { 1474 this._o.onDraw(this); 1475 } 1476 if (opts.bound) { 1477 opts.field.setAttribute("aria-label", opts.ariaLabel); 1478 } 1479 }, 1480 adjustPosition: function() { 1481 var field, pEl, width, height, viewportWidth, viewportHeight, scrollTop, left, top, clientRect, leftAligned, bottomAligned; 1482 if (this._o.container) return; 1483 this.el.style.position = "absolute"; 1484 field = this._o.trigger; 1485 pEl = field; 1486 width = this.el.offsetWidth; 1487 height = this.el.offsetHeight; 1488 viewportWidth = window.innerWidth || document2.documentElement.clientWidth; 1489 viewportHeight = window.innerHeight || document2.documentElement.clientHeight; 1490 scrollTop = window.pageYOffset || document2.body.scrollTop || document2.documentElement.scrollTop; 1491 leftAligned = true; 1492 bottomAligned = true; 1493 if (typeof field.getBoundingClientRect === "function") { 1494 clientRect = field.getBoundingClientRect(); 1495 left = clientRect.left + window.pageXOffset; 1496 top = clientRect.bottom + window.pageYOffset; 1497 } else { 1498 left = pEl.offsetLeft; 1499 top = pEl.offsetTop + pEl.offsetHeight; 1500 while (pEl = pEl.offsetParent) { 1501 left += pEl.offsetLeft; 1502 top += pEl.offsetTop; 1503 } 1504 } 1505 if (this._o.reposition && left + width > viewportWidth || this._o.position.indexOf("right") > -1 && left - width + field.offsetWidth > 0) { 1506 left = left - width + field.offsetWidth; 1507 leftAligned = false; 1508 } 1509 if (this._o.reposition && top + height > viewportHeight + scrollTop || this._o.position.indexOf("top") > -1 && top - height - field.offsetHeight > 0) { 1510 top = top - height - field.offsetHeight; 1511 bottomAligned = false; 1512 } 1513 this.el.style.left = left + "px"; 1514 this.el.style.top = top + "px"; 1515 addClass(this.el, leftAligned ? "left-aligned" : "right-aligned"); 1516 addClass(this.el, bottomAligned ? "bottom-aligned" : "top-aligned"); 1517 removeClass(this.el, !leftAligned ? "left-aligned" : "right-aligned"); 1518 removeClass(this.el, !bottomAligned ? "bottom-aligned" : "top-aligned"); 1519 }, 1520 /** 1521 * render HTML for a particular month 1522 */ 1523 render: function(year, month, randId) { 1524 var opts = this._o, now2 = /* @__PURE__ */ new Date(), days = getDaysInMonth(year, month), before = new Date(year, month, 1).getDay(), data = [], row = []; 1525 setToStartOfDay(now2); 1526 if (opts.firstDay > 0) { 1527 before -= opts.firstDay; 1528 if (before < 0) { 1529 before += 7; 1530 } 1531 } 1532 var previousMonth = month === 0 ? 11 : month - 1, nextMonth = month === 11 ? 0 : month + 1, yearOfPreviousMonth = month === 0 ? year - 1 : year, yearOfNextMonth = month === 11 ? year + 1 : year, daysInPreviousMonth = getDaysInMonth(yearOfPreviousMonth, previousMonth); 1533 var cells = days + before, after = cells; 1534 while (after > 7) { 1535 after -= 7; 1536 } 1537 cells += 7 - after; 1538 var isWeekSelected = false; 1539 for (var i = 0, r = 0; i < cells; i++) { 1540 var day = new Date(year, month, 1 + (i - before)), isSelected = isDate(this._d) ? compareDates(day, this._d) : false, isToday = compareDates(day, now2), hasEvent = opts.events.indexOf(day.toDateString()) !== -1 ? true : false, isEmpty = i < before || i >= days + before, dayNumber = 1 + (i - before), monthNumber = month, yearNumber = year, isStartRange = opts.startRange && compareDates(opts.startRange, day), isEndRange = opts.endRange && compareDates(opts.endRange, day), isInRange = opts.startRange && opts.endRange && opts.startRange < day && day < opts.endRange, isDisabled = opts.minDate && day < opts.minDate || opts.maxDate && day > opts.maxDate || opts.disableWeekends && isWeekend(day) || opts.disableDayFn && opts.disableDayFn(day); 1541 if (isEmpty) { 1542 if (i < before) { 1543 dayNumber = daysInPreviousMonth + dayNumber; 1544 monthNumber = previousMonth; 1545 yearNumber = yearOfPreviousMonth; 1546 } else { 1547 dayNumber = dayNumber - days; 1548 monthNumber = nextMonth; 1549 yearNumber = yearOfNextMonth; 1550 } 1551 } 1552 var dayConfig = { 1553 day: dayNumber, 1554 month: monthNumber, 1555 year: yearNumber, 1556 hasEvent, 1557 isSelected, 1558 isToday, 1559 isDisabled, 1560 isEmpty, 1561 isStartRange, 1562 isEndRange, 1563 isInRange, 1564 showDaysInNextAndPreviousMonths: opts.showDaysInNextAndPreviousMonths, 1565 enableSelectionDaysInNextAndPreviousMonths: opts.enableSelectionDaysInNextAndPreviousMonths 1566 }; 1567 if (opts.pickWholeWeek && isSelected) { 1568 isWeekSelected = true; 1569 } 1570 row.push(renderDay(dayConfig)); 1571 if (++r === 7) { 1572 if (opts.showWeekNumber) { 1573 row.unshift(renderWeek(i - before, month, year, opts.firstWeekOfYearMinDays)); 1574 } 1575 data.push(renderRow(row, opts.isRTL, opts.pickWholeWeek, isWeekSelected)); 1576 row = []; 1577 r = 0; 1578 isWeekSelected = false; 1579 } 1580 } 1581 return renderTable(opts, data, randId); 1582 }, 1583 isVisible: function() { 1584 return this._v; 1585 }, 1586 show: function() { 1587 if (!this.isVisible()) { 1588 this._v = true; 1589 this.draw(); 1590 removeClass(this.el, "is-hidden"); 1591 if (this._o.bound) { 1592 addEvent(document2, "click", this._onClick); 1593 this.adjustPosition(); 1594 } 1595 if (typeof this._o.onOpen === "function") { 1596 this._o.onOpen.call(this); 1597 } 1598 } 1599 }, 1600 hide: function() { 1601 var v = this._v; 1602 if (v !== false) { 1603 if (this._o.bound) { 1604 removeEvent(document2, "click", this._onClick); 1605 } 1606 if (!this._o.container) { 1607 this.el.style.position = "static"; 1608 this.el.style.left = "auto"; 1609 this.el.style.top = "auto"; 1610 } 1611 addClass(this.el, "is-hidden"); 1612 this._v = false; 1613 if (v !== void 0 && typeof this._o.onClose === "function") { 1614 this._o.onClose.call(this); 1615 } 1616 } 1617 }, 1618 /** 1619 * GAME OVER 1620 */ 1621 destroy: function() { 1622 var opts = this._o; 1623 this.hide(); 1624 removeEvent(this.el, "mousedown", this._onMouseDown, true); 1625 removeEvent(this.el, "touchend", this._onMouseDown, true); 1626 removeEvent(this.el, "change", this._onChange); 1627 if (opts.keyboardInput) { 1628 removeEvent(document2, "keydown", this._onKeyChange); 1629 } 1630 if (opts.field) { 1631 removeEvent(opts.field, "change", this._onInputChange); 1632 if (opts.bound) { 1633 removeEvent(opts.trigger, "click", this._onInputClick); 1634 removeEvent(opts.trigger, "focus", this._onInputFocus); 1635 removeEvent(opts.trigger, "blur", this._onInputBlur); 1636 } 1637 } 1638 if (this.el.parentNode) { 1639 this.el.parentNode.removeChild(this.el); 1640 } 1641 } 1642 }; 1643 return Pikaday2; 1644 }); 1645 } 1646}); 1647
vendor: 167,495 bytes, lines 1648-6861
1648// node_modules/@hotwired/turbo/dist/turbo.es2017-esm.js 1649var turbo_es2017_esm_exports = {}; 1650__export(turbo_es2017_esm_exports, { 1651 FetchEnctype: () => FetchEnctype, 1652 FetchMethod: () => FetchMethod, 1653 FetchRequest: () => FetchRequest, 1654 FetchResponse: () => FetchResponse, 1655 FrameElement: () => FrameElement, 1656 FrameLoadingStyle: () => FrameLoadingStyle, 1657 FrameRenderer: () => FrameRenderer, 1658 PageRenderer: () => PageRenderer, 1659 PageSnapshot: () => PageSnapshot, 1660 StreamActions: () => StreamActions, 1661 StreamElement: () => StreamElement, 1662 StreamSourceElement: () => StreamSourceElement, 1663 cache: () => cache, 1664 clearCache: () => clearCache, 1665 config: () => config, 1666 connectStreamSource: () => connectStreamSource, 1667 disconnectStreamSource: () => disconnectStreamSource, 1668 fetch: () => fetchWithTurboHeaders, 1669 fetchEnctypeFromString: () => fetchEnctypeFromString, 1670 fetchMethodFromString: () => fetchMethodFromString, 1671 isSafe: () => isSafe, 1672 navigator: () => navigator$1, 1673 registerAdapter: () => registerAdapter, 1674 renderStreamMessage: () => renderStreamMessage, 1675 session: () => session, 1676 setConfirmMethod: () => setConfirmMethod, 1677 setFormMode: () => setFormMode, 1678 setProgressBarDelay: () => setProgressBarDelay, 1679 start: () => start, 1680 visit: () => visit 1681}); 1682(function(prototype) { 1683 if (typeof prototype.requestSubmit == "function") return; 1684 prototype.requestSubmit = function(submitter2) { 1685 if (submitter2) { 1686 validateSubmitter(submitter2, this); 1687 submitter2.click(); 1688 } else { 1689 submitter2 = document.createElement("input"); 1690 submitter2.type = "submit"; 1691 submitter2.hidden = true; 1692 this.appendChild(submitter2); 1693 submitter2.click(); 1694 this.removeChild(submitter2); 1695 } 1696 }; 1697 function validateSubmitter(submitter2, form) { 1698 submitter2 instanceof HTMLElement || raise(TypeError, "parameter 1 is not of type 'HTMLElement'"); 1699 submitter2.type == "submit" || raise(TypeError, "The specified element is not a submit button"); 1700 submitter2.form == form || raise(DOMException, "The specified element is not owned by this form element", "NotFoundError"); 1701 } 1702 function raise(errorConstructor, message, name) { 1703 throw new errorConstructor("Failed to execute 'requestSubmit' on 'HTMLFormElement': " + message + ".", name); 1704 } 1705})(HTMLFormElement.prototype); 1706var submittersByForm = /* @__PURE__ */ new WeakMap(); 1707function findSubmitterFromClickTarget(target) { 1708 const element = target instanceof Element ? target : target instanceof Node ? target.parentElement : null; 1709 const candidate = element ? element.closest("input, button") : null; 1710 return candidate?.type == "submit" ? candidate : null; 1711} 1712function clickCaptured(event) { 1713 const submitter2 = findSubmitterFromClickTarget(event.target); 1714 if (submitter2 && submitter2.form) { 1715 submittersByForm.set(submitter2.form, submitter2); 1716 } 1717} 1718(function() { 1719 if ("submitter" in Event.prototype) return; 1720 let prototype = window.Event.prototype; 1721 if ("SubmitEvent" in window) { 1722 const prototypeOfSubmitEvent = window.SubmitEvent.prototype; 1723 if (/Apple Computer/.test(navigator.vendor) && !("submitter" in prototypeOfSubmitEvent)) { 1724 prototype = prototypeOfSubmitEvent; 1725 } else { 1726 return; 1727 } 1728 } 1729 addEventListener("click", clickCaptured, true); 1730 Object.defineProperty(prototype, "submitter", { 1731 get() { 1732 if (this.type == "submit" && this.target instanceof HTMLFormElement) { 1733 return submittersByForm.get(this.target); 1734 } 1735 } 1736 }); 1737})(); 1738var FrameLoadingStyle = { 1739 eager: "eager", 1740 lazy: "lazy" 1741}; 1742var FrameElement = class _FrameElement extends HTMLElement { 1743 static delegateConstructor = void 0; 1744 loaded = Promise.resolve(); 1745 static get observedAttributes() { 1746 return ["disabled", "loading", "src"]; 1747 } 1748 constructor() { 1749 super(); 1750 this.delegate = new _FrameElement.delegateConstructor(this); 1751 } 1752 connectedCallback() { 1753 this.delegate.connect(); 1754 } 1755 disconnectedCallback() { 1756 this.delegate.disconnect(); 1757 } 1758 reload() { 1759 return this.delegate.sourceURLReloaded(); 1760 } 1761 attributeChangedCallback(name) { 1762 if (name == "loading") { 1763 this.delegate.loadingStyleChanged(); 1764 } else if (name == "src") { 1765 this.delegate.sourceURLChanged(); 1766 } else if (name == "disabled") { 1767 this.delegate.disabledChanged(); 1768 } 1769 } 1770 /** 1771 * Gets the URL to lazily load source HTML from 1772 */ 1773 get src() { 1774 return this.getAttribute("src"); 1775 } 1776 /** 1777 * Sets the URL to lazily load source HTML from 1778 */ 1779 set src(value) { 1780 if (value) { 1781 this.setAttribute("src", value); 1782 } else { 1783 this.removeAttribute("src"); 1784 } 1785 } 1786 /** 1787 * Gets the refresh mode for the frame. 1788 */ 1789 get refresh() { 1790 return this.getAttribute("refresh"); 1791 } 1792 /** 1793 * Sets the refresh mode for the frame. 1794 */ 1795 set refresh(value) { 1796 if (value) { 1797 this.setAttribute("refresh", value); 1798 } else { 1799 this.removeAttribute("refresh"); 1800 } 1801 } 1802 get shouldReloadWithMorph() { 1803 return this.src && this.refresh === "morph"; 1804 } 1805 /** 1806 * Determines if the element is loading 1807 */ 1808 get loading() { 1809 return frameLoadingStyleFromString(this.getAttribute("loading") || ""); 1810 } 1811 /** 1812 * Sets the value of if the element is loading 1813 */ 1814 set loading(value) { 1815 if (value) { 1816 this.setAttribute("loading", value); 1817 } else { 1818 this.removeAttribute("loading"); 1819 } 1820 } 1821 /** 1822 * Gets the disabled state of the frame. 1823 * 1824 * If disabled, no requests will be intercepted by the frame. 1825 */ 1826 get disabled() { 1827 return this.hasAttribute("disabled"); 1828 } 1829 /** 1830 * Sets the disabled state of the frame. 1831 * 1832 * If disabled, no requests will be intercepted by the frame. 1833 */ 1834 set disabled(value) { 1835 if (value) { 1836 this.setAttribute("disabled", ""); 1837 } else { 1838 this.removeAttribute("disabled"); 1839 } 1840 } 1841 /** 1842 * Gets the autoscroll state of the frame. 1843 * 1844 * If true, the frame will be scrolled into view automatically on update. 1845 */ 1846 get autoscroll() { 1847 return this.hasAttribute("autoscroll"); 1848 } 1849 /** 1850 * Sets the autoscroll state of the frame. 1851 * 1852 * If true, the frame will be scrolled into view automatically on update. 1853 */ 1854 set autoscroll(value) { 1855 if (value) { 1856 this.setAttribute("autoscroll", ""); 1857 } else { 1858 this.removeAttribute("autoscroll"); 1859 } 1860 } 1861 /** 1862 * Determines if the element has finished loading 1863 */ 1864 get complete() { 1865 return !this.delegate.isLoading; 1866 } 1867 /** 1868 * Gets the active state of the frame. 1869 * 1870 * If inactive, source changes will not be observed. 1871 */ 1872 get isActive() { 1873 return this.ownerDocument === document && !this.isPreview; 1874 } 1875 /** 1876 * Sets the active state of the frame. 1877 * 1878 * If inactive, source changes will not be observed. 1879 */ 1880 get isPreview() { 1881 return this.ownerDocument?.documentElement?.hasAttribute("data-turbo-preview"); 1882 } 1883}; 1884function frameLoadingStyleFromString(style) { 1885 switch (style.toLowerCase()) { 1886 case "lazy": 1887 return FrameLoadingStyle.lazy; 1888 default: 1889 return FrameLoadingStyle.eager; 1890 } 1891} 1892var drive = { 1893 enabled: true, 1894 progressBarDelay: 500, 1895 unvisitableExtensions: /* @__PURE__ */ new Set( 1896 [ 1897 ".7z", 1898 ".aac", 1899 ".apk", 1900 ".avi", 1901 ".bmp", 1902 ".bz2", 1903 ".css", 1904 ".csv", 1905 ".deb", 1906 ".dmg", 1907 ".doc", 1908 ".docx", 1909 ".exe", 1910 ".gif", 1911 ".gz", 1912 ".heic", 1913 ".heif", 1914 ".ico", 1915 ".iso", 1916 ".jpeg", 1917 ".jpg", 1918 ".js", 1919 ".json", 1920 ".m4a", 1921 ".mkv", 1922 ".mov", 1923 ".mp3", 1924 ".mp4", 1925 ".mpeg", 1926 ".mpg", 1927 ".msi", 1928 ".ogg", 1929 ".ogv", 1930 ".pdf", 1931 ".pkg", 1932 ".png", 1933 ".ppt", 1934 ".pptx", 1935 ".rar", 1936 ".rtf", 1937 ".svg", 1938 ".tar", 1939 ".tif", 1940 ".tiff", 1941 ".txt", 1942 ".wav", 1943 ".webm", 1944 ".webp", 1945 ".wma", 1946 ".wmv", 1947 ".xls", 1948 ".xlsx", 1949 ".xml", 1950 ".zip" 1951 ] 1952 ) 1953}; 1954function activateScriptElement(element) { 1955 if (element.getAttribute("data-turbo-eval") == "false") { 1956 return element; 1957 } else { 1958 const createdScriptElement = document.createElement("script"); 1959 const cspNonce = getMetaContent("csp-nonce"); 1960 if (cspNonce) { 1961 createdScriptElement.nonce = cspNonce; 1962 } 1963 createdScriptElement.textContent = element.textContent; 1964 createdScriptElement.async = false; 1965 copyElementAttributes(createdScriptElement, element); 1966 return createdScriptElement; 1967 } 1968} 1969function copyElementAttributes(destinationElement, sourceElement) { 1970 for (const { name, value } of sourceElement.attributes) { 1971 destinationElement.setAttribute(name, value); 1972 } 1973} 1974function createDocumentFragment(html) { 1975 const template = document.createElement("template"); 1976 template.innerHTML = html; 1977 return template.content; 1978} 1979function dispatch(eventName, { target, cancelable, detail } = {}) { 1980 const event = new CustomEvent(eventName, { 1981 cancelable, 1982 bubbles: true, 1983 composed: true, 1984 detail 1985 }); 1986 if (target && target.isConnected) { 1987 target.dispatchEvent(event); 1988 } else { 1989 document.documentElement.dispatchEvent(event); 1990 } 1991 return event; 1992} 1993function cancelEvent(event) { 1994 event.preventDefault(); 1995 event.stopImmediatePropagation(); 1996} 1997function nextRepaint() { 1998 if (document.visibilityState === "hidden") { 1999 return nextEventLoopTick(); 2000 } else { 2001 return nextAnimationFrame(); 2002 } 2003} 2004function nextAnimationFrame() { 2005 return new Promise((resolve) => requestAnimationFrame(() => resolve())); 2006} 2007function nextEventLoopTick() { 2008 return new Promise((resolve) => setTimeout(() => resolve(), 0)); 2009} 2010function nextMicrotask() { 2011 return Promise.resolve(); 2012} 2013function parseHTMLDocument(html = "") { 2014 return new DOMParser().parseFromString(html, "text/html"); 2015} 2016function unindent(strings, ...values) { 2017 const lines = interpolate(strings, values).replace(/^\n/, "").split("\n"); 2018 const match = lines[0].match(/^\s+/); 2019 const indent = match ? match[0].length : 0; 2020 return lines.map((line) => line.slice(indent)).join("\n"); 2021} 2022function interpolate(strings, values) { 2023 return strings.reduce((result, string, i) => { 2024 const value = values[i] == void 0 ? "" : values[i]; 2025 return result + string + value; 2026 }, ""); 2027} 2028function uuid() { 2029 return Array.from({ length: 36 }).map((_, i) => { 2030 if (i == 8 || i == 13 || i == 18 || i == 23) { 2031 return "-"; 2032 } else if (i == 14) { 2033 return "4"; 2034 } else if (i == 19) { 2035 return (Math.floor(Math.random() * 4) + 8).toString(16); 2036 } else { 2037 return Math.floor(Math.random() * 15).toString(16); 2038 } 2039 }).join(""); 2040} 2041function getAttribute(attributeName, ...elements) { 2042 for (const value of elements.map((element) => element?.getAttribute(attributeName))) { 2043 if (typeof value == "string") return value; 2044 } 2045 return null; 2046} 2047function hasAttribute(attributeName, ...elements) { 2048 return elements.some((element) => element && element.hasAttribute(attributeName)); 2049} 2050function markAsBusy(...elements) { 2051 for (const element of elements) { 2052 if (element.localName == "turbo-frame") { 2053 element.setAttribute("busy", ""); 2054 } 2055 element.setAttribute("aria-busy", "true"); 2056 } 2057} 2058function clearBusyState(...elements) { 2059 for (const element of elements) { 2060 if (element.localName == "turbo-frame") { 2061 element.removeAttribute("busy"); 2062 } 2063 element.removeAttribute("aria-busy"); 2064 } 2065} 2066function waitForLoad(element, timeoutInMilliseconds = 2e3) { 2067 return new Promise((resolve) => { 2068 const onComplete = () => { 2069 element.removeEventListener("error", onComplete); 2070 element.removeEventListener("load", onComplete); 2071 resolve(); 2072 }; 2073 element.addEventListener("load", onComplete, { once: true }); 2074 element.addEventListener("error", onComplete, { once: true }); 2075 setTimeout(resolve, timeoutInMilliseconds); 2076 }); 2077} 2078function getHistoryMethodForAction(action) { 2079 switch (action) { 2080 case "replace": 2081 return history.replaceState; 2082 case "advance": 2083 case "restore": 2084 return history.pushState; 2085 } 2086} 2087function isAction(action) { 2088 return action == "advance" || action == "replace" || action == "restore"; 2089} 2090function getVisitAction(...elements) { 2091 const action = getAttribute("data-turbo-action", ...elements); 2092 return isAction(action) ? action : null; 2093} 2094function getMetaElement(name) { 2095 return document.querySelector(`meta[name="${name}"]`); 2096} 2097function getMetaContent(name) { 2098 const element = getMetaElement(name); 2099 return element && element.content; 2100} 2101function setMetaContent(name, content) { 2102 let element = getMetaElement(name); 2103 if (!element) { 2104 element = document.createElement("meta"); 2105 element.setAttribute("name", name); 2106 document.head.appendChild(element); 2107 } 2108 element.setAttribute("content", content); 2109 return element; 2110} 2111function findClosestRecursively(element, selector) { 2112 if (element instanceof Element) { 2113 return element.closest(selector) || findClosestRecursively(element.assignedSlot || element.getRootNode()?.host, selector); 2114 } 2115} 2116function elementIsFocusable(element) { 2117 const inertDisabledOrHidden = "[inert], :disabled, [hidden], details:not([open]), dialog:not([open])"; 2118 return !!element && element.closest(inertDisabledOrHidden) == null && typeof element.focus == "function"; 2119} 2120function queryAutofocusableElement(elementOrDocumentFragment) { 2121 return Array.from(elementOrDocumentFragment.querySelectorAll("[autofocus]")).find(elementIsFocusable); 2122} 2123async function around(callback, reader) { 2124 const before = reader(); 2125 callback(); 2126 await nextAnimationFrame(); 2127 const after = reader(); 2128 return [before, after]; 2129} 2130function doesNotTargetIFrame(name) { 2131 if (name === "_blank") { 2132 return false; 2133 } else if (name) { 2134 for (const element of document.getElementsByName(name)) { 2135 if (element instanceof HTMLIFrameElement) return false; 2136 } 2137 return true; 2138 } else { 2139 return true; 2140 } 2141} 2142function findLinkFromClickTarget(target) { 2143 return findClosestRecursively(target, "a[href]:not([target^=_]):not([download])"); 2144} 2145function getLocationForLink(link) { 2146 return expandURL(link.getAttribute("href") || ""); 2147} 2148function debounce(fn, delay) { 2149 let timeoutId = null; 2150 return (...args) => { 2151 const callback = () => fn.apply(this, args); 2152 clearTimeout(timeoutId); 2153 timeoutId = setTimeout(callback, delay); 2154 }; 2155} 2156var submitter = { 2157 "aria-disabled": { 2158 beforeSubmit: (submitter2) => { 2159 submitter2.setAttribute("aria-disabled", "true"); 2160 submitter2.addEventListener("click", cancelEvent); 2161 }, 2162 afterSubmit: (submitter2) => { 2163 submitter2.removeAttribute("aria-disabled"); 2164 submitter2.removeEventListener("click", cancelEvent); 2165 } 2166 }, 2167 "disabled": { 2168 beforeSubmit: (submitter2) => submitter2.disabled = true, 2169 afterSubmit: (submitter2) => submitter2.disabled = false 2170 } 2171}; 2172var Config = class { 2173 #submitter = null; 2174 constructor(config2) { 2175 Object.assign(this, config2); 2176 } 2177 get submitter() { 2178 return this.#submitter; 2179 } 2180 set submitter(value) { 2181 this.#submitter = submitter[value] || value; 2182 } 2183}; 2184var forms = new Config({ 2185 mode: "on", 2186 submitter: "disabled" 2187}); 2188var config = { 2189 drive, 2190 forms 2191}; 2192function expandURL(locatable) { 2193 return new URL(locatable.toString(), document.baseURI); 2194} 2195function getAnchor(url) { 2196 let anchorMatch; 2197 if (url.hash) { 2198 return url.hash.slice(1); 2199 } else if (anchorMatch = url.href.match(/#(.*)$/)) { 2200 return anchorMatch[1]; 2201 } 2202} 2203function getAction$1(form, submitter2) { 2204 const action = submitter2?.getAttribute("formaction") || form.getAttribute("action") || form.action; 2205 return expandURL(action); 2206} 2207function getExtension(url) { 2208 return (getLastPathComponent(url).match(/\.[^.]*$/) || [])[0] || ""; 2209} 2210function isPrefixedBy(baseURL, url) { 2211 const prefix = getPrefix(url); 2212 return baseURL.href === expandURL(prefix).href || baseURL.href.startsWith(prefix); 2213} 2214function locationIsVisitable(location2, rootLocation) { 2215 return isPrefixedBy(location2, rootLocation) && !config.drive.unvisitableExtensions.has(getExtension(location2)); 2216} 2217function getRequestURL(url) { 2218 const anchor = getAnchor(url); 2219 return anchor != null ? url.href.slice(0, -(anchor.length + 1)) : url.href; 2220} 2221function toCacheKey(url) { 2222 return getRequestURL(url); 2223} 2224function urlsAreEqual(left, right) { 2225 return expandURL(left).href == expandURL(right).href; 2226} 2227function getPathComponents(url) { 2228 return url.pathname.split("/").slice(1); 2229} 2230function getLastPathComponent(url) { 2231 return getPathComponents(url).slice(-1)[0]; 2232} 2233function getPrefix(url) { 2234 return addTrailingSlash(url.origin + url.pathname); 2235} 2236function addTrailingSlash(value) { 2237 return value.endsWith("/") ? value : value + "/"; 2238} 2239var FetchResponse = class { 2240 constructor(response) { 2241 this.response = response; 2242 } 2243 get succeeded() { 2244 return this.response.ok; 2245 } 2246 get failed() { 2247 return !this.succeeded; 2248 } 2249 get clientError() { 2250 return this.statusCode >= 400 && this.statusCode <= 499; 2251 } 2252 get serverError() { 2253 return this.statusCode >= 500 && this.statusCode <= 599; 2254 } 2255 get redirected() { 2256 return this.response.redirected; 2257 } 2258 get location() { 2259 return expandURL(this.response.url); 2260 } 2261 get isHTML() { 2262 return this.contentType && this.contentType.match(/^(?:text\/([^\s;,]+\b)?html|application\/xhtml\+xml)\b/); 2263 } 2264 get statusCode() { 2265 return this.response.status; 2266 } 2267 get contentType() { 2268 return this.header("Content-Type"); 2269 } 2270 get responseText() { 2271 return this.response.clone().text(); 2272 } 2273 get responseHTML() { 2274 if (this.isHTML) { 2275 return this.response.clone().text(); 2276 } else { 2277 return Promise.resolve(void 0); 2278 } 2279 } 2280 header(name) { 2281 return this.response.headers.get(name); 2282 } 2283}; 2284var LimitedSet = class extends Set { 2285 constructor(maxSize) { 2286 super(); 2287 this.maxSize = maxSize; 2288 } 2289 add(value) { 2290 if (this.size >= this.maxSize) { 2291 const iterator = this.values(); 2292 const oldestValue = iterator.next().value; 2293 this.delete(oldestValue); 2294 } 2295 super.add(value); 2296 } 2297}; 2298var recentRequests = new LimitedSet(20); 2299var nativeFetch = window.fetch; 2300function fetchWithTurboHeaders(url, options = {}) { 2301 const modifiedHeaders = new Headers(options.headers || {}); 2302 const requestUID = uuid(); 2303 recentRequests.add(requestUID); 2304 modifiedHeaders.append("X-Turbo-Request-Id", requestUID); 2305 return nativeFetch(url, { 2306 ...options, 2307 headers: modifiedHeaders 2308 }); 2309} 2310function fetchMethodFromString(method) { 2311 switch (method.toLowerCase()) { 2312 case "get": 2313 return FetchMethod.get; 2314 case "post": 2315 return FetchMethod.post; 2316 case "put": 2317 return FetchMethod.put; 2318 case "patch": 2319 return FetchMethod.patch; 2320 case "delete": 2321 return FetchMethod.delete; 2322 } 2323} 2324var FetchMethod = { 2325 get: "get", 2326 post: "post", 2327 put: "put", 2328 patch: "patch", 2329 delete: "delete" 2330}; 2331function fetchEnctypeFromString(encoding) { 2332 switch (encoding.toLowerCase()) { 2333 case FetchEnctype.multipart: 2334 return FetchEnctype.multipart; 2335 case FetchEnctype.plain: 2336 return FetchEnctype.plain; 2337 default: 2338 return FetchEnctype.urlEncoded; 2339 } 2340} 2341var FetchEnctype = { 2342 urlEncoded: "application/x-www-form-urlencoded", 2343 multipart: "multipart/form-data", 2344 plain: "text/plain" 2345}; 2346var FetchRequest = class { 2347 abortController = new AbortController(); 2348 #resolveRequestPromise = (_value) => { 2349 }; 2350 constructor(delegate, method, location2, requestBody = new URLSearchParams(), target = null, enctype = FetchEnctype.urlEncoded) { 2351 const [url, body] = buildResourceAndBody(expandURL(location2), method, requestBody, enctype); 2352 this.delegate = delegate; 2353 this.url = url; 2354 this.target = target; 2355 this.fetchOptions = { 2356 credentials: "same-origin", 2357 redirect: "follow", 2358 method: method.toUpperCase(), 2359 headers: { ...this.defaultHeaders }, 2360 body, 2361 signal: this.abortSignal, 2362 referrer: this.delegate.referrer?.href 2363 }; 2364 this.enctype = enctype; 2365 } 2366 get method() { 2367 return this.fetchOptions.method; 2368 } 2369 set method(value) { 2370 const fetchBody = this.isSafe ? this.url.searchParams : this.fetchOptions.body || new FormData(); 2371 const fetchMethod = fetchMethodFromString(value) || FetchMethod.get; 2372 this.url.search = ""; 2373 const [url, body] = buildResourceAndBody(this.url, fetchMethod, fetchBody, this.enctype); 2374 this.url = url; 2375 this.fetchOptions.body = body; 2376 this.fetchOptions.method = fetchMethod.toUpperCase(); 2377 } 2378 get headers() { 2379 return this.fetchOptions.headers; 2380 } 2381 set headers(value) { 2382 this.fetchOptions.headers = value; 2383 } 2384 get body() { 2385 if (this.isSafe) { 2386 return this.url.searchParams; 2387 } else { 2388 return this.fetchOptions.body; 2389 } 2390 } 2391 set body(value) { 2392 this.fetchOptions.body = value; 2393 } 2394 get location() { 2395 return this.url; 2396 } 2397 get params() { 2398 return this.url.searchParams; 2399 } 2400 get entries() { 2401 return this.body ? Array.from(this.body.entries()) : []; 2402 } 2403 cancel() { 2404 this.abortController.abort(); 2405 } 2406 async perform() { 2407 const { fetchOptions } = this; 2408 this.delegate.prepareRequest(this); 2409 const event = await this.#allowRequestToBeIntercepted(fetchOptions); 2410 try { 2411 this.delegate.requestStarted(this); 2412 if (event.detail.fetchRequest) { 2413 this.response = event.detail.fetchRequest.response; 2414 } else { 2415 this.response = fetchWithTurboHeaders(this.url.href, fetchOptions); 2416 } 2417 const response = await this.response; 2418 return await this.receive(response); 2419 } catch (error2) { 2420 if (error2.name !== "AbortError") { 2421 if (this.#willDelegateErrorHandling(error2)) { 2422 this.delegate.requestErrored(this, error2); 2423 } 2424 throw error2; 2425 } 2426 } finally { 2427 this.delegate.requestFinished(this); 2428 } 2429 } 2430 async receive(response) { 2431 const fetchResponse = new FetchResponse(response); 2432 const event = dispatch("turbo:before-fetch-response", { 2433 cancelable: true, 2434 detail: { fetchResponse }, 2435 target: this.target 2436 }); 2437 if (event.defaultPrevented) { 2438 this.delegate.requestPreventedHandlingResponse(this, fetchResponse); 2439 } else if (fetchResponse.succeeded) { 2440 this.delegate.requestSucceededWithResponse(this, fetchResponse); 2441 } else { 2442 this.delegate.requestFailedWithResponse(this, fetchResponse); 2443 } 2444 return fetchResponse; 2445 } 2446 get defaultHeaders() { 2447 return { 2448 Accept: "text/html, application/xhtml+xml" 2449 }; 2450 } 2451 get isSafe() { 2452 return isSafe(this.method); 2453 } 2454 get abortSignal() { 2455 return this.abortController.signal; 2456 } 2457 acceptResponseType(mimeType) { 2458 this.headers["Accept"] = [mimeType, this.headers["Accept"]].join(", "); 2459 } 2460 async #allowRequestToBeIntercepted(fetchOptions) { 2461 const requestInterception = new Promise((resolve) => this.#resolveRequestPromise = resolve); 2462 const event = dispatch("turbo:before-fetch-request", { 2463 cancelable: true, 2464 detail: { 2465 fetchOptions, 2466 url: this.url, 2467 resume: this.#resolveRequestPromise 2468 }, 2469 target: this.target 2470 }); 2471 this.url = event.detail.url; 2472 if (event.defaultPrevented) await requestInterception; 2473 return event; 2474 } 2475 #willDelegateErrorHandling(error2) { 2476 const event = dispatch("turbo:fetch-request-error", { 2477 target: this.target, 2478 cancelable: true, 2479 detail: { request: this, error: error2 } 2480 }); 2481 return !event.defaultPrevented; 2482 } 2483}; 2484function isSafe(fetchMethod) { 2485 return fetchMethodFromString(fetchMethod) == FetchMethod.get; 2486} 2487function buildResourceAndBody(resource, method, requestBody, enctype) { 2488 const searchParams = Array.from(requestBody).length > 0 ? new URLSearchParams(entriesExcludingFiles(requestBody)) : resource.searchParams; 2489 if (isSafe(method)) { 2490 return [mergeIntoURLSearchParams(resource, searchParams), null]; 2491 } else if (enctype == FetchEnctype.urlEncoded) { 2492 return [resource, searchParams]; 2493 } else { 2494 return [resource, requestBody]; 2495 } 2496} 2497function entriesExcludingFiles(requestBody) { 2498 const entries = []; 2499 for (const [name, value] of requestBody) { 2500 if (value instanceof File) continue; 2501 else entries.push([name, value]); 2502 } 2503 return entries; 2504} 2505function mergeIntoURLSearchParams(url, requestBody) { 2506 const searchParams = new URLSearchParams(entriesExcludingFiles(requestBody)); 2507 url.search = searchParams.toString(); 2508 return url; 2509} 2510var AppearanceObserver = class { 2511 started = false; 2512 constructor(delegate, element) { 2513 this.delegate = delegate; 2514 this.element = element; 2515 this.intersectionObserver = new IntersectionObserver(this.intersect); 2516 } 2517 start() { 2518 if (!this.started) { 2519 this.started = true; 2520 this.intersectionObserver.observe(this.element); 2521 } 2522 } 2523 stop() { 2524 if (this.started) { 2525 this.started = false; 2526 this.intersectionObserver.unobserve(this.element); 2527 } 2528 } 2529 intersect = (entries) => { 2530 const lastEntry = entries.slice(-1)[0]; 2531 if (lastEntry?.isIntersecting) { 2532 this.delegate.elementAppearedInViewport(this.element); 2533 } 2534 }; 2535}; 2536var StreamMessage = class { 2537 static contentType = "text/vnd.turbo-stream.html"; 2538 static wrap(message) { 2539 if (typeof message == "string") { 2540 return new this(createDocumentFragment(message)); 2541 } else { 2542 return message; 2543 } 2544 } 2545 constructor(fragment) { 2546 this.fragment = importStreamElements(fragment); 2547 } 2548}; 2549function importStreamElements(fragment) { 2550 for (const element of fragment.querySelectorAll("turbo-stream")) { 2551 const streamElement = document.importNode(element, true); 2552 for (const inertScriptElement of streamElement.templateElement.content.querySelectorAll("script")) { 2553 inertScriptElement.replaceWith(activateScriptElement(inertScriptElement)); 2554 } 2555 element.replaceWith(streamElement); 2556 } 2557 return fragment; 2558} 2559var PREFETCH_DELAY = 100; 2560var PrefetchCache = class { 2561 #prefetchTimeout = null; 2562 #prefetched = null; 2563 get(url) { 2564 if (this.#prefetched && this.#prefetched.url === url && this.#prefetched.expire > Date.now()) { 2565 return this.#prefetched.request; 2566 } 2567 } 2568 setLater(url, request, ttl) { 2569 this.clear(); 2570 this.#prefetchTimeout = setTimeout(() => { 2571 request.perform(); 2572 this.set(url, request, ttl); 2573 this.#prefetchTimeout = null; 2574 }, PREFETCH_DELAY); 2575 } 2576 set(url, request, ttl) { 2577 this.#prefetched = { url, request, expire: new Date((/* @__PURE__ */ new Date()).getTime() + ttl) }; 2578 } 2579 clear() { 2580 if (this.#prefetchTimeout) clearTimeout(this.#prefetchTimeout); 2581 this.#prefetched = null; 2582 } 2583}; 2584var cacheTtl = 10 * 1e3; 2585var prefetchCache = new PrefetchCache(); 2586var FormSubmissionState = { 2587 initialized: "initialized", 2588 requesting: "requesting", 2589 waiting: "waiting", 2590 receiving: "receiving", 2591 stopping: "stopping", 2592 stopped: "stopped" 2593}; 2594var FormSubmission = class _FormSubmission { 2595 state = FormSubmissionState.initialized; 2596 static confirmMethod(message) { 2597 return Promise.resolve(confirm(message)); 2598 } 2599 constructor(delegate, formElement, submitter2, mustRedirect = false) { 2600 const method = getMethod(formElement, submitter2); 2601 const action = getAction(getFormAction(formElement, submitter2), method); 2602 const body = buildFormData(formElement, submitter2); 2603 const enctype = getEnctype(formElement, submitter2); 2604 this.delegate = delegate; 2605 this.formElement = formElement; 2606 this.submitter = submitter2; 2607 this.fetchRequest = new FetchRequest(this, method, action, body, formElement, enctype); 2608 this.mustRedirect = mustRedirect; 2609 } 2610 get method() { 2611 return this.fetchRequest.method; 2612 } 2613 set method(value) { 2614 this.fetchRequest.method = value; 2615 } 2616 get action() { 2617 return this.fetchRequest.url.toString(); 2618 } 2619 set action(value) { 2620 this.fetchRequest.url = expandURL(value); 2621 } 2622 get body() { 2623 return this.fetchRequest.body; 2624 } 2625 get enctype() { 2626 return this.fetchRequest.enctype; 2627 } 2628 get isSafe() { 2629 return this.fetchRequest.isSafe; 2630 } 2631 get location() { 2632 return this.fetchRequest.url; 2633 } 2634 // The submission process 2635 async start() { 2636 const { initialized, requesting } = FormSubmissionState; 2637 const confirmationMessage = getAttribute("data-turbo-confirm", this.submitter, this.formElement); 2638 if (typeof confirmationMessage === "string") { 2639 const confirmMethod = typeof config.forms.confirm === "function" ? config.forms.confirm : _FormSubmission.confirmMethod; 2640 const answer = await confirmMethod(confirmationMessage, this.formElement, this.submitter); 2641 if (!answer) { 2642 return; 2643 } 2644 } 2645 if (this.state == initialized) { 2646 this.state = requesting; 2647 return this.fetchRequest.perform(); 2648 } 2649 } 2650 stop() { 2651 const { stopping, stopped } = FormSubmissionState; 2652 if (this.state != stopping && this.state != stopped) { 2653 this.state = stopping; 2654 this.fetchRequest.cancel(); 2655 return true; 2656 } 2657 } 2658 // Fetch request delegate 2659 prepareRequest(request) { 2660 if (!request.isSafe) { 2661 const token = getCookieValue(getMetaContent("csrf-param")) || getMetaContent("csrf-token"); 2662 if (token) { 2663 request.headers["X-CSRF-Token"] = token; 2664 } 2665 } 2666 if (this.requestAcceptsTurboStreamResponse(request)) { 2667 request.acceptResponseType(StreamMessage.contentType); 2668 } 2669 } 2670 requestStarted(_request) { 2671 this.state = FormSubmissionState.waiting; 2672 if (this.submitter) config.forms.submitter.beforeSubmit(this.submitter); 2673 this.setSubmitsWith(); 2674 markAsBusy(this.formElement); 2675 dispatch("turbo:submit-start", { 2676 target: this.formElement, 2677 detail: { formSubmission: this } 2678 }); 2679 this.delegate.formSubmissionStarted(this); 2680 } 2681 requestPreventedHandlingResponse(request, response) { 2682 prefetchCache.clear(); 2683 this.result = { success: response.succeeded, fetchResponse: response }; 2684 } 2685 requestSucceededWithResponse(request, response) { 2686 if (response.clientError || response.serverError) { 2687 this.delegate.formSubmissionFailedWithResponse(this, response); 2688 return; 2689 } 2690 prefetchCache.clear(); 2691 if (this.requestMustRedirect(request) && responseSucceededWithoutRedirect(response)) { 2692 const error2 = new Error("Form responses must redirect to another location"); 2693 this.delegate.formSubmissionErrored(this, error2); 2694 } else { 2695 this.state = FormSubmissionState.receiving; 2696 this.result = { success: true, fetchResponse: response }; 2697 this.delegate.formSubmissionSucceededWithResponse(this, response); 2698 } 2699 } 2700 requestFailedWithResponse(request, response) { 2701 this.result = { success: false, fetchResponse: response }; 2702 this.delegate.formSubmissionFailedWithResponse(this, response); 2703 } 2704 requestErrored(request, error2) { 2705 this.result = { success: false, error: error2 }; 2706 this.delegate.formSubmissionErrored(this, error2); 2707 } 2708 requestFinished(_request) { 2709 this.state = FormSubmissionState.stopped; 2710 if (this.submitter) config.forms.submitter.afterSubmit(this.submitter); 2711 this.resetSubmitterText(); 2712 clearBusyState(this.formElement); 2713 dispatch("turbo:submit-end", { 2714 target: this.formElement, 2715 detail: { formSubmission: this, ...this.result } 2716 }); 2717 this.delegate.formSubmissionFinished(this); 2718 } 2719 // Private 2720 setSubmitsWith() { 2721 if (!this.submitter || !this.submitsWith) return; 2722 if (this.submitter.matches("button")) { 2723 this.originalSubmitText = this.submitter.innerHTML; 2724 this.submitter.innerHTML = this.submitsWith; 2725 } else if (this.submitter.matches("input")) { 2726 const input = this.submitter; 2727 this.originalSubmitText = input.value; 2728 input.value = this.submitsWith; 2729 } 2730 } 2731 resetSubmitterText() { 2732 if (!this.submitter || !this.originalSubmitText) return; 2733 if (this.submitter.matches("button")) { 2734 this.submitter.innerHTML = this.originalSubmitText; 2735 } else if (this.submitter.matches("input")) { 2736 const input = this.submitter; 2737 input.value = this.originalSubmitText; 2738 } 2739 } 2740 requestMustRedirect(request) { 2741 return !request.isSafe && this.mustRedirect; 2742 } 2743 requestAcceptsTurboStreamResponse(request) { 2744 return !request.isSafe || hasAttribute("data-turbo-stream", this.submitter, this.formElement); 2745 } 2746 get submitsWith() { 2747 return this.submitter?.getAttribute("data-turbo-submits-with"); 2748 } 2749}; 2750function buildFormData(formElement, submitter2) { 2751 const formData = new FormData(formElement); 2752 const name = submitter2?.getAttribute("name"); 2753 const value = submitter2?.getAttribute("value"); 2754 if (name) { 2755 formData.append(name, value || ""); 2756 } 2757 return formData; 2758} 2759function getCookieValue(cookieName) { 2760 if (cookieName != null) { 2761 const cookies = document.cookie ? document.cookie.split("; ") : []; 2762 const cookie = cookies.find((cookie2) => cookie2.startsWith(cookieName)); 2763 if (cookie) { 2764 const value = cookie.split("=").slice(1).join("="); 2765 return value ? decodeURIComponent(value) : void 0; 2766 } 2767 } 2768} 2769function responseSucceededWithoutRedirect(response) { 2770 return response.statusCode == 200 && !response.redirected; 2771} 2772function getFormAction(formElement, submitter2) { 2773 const formElementAction = typeof formElement.action === "string" ? formElement.action : null; 2774 if (submitter2?.hasAttribute("formaction")) { 2775 return submitter2.getAttribute("formaction") || ""; 2776 } else { 2777 return formElement.getAttribute("action") || formElementAction || ""; 2778 } 2779} 2780function getAction(formAction, fetchMethod) { 2781 const action = expandURL(formAction); 2782 if (isSafe(fetchMethod)) { 2783 action.search = ""; 2784 } 2785 return action; 2786} 2787function getMethod(formElement, submitter2) { 2788 const method = submitter2?.getAttribute("formmethod") || formElement.getAttribute("method") || ""; 2789 return fetchMethodFromString(method.toLowerCase()) || FetchMethod.get; 2790} 2791function getEnctype(formElement, submitter2) { 2792 return fetchEnctypeFromString(submitter2?.getAttribute("formenctype") || formElement.enctype); 2793} 2794var Snapshot = class { 2795 constructor(element) { 2796 this.element = element; 2797 } 2798 get activeElement() { 2799 return this.element.ownerDocument.activeElement; 2800 } 2801 get children() { 2802 return [...this.element.children]; 2803 } 2804 hasAnchor(anchor) { 2805 return this.getElementForAnchor(anchor) != null; 2806 } 2807 getElementForAnchor(anchor) { 2808 return anchor ? this.element.querySelector(`[id='${anchor}'], a[name='${anchor}']`) : null; 2809 } 2810 get isConnected() { 2811 return this.element.isConnected; 2812 } 2813 get firstAutofocusableElement() { 2814 return queryAutofocusableElement(this.element); 2815 } 2816 get permanentElements() { 2817 return queryPermanentElementsAll(this.element); 2818 } 2819 getPermanentElementById(id) { 2820 return getPermanentElementById(this.element, id); 2821 } 2822 getPermanentElementMapForSnapshot(snapshot) { 2823 const permanentElementMap = {}; 2824 for (const currentPermanentElement of this.permanentElements) { 2825 const { id } = currentPermanentElement; 2826 const newPermanentElement = snapshot.getPermanentElementById(id); 2827 if (newPermanentElement) { 2828 permanentElementMap[id] = [currentPermanentElement, newPermanentElement]; 2829 } 2830 } 2831 return permanentElementMap; 2832 } 2833}; 2834function getPermanentElementById(node, id) { 2835 return node.querySelector(`#${id}[data-turbo-permanent]`); 2836} 2837function queryPermanentElementsAll(node) { 2838 return node.querySelectorAll("[id][data-turbo-permanent]"); 2839} 2840var FormSubmitObserver = class { 2841 started = false; 2842 constructor(delegate, eventTarget) { 2843 this.delegate = delegate; 2844 this.eventTarget = eventTarget; 2845 } 2846 start() { 2847 if (!this.started) { 2848 this.eventTarget.addEventListener("submit", this.submitCaptured, true); 2849 this.started = true; 2850 } 2851 } 2852 stop() { 2853 if (this.started) { 2854 this.eventTarget.removeEventListener("submit", this.submitCaptured, true); 2855 this.started = false; 2856 } 2857 } 2858 submitCaptured = () => { 2859 this.eventTarget.removeEventListener("submit", this.submitBubbled, false); 2860 this.eventTarget.addEventListener("submit", this.submitBubbled, false); 2861 }; 2862 submitBubbled = (event) => { 2863 if (!event.defaultPrevented) { 2864 const form = event.target instanceof HTMLFormElement ? event.target : void 0; 2865 const submitter2 = event.submitter || void 0; 2866 if (form && submissionDoesNotDismissDialog(form, submitter2) && submissionDoesNotTargetIFrame(form, submitter2) && this.delegate.willSubmitForm(form, submitter2)) { 2867 event.preventDefault(); 2868 event.stopImmediatePropagation(); 2869 this.delegate.formSubmitted(form, submitter2); 2870 } 2871 } 2872 }; 2873}; 2874function submissionDoesNotDismissDialog(form, submitter2) { 2875 const method = submitter2?.getAttribute("formmethod") || form.getAttribute("method"); 2876 return method != "dialog"; 2877} 2878function submissionDoesNotTargetIFrame(form, submitter2) { 2879 const target = submitter2?.getAttribute("formtarget") || form.getAttribute("target"); 2880 return doesNotTargetIFrame(target); 2881} 2882var View = class { 2883 #resolveRenderPromise = (_value) => { 2884 }; 2885 #resolveInterceptionPromise = (_value) => { 2886 }; 2887 constructor(delegate, element) { 2888 this.delegate = delegate; 2889 this.element = element; 2890 } 2891 // Scrolling 2892 scrollToAnchor(anchor) { 2893 const element = this.snapshot.getElementForAnchor(anchor); 2894 if (element) { 2895 this.scrollToElement(element); 2896 this.focusElement(element); 2897 } else { 2898 this.scrollToPosition({ x: 0, y: 0 }); 2899 } 2900 } 2901 scrollToAnchorFromLocation(location2) { 2902 this.scrollToAnchor(getAnchor(location2)); 2903 } 2904 scrollToElement(element) { 2905 element.scrollIntoView(); 2906 } 2907 focusElement(element) { 2908 if (element instanceof HTMLElement) { 2909 if (element.hasAttribute("tabindex")) { 2910 element.focus(); 2911 } else { 2912 element.setAttribute("tabindex", "-1"); 2913 element.focus(); 2914 element.removeAttribute("tabindex"); 2915 } 2916 } 2917 } 2918 scrollToPosition({ x, y }) { 2919 this.scrollRoot.scrollTo(x, y); 2920 } 2921 scrollToTop() { 2922 this.scrollToPosition({ x: 0, y: 0 }); 2923 } 2924 get scrollRoot() { 2925 return window; 2926 } 2927 // Rendering 2928 async render(renderer) { 2929 const { isPreview, shouldRender, willRender, newSnapshot: snapshot } = renderer; 2930 const shouldInvalidate = willRender; 2931 if (shouldRender) { 2932 try { 2933 this.renderPromise = new Promise((resolve) => this.#resolveRenderPromise = resolve); 2934 this.renderer = renderer; 2935 await this.prepareToRenderSnapshot(renderer); 2936 const renderInterception = new Promise((resolve) => this.#resolveInterceptionPromise = resolve); 2937 const options = { resume: this.#resolveInterceptionPromise, render: this.renderer.renderElement, renderMethod: this.renderer.renderMethod }; 2938 const immediateRender = this.delegate.allowsImmediateRender(snapshot, options); 2939 if (!immediateRender) await renderInterception; 2940 await this.renderSnapshot(renderer); 2941 this.delegate.viewRenderedSnapshot(snapshot, isPreview, this.renderer.renderMethod); 2942 this.delegate.preloadOnLoadLinksForView(this.element); 2943 this.finishRenderingSnapshot(renderer); 2944 } finally { 2945 delete this.renderer; 2946 this.#resolveRenderPromise(void 0); 2947 delete this.renderPromise; 2948 } 2949 } else if (shouldInvalidate) { 2950 this.invalidate(renderer.reloadReason); 2951 } 2952 } 2953 invalidate(reason) { 2954 this.delegate.viewInvalidated(reason); 2955 } 2956 async prepareToRenderSnapshot(renderer) { 2957 this.markAsPreview(renderer.isPreview); 2958 await renderer.prepareToRender(); 2959 } 2960 markAsPreview(isPreview) { 2961 if (isPreview) { 2962 this.element.setAttribute("data-turbo-preview", ""); 2963 } else { 2964 this.element.removeAttribute("data-turbo-preview"); 2965 } 2966 } 2967 markVisitDirection(direction) { 2968 this.element.setAttribute("data-turbo-visit-direction", direction); 2969 } 2970 unmarkVisitDirection() { 2971 this.element.removeAttribute("data-turbo-visit-direction"); 2972 } 2973 async renderSnapshot(renderer) { 2974 await renderer.render(); 2975 } 2976 finishRenderingSnapshot(renderer) { 2977 renderer.finishRendering(); 2978 } 2979}; 2980var FrameView = class extends View { 2981 missing() { 2982 this.element.innerHTML = `<strong class="turbo-frame-error">Content missing</strong>`; 2983 } 2984 get snapshot() { 2985 return new Snapshot(this.element); 2986 } 2987}; 2988var LinkInterceptor = class { 2989 constructor(delegate, element) { 2990 this.delegate = delegate; 2991 this.element = element; 2992 } 2993 start() { 2994 this.element.addEventListener("click", this.clickBubbled); 2995 document.addEventListener("turbo:click", this.linkClicked); 2996 document.addEventListener("turbo:before-visit", this.willVisit); 2997 } 2998 stop() { 2999 this.element.removeEventListener("click", this.clickBubbled); 3000 document.removeEventListener("turbo:click", this.linkClicked); 3001 document.removeEventListener("turbo:before-visit", this.willVisit); 3002 } 3003 clickBubbled = (event) => { 3004 if (this.clickEventIsSignificant(event)) { 3005 this.clickEvent = event; 3006 } else { 3007 delete this.clickEvent; 3008 } 3009 }; 3010 linkClicked = (event) => { 3011 if (this.clickEvent && this.clickEventIsSignificant(event)) { 3012 if (this.delegate.shouldInterceptLinkClick(event.target, event.detail.url, event.detail.originalEvent)) { 3013 this.clickEvent.preventDefault(); 3014 event.preventDefault(); 3015 this.delegate.linkClickIntercepted(event.target, event.detail.url, event.detail.originalEvent); 3016 } 3017 } 3018 delete this.clickEvent; 3019 }; 3020 willVisit = (_event) => { 3021 delete this.clickEvent; 3022 }; 3023 clickEventIsSignificant(event) { 3024 const target = event.composed ? event.target?.parentElement : event.target; 3025 const element = findLinkFromClickTarget(target) || target; 3026 return element instanceof Element && element.closest("turbo-frame, html") == this.element; 3027 } 3028}; 3029var LinkClickObserver = class { 3030 started = false; 3031 constructor(delegate, eventTarget) { 3032 this.delegate = delegate; 3033 this.eventTarget = eventTarget; 3034 } 3035 start() { 3036 if (!this.started) { 3037 this.eventTarget.addEventListener("click", this.clickCaptured, true); 3038 this.started = true; 3039 } 3040 } 3041 stop() { 3042 if (this.started) { 3043 this.eventTarget.removeEventListener("click", this.clickCaptured, true); 3044 this.started = false; 3045 } 3046 } 3047 clickCaptured = () => { 3048 this.eventTarget.removeEventListener("click", this.clickBubbled, false); 3049 this.eventTarget.addEventListener("click", this.clickBubbled, false); 3050 }; 3051 clickBubbled = (event) => { 3052 if (event instanceof MouseEvent && this.clickEventIsSignificant(event)) { 3053 const target = event.composedPath && event.composedPath()[0] || event.target; 3054 const link = findLinkFromClickTarget(target); 3055 if (link && doesNotTargetIFrame(link.target)) { 3056 const location2 = getLocationForLink(link); 3057 if (this.delegate.willFollowLinkToLocation(link, location2, event)) { 3058 event.preventDefault(); 3059 this.delegate.followedLinkToLocation(link, location2); 3060 } 3061 } 3062 } 3063 }; 3064 clickEventIsSignificant(event) { 3065 return !(event.target && event.target.isContentEditable || event.defaultPrevented || event.which > 1 || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey); 3066 } 3067}; 3068var FormLinkClickObserver = class { 3069 constructor(delegate, element) { 3070 this.delegate = delegate; 3071 this.linkInterceptor = new LinkClickObserver(this, element); 3072 } 3073 start() { 3074 this.linkInterceptor.start(); 3075 } 3076 stop() { 3077 this.linkInterceptor.stop(); 3078 } 3079 // Link hover observer delegate 3080 canPrefetchRequestToLocation(link, location2) { 3081 return false; 3082 } 3083 prefetchAndCacheRequestToLocation(link, location2) { 3084 return; 3085 } 3086 // Link click observer delegate 3087 willFollowLinkToLocation(link, location2, originalEvent) { 3088 return this.delegate.willSubmitFormLinkToLocation(link, location2, originalEvent) && (link.hasAttribute("data-turbo-method") || link.hasAttribute("data-turbo-stream")); 3089 } 3090 followedLinkToLocation(link, location2) { 3091 const form = document.createElement("form"); 3092 const type = "hidden"; 3093 for (const [name, value] of location2.searchParams) { 3094 form.append(Object.assign(document.createElement("input"), { type, name, value })); 3095 } 3096 const action = Object.assign(location2, { search: "" }); 3097 form.setAttribute("data-turbo", "true"); 3098 form.setAttribute("action", action.href); 3099 form.setAttribute("hidden", ""); 3100 const method = link.getAttribute("data-turbo-method"); 3101 if (method) form.setAttribute("method", method); 3102 const turboFrame = link.getAttribute("data-turbo-frame"); 3103 if (turboFrame) form.setAttribute("data-turbo-frame", turboFrame); 3104 const turboAction = getVisitAction(link); 3105 if (turboAction) form.setAttribute("data-turbo-action", turboAction); 3106 const turboConfirm = link.getAttribute("data-turbo-confirm"); 3107 if (turboConfirm) form.setAttribute("data-turbo-confirm", turboConfirm); 3108 const turboStream = link.hasAttribute("data-turbo-stream"); 3109 if (turboStream) form.setAttribute("data-turbo-stream", ""); 3110 this.delegate.submittedFormLinkToLocation(link, location2, form); 3111 document.body.appendChild(form); 3112 form.addEventListener("turbo:submit-end", () => form.remove(), { once: true }); 3113 requestAnimationFrame(() => form.requestSubmit()); 3114 } 3115}; 3116var Bardo = class { 3117 static async preservingPermanentElements(delegate, permanentElementMap, callback) { 3118 const bardo = new this(delegate, permanentElementMap); 3119 bardo.enter(); 3120 await callback(); 3121 bardo.leave(); 3122 } 3123 constructor(delegate, permanentElementMap) { 3124 this.delegate = delegate; 3125 this.permanentElementMap = permanentElementMap; 3126 } 3127 enter() { 3128 for (const id in this.permanentElementMap) { 3129 const [currentPermanentElement, newPermanentElement] = this.permanentElementMap[id]; 3130 this.delegate.enteringBardo(currentPermanentElement, newPermanentElement); 3131 this.replaceNewPermanentElementWithPlaceholder(newPermanentElement); 3132 } 3133 } 3134 leave() { 3135 for (const id in this.permanentElementMap) { 3136 const [currentPermanentElement] = this.permanentElementMap[id]; 3137 this.replaceCurrentPermanentElementWithClone(currentPermanentElement); 3138 this.replacePlaceholderWithPermanentElement(currentPermanentElement); 3139 this.delegate.leavingBardo(currentPermanentElement); 3140 } 3141 } 3142 replaceNewPermanentElementWithPlaceholder(permanentElement) { 3143 const placeholder = createPlaceholderForPermanentElement(permanentElement); 3144 permanentElement.replaceWith(placeholder); 3145 } 3146 replaceCurrentPermanentElementWithClone(permanentElement) { 3147 const clone = permanentElement.cloneNode(true); 3148 permanentElement.replaceWith(clone); 3149 } 3150 replacePlaceholderWithPermanentElement(permanentElement) { 3151 const placeholder = this.getPlaceholderById(permanentElement.id); 3152 placeholder?.replaceWith(permanentElement); 3153 } 3154 getPlaceholderById(id) { 3155 return this.placeholders.find((element) => element.content == id); 3156 } 3157 get placeholders() { 3158 return [...document.querySelectorAll("meta[name=turbo-permanent-placeholder][content]")]; 3159 } 3160}; 3161function createPlaceholderForPermanentElement(permanentElement) { 3162 const element = document.createElement("meta"); 3163 element.setAttribute("name", "turbo-permanent-placeholder"); 3164 element.setAttribute("content", permanentElement.id); 3165 return element; 3166} 3167var Renderer = class { 3168 #activeElement = null; 3169 static renderElement(currentElement, newElement) { 3170 } 3171 constructor(currentSnapshot, newSnapshot, isPreview, willRender = true) { 3172 this.currentSnapshot = currentSnapshot; 3173 this.newSnapshot = newSnapshot; 3174 this.isPreview = isPreview; 3175 this.willRender = willRender; 3176 this.renderElement = this.constructor.renderElement; 3177 this.promise = new Promise((resolve, reject) => this.resolvingFunctions = { resolve, reject }); 3178 } 3179 get shouldRender() { 3180 return true; 3181 } 3182 get shouldAutofocus() { 3183 return true; 3184 } 3185 get reloadReason() { 3186 return; 3187 } 3188 prepareToRender() { 3189 return; 3190 } 3191 render() { 3192 } 3193 finishRendering() { 3194 if (this.resolvingFunctions) { 3195 this.resolvingFunctions.resolve(); 3196 delete this.resolvingFunctions; 3197 } 3198 } 3199 async preservingPermanentElements(callback) { 3200 await Bardo.preservingPermanentElements(this, this.permanentElementMap, callback); 3201 } 3202 focusFirstAutofocusableElement() { 3203 if (this.shouldAutofocus) { 3204 const element = this.connectedSnapshot.firstAutofocusableElement; 3205 if (element) { 3206 element.focus(); 3207 } 3208 } 3209 } 3210 // Bardo delegate 3211 enteringBardo(currentPermanentElement) { 3212 if (this.#activeElement) return; 3213 if (currentPermanentElement.contains(this.currentSnapshot.activeElement)) { 3214 this.#activeElement = this.currentSnapshot.activeElement; 3215 } 3216 } 3217 leavingBardo(currentPermanentElement) { 3218 if (currentPermanentElement.contains(this.#activeElement) && this.#activeElement instanceof HTMLElement) { 3219 this.#activeElement.focus(); 3220 this.#activeElement = null; 3221 } 3222 } 3223 get connectedSnapshot() { 3224 return this.newSnapshot.isConnected ? this.newSnapshot : this.currentSnapshot; 3225 } 3226 get currentElement() { 3227 return this.currentSnapshot.element; 3228 } 3229 get newElement() { 3230 return this.newSnapshot.element; 3231 } 3232 get permanentElementMap() { 3233 return this.currentSnapshot.getPermanentElementMapForSnapshot(this.newSnapshot); 3234 } 3235 get renderMethod() { 3236 return "replace"; 3237 } 3238}; 3239var FrameRenderer = class extends Renderer { 3240 static renderElement(currentElement, newElement) { 3241 const destinationRange = document.createRange(); 3242 destinationRange.selectNodeContents(currentElement); 3243 destinationRange.deleteContents(); 3244 const frameElement = newElement; 3245 const sourceRange = frameElement.ownerDocument?.createRange(); 3246 if (sourceRange) { 3247 sourceRange.selectNodeContents(frameElement); 3248 currentElement.appendChild(sourceRange.extractContents()); 3249 } 3250 } 3251 constructor(delegate, currentSnapshot, newSnapshot, renderElement, isPreview, willRender = true) { 3252 super(currentSnapshot, newSnapshot, renderElement, isPreview, willRender); 3253 this.delegate = delegate; 3254 } 3255 get shouldRender() { 3256 return true; 3257 } 3258 async render() { 3259 await nextRepaint(); 3260 this.preservingPermanentElements(() => { 3261 this.loadFrameElement(); 3262 }); 3263 this.scrollFrameIntoView(); 3264 await nextRepaint(); 3265 this.focusFirstAutofocusableElement(); 3266 await nextRepaint(); 3267 this.activateScriptElements(); 3268 } 3269 loadFrameElement() { 3270 this.delegate.willRenderFrame(this.currentElement, this.newElement); 3271 this.renderElement(this.currentElement, this.newElement); 3272 } 3273 scrollFrameIntoView() { 3274 if (this.currentElement.autoscroll || this.newElement.autoscroll) { 3275 const element = this.currentElement.firstElementChild; 3276 const block = readScrollLogicalPosition(this.currentElement.getAttribute("data-autoscroll-block"), "end"); 3277 const behavior = readScrollBehavior(this.currentElement.getAttribute("data-autoscroll-behavior"), "auto"); 3278 if (element) { 3279 element.scrollIntoView({ block, behavior }); 3280 return true; 3281 } 3282 } 3283 return false; 3284 } 3285 activateScriptElements() { 3286 for (const inertScriptElement of this.newScriptElements) { 3287 const activatedScriptElement = activateScriptElement(inertScriptElement); 3288 inertScriptElement.replaceWith(activatedScriptElement); 3289 } 3290 } 3291 get newScriptElements() { 3292 return this.currentElement.querySelectorAll("script"); 3293 } 3294}; 3295function readScrollLogicalPosition(value, defaultValue) { 3296 if (value == "end" || value == "start" || value == "center" || value == "nearest") { 3297 return value; 3298 } else { 3299 return defaultValue; 3300 } 3301} 3302function readScrollBehavior(value, defaultValue) { 3303 if (value == "auto" || value == "smooth") { 3304 return value; 3305 } else { 3306 return defaultValue; 3307 } 3308} 3309var Idiomorph = /* @__PURE__ */ function() { 3310 let EMPTY_SET = /* @__PURE__ */ new Set(); 3311 let defaults = { 3312 morphStyle: "outerHTML", 3313 callbacks: { 3314 beforeNodeAdded: noOp, 3315 afterNodeAdded: noOp, 3316 beforeNodeMorphed: noOp, 3317 afterNodeMorphed: noOp, 3318 beforeNodeRemoved: noOp, 3319 afterNodeRemoved: noOp, 3320 beforeAttributeUpdated: noOp 3321 }, 3322 head: { 3323 style: "merge", 3324 shouldPreserve: function(elt) { 3325 return elt.getAttribute("im-preserve") === "true"; 3326 }, 3327 shouldReAppend: function(elt) { 3328 return elt.getAttribute("im-re-append") === "true"; 3329 }, 3330 shouldRemove: noOp, 3331 afterHeadMorphed: noOp 3332 } 3333 }; 3334 function morph(oldNode, newContent, config2 = {}) { 3335 if (oldNode instanceof Document) { 3336 oldNode = oldNode.documentElement; 3337 } 3338 if (typeof newContent === "string") { 3339 newContent = parseContent(newContent); 3340 } 3341 let normalizedContent = normalizeContent(newContent); 3342 let ctx = createMorphContext(oldNode, normalizedContent, config2); 3343 return morphNormalizedContent(oldNode, normalizedContent, ctx); 3344 } 3345 function morphNormalizedContent(oldNode, normalizedNewContent, ctx) { 3346 if (ctx.head.block) { 3347 let oldHead = oldNode.querySelector("head"); 3348 let newHead = normalizedNewContent.querySelector("head"); 3349 if (oldHead && newHead) { 3350 let promises = handleHeadElement(newHead, oldHead, ctx); 3351 Promise.all(promises).then(function() { 3352 morphNormalizedContent(oldNode, normalizedNewContent, Object.assign(ctx, { 3353 head: { 3354 block: false, 3355 ignore: true 3356 } 3357 })); 3358 }); 3359 return; 3360 } 3361 } 3362 if (ctx.morphStyle === "innerHTML") { 3363 morphChildren2(normalizedNewContent, oldNode, ctx); 3364 return oldNode.children; 3365 } else if (ctx.morphStyle === "outerHTML" || ctx.morphStyle == null) { 3366 let bestMatch = findBestNodeMatch(normalizedNewContent, oldNode, ctx); 3367 let previousSibling = bestMatch?.previousSibling; 3368 let nextSibling = bestMatch?.nextSibling; 3369 let morphedNode = morphOldNodeTo(oldNode, bestMatch, ctx); 3370 if (bestMatch) { 3371 return insertSiblings(previousSibling, morphedNode, nextSibling); 3372 } else { 3373 return []; 3374 } 3375 } else { 3376 throw "Do not understand how to morph style " + ctx.morphStyle; 3377 } 3378 } 3379 function ignoreValueOfActiveElement(possibleActiveElement, ctx) { 3380 return ctx.ignoreActiveValue && possibleActiveElement === document.activeElement && possibleActiveElement !== document.body; 3381 } 3382 function morphOldNodeTo(oldNode, newContent, ctx) { 3383 if (ctx.ignoreActive && oldNode === document.activeElement) ; 3384 else if (newContent == null) { 3385 if (ctx.callbacks.beforeNodeRemoved(oldNode) === false) return oldNode; 3386 oldNode.remove(); 3387 ctx.callbacks.afterNodeRemoved(oldNode); 3388 return null; 3389 } else if (!isSoftMatch(oldNode, newContent)) { 3390 if (ctx.callbacks.beforeNodeRemoved(oldNode) === false) return oldNode; 3391 if (ctx.callbacks.beforeNodeAdded(newContent) === false) return oldNode; 3392 oldNode.parentElement.replaceChild(newContent, oldNode); 3393 ctx.callbacks.afterNodeAdded(newContent); 3394 ctx.callbacks.afterNodeRemoved(oldNode); 3395 return newContent; 3396 } else { 3397 if (ctx.callbacks.beforeNodeMorphed(oldNode, newContent) === false) return oldNode; 3398 if (oldNode instanceof HTMLHeadElement && ctx.head.ignore) ; 3399 else if (oldNode instanceof HTMLHeadElement && ctx.head.style !== "morph") { 3400 handleHeadElement(newContent, oldNode, ctx); 3401 } else { 3402 syncNodeFrom(newContent, oldNode, ctx); 3403 if (!ignoreValueOfActiveElement(oldNode, ctx)) { 3404 morphChildren2(newContent, oldNode, ctx); 3405 } 3406 } 3407 ctx.callbacks.afterNodeMorphed(oldNode, newContent); 3408 return oldNode; 3409 } 3410 } 3411 function morphChildren2(newParent, oldParent, ctx) { 3412 let nextNewChild = newParent.firstChild; 3413 let insertionPoint = oldParent.firstChild; 3414 let newChild; 3415 while (nextNewChild) { 3416 newChild = nextNewChild; 3417 nextNewChild = newChild.nextSibling; 3418 if (insertionPoint == null) { 3419 if (ctx.callbacks.beforeNodeAdded(newChild) === false) return; 3420 oldParent.appendChild(newChild); 3421 ctx.callbacks.afterNodeAdded(newChild); 3422 removeIdsFromConsideration(ctx, newChild); 3423 continue; 3424 } 3425 if (isIdSetMatch(newChild, insertionPoint, ctx)) { 3426 morphOldNodeTo(insertionPoint, newChild, ctx); 3427 insertionPoint = insertionPoint.nextSibling; 3428 removeIdsFromConsideration(ctx, newChild); 3429 continue; 3430 } 3431 let idSetMatch = findIdSetMatch(newParent, oldParent, newChild, insertionPoint, ctx); 3432 if (idSetMatch) { 3433 insertionPoint = removeNodesBetween(insertionPoint, idSetMatch, ctx); 3434 morphOldNodeTo(idSetMatch, newChild, ctx); 3435 removeIdsFromConsideration(ctx, newChild); 3436 continue; 3437 } 3438 let softMatch = findSoftMatch(newParent, oldParent, newChild, insertionPoint, ctx); 3439 if (softMatch) { 3440 insertionPoint = removeNodesBetween(insertionPoint, softMatch, ctx); 3441 morphOldNodeTo(softMatch, newChild, ctx); 3442 removeIdsFromConsideration(ctx, newChild); 3443 continue; 3444 } 3445 if (ctx.callbacks.beforeNodeAdded(newChild) === false) return; 3446 oldParent.insertBefore(newChild, insertionPoint); 3447 ctx.callbacks.afterNodeAdded(newChild); 3448 removeIdsFromConsideration(ctx, newChild); 3449 } 3450 while (insertionPoint !== null) { 3451 let tempNode = insertionPoint; 3452 insertionPoint = insertionPoint.nextSibling; 3453 removeNode(tempNode, ctx); 3454 } 3455 } 3456 function ignoreAttribute(attr, to, updateType, ctx) { 3457 if (attr === "value" && ctx.ignoreActiveValue && to === document.activeElement) { 3458 return true; 3459 } 3460 return ctx.callbacks.beforeAttributeUpdated(attr, to, updateType) === false; 3461 } 3462 function syncNodeFrom(from, to, ctx) { 3463 let type = from.nodeType; 3464 if (type === 1) { 3465 const fromAttributes = from.attributes; 3466 const toAttributes = to.attributes; 3467 for (const fromAttribute of fromAttributes) { 3468 if (ignoreAttribute(fromAttribute.name, to, "update", ctx)) { 3469 continue; 3470 } 3471 if (to.getAttribute(fromAttribute.name) !== fromAttribute.value) { 3472 to.setAttribute(fromAttribute.name, fromAttribute.value); 3473 } 3474 } 3475 for (let i = toAttributes.length - 1; 0 <= i; i--) { 3476 const toAttribute = toAttributes[i]; 3477 if (ignoreAttribute(toAttribute.name, to, "remove", ctx)) { 3478 continue; 3479 } 3480 if (!from.hasAttribute(toAttribute.name)) { 3481 to.removeAttribute(toAttribute.name); 3482 } 3483 } 3484 } 3485 if (type === 8 || type === 3) { 3486 if (to.nodeValue !== from.nodeValue) { 3487 to.nodeValue = from.nodeValue; 3488 } 3489 } 3490 if (!ignoreValueOfActiveElement(to, ctx)) { 3491 syncInputValue(from, to, ctx); 3492 } 3493 } 3494 function syncBooleanAttribute(from, to, attributeName, ctx) { 3495 if (from[attributeName] !== to[attributeName]) { 3496 let ignoreUpdate = ignoreAttribute(attributeName, to, "update", ctx); 3497 if (!ignoreUpdate) { 3498 to[attributeName] = from[attributeName]; 3499 } 3500 if (from[attributeName]) { 3501 if (!ignoreUpdate) { 3502 to.setAttribute(attributeName, from[attributeName]); 3503 } 3504 } else { 3505 if (!ignoreAttribute(attributeName, to, "remove", ctx)) { 3506 to.removeAttribute(attributeName); 3507 } 3508 } 3509 } 3510 } 3511 function syncInputValue(from, to, ctx) { 3512 if (from instanceof HTMLInputElement && to instanceof HTMLInputElement && from.type !== "file") { 3513 let fromValue = from.value; 3514 let toValue = to.value; 3515 syncBooleanAttribute(from, to, "checked", ctx); 3516 syncBooleanAttribute(from, to, "disabled", ctx); 3517 if (!from.hasAttribute("value")) { 3518 if (!ignoreAttribute("value", to, "remove", ctx)) { 3519 to.value = ""; 3520 to.removeAttribute("value"); 3521 } 3522 } else if (fromValue !== toValue) { 3523 if (!ignoreAttribute("value", to, "update", ctx)) { 3524 to.setAttribute("value", fromValue); 3525 to.value = fromValue; 3526 } 3527 } 3528 } else if (from instanceof HTMLOptionElement) { 3529 syncBooleanAttribute(from, to, "selected", ctx); 3530 } else if (from instanceof HTMLTextAreaElement && to instanceof HTMLTextAreaElement) { 3531 let fromValue = from.value; 3532 let toValue = to.value; 3533 if (ignoreAttribute("value", to, "update", ctx)) { 3534 return; 3535 } 3536 if (fromValue !== toValue) { 3537 to.value = fromValue; 3538 } 3539 if (to.firstChild && to.firstChild.nodeValue !== fromValue) { 3540 to.firstChild.nodeValue = fromValue; 3541 } 3542 } 3543 } 3544 function handleHeadElement(newHeadTag, currentHead, ctx) { 3545 let added = []; 3546 let removed = []; 3547 let preserved = []; 3548 let nodesToAppend = []; 3549 let headMergeStyle = ctx.head.style; 3550 let srcToNewHeadNodes = /* @__PURE__ */ new Map(); 3551 for (const newHeadChild of newHeadTag.children) { 3552 srcToNewHeadNodes.set(newHeadChild.outerHTML, newHeadChild); 3553 } 3554 for (const currentHeadElt of currentHead.children) { 3555 let inNewContent = srcToNewHeadNodes.has(currentHeadElt.outerHTML); 3556 let isReAppended = ctx.head.shouldReAppend(currentHeadElt); 3557 let isPreserved = ctx.head.shouldPreserve(currentHeadElt); 3558 if (inNewContent || isPreserved) { 3559 if (isReAppended) { 3560 removed.push(currentHeadElt); 3561 } else { 3562 srcToNewHeadNodes.delete(currentHeadElt.outerHTML); 3563 preserved.push(currentHeadElt); 3564 } 3565 } else { 3566 if (headMergeStyle === "append") { 3567 if (isReAppended) { 3568 removed.push(currentHeadElt); 3569 nodesToAppend.push(currentHeadElt); 3570 } 3571 } else { 3572 if (ctx.head.shouldRemove(currentHeadElt) !== false) { 3573 removed.push(currentHeadElt); 3574 } 3575 } 3576 } 3577 } 3578 nodesToAppend.push(...srcToNewHeadNodes.values()); 3579 let promises = []; 3580 for (const newNode of nodesToAppend) { 3581 let newElt = document.createRange().createContextualFragment(newNode.outerHTML).firstChild; 3582 if (ctx.callbacks.beforeNodeAdded(newElt) !== false) { 3583 if (newElt.href || newElt.src) { 3584 let resolve = null; 3585 let promise = new Promise(function(_resolve) { 3586 resolve = _resolve; 3587 }); 3588 newElt.addEventListener("load", function() { 3589 resolve(); 3590 }); 3591 promises.push(promise); 3592 } 3593 currentHead.appendChild(newElt); 3594 ctx.callbacks.afterNodeAdded(newElt); 3595 added.push(newElt); 3596 } 3597 } 3598 for (const removedElement of removed) { 3599 if (ctx.callbacks.beforeNodeRemoved(removedElement) !== false) { 3600 currentHead.removeChild(removedElement); 3601 ctx.callbacks.afterNodeRemoved(removedElement); 3602 } 3603 } 3604 ctx.head.afterHeadMorphed(currentHead, { added, kept: preserved, removed }); 3605 return promises; 3606 } 3607 function noOp() { 3608 } 3609 function mergeDefaults(config2) { 3610 let finalConfig = {}; 3611 Object.assign(finalConfig, defaults); 3612 Object.assign(finalConfig, config2); 3613 finalConfig.callbacks = {}; 3614 Object.assign(finalConfig.callbacks, defaults.callbacks); 3615 Object.assign(finalConfig.callbacks, config2.callbacks); 3616 finalConfig.head = {}; 3617 Object.assign(finalConfig.head, defaults.head); 3618 Object.assign(finalConfig.head, config2.head); 3619 return finalConfig; 3620 } 3621 function createMorphContext(oldNode, newContent, config2) { 3622 config2 = mergeDefaults(config2); 3623 return { 3624 target: oldNode, 3625 newContent, 3626 config: config2, 3627 morphStyle: config2.morphStyle, 3628 ignoreActive: config2.ignoreActive, 3629 ignoreActiveValue: config2.ignoreActiveValue, 3630 idMap: createIdMap(oldNode, newContent), 3631 deadIds: /* @__PURE__ */ new Set(), 3632 callbacks: config2.callbacks, 3633 head: config2.head 3634 }; 3635 } 3636 function isIdSetMatch(node1, node2, ctx) { 3637 if (node1 == null || node2 == null) { 3638 return false; 3639 } 3640 if (node1.nodeType === node2.nodeType && node1.tagName === node2.tagName) { 3641 if (node1.id !== "" && node1.id === node2.id) { 3642 return true; 3643 } else { 3644 return getIdIntersectionCount(ctx, node1, node2) > 0; 3645 } 3646 } 3647 return false; 3648 } 3649 function isSoftMatch(node1, node2) { 3650 if (node1 == null || node2 == null) { 3651 return false; 3652 } 3653 return node1.nodeType === node2.nodeType && node1.tagName === node2.tagName; 3654 } 3655 function removeNodesBetween(startInclusive, endExclusive, ctx) { 3656 while (startInclusive !== endExclusive) { 3657 let tempNode = startInclusive; 3658 startInclusive = startInclusive.nextSibling; 3659 removeNode(tempNode, ctx); 3660 } 3661 removeIdsFromConsideration(ctx, endExclusive); 3662 return endExclusive.nextSibling; 3663 } 3664 function findIdSetMatch(newContent, oldParent, newChild, insertionPoint, ctx) { 3665 let newChildPotentialIdCount = getIdIntersectionCount(ctx, newChild, oldParent); 3666 let potentialMatch = null; 3667 if (newChildPotentialIdCount > 0) { 3668 let potentialMatch2 = insertionPoint; 3669 let otherMatchCount = 0; 3670 while (potentialMatch2 != null) { 3671 if (isIdSetMatch(newChild, potentialMatch2, ctx)) { 3672 return potentialMatch2; 3673 } 3674 otherMatchCount += getIdIntersectionCount(ctx, potentialMatch2, newContent); 3675 if (otherMatchCount > newChildPotentialIdCount) { 3676 return null; 3677 } 3678 potentialMatch2 = potentialMatch2.nextSibling; 3679 } 3680 } 3681 return potentialMatch; 3682 } 3683 function findSoftMatch(newContent, oldParent, newChild, insertionPoint, ctx) { 3684 let potentialSoftMatch = insertionPoint; 3685 let nextSibling = newChild.nextSibling; 3686 let siblingSoftMatchCount = 0; 3687 while (potentialSoftMatch != null) { 3688 if (getIdIntersectionCount(ctx, potentialSoftMatch, newContent) > 0) { 3689 return null; 3690 } 3691 if (isSoftMatch(newChild, potentialSoftMatch)) { 3692 return potentialSoftMatch; 3693 } 3694 if (isSoftMatch(nextSibling, potentialSoftMatch)) { 3695 siblingSoftMatchCount++; 3696 nextSibling = nextSibling.nextSibling; 3697 if (siblingSoftMatchCount >= 2) { 3698 return null; 3699 } 3700 } 3701 potentialSoftMatch = potentialSoftMatch.nextSibling; 3702 } 3703 return potentialSoftMatch; 3704 } 3705 function parseContent(newContent) { 3706 let parser = new DOMParser(); 3707 let contentWithSvgsRemoved = newContent.replace(/<svg(\s[^>]*>|>)([\s\S]*?)<\/svg>/gim, ""); 3708 if (contentWithSvgsRemoved.match(/<\/html>/) || contentWithSvgsRemoved.match(/<\/head>/) || contentWithSvgsRemoved.match(/<\/body>/)) { 3709 let content = parser.parseFromString(newContent, "text/html"); 3710 if (contentWithSvgsRemoved.match(/<\/html>/)) { 3711 content.generatedByIdiomorph = true; 3712 return content; 3713 } else { 3714 let htmlElement = content.firstChild; 3715 if (htmlElement) { 3716 htmlElement.generatedByIdiomorph = true; 3717 return htmlElement; 3718 } else { 3719 return null; 3720 } 3721 } 3722 } else { 3723 let responseDoc = parser.parseFromString("<body><template>" + newContent + "</template></body>", "text/html"); 3724 let content = responseDoc.body.querySelector("template").content; 3725 content.generatedByIdiomorph = true; 3726 return content; 3727 } 3728 } 3729 function normalizeContent(newContent) { 3730 if (newContent == null) { 3731 const dummyParent = document.createElement("div"); 3732 return dummyParent; 3733 } else if (newContent.generatedByIdiomorph) { 3734 return newContent; 3735 } else if (newContent instanceof Node) { 3736 const dummyParent = document.createElement("div"); 3737 dummyParent.append(newContent); 3738 return dummyParent; 3739 } else { 3740 const dummyParent = document.createElement("div"); 3741 for (const elt of [...newContent]) { 3742 dummyParent.append(elt); 3743 } 3744 return dummyParent; 3745 } 3746 } 3747 function insertSiblings(previousSibling, morphedNode, nextSibling) { 3748 let stack = []; 3749 let added = []; 3750 while (previousSibling != null) { 3751 stack.push(previousSibling); 3752 previousSibling = previousSibling.previousSibling; 3753 } 3754 while (stack.length > 0) { 3755 let node = stack.pop(); 3756 added.push(node); 3757 morphedNode.parentElement.insertBefore(node, morphedNode); 3758 } 3759 added.push(morphedNode); 3760 while (nextSibling != null) { 3761 stack.push(nextSibling); 3762 added.push(nextSibling); 3763 nextSibling = nextSibling.nextSibling; 3764 } 3765 while (stack.length > 0) { 3766 morphedNode.parentElement.insertBefore(stack.pop(), morphedNode.nextSibling); 3767 } 3768 return added; 3769 } 3770 function findBestNodeMatch(newContent, oldNode, ctx) { 3771 let currentElement; 3772 currentElement = newContent.firstChild; 3773 let bestElement = currentElement; 3774 let score = 0; 3775 while (currentElement) { 3776 let newScore = scoreElement(currentElement, oldNode, ctx); 3777 if (newScore > score) { 3778 bestElement = currentElement; 3779 score = newScore; 3780 } 3781 currentElement = currentElement.nextSibling; 3782 } 3783 return bestElement; 3784 } 3785 function scoreElement(node1, node2, ctx) { 3786 if (isSoftMatch(node1, node2)) { 3787 return 0.5 + getIdIntersectionCount(ctx, node1, node2); 3788 } 3789 return 0; 3790 } 3791 function removeNode(tempNode, ctx) { 3792 removeIdsFromConsideration(ctx, tempNode); 3793 if (ctx.callbacks.beforeNodeRemoved(tempNode) === false) return; 3794 tempNode.remove(); 3795 ctx.callbacks.afterNodeRemoved(tempNode); 3796 } 3797 function isIdInConsideration(ctx, id) { 3798 return !ctx.deadIds.has(id); 3799 } 3800 function idIsWithinNode(ctx, id, targetNode) { 3801 let idSet = ctx.idMap.get(targetNode) || EMPTY_SET; 3802 return idSet.has(id); 3803 } 3804 function removeIdsFromConsideration(ctx, node) { 3805 let idSet = ctx.idMap.get(node) || EMPTY_SET; 3806 for (const id of idSet) { 3807 ctx.deadIds.add(id); 3808 } 3809 } 3810 function getIdIntersectionCount(ctx, node1, node2) { 3811 let sourceSet = ctx.idMap.get(node1) || EMPTY_SET; 3812 let matchCount = 0; 3813 for (const id of sourceSet) { 3814 if (isIdInConsideration(ctx, id) && idIsWithinNode(ctx, id, node2)) { 3815 ++matchCount; 3816 } 3817 } 3818 return matchCount; 3819 } 3820 function populateIdMapForNode(node, idMap) { 3821 let nodeParent = node.parentElement; 3822 let idElements = node.querySelectorAll("[id]"); 3823 for (const elt of idElements) { 3824 let current = elt; 3825 while (current !== nodeParent && current != null) { 3826 let idSet = idMap.get(current); 3827 if (idSet == null) { 3828 idSet = /* @__PURE__ */ new Set(); 3829 idMap.set(current, idSet); 3830 } 3831 idSet.add(elt.id); 3832 current = current.parentElement; 3833 } 3834 } 3835 } 3836 function createIdMap(oldContent, newContent) { 3837 let idMap = /* @__PURE__ */ new Map(); 3838 populateIdMapForNode(oldContent, idMap); 3839 populateIdMapForNode(newContent, idMap); 3840 return idMap; 3841 } 3842 return { 3843 morph, 3844 defaults 3845 }; 3846}(); 3847function morphElements(currentElement, newElement, { callbacks, ...options } = {}) { 3848 Idiomorph.morph(currentElement, newElement, { 3849 ...options, 3850 callbacks: new DefaultIdiomorphCallbacks(callbacks) 3851 }); 3852} 3853function morphChildren(currentElement, newElement) { 3854 morphElements(currentElement, newElement.children, { 3855 morphStyle: "innerHTML" 3856 }); 3857} 3858var DefaultIdiomorphCallbacks = class { 3859 #beforeNodeMorphed; 3860 constructor({ beforeNodeMorphed } = {}) { 3861 this.#beforeNodeMorphed = beforeNodeMorphed || (() => true); 3862 } 3863 beforeNodeAdded = (node) => { 3864 return !(node.id && node.hasAttribute("data-turbo-permanent") && document.getElementById(node.id)); 3865 }; 3866 beforeNodeMorphed = (currentElement, newElement) => { 3867 if (currentElement instanceof Element) { 3868 if (!currentElement.hasAttribute("data-turbo-permanent") && this.#beforeNodeMorphed(currentElement, newElement)) { 3869 const event = dispatch("turbo:before-morph-element", { 3870 cancelable: true, 3871 target: currentElement, 3872 detail: { currentElement, newElement } 3873 }); 3874 return !event.defaultPrevented; 3875 } else { 3876 return false; 3877 } 3878 } 3879 }; 3880 beforeAttributeUpdated = (attributeName, target, mutationType) => { 3881 const event = dispatch("turbo:before-morph-attribute", { 3882 cancelable: true, 3883 target, 3884 detail: { attributeName, mutationType } 3885 }); 3886 return !event.defaultPrevented; 3887 }; 3888 beforeNodeRemoved = (node) => { 3889 return this.beforeNodeMorphed(node); 3890 }; 3891 afterNodeMorphed = (currentElement, newElement) => { 3892 if (currentElement instanceof Element) { 3893 dispatch("turbo:morph-element", { 3894 target: currentElement, 3895 detail: { currentElement, newElement } 3896 }); 3897 } 3898 }; 3899}; 3900var MorphingFrameRenderer = class extends FrameRenderer { 3901 static renderElement(currentElement, newElement) { 3902 dispatch("turbo:before-frame-morph", { 3903 target: currentElement, 3904 detail: { currentElement, newElement } 3905 }); 3906 morphChildren(currentElement, newElement); 3907 } 3908 async preservingPermanentElements(callback) { 3909 return await callback(); 3910 } 3911}; 3912var ProgressBar = class _ProgressBar { 3913 static animationDuration = 300; 3914 /*ms*/ 3915 static get defaultCSS() { 3916 return unindent` 3917 .turbo-progress-bar { 3918 position: fixed; 3919 display: block; 3920 top: 0; 3921 left: 0; 3922 height: 3px; 3923 background: #0076ff; 3924 z-index: 2147483647; 3925 transition: 3926 width ${_ProgressBar.animationDuration}ms ease-out, 3927 opacity ${_ProgressBar.animationDuration / 2}ms ${_ProgressBar.animationDuration / 2}ms ease-in; 3928 transform: translate3d(0, 0, 0); 3929 } 3930 `; 3931 } 3932 hiding = false; 3933 value = 0; 3934 visible = false; 3935 constructor() { 3936 this.stylesheetElement = this.createStylesheetElement(); 3937 this.progressElement = this.createProgressElement(); 3938 this.installStylesheetElement(); 3939 this.setValue(0); 3940 } 3941 show() { 3942 if (!this.visible) { 3943 this.visible = true; 3944 this.installProgressElement(); 3945 this.startTrickling(); 3946 } 3947 } 3948 hide() { 3949 if (this.visible && !this.hiding) { 3950 this.hiding = true; 3951 this.fadeProgressElement(() => { 3952 this.uninstallProgressElement(); 3953 this.stopTrickling(); 3954 this.visible = false; 3955 this.hiding = false; 3956 }); 3957 } 3958 } 3959 setValue(value) { 3960 this.value = value; 3961 this.refresh(); 3962 } 3963 // Private 3964 installStylesheetElement() { 3965 document.head.insertBefore(this.stylesheetElement, document.head.firstChild); 3966 } 3967 installProgressElement() { 3968 this.progressElement.style.width = "0"; 3969 this.progressElement.style.opacity = "1"; 3970 document.documentElement.insertBefore(this.progressElement, document.body); 3971 this.refresh(); 3972 } 3973 fadeProgressElement(callback) { 3974 this.progressElement.style.opacity = "0"; 3975 setTimeout(callback, _ProgressBar.animationDuration * 1.5); 3976 } 3977 uninstallProgressElement() { 3978 if (this.progressElement.parentNode) { 3979 document.documentElement.removeChild(this.progressElement); 3980 } 3981 } 3982 startTrickling() { 3983 if (!this.trickleInterval) { 3984 this.trickleInterval = window.setInterval(this.trickle, _ProgressBar.animationDuration); 3985 } 3986 } 3987 stopTrickling() { 3988 window.clearInterval(this.trickleInterval); 3989 delete this.trickleInterval; 3990 } 3991 trickle = () => { 3992 this.setValue(this.value + Math.random() / 100); 3993 }; 3994 refresh() { 3995 requestAnimationFrame(() => { 3996 this.progressElement.style.width = `${10 + this.value * 90}%`; 3997 }); 3998 } 3999 createStylesheetElement() { 4000 const element = document.createElement("style"); 4001 element.type = "text/css"; 4002 element.textContent = _ProgressBar.defaultCSS; 4003 if (this.cspNonce) { 4004 element.nonce = this.cspNonce; 4005 } 4006 return element; 4007 } 4008 createProgressElement() { 4009 const element = document.createElement("div"); 4010 element.className = "turbo-progress-bar"; 4011 return element; 4012 } 4013 get cspNonce() { 4014 return getMetaContent("csp-nonce"); 4015 } 4016}; 4017var HeadSnapshot = class extends Snapshot { 4018 detailsByOuterHTML = this.children.filter((element) => !elementIsNoscript(element)).map((element) => elementWithoutNonce(element)).reduce((result, element) => { 4019 const { outerHTML } = element; 4020 const details = outerHTML in result ? result[outerHTML] : { 4021 type: elementType(element), 4022 tracked: elementIsTracked(element), 4023 elements: [] 4024 }; 4025 return { 4026 ...result, 4027 [outerHTML]: { 4028 ...details, 4029 elements: [...details.elements, element] 4030 } 4031 }; 4032 }, {}); 4033 get trackedElementSignature() { 4034 return Object.keys(this.detailsByOuterHTML).filter((outerHTML) => this.detailsByOuterHTML[outerHTML].tracked).join(""); 4035 } 4036 getScriptElementsNotInSnapshot(snapshot) { 4037 return this.getElementsMatchingTypeNotInSnapshot("script", snapshot); 4038 } 4039 getStylesheetElementsNotInSnapshot(snapshot) { 4040 return this.getElementsMatchingTypeNotInSnapshot("stylesheet", snapshot); 4041 } 4042 getElementsMatchingTypeNotInSnapshot(matchedType, snapshot) { 4043 return Object.keys(this.detailsByOuterHTML).filter((outerHTML) => !(outerHTML in snapshot.detailsByOuterHTML)).map((outerHTML) => this.detailsByOuterHTML[outerHTML]).filter(({ type }) => type == matchedType).map(({ elements: [element] }) => element); 4044 } 4045 get provisionalElements() { 4046 return Object.keys(this.detailsByOuterHTML).reduce((result, outerHTML) => { 4047 const { type, tracked, elements } = this.detailsByOuterHTML[outerHTML]; 4048 if (type == null && !tracked) { 4049 return [...result, ...elements]; 4050 } else if (elements.length > 1) { 4051 return [...result, ...elements.slice(1)]; 4052 } else { 4053 return result; 4054 } 4055 }, []); 4056 } 4057 getMetaValue(name) { 4058 const element = this.findMetaElementByName(name); 4059 return element ? element.getAttribute("content") : null; 4060 } 4061 findMetaElementByName(name) { 4062 return Object.keys(this.detailsByOuterHTML).reduce((result, outerHTML) => { 4063 const { 4064 elements: [element] 4065 } = this.detailsByOuterHTML[outerHTML]; 4066 return elementIsMetaElementWithName(element, name) ? element : result; 4067 }, void 0 | void 0); 4068 } 4069}; 4070function elementType(element) { 4071 if (elementIsScript(element)) { 4072 return "script"; 4073 } else if (elementIsStylesheet(element)) { 4074 return "stylesheet"; 4075 } 4076} 4077function elementIsTracked(element) { 4078 return element.getAttribute("data-turbo-track") == "reload"; 4079} 4080function elementIsScript(element) { 4081 const tagName = element.localName; 4082 return tagName == "script"; 4083} 4084function elementIsNoscript(element) { 4085 const tagName = element.localName; 4086 return tagName == "noscript"; 4087} 4088function elementIsStylesheet(element) { 4089 const tagName = element.localName; 4090 return tagName == "style" || tagName == "link" && element.getAttribute("rel") == "stylesheet"; 4091} 4092function elementIsMetaElementWithName(element, name) { 4093 const tagName = element.localName; 4094 return tagName == "meta" && element.getAttribute("name") == name; 4095} 4096function elementWithoutNonce(element) { 4097 if (element.hasAttribute("nonce")) { 4098 element.setAttribute("nonce", ""); 4099 } 4100 return element; 4101} 4102var PageSnapshot = class _PageSnapshot extends Snapshot { 4103 static fromHTMLString(html = "") { 4104 return this.fromDocument(parseHTMLDocument(html)); 4105 } 4106 static fromElement(element) { 4107 return this.fromDocument(element.ownerDocument); 4108 } 4109 static fromDocument({ documentElement, body, head }) { 4110 return new this(documentElement, body, new HeadSnapshot(head)); 4111 } 4112 constructor(documentElement, body, headSnapshot) { 4113 super(body); 4114 this.documentElement = documentElement; 4115 this.headSnapshot = headSnapshot; 4116 } 4117 clone() { 4118 const clonedElement = this.element.cloneNode(true); 4119 const selectElements = this.element.querySelectorAll("select"); 4120 const clonedSelectElements = clonedElement.querySelectorAll("select"); 4121 for (const [index, source] of selectElements.entries()) { 4122 const clone = clonedSelectElements[index]; 4123 for (const option of clone.selectedOptions) option.selected = false; 4124 for (const option of source.selectedOptions) clone.options[option.index].selected = true; 4125 } 4126 for (const clonedPasswordInput of clonedElement.querySelectorAll('input[type="password"]')) { 4127 clonedPasswordInput.value = ""; 4128 } 4129 return new _PageSnapshot(this.documentElement, clonedElement, this.headSnapshot); 4130 } 4131 get lang() { 4132 return this.documentElement.getAttribute("lang"); 4133 } 4134 get headElement() { 4135 return this.headSnapshot.element; 4136 } 4137 get rootLocation() { 4138 const root = this.getSetting("root") ?? "/"; 4139 return expandURL(root); 4140 } 4141 get cacheControlValue() { 4142 return this.getSetting("cache-control"); 4143 } 4144 get isPreviewable() { 4145 return this.cacheControlValue != "no-preview"; 4146 } 4147 get isCacheable() { 4148 return this.cacheControlValue != "no-cache"; 4149 } 4150 get isVisitable() { 4151 return this.getSetting("visit-control") != "reload"; 4152 } 4153 get prefersViewTransitions() { 4154 return this.headSnapshot.getMetaValue("view-transition") === "same-origin"; 4155 } 4156 get shouldMorphPage() { 4157 return this.getSetting("refresh-method") === "morph"; 4158 } 4159 get shouldPreserveScrollPosition() { 4160 return this.getSetting("refresh-scroll") === "preserve"; 4161 } 4162 // Private 4163 getSetting(name) { 4164 return this.headSnapshot.getMetaValue(`turbo-${name}`); 4165 } 4166}; 4167var ViewTransitioner = class { 4168 #viewTransitionStarted = false; 4169 #lastOperation = Promise.resolve(); 4170 renderChange(useViewTransition, render) { 4171 if (useViewTransition && this.viewTransitionsAvailable && !this.#viewTransitionStarted) { 4172 this.#viewTransitionStarted = true; 4173 this.#lastOperation = this.#lastOperation.then(async () => { 4174 await document.startViewTransition(render).finished; 4175 }); 4176 } else { 4177 this.#lastOperation = this.#lastOperation.then(render); 4178 } 4179 return this.#lastOperation; 4180 } 4181 get viewTransitionsAvailable() { 4182 return document.startViewTransition; 4183 } 4184}; 4185var defaultOptions = { 4186 action: "advance", 4187 historyChanged: false, 4188 visitCachedSnapshot: () => { 4189 }, 4190 willRender: true, 4191 updateHistory: true, 4192 shouldCacheSnapshot: true, 4193 acceptsStreamResponse: false 4194}; 4195var TimingMetric = { 4196 visitStart: "visitStart", 4197 requestStart: "requestStart", 4198 requestEnd: "requestEnd", 4199 visitEnd: "visitEnd" 4200}; 4201var VisitState = { 4202 initialized: "initialized", 4203 started: "started", 4204 canceled: "canceled", 4205 failed: "failed", 4206 completed: "completed" 4207}; 4208var SystemStatusCode = { 4209 networkFailure: 0, 4210 timeoutFailure: -1, 4211 contentTypeMismatch: -2 4212}; 4213var Direction = { 4214 advance: "forward", 4215 restore: "back", 4216 replace: "none" 4217}; 4218var Visit = class { 4219 identifier = uuid(); 4220 // Required by turbo-ios 4221 timingMetrics = {}; 4222 followedRedirect = false; 4223 historyChanged = false; 4224 scrolled = false; 4225 shouldCacheSnapshot = true; 4226 acceptsStreamResponse = false; 4227 snapshotCached = false; 4228 state = VisitState.initialized; 4229 viewTransitioner = new ViewTransitioner(); 4230 constructor(delegate, location2, restorationIdentifier, options = {}) { 4231 this.delegate = delegate; 4232 this.location = location2; 4233 this.restorationIdentifier = restorationIdentifier || uuid(); 4234 const { 4235 action, 4236 historyChanged, 4237 referrer, 4238 snapshot, 4239 snapshotHTML, 4240 response, 4241 visitCachedSnapshot, 4242 willRender, 4243 updateHistory, 4244 shouldCacheSnapshot, 4245 acceptsStreamResponse, 4246 direction 4247 } = { 4248 ...defaultOptions, 4249 ...options 4250 }; 4251 this.action = action; 4252 this.historyChanged = historyChanged; 4253 this.referrer = referrer; 4254 this.snapshot = snapshot; 4255 this.snapshotHTML = snapshotHTML; 4256 this.response = response; 4257 this.isSamePage = this.delegate.locationWithActionIsSamePage(this.location, this.action); 4258 this.isPageRefresh = this.view.isPageRefresh(this); 4259 this.visitCachedSnapshot = visitCachedSnapshot; 4260 this.willRender = willRender; 4261 this.updateHistory = updateHistory; 4262 this.scrolled = !willRender; 4263 this.shouldCacheSnapshot = shouldCacheSnapshot; 4264 this.acceptsStreamResponse = acceptsStreamResponse; 4265 this.direction = direction || Direction[action]; 4266 } 4267 get adapter() { 4268 return this.delegate.adapter; 4269 } 4270 get view() { 4271 return this.delegate.view; 4272 } 4273 get history() { 4274 return this.delegate.history; 4275 } 4276 get restorationData() { 4277 return this.history.getRestorationDataForIdentifier(this.restorationIdentifier); 4278 } 4279 get silent() { 4280 return this.isSamePage; 4281 } 4282 start() { 4283 if (this.state == VisitState.initialized) { 4284 this.recordTimingMetric(TimingMetric.visitStart); 4285 this.state = VisitState.started; 4286 this.adapter.visitStarted(this); 4287 this.delegate.visitStarted(this); 4288 } 4289 } 4290 cancel() { 4291 if (this.state == VisitState.started) { 4292 if (this.request) { 4293 this.request.cancel(); 4294 } 4295 this.cancelRender(); 4296 this.state = VisitState.canceled; 4297 } 4298 } 4299 complete() { 4300 if (this.state == VisitState.started) { 4301 this.recordTimingMetric(TimingMetric.visitEnd); 4302 this.adapter.visitCompleted(this); 4303 this.state = VisitState.completed; 4304 this.followRedirect(); 4305 if (!this.followedRedirect) { 4306 this.delegate.visitCompleted(this); 4307 } 4308 } 4309 } 4310 fail() { 4311 if (this.state == VisitState.started) { 4312 this.state = VisitState.failed; 4313 this.adapter.visitFailed(this); 4314 this.delegate.visitCompleted(this); 4315 } 4316 } 4317 changeHistory() { 4318 if (!this.historyChanged && this.updateHistory) { 4319 const actionForHistory = this.location.href === this.referrer?.href ? "replace" : this.action; 4320 const method = getHistoryMethodForAction(actionForHistory); 4321 this.history.update(method, this.location, this.restorationIdentifier); 4322 this.historyChanged = true; 4323 } 4324 } 4325 issueRequest() { 4326 if (this.hasPreloadedResponse()) { 4327 this.simulateRequest(); 4328 } else if (this.shouldIssueRequest() && !this.request) { 4329 this.request = new FetchRequest(this, FetchMethod.get, this.location); 4330 this.request.perform(); 4331 } 4332 } 4333 simulateRequest() { 4334 if (this.response) { 4335 this.startRequest(); 4336 this.recordResponse(); 4337 this.finishRequest(); 4338 } 4339 } 4340 startRequest() { 4341 this.recordTimingMetric(TimingMetric.requestStart); 4342 this.adapter.visitRequestStarted(this); 4343 } 4344 recordResponse(response = this.response) { 4345 this.response = response; 4346 if (response) { 4347 const { statusCode } = response; 4348 if (isSuccessful(statusCode)) { 4349 this.adapter.visitRequestCompleted(this); 4350 } else { 4351 this.adapter.visitRequestFailedWithStatusCode(this, statusCode); 4352 } 4353 } 4354 } 4355 finishRequest() { 4356 this.recordTimingMetric(TimingMetric.requestEnd); 4357 this.adapter.visitRequestFinished(this); 4358 } 4359 loadResponse() { 4360 if (this.response) { 4361 const { statusCode, responseHTML } = this.response; 4362 this.render(async () => { 4363 if (this.shouldCacheSnapshot) this.cacheSnapshot(); 4364 if (this.view.renderPromise) await this.view.renderPromise; 4365 if (isSuccessful(statusCode) && responseHTML != null) { 4366 const snapshot = PageSnapshot.fromHTMLString(responseHTML); 4367 await this.renderPageSnapshot(snapshot, false); 4368 this.adapter.visitRendered(this); 4369 this.complete(); 4370 } else { 4371 await this.view.renderError(PageSnapshot.fromHTMLString(responseHTML), this); 4372 this.adapter.visitRendered(this); 4373 this.fail(); 4374 } 4375 }); 4376 } 4377 } 4378 getCachedSnapshot() { 4379 const snapshot = this.view.getCachedSnapshotForLocation(this.location) || this.getPreloadedSnapshot(); 4380 if (snapshot && (!getAnchor(this.location) || snapshot.hasAnchor(getAnchor(this.location)))) { 4381 if (this.action == "restore" || snapshot.isPreviewable) { 4382 return snapshot; 4383 } 4384 } 4385 } 4386 getPreloadedSnapshot() { 4387 if (this.snapshotHTML) { 4388 return PageSnapshot.fromHTMLString(this.snapshotHTML); 4389 } 4390 } 4391 hasCachedSnapshot() { 4392 return this.getCachedSnapshot() != null; 4393 } 4394 loadCachedSnapshot() { 4395 const snapshot = this.getCachedSnapshot(); 4396 if (snapshot) { 4397 const isPreview = this.shouldIssueRequest(); 4398 this.render(async () => { 4399 this.cacheSnapshot(); 4400 if (this.isSamePage || this.isPageRefresh) { 4401 this.adapter.visitRendered(this); 4402 } else { 4403 if (this.view.renderPromise) await this.view.renderPromise; 4404 await this.renderPageSnapshot(snapshot, isPreview); 4405 this.adapter.visitRendered(this); 4406 if (!isPreview) { 4407 this.complete(); 4408 } 4409 } 4410 }); 4411 } 4412 } 4413 followRedirect() { 4414 if (this.redirectedToLocation && !this.followedRedirect && this.response?.redirected) { 4415 this.adapter.visitProposedToLocation(this.redirectedToLocation, { 4416 action: "replace", 4417 response: this.response, 4418 shouldCacheSnapshot: false, 4419 willRender: false 4420 }); 4421 this.followedRedirect = true; 4422 } 4423 } 4424 goToSamePageAnchor() { 4425 if (this.isSamePage) { 4426 this.render(async () => { 4427 this.cacheSnapshot(); 4428 this.performScroll(); 4429 this.changeHistory(); 4430 this.adapter.visitRendered(this); 4431 }); 4432 } 4433 } 4434 // Fetch request delegate 4435 prepareRequest(request) { 4436 if (this.acceptsStreamResponse) { 4437 request.acceptResponseType(StreamMessage.contentType); 4438 } 4439 } 4440 requestStarted() { 4441 this.startRequest(); 4442 } 4443 requestPreventedHandlingResponse(_request, _response) { 4444 } 4445 async requestSucceededWithResponse(request, response) { 4446 const responseHTML = await response.responseHTML; 4447 const { redirected, statusCode } = response; 4448 if (responseHTML == void 0) { 4449 this.recordResponse({ 4450 statusCode: SystemStatusCode.contentTypeMismatch, 4451 redirected 4452 }); 4453 } else { 4454 this.redirectedToLocation = response.redirected ? response.location : void 0; 4455 this.recordResponse({ statusCode, responseHTML, redirected }); 4456 } 4457 } 4458 async requestFailedWithResponse(request, response) { 4459 const responseHTML = await response.responseHTML; 4460 const { redirected, statusCode } = response; 4461 if (responseHTML == void 0) { 4462 this.recordResponse({ 4463 statusCode: SystemStatusCode.contentTypeMismatch, 4464 redirected 4465 }); 4466 } else { 4467 this.recordResponse({ statusCode, responseHTML, redirected }); 4468 } 4469 } 4470 requestErrored(_request, _error) { 4471 this.recordResponse({ 4472 statusCode: SystemStatusCode.networkFailure, 4473 redirected: false 4474 }); 4475 } 4476 requestFinished() { 4477 this.finishRequest(); 4478 } 4479 // Scrolling 4480 performScroll() { 4481 if (!this.scrolled && !this.view.forceReloaded && !this.view.shouldPreserveScrollPosition(this)) { 4482 if (this.action == "restore") { 4483 this.scrollToRestoredPosition() || this.scrollToAnchor() || this.view.scrollToTop(); 4484 } else { 4485 this.scrollToAnchor() || this.view.scrollToTop(); 4486 } 4487 if (this.isSamePage) { 4488 this.delegate.visitScrolledToSamePageLocation(this.view.lastRenderedLocation, this.location); 4489 } 4490 this.scrolled = true; 4491 } 4492 } 4493 scrollToRestoredPosition() { 4494 const { scrollPosition } = this.restorationData; 4495 if (scrollPosition) { 4496 this.view.scrollToPosition(scrollPosition); 4497 return true; 4498 } 4499 } 4500 scrollToAnchor() { 4501 const anchor = getAnchor(this.location); 4502 if (anchor != null) { 4503 this.view.scrollToAnchor(anchor); 4504 return true; 4505 } 4506 } 4507 // Instrumentation 4508 recordTimingMetric(metric) { 4509 this.timingMetrics[metric] = (/* @__PURE__ */ new Date()).getTime(); 4510 } 4511 getTimingMetrics() { 4512 return { ...this.timingMetrics }; 4513 } 4514 // Private 4515 getHistoryMethodForAction(action) { 4516 switch (action) { 4517 case "replace": 4518 return history.replaceState; 4519 case "advance": 4520 case "restore": 4521 return history.pushState; 4522 } 4523 } 4524 hasPreloadedResponse() { 4525 return typeof this.response == "object"; 4526 } 4527 shouldIssueRequest() { 4528 if (this.isSamePage) { 4529 return false; 4530 } else if (this.action == "restore") { 4531 return !this.hasCachedSnapshot(); 4532 } else { 4533 return this.willRender; 4534 } 4535 } 4536 cacheSnapshot() { 4537 if (!this.snapshotCached) { 4538 this.view.cacheSnapshot(this.snapshot).then((snapshot) => snapshot && this.visitCachedSnapshot(snapshot)); 4539 this.snapshotCached = true; 4540 } 4541 } 4542 async render(callback) { 4543 this.cancelRender(); 4544 await new Promise((resolve) => { 4545 this.frame = document.visibilityState === "hidden" ? setTimeout(() => resolve(), 0) : requestAnimationFrame(() => resolve()); 4546 }); 4547 await callback(); 4548 delete this.frame; 4549 } 4550 async renderPageSnapshot(snapshot, isPreview) { 4551 await this.viewTransitioner.renderChange(this.view.shouldTransitionTo(snapshot), async () => { 4552 await this.view.renderPage(snapshot, isPreview, this.willRender, this); 4553 this.performScroll(); 4554 }); 4555 } 4556 cancelRender() { 4557 if (this.frame) { 4558 cancelAnimationFrame(this.frame); 4559 delete this.frame; 4560 } 4561 } 4562}; 4563function isSuccessful(statusCode) { 4564 return statusCode >= 200 && statusCode < 300; 4565} 4566var BrowserAdapter = class { 4567 progressBar = new ProgressBar(); 4568 constructor(session2) { 4569 this.session = session2; 4570 } 4571 visitProposedToLocation(location2, options) { 4572 if (locationIsVisitable(location2, this.navigator.rootLocation)) { 4573 this.navigator.startVisit(location2, options?.restorationIdentifier || uuid(), options); 4574 } else { 4575 window.location.href = location2.toString(); 4576 } 4577 } 4578 visitStarted(visit2) { 4579 this.location = visit2.location; 4580 visit2.loadCachedSnapshot(); 4581 visit2.issueRequest(); 4582 visit2.goToSamePageAnchor(); 4583 } 4584 visitRequestStarted(visit2) { 4585 this.progressBar.setValue(0); 4586 if (visit2.hasCachedSnapshot() || visit2.action != "restore") { 4587 this.showVisitProgressBarAfterDelay(); 4588 } else { 4589 this.showProgressBar(); 4590 } 4591 } 4592 visitRequestCompleted(visit2) { 4593 visit2.loadResponse(); 4594 } 4595 visitRequestFailedWithStatusCode(visit2, statusCode) { 4596 switch (statusCode) { 4597 case SystemStatusCode.networkFailure: 4598 case SystemStatusCode.timeoutFailure: 4599 case SystemStatusCode.contentTypeMismatch: 4600 return this.reload({ 4601 reason: "request_failed", 4602 context: { 4603 statusCode 4604 } 4605 }); 4606 default: 4607 return visit2.loadResponse(); 4608 } 4609 } 4610 visitRequestFinished(_visit) { 4611 } 4612 visitCompleted(_visit) { 4613 this.progressBar.setValue(1); 4614 this.hideVisitProgressBar(); 4615 } 4616 pageInvalidated(reason) { 4617 this.reload(reason); 4618 } 4619 visitFailed(_visit) { 4620 this.progressBar.setValue(1); 4621 this.hideVisitProgressBar(); 4622 } 4623 visitRendered(_visit) { 4624 } 4625 // Form Submission Delegate 4626 formSubmissionStarted(_formSubmission) { 4627 this.progressBar.setValue(0); 4628 this.showFormProgressBarAfterDelay(); 4629 } 4630 formSubmissionFinished(_formSubmission) { 4631 this.progressBar.setValue(1); 4632 this.hideFormProgressBar(); 4633 } 4634 // Private 4635 showVisitProgressBarAfterDelay() { 4636 this.visitProgressBarTimeout = window.setTimeout(this.showProgressBar, this.session.progressBarDelay); 4637 } 4638 hideVisitProgressBar() { 4639 this.progressBar.hide(); 4640 if (this.visitProgressBarTimeout != null) { 4641 window.clearTimeout(this.visitProgressBarTimeout); 4642 delete this.visitProgressBarTimeout; 4643 } 4644 } 4645 showFormProgressBarAfterDelay() { 4646 if (this.formProgressBarTimeout == null) { 4647 this.formProgressBarTimeout = window.setTimeout(this.showProgressBar, this.session.progressBarDelay); 4648 } 4649 } 4650 hideFormProgressBar() { 4651 this.progressBar.hide(); 4652 if (this.formProgressBarTimeout != null) { 4653 window.clearTimeout(this.formProgressBarTimeout); 4654 delete this.formProgressBarTimeout; 4655 } 4656 } 4657 showProgressBar = () => { 4658 this.progressBar.show(); 4659 }; 4660 reload(reason) { 4661 dispatch("turbo:reload", { detail: reason }); 4662 window.location.href = this.location?.toString() || window.location.href; 4663 } 4664 get navigator() { 4665 return this.session.navigator; 4666 } 4667}; 4668var CacheObserver = class { 4669 selector = "[data-turbo-temporary]"; 4670 deprecatedSelector = "[data-turbo-cache=false]"; 4671 started = false; 4672 start() { 4673 if (!this.started) { 4674 this.started = true; 4675 addEventListener("turbo:before-cache", this.removeTemporaryElements, false); 4676 } 4677 } 4678 stop() { 4679 if (this.started) { 4680 this.started = false; 4681 removeEventListener("turbo:before-cache", this.removeTemporaryElements, false); 4682 } 4683 } 4684 removeTemporaryElements = (_event) => { 4685 for (const element of this.temporaryElements) { 4686 element.remove(); 4687 } 4688 }; 4689 get temporaryElements() { 4690 return [...document.querySelectorAll(this.selector), ...this.temporaryElementsWithDeprecation]; 4691 } 4692 get temporaryElementsWithDeprecation() { 4693 const elements = document.querySelectorAll(this.deprecatedSelector); 4694 if (elements.length) { 4695 console.warn( 4696 `The ${this.deprecatedSelector} selector is deprecated and will be removed in a future version. Use ${this.selector} instead.` 4697 ); 4698 } 4699 return [...elements]; 4700 } 4701}; 4702var FrameRedirector = class { 4703 constructor(session2, element) { 4704 this.session = session2; 4705 this.element = element; 4706 this.linkInterceptor = new LinkInterceptor(this, element); 4707 this.formSubmitObserver = new FormSubmitObserver(this, element); 4708 } 4709 start() { 4710 this.linkInterceptor.start(); 4711 this.formSubmitObserver.start(); 4712 } 4713 stop() { 4714 this.linkInterceptor.stop(); 4715 this.formSubmitObserver.stop(); 4716 } 4717 // Link interceptor delegate 4718 shouldInterceptLinkClick(element, _location, _event) { 4719 return this.#shouldRedirect(element); 4720 } 4721 linkClickIntercepted(element, url, event) { 4722 const frame = this.#findFrameElement(element); 4723 if (frame) { 4724 frame.delegate.linkClickIntercepted(element, url, event); 4725 } 4726 } 4727 // Form submit observer delegate 4728 willSubmitForm(element, submitter2) { 4729 return element.closest("turbo-frame") == null && this.#shouldSubmit(element, submitter2) && this.#shouldRedirect(element, submitter2); 4730 } 4731 formSubmitted(element, submitter2) { 4732 const frame = this.#findFrameElement(element, submitter2); 4733 if (frame) { 4734 frame.delegate.formSubmitted(element, submitter2); 4735 } 4736 } 4737 #shouldSubmit(form, submitter2) { 4738 const action = getAction$1(form, submitter2); 4739 const meta = this.element.ownerDocument.querySelector(`meta[name="turbo-root"]`); 4740 const rootLocation = expandURL(meta?.content ?? "/"); 4741 return this.#shouldRedirect(form, submitter2) && locationIsVisitable(action, rootLocation); 4742 } 4743 #shouldRedirect(element, submitter2) { 4744 const isNavigatable = element instanceof HTMLFormElement ? this.session.submissionIsNavigatable(element, submitter2) : this.session.elementIsNavigatable(element); 4745 if (isNavigatable) { 4746 const frame = this.#findFrameElement(element, submitter2); 4747 return frame ? frame != element.closest("turbo-frame") : false; 4748 } else { 4749 return false; 4750 } 4751 } 4752 #findFrameElement(element, submitter2) { 4753 const id = submitter2?.getAttribute("data-turbo-frame") || element.getAttribute("data-turbo-frame"); 4754 if (id && id != "_top") { 4755 const frame = this.element.querySelector(`#${id}:not([disabled])`); 4756 if (frame instanceof FrameElement) { 4757 return frame; 4758 } 4759 } 4760 } 4761}; 4762var History = class { 4763 location; 4764 restorationIdentifier = uuid(); 4765 restorationData = {}; 4766 started = false; 4767 pageLoaded = false; 4768 currentIndex = 0; 4769 constructor(delegate) { 4770 this.delegate = delegate; 4771 } 4772 start() { 4773 if (!this.started) { 4774 addEventListener("popstate", this.onPopState, false); 4775 addEventListener("load", this.onPageLoad, false); 4776 this.currentIndex = history.state?.turbo?.restorationIndex || 0; 4777 this.started = true; 4778 this.replace(new URL(window.location.href)); 4779 } 4780 } 4781 stop() { 4782 if (this.started) { 4783 removeEventListener("popstate", this.onPopState, false); 4784 removeEventListener("load", this.onPageLoad, false); 4785 this.started = false; 4786 } 4787 } 4788 push(location2, restorationIdentifier) { 4789 this.update(history.pushState, location2, restorationIdentifier); 4790 } 4791 replace(location2, restorationIdentifier) { 4792 this.update(history.replaceState, location2, restorationIdentifier); 4793 } 4794 update(method, location2, restorationIdentifier = uuid()) { 4795 if (method === history.pushState) ++this.currentIndex; 4796 const state = { turbo: { restorationIdentifier, restorationIndex: this.currentIndex } }; 4797 method.call(history, state, "", location2.href); 4798 this.location = location2; 4799 this.restorationIdentifier = restorationIdentifier; 4800 } 4801 // Restoration data 4802 getRestorationDataForIdentifier(restorationIdentifier) { 4803 return this.restorationData[restorationIdentifier] || {}; 4804 } 4805 updateRestorationData(additionalData) { 4806 const { restorationIdentifier } = this; 4807 const restorationData = this.restorationData[restorationIdentifier]; 4808 this.restorationData[restorationIdentifier] = { 4809 ...restorationData, 4810 ...additionalData 4811 }; 4812 } 4813 // Scroll restoration 4814 assumeControlOfScrollRestoration() { 4815 if (!this.previousScrollRestoration) { 4816 this.previousScrollRestoration = history.scrollRestoration ?? "auto"; 4817 history.scrollRestoration = "manual"; 4818 } 4819 } 4820 relinquishControlOfScrollRestoration() { 4821 if (this.previousScrollRestoration) { 4822 history.scrollRestoration = this.previousScrollRestoration; 4823 delete this.previousScrollRestoration; 4824 } 4825 } 4826 // Event handlers 4827 onPopState = (event) => { 4828 if (this.shouldHandlePopState()) { 4829 const { turbo } = event.state || {}; 4830 if (turbo) { 4831 this.location = new URL(window.location.href); 4832 const { restorationIdentifier, restorationIndex } = turbo; 4833 this.restorationIdentifier = restorationIdentifier; 4834 const direction = restorationIndex > this.currentIndex ? "forward" : "back"; 4835 this.delegate.historyPoppedToLocationWithRestorationIdentifierAndDirection(this.location, restorationIdentifier, direction); 4836 this.currentIndex = restorationIndex; 4837 } 4838 } 4839 }; 4840 onPageLoad = async (_event) => { 4841 await nextMicrotask(); 4842 this.pageLoaded = true; 4843 }; 4844 // Private 4845 shouldHandlePopState() { 4846 return this.pageIsLoaded(); 4847 } 4848 pageIsLoaded() { 4849 return this.pageLoaded || document.readyState == "complete"; 4850 } 4851}; 4852var LinkPrefetchObserver = class { 4853 started = false; 4854 #prefetchedLink = null; 4855 constructor(delegate, eventTarget) { 4856 this.delegate = delegate; 4857 this.eventTarget = eventTarget; 4858 } 4859 start() { 4860 if (this.started) return; 4861 if (this.eventTarget.readyState === "loading") { 4862 this.eventTarget.addEventListener("DOMContentLoaded", this.#enable, { once: true }); 4863 } else { 4864 this.#enable(); 4865 } 4866 } 4867 stop() { 4868 if (!this.started) return; 4869 this.eventTarget.removeEventListener("mouseenter", this.#tryToPrefetchRequest, { 4870 capture: true, 4871 passive: true 4872 }); 4873 this.eventTarget.removeEventListener("mouseleave", this.#cancelRequestIfObsolete, { 4874 capture: true, 4875 passive: true 4876 }); 4877 this.eventTarget.removeEventListener("turbo:before-fetch-request", this.#tryToUsePrefetchedRequest, true); 4878 this.started = false; 4879 } 4880 #enable = () => { 4881 this.eventTarget.addEventListener("mouseenter", this.#tryToPrefetchRequest, { 4882 capture: true, 4883 passive: true 4884 }); 4885 this.eventTarget.addEventListener("mouseleave", this.#cancelRequestIfObsolete, { 4886 capture: true, 4887 passive: true 4888 }); 4889 this.eventTarget.addEventListener("turbo:before-fetch-request", this.#tryToUsePrefetchedRequest, true); 4890 this.started = true; 4891 }; 4892 #tryToPrefetchRequest = (event) => { 4893 if (getMetaContent("turbo-prefetch") === "false") return; 4894 const target = event.target; 4895 const isLink = target.matches && target.matches("a[href]:not([target^=_]):not([download])"); 4896 if (isLink && this.#isPrefetchable(target)) { 4897 const link = target; 4898 const location2 = getLocationForLink(link); 4899 if (this.delegate.canPrefetchRequestToLocation(link, location2)) { 4900 this.#prefetchedLink = link; 4901 const fetchRequest = new FetchRequest( 4902 this, 4903 FetchMethod.get, 4904 location2, 4905 new URLSearchParams(), 4906 target 4907 ); 4908 prefetchCache.setLater(location2.toString(), fetchRequest, this.#cacheTtl); 4909 } 4910 } 4911 }; 4912 #cancelRequestIfObsolete = (event) => { 4913 if (event.target === this.#prefetchedLink) this.#cancelPrefetchRequest(); 4914 }; 4915 #cancelPrefetchRequest = () => { 4916 prefetchCache.clear(); 4917 this.#prefetchedLink = null; 4918 }; 4919 #tryToUsePrefetchedRequest = (event) => { 4920 if (event.target.tagName !== "FORM" && event.detail.fetchOptions.method === "GET") { 4921 const cached = prefetchCache.get(event.detail.url.toString()); 4922 if (cached) { 4923 event.detail.fetchRequest = cached; 4924 } 4925 prefetchCache.clear(); 4926 } 4927 }; 4928 prepareRequest(request) { 4929 const link = request.target; 4930 request.headers["X-Sec-Purpose"] = "prefetch"; 4931 const turboFrame = link.closest("turbo-frame"); 4932 const turboFrameTarget = link.getAttribute("data-turbo-frame") || turboFrame?.getAttribute("target") || turboFrame?.id; 4933 if (turboFrameTarget && turboFrameTarget !== "_top") { 4934 request.headers["Turbo-Frame"] = turboFrameTarget; 4935 } 4936 } 4937 // Fetch request interface 4938 requestSucceededWithResponse() { 4939 } 4940 requestStarted(fetchRequest) { 4941 } 4942 requestErrored(fetchRequest) { 4943 } 4944 requestFinished(fetchRequest) { 4945 } 4946 requestPreventedHandlingResponse(fetchRequest, fetchResponse) { 4947 } 4948 requestFailedWithResponse(fetchRequest, fetchResponse) { 4949 } 4950 get #cacheTtl() { 4951 return Number(getMetaContent("turbo-prefetch-cache-time")) || cacheTtl; 4952 } 4953 #isPrefetchable(link) { 4954 const href = link.getAttribute("href"); 4955 if (!href) return false; 4956 if (unfetchableLink(link)) return false; 4957 if (linkToTheSamePage(link)) return false; 4958 if (linkOptsOut(link)) return false; 4959 if (nonSafeLink(link)) return false; 4960 if (eventPrevented(link)) return false; 4961 return true; 4962 } 4963}; 4964var unfetchableLink = (link) => { 4965 return link.origin !== document.location.origin || !["http:", "https:"].includes(link.protocol) || link.hasAttribute("target"); 4966}; 4967var linkToTheSamePage = (link) => { 4968 return link.pathname + link.search === document.location.pathname + document.location.search || link.href.startsWith("#"); 4969}; 4970var linkOptsOut = (link) => { 4971 if (link.getAttribute("data-turbo-prefetch") === "false") return true; 4972 if (link.getAttribute("data-turbo") === "false") return true; 4973 const turboPrefetchParent = findClosestRecursively(link, "[data-turbo-prefetch]"); 4974 if (turboPrefetchParent && turboPrefetchParent.getAttribute("data-turbo-prefetch") === "false") return true; 4975 return false; 4976}; 4977var nonSafeLink = (link) => { 4978 const turboMethod = link.getAttribute("data-turbo-method"); 4979 if (turboMethod && turboMethod.toLowerCase() !== "get") return true; 4980 if (isUJS(link)) return true; 4981 if (link.hasAttribute("data-turbo-confirm")) return true; 4982 if (link.hasAttribute("data-turbo-stream")) return true; 4983 return false; 4984}; 4985var isUJS = (link) => { 4986 return link.hasAttribute("data-remote") || link.hasAttribute("data-behavior") || link.hasAttribute("data-confirm") || link.hasAttribute("data-method"); 4987}; 4988var eventPrevented = (link) => { 4989 const event = dispatch("turbo:before-prefetch", { target: link, cancelable: true }); 4990 return event.defaultPrevented; 4991}; 4992var Navigator = class { 4993 constructor(delegate) { 4994 this.delegate = delegate; 4995 } 4996 proposeVisit(location2, options = {}) { 4997 if (this.delegate.allowsVisitingLocationWithAction(location2, options.action)) { 4998 this.delegate.visitProposedToLocation(location2, options); 4999 } 5000 } 5001 startVisit(locatable, restorationIdentifier, options = {}) { 5002 this.stop(); 5003 this.currentVisit = new Visit(this, expandURL(locatable), restorationIdentifier, { 5004 referrer: this.location, 5005 ...options 5006 }); 5007 this.currentVisit.start(); 5008 } 5009 submitForm(form, submitter2) { 5010 this.stop(); 5011 this.formSubmission = new FormSubmission(this, form, submitter2, true); 5012 this.formSubmission.start(); 5013 } 5014 stop() { 5015 if (this.formSubmission) { 5016 this.formSubmission.stop(); 5017 delete this.formSubmission; 5018 } 5019 if (this.currentVisit) { 5020 this.currentVisit.cancel(); 5021 delete this.currentVisit; 5022 } 5023 } 5024 get adapter() { 5025 return this.delegate.adapter; 5026 } 5027 get view() { 5028 return this.delegate.view; 5029 } 5030 get rootLocation() { 5031 return this.view.snapshot.rootLocation; 5032 } 5033 get history() { 5034 return this.delegate.history; 5035 } 5036 // Form submission delegate 5037 formSubmissionStarted(formSubmission) { 5038 if (typeof this.adapter.formSubmissionStarted === "function") { 5039 this.adapter.formSubmissionStarted(formSubmission); 5040 } 5041 } 5042 async formSubmissionSucceededWithResponse(formSubmission, fetchResponse) { 5043 if (formSubmission == this.formSubmission) { 5044 const responseHTML = await fetchResponse.responseHTML; 5045 if (responseHTML) { 5046 const shouldCacheSnapshot = formSubmission.isSafe; 5047 if (!shouldCacheSnapshot) { 5048 this.view.clearSnapshotCache(); 5049 } 5050 const { statusCode, redirected } = fetchResponse; 5051 const action = this.#getActionForFormSubmission(formSubmission, fetchResponse); 5052 const visitOptions = { 5053 action, 5054 shouldCacheSnapshot, 5055 response: { statusCode, responseHTML, redirected } 5056 }; 5057 this.proposeVisit(fetchResponse.location, visitOptions); 5058 } 5059 } 5060 } 5061 async formSubmissionFailedWithResponse(formSubmission, fetchResponse) { 5062 const responseHTML = await fetchResponse.responseHTML; 5063 if (responseHTML) { 5064 const snapshot = PageSnapshot.fromHTMLString(responseHTML); 5065 if (fetchResponse.serverError) { 5066 await this.view.renderError(snapshot, this.currentVisit); 5067 } else { 5068 await this.view.renderPage(snapshot, false, true, this.currentVisit); 5069 } 5070 if (!snapshot.shouldPreserveScrollPosition) { 5071 this.view.scrollToTop(); 5072 } 5073 this.view.clearSnapshotCache(); 5074 } 5075 } 5076 formSubmissionErrored(formSubmission, error2) { 5077 console.error(error2); 5078 } 5079 formSubmissionFinished(formSubmission) { 5080 if (typeof this.adapter.formSubmissionFinished === "function") { 5081 this.adapter.formSubmissionFinished(formSubmission); 5082 } 5083 } 5084 // Visit delegate 5085 visitStarted(visit2) { 5086 this.delegate.visitStarted(visit2); 5087 } 5088 visitCompleted(visit2) { 5089 this.delegate.visitCompleted(visit2); 5090 delete this.currentVisit; 5091 } 5092 locationWithActionIsSamePage(location2, action) { 5093 const anchor = getAnchor(location2); 5094 const currentAnchor = getAnchor(this.view.lastRenderedLocation); 5095 const isRestorationToTop = action === "restore" && typeof anchor === "undefined"; 5096 return action !== "replace" && getRequestURL(location2) === getRequestURL(this.view.lastRenderedLocation) && (isRestorationToTop || anchor != null && anchor !== currentAnchor); 5097 } 5098 visitScrolledToSamePageLocation(oldURL, newURL) { 5099 this.delegate.visitScrolledToSamePageLocation(oldURL, newURL); 5100 } 5101 // Visits 5102 get location() { 5103 return this.history.location; 5104 } 5105 get restorationIdentifier() { 5106 return this.history.restorationIdentifier; 5107 } 5108 #getActionForFormSubmission(formSubmission, fetchResponse) { 5109 const { submitter: submitter2, formElement } = formSubmission; 5110 return getVisitAction(submitter2, formElement) || this.#getDefaultAction(fetchResponse); 5111 } 5112 #getDefaultAction(fetchResponse) { 5113 const sameLocationRedirect = fetchResponse.redirected && fetchResponse.location.href === this.location?.href; 5114 return sameLocationRedirect ? "replace" : "advance"; 5115 } 5116}; 5117var PageStage = { 5118 initial: 0, 5119 loading: 1, 5120 interactive: 2, 5121 complete: 3 5122}; 5123var PageObserver = class { 5124 stage = PageStage.initial; 5125 started = false; 5126 constructor(delegate) { 5127 this.delegate = delegate; 5128 } 5129 start() { 5130 if (!this.started) { 5131 if (this.stage == PageStage.initial) { 5132 this.stage = PageStage.loading; 5133 } 5134 document.addEventListener("readystatechange", this.interpretReadyState, false); 5135 addEventListener("pagehide", this.pageWillUnload, false); 5136 this.started = true; 5137 } 5138 } 5139 stop() { 5140 if (this.started) { 5141 document.removeEventListener("readystatechange", this.interpretReadyState, false); 5142 removeEventListener("pagehide", this.pageWillUnload, false); 5143 this.started = false; 5144 } 5145 } 5146 interpretReadyState = () => { 5147 const { readyState } = this; 5148 if (readyState == "interactive") { 5149 this.pageIsInteractive(); 5150 } else if (readyState == "complete") { 5151 this.pageIsComplete(); 5152 } 5153 }; 5154 pageIsInteractive() { 5155 if (this.stage == PageStage.loading) { 5156 this.stage = PageStage.interactive; 5157 this.delegate.pageBecameInteractive(); 5158 } 5159 } 5160 pageIsComplete() { 5161 this.pageIsInteractive(); 5162 if (this.stage == PageStage.interactive) { 5163 this.stage = PageStage.complete; 5164 this.delegate.pageLoaded(); 5165 } 5166 } 5167 pageWillUnload = () => { 5168 this.delegate.pageWillUnload(); 5169 }; 5170 get readyState() { 5171 return document.readyState; 5172 } 5173}; 5174var ScrollObserver = class { 5175 started = false; 5176 constructor(delegate) { 5177 this.delegate = delegate; 5178 } 5179 start() { 5180 if (!this.started) { 5181 addEventListener("scroll", this.onScroll, false); 5182 this.onScroll(); 5183 this.started = true; 5184 } 5185 } 5186 stop() { 5187 if (this.started) { 5188 removeEventListener("scroll", this.onScroll, false); 5189 this.started = false; 5190 } 5191 } 5192 onScroll = () => { 5193 this.updatePosition({ x: window.pageXOffset, y: window.pageYOffset }); 5194 }; 5195 // Private 5196 updatePosition(position) { 5197 this.delegate.scrollPositionChanged(position); 5198 } 5199}; 5200var StreamMessageRenderer = class { 5201 render({ fragment }) { 5202 Bardo.preservingPermanentElements(this, getPermanentElementMapForFragment(fragment), () => { 5203 withAutofocusFromFragment(fragment, () => { 5204 withPreservedFocus(() => { 5205 document.documentElement.appendChild(fragment); 5206 }); 5207 }); 5208 }); 5209 } 5210 // Bardo delegate 5211 enteringBardo(currentPermanentElement, newPermanentElement) { 5212 newPermanentElement.replaceWith(currentPermanentElement.cloneNode(true)); 5213 } 5214 leavingBardo() { 5215 } 5216}; 5217function getPermanentElementMapForFragment(fragment) { 5218 const permanentElementsInDocument = queryPermanentElementsAll(document.documentElement); 5219 const permanentElementMap = {}; 5220 for (const permanentElementInDocument of permanentElementsInDocument) { 5221 const { id } = permanentElementInDocument; 5222 for (const streamElement of fragment.querySelectorAll("turbo-stream")) { 5223 const elementInStream = getPermanentElementById(streamElement.templateElement.content, id); 5224 if (elementInStream) { 5225 permanentElementMap[id] = [permanentElementInDocument, elementInStream]; 5226 } 5227 } 5228 } 5229 return permanentElementMap; 5230} 5231async function withAutofocusFromFragment(fragment, callback) { 5232 const generatedID = `turbo-stream-autofocus-${uuid()}`; 5233 const turboStreams = fragment.querySelectorAll("turbo-stream"); 5234 const elementWithAutofocus = firstAutofocusableElementInStreams(turboStreams); 5235 let willAutofocusId = null; 5236 if (elementWithAutofocus) { 5237 if (elementWithAutofocus.id) { 5238 willAutofocusId = elementWithAutofocus.id; 5239 } else { 5240 willAutofocusId = generatedID; 5241 } 5242 elementWithAutofocus.id = willAutofocusId; 5243 } 5244 callback(); 5245 await nextRepaint(); 5246 const hasNoActiveElement = document.activeElement == null || document.activeElement == document.body; 5247 if (hasNoActiveElement && willAutofocusId) { 5248 const elementToAutofocus = document.getElementById(willAutofocusId); 5249 if (elementIsFocusable(elementToAutofocus)) { 5250 elementToAutofocus.focus(); 5251 } 5252 if (elementToAutofocus && elementToAutofocus.id == generatedID) { 5253 elementToAutofocus.removeAttribute("id"); 5254 } 5255 } 5256} 5257async function withPreservedFocus(callback) { 5258 const [activeElementBeforeRender, activeElementAfterRender] = await around(callback, () => document.activeElement); 5259 const restoreFocusTo = activeElementBeforeRender && activeElementBeforeRender.id; 5260 if (restoreFocusTo) { 5261 const elementToFocus = document.getElementById(restoreFocusTo); 5262 if (elementIsFocusable(elementToFocus) && elementToFocus != activeElementAfterRender) { 5263 elementToFocus.focus(); 5264 } 5265 } 5266} 5267function firstAutofocusableElementInStreams(nodeListOfStreamElements) { 5268 for (const streamElement of nodeListOfStreamElements) { 5269 const elementWithAutofocus = queryAutofocusableElement(streamElement.templateElement.content); 5270 if (elementWithAutofocus) return elementWithAutofocus; 5271 } 5272 return null; 5273} 5274var StreamObserver = class { 5275 sources = /* @__PURE__ */ new Set(); 5276 #started = false; 5277 constructor(delegate) { 5278 this.delegate = delegate; 5279 } 5280 start() { 5281 if (!this.#started) { 5282 this.#started = true; 5283 addEventListener("turbo:before-fetch-response", this.inspectFetchResponse, false); 5284 } 5285 } 5286 stop() { 5287 if (this.#started) { 5288 this.#started = false; 5289 removeEventListener("turbo:before-fetch-response", this.inspectFetchResponse, false); 5290 } 5291 } 5292 connectStreamSource(source) { 5293 if (!this.streamSourceIsConnected(source)) { 5294 this.sources.add(source); 5295 source.addEventListener("message", this.receiveMessageEvent, false); 5296 } 5297 } 5298 disconnectStreamSource(source) { 5299 if (this.streamSourceIsConnected(source)) { 5300 this.sources.delete(source); 5301 source.removeEventListener("message", this.receiveMessageEvent, false); 5302 } 5303 } 5304 streamSourceIsConnected(source) { 5305 return this.sources.has(source); 5306 } 5307 inspectFetchResponse = (event) => { 5308 const response = fetchResponseFromEvent(event); 5309 if (response && fetchResponseIsStream(response)) { 5310 event.preventDefault(); 5311 this.receiveMessageResponse(response); 5312 } 5313 }; 5314 receiveMessageEvent = (event) => { 5315 if (this.#started && typeof event.data == "string") { 5316 this.receiveMessageHTML(event.data); 5317 } 5318 }; 5319 async receiveMessageResponse(response) { 5320 const html = await response.responseHTML; 5321 if (html) { 5322 this.receiveMessageHTML(html); 5323 } 5324 } 5325 receiveMessageHTML(html) { 5326 this.delegate.receivedMessageFromStream(StreamMessage.wrap(html)); 5327 } 5328}; 5329function fetchResponseFromEvent(event) { 5330 const fetchResponse = event.detail?.fetchResponse; 5331 if (fetchResponse instanceof FetchResponse) { 5332 return fetchResponse; 5333 } 5334} 5335function fetchResponseIsStream(response) { 5336 const contentType = response.contentType ?? ""; 5337 return contentType.startsWith(StreamMessage.contentType); 5338} 5339var ErrorRenderer = class extends Renderer { 5340 static renderElement(currentElement, newElement) { 5341 const { documentElement, body } = document; 5342 documentElement.replaceChild(newElement, body); 5343 } 5344 async render() { 5345 this.replaceHeadAndBody(); 5346 this.activateScriptElements(); 5347 } 5348 replaceHeadAndBody() { 5349 const { documentElement, head } = document; 5350 documentElement.replaceChild(this.newHead, head); 5351 this.renderElement(this.currentElement, this.newElement); 5352 } 5353 activateScriptElements() { 5354 for (const replaceableElement of this.scriptElements) { 5355 const parentNode = replaceableElement.parentNode; 5356 if (parentNode) { 5357 const element = activateScriptElement(replaceableElement); 5358 parentNode.replaceChild(element, replaceableElement); 5359 } 5360 } 5361 } 5362 get newHead() { 5363 return this.newSnapshot.headSnapshot.element; 5364 } 5365 get scriptElements() { 5366 return document.documentElement.querySelectorAll("script"); 5367 } 5368}; 5369var PageRenderer = class extends Renderer { 5370 static renderElement(currentElement, newElement) { 5371 if (document.body && newElement instanceof HTMLBodyElement) { 5372 document.body.replaceWith(newElement); 5373 } else { 5374 document.documentElement.appendChild(newElement); 5375 } 5376 } 5377 get shouldRender() { 5378 return this.newSnapshot.isVisitable && this.trackedElementsAreIdentical; 5379 } 5380 get reloadReason() { 5381 if (!this.newSnapshot.isVisitable) { 5382 return { 5383 reason: "turbo_visit_control_is_reload" 5384 }; 5385 } 5386 if (!this.trackedElementsAreIdentical) { 5387 return { 5388 reason: "tracked_element_mismatch" 5389 }; 5390 } 5391 } 5392 async prepareToRender() { 5393 this.#setLanguage(); 5394 await this.mergeHead(); 5395 } 5396 async render() { 5397 if (this.willRender) { 5398 await this.replaceBody(); 5399 } 5400 } 5401 finishRendering() { 5402 super.finishRendering(); 5403 if (!this.isPreview) { 5404 this.focusFirstAutofocusableElement(); 5405 } 5406 } 5407 get currentHeadSnapshot() { 5408 return this.currentSnapshot.headSnapshot; 5409 } 5410 get newHeadSnapshot() { 5411 return this.newSnapshot.headSnapshot; 5412 } 5413 get newElement() { 5414 return this.newSnapshot.element; 5415 } 5416 #setLanguage() { 5417 const { documentElement } = this.currentSnapshot; 5418 const { lang } = this.newSnapshot; 5419 if (lang) { 5420 documentElement.setAttribute("lang", lang); 5421 } else { 5422 documentElement.removeAttribute("lang"); 5423 } 5424 } 5425 async mergeHead() { 5426 const mergedHeadElements = this.mergeProvisionalElements(); 5427 const newStylesheetElements = this.copyNewHeadStylesheetElements(); 5428 this.copyNewHeadScriptElements(); 5429 await mergedHeadElements; 5430 await newStylesheetElements; 5431 if (this.willRender) { 5432 this.removeUnusedDynamicStylesheetElements(); 5433 } 5434 } 5435 async replaceBody() { 5436 await this.preservingPermanentElements(async () => { 5437 this.activateNewBody(); 5438 await this.assignNewBody(); 5439 }); 5440 } 5441 get trackedElementsAreIdentical() { 5442 return this.currentHeadSnapshot.trackedElementSignature == this.newHeadSnapshot.trackedElementSignature; 5443 } 5444 async copyNewHeadStylesheetElements() { 5445 const loadingElements = []; 5446 for (const element of this.newHeadStylesheetElements) { 5447 loadingElements.push(waitForLoad(element)); 5448 document.head.appendChild(element); 5449 } 5450 await Promise.all(loadingElements); 5451 } 5452 copyNewHeadScriptElements() { 5453 for (const element of this.newHeadScriptElements) { 5454 document.head.appendChild(activateScriptElement(element)); 5455 } 5456 } 5457 removeUnusedDynamicStylesheetElements() { 5458 for (const element of this.unusedDynamicStylesheetElements) { 5459 document.head.removeChild(element); 5460 } 5461 } 5462 async mergeProvisionalElements() { 5463 const newHeadElements = [...this.newHeadProvisionalElements]; 5464 for (const element of this.currentHeadProvisionalElements) { 5465 if (!this.isCurrentElementInElementList(element, newHeadElements)) { 5466 document.head.removeChild(element); 5467 } 5468 } 5469 for (const element of newHeadElements) { 5470 document.head.appendChild(element); 5471 } 5472 } 5473 isCurrentElementInElementList(element, elementList) { 5474 for (const [index, newElement] of elementList.entries()) { 5475 if (element.tagName == "TITLE") { 5476 if (newElement.tagName != "TITLE") { 5477 continue; 5478 } 5479 if (element.innerHTML == newElement.innerHTML) { 5480 elementList.splice(index, 1); 5481 return true; 5482 } 5483 } 5484 if (newElement.isEqualNode(element)) { 5485 elementList.splice(index, 1); 5486 return true; 5487 } 5488 } 5489 return false; 5490 } 5491 removeCurrentHeadProvisionalElements() { 5492 for (const element of this.currentHeadProvisionalElements) { 5493 document.head.removeChild(element); 5494 } 5495 } 5496 copyNewHeadProvisionalElements() { 5497 for (const element of this.newHeadProvisionalElements) { 5498 document.head.appendChild(element); 5499 } 5500 } 5501 activateNewBody() { 5502 document.adoptNode(this.newElement); 5503 this.activateNewBodyScriptElements(); 5504 } 5505 activateNewBodyScriptElements() { 5506 for (const inertScriptElement of this.newBodyScriptElements) { 5507 const activatedScriptElement = activateScriptElement(inertScriptElement); 5508 inertScriptElement.replaceWith(activatedScriptElement); 5509 } 5510 } 5511 async assignNewBody() { 5512 await this.renderElement(this.currentElement, this.newElement); 5513 } 5514 get unusedDynamicStylesheetElements() { 5515 return this.oldHeadStylesheetElements.filter((element) => { 5516 return element.getAttribute("data-turbo-track") === "dynamic"; 5517 }); 5518 } 5519 get oldHeadStylesheetElements() { 5520 return this.currentHeadSnapshot.getStylesheetElementsNotInSnapshot(this.newHeadSnapshot); 5521 } 5522 get newHeadStylesheetElements() { 5523 return this.newHeadSnapshot.getStylesheetElementsNotInSnapshot(this.currentHeadSnapshot); 5524 } 5525 get newHeadScriptElements() { 5526 return this.newHeadSnapshot.getScriptElementsNotInSnapshot(this.currentHeadSnapshot); 5527 } 5528 get currentHeadProvisionalElements() { 5529 return this.currentHeadSnapshot.provisionalElements; 5530 } 5531 get newHeadProvisionalElements() { 5532 return this.newHeadSnapshot.provisionalElements; 5533 } 5534 get newBodyScriptElements() { 5535 return this.newElement.querySelectorAll("script"); 5536 } 5537}; 5538var MorphingPageRenderer = class extends PageRenderer { 5539 static renderElement(currentElement, newElement) { 5540 morphElements(currentElement, newElement, { 5541 callbacks: { 5542 beforeNodeMorphed: (element) => !canRefreshFrame(element) 5543 } 5544 }); 5545 for (const frame of currentElement.querySelectorAll("turbo-frame")) { 5546 if (canRefreshFrame(frame)) frame.reload(); 5547 } 5548 dispatch("turbo:morph", { detail: { currentElement, newElement } }); 5549 } 5550 async preservingPermanentElements(callback) { 5551 return await callback(); 5552 } 5553 get renderMethod() { 5554 return "morph"; 5555 } 5556 get shouldAutofocus() { 5557 return false; 5558 } 5559}; 5560function canRefreshFrame(frame) { 5561 return frame instanceof FrameElement && frame.src && frame.refresh === "morph" && !frame.closest("[data-turbo-permanent]"); 5562} 5563var SnapshotCache = class { 5564 keys = []; 5565 snapshots = {}; 5566 constructor(size) { 5567 this.size = size; 5568 } 5569 has(location2) { 5570 return toCacheKey(location2) in this.snapshots; 5571 } 5572 get(location2) { 5573 if (this.has(location2)) { 5574 const snapshot = this.read(location2); 5575 this.touch(location2); 5576 return snapshot; 5577 } 5578 } 5579 put(location2, snapshot) { 5580 this.write(location2, snapshot); 5581 this.touch(location2); 5582 return snapshot; 5583 } 5584 clear() { 5585 this.snapshots = {}; 5586 } 5587 // Private 5588 read(location2) { 5589 return this.snapshots[toCacheKey(location2)]; 5590 } 5591 write(location2, snapshot) { 5592 this.snapshots[toCacheKey(location2)] = snapshot; 5593 } 5594 touch(location2) { 5595 const key = toCacheKey(location2); 5596 const index = this.keys.indexOf(key); 5597 if (index > -1) this.keys.splice(index, 1); 5598 this.keys.unshift(key); 5599 this.trim(); 5600 } 5601 trim() { 5602 for (const key of this.keys.splice(this.size)) { 5603 delete this.snapshots[key]; 5604 } 5605 } 5606}; 5607var PageView = class extends View { 5608 snapshotCache = new SnapshotCache(10); 5609 lastRenderedLocation = new URL(location.href); 5610 forceReloaded = false; 5611 shouldTransitionTo(newSnapshot) { 5612 return this.snapshot.prefersViewTransitions && newSnapshot.prefersViewTransitions; 5613 } 5614 renderPage(snapshot, isPreview = false, willRender = true, visit2) { 5615 const shouldMorphPage = this.isPageRefresh(visit2) && this.snapshot.shouldMorphPage; 5616 const rendererClass = shouldMorphPage ? MorphingPageRenderer : PageRenderer; 5617 const renderer = new rendererClass(this.snapshot, snapshot, isPreview, willRender); 5618 if (!renderer.shouldRender) { 5619 this.forceReloaded = true; 5620 } else { 5621 visit2?.changeHistory(); 5622 } 5623 return this.render(renderer); 5624 } 5625 renderError(snapshot, visit2) { 5626 visit2?.changeHistory(); 5627 const renderer = new ErrorRenderer(this.snapshot, snapshot, false); 5628 return this.render(renderer); 5629 } 5630 clearSnapshotCache() { 5631 this.snapshotCache.clear(); 5632 } 5633 async cacheSnapshot(snapshot = this.snapshot) { 5634 if (snapshot.isCacheable) { 5635 this.delegate.viewWillCacheSnapshot(); 5636 const { lastRenderedLocation: location2 } = this; 5637 await nextEventLoopTick(); 5638 const cachedSnapshot = snapshot.clone(); 5639 this.snapshotCache.put(location2, cachedSnapshot); 5640 return cachedSnapshot; 5641 } 5642 } 5643 getCachedSnapshotForLocation(location2) { 5644 return this.snapshotCache.get(location2); 5645 } 5646 isPageRefresh(visit2) { 5647 return !visit2 || this.lastRenderedLocation.pathname === visit2.location.pathname && visit2.action === "replace"; 5648 } 5649 shouldPreserveScrollPosition(visit2) { 5650 return this.isPageRefresh(visit2) && this.snapshot.shouldPreserveScrollPosition; 5651 } 5652 get snapshot() { 5653 return PageSnapshot.fromElement(this.element); 5654 } 5655}; 5656var Preloader = class { 5657 selector = "a[data-turbo-preload]"; 5658 constructor(delegate, snapshotCache) { 5659 this.delegate = delegate; 5660 this.snapshotCache = snapshotCache; 5661 } 5662 start() { 5663 if (document.readyState === "loading") { 5664 document.addEventListener("DOMContentLoaded", this.#preloadAll); 5665 } else { 5666 this.preloadOnLoadLinksForView(document.body); 5667 } 5668 } 5669 stop() { 5670 document.removeEventListener("DOMContentLoaded", this.#preloadAll); 5671 } 5672 preloadOnLoadLinksForView(element) { 5673 for (const link of element.querySelectorAll(this.selector)) { 5674 if (this.delegate.shouldPreloadLink(link)) { 5675 this.preloadURL(link); 5676 } 5677 } 5678 } 5679 async preloadURL(link) { 5680 const location2 = new URL(link.href); 5681 if (this.snapshotCache.has(location2)) { 5682 return; 5683 } 5684 const fetchRequest = new FetchRequest(this, FetchMethod.get, location2, new URLSearchParams(), link); 5685 await fetchRequest.perform(); 5686 } 5687 // Fetch request delegate 5688 prepareRequest(fetchRequest) { 5689 fetchRequest.headers["X-Sec-Purpose"] = "prefetch"; 5690 } 5691 async requestSucceededWithResponse(fetchRequest, fetchResponse) { 5692 try { 5693 const responseHTML = await fetchResponse.responseHTML; 5694 const snapshot = PageSnapshot.fromHTMLString(responseHTML); 5695 this.snapshotCache.put(fetchRequest.url, snapshot); 5696 } catch (_) { 5697 } 5698 } 5699 requestStarted(fetchRequest) { 5700 } 5701 requestErrored(fetchRequest) { 5702 } 5703 requestFinished(fetchRequest) { 5704 } 5705 requestPreventedHandlingResponse(fetchRequest, fetchResponse) { 5706 } 5707 requestFailedWithResponse(fetchRequest, fetchResponse) { 5708 } 5709 #preloadAll = () => { 5710 this.preloadOnLoadLinksForView(document.body); 5711 }; 5712}; 5713var Cache = class { 5714 constructor(session2) { 5715 this.session = session2; 5716 } 5717 clear() { 5718 this.session.clearCache(); 5719 } 5720 resetCacheControl() { 5721 this.#setCacheControl(""); 5722 } 5723 exemptPageFromCache() { 5724 this.#setCacheControl("no-cache"); 5725 } 5726 exemptPageFromPreview() { 5727 this.#setCacheControl("no-preview"); 5728 } 5729 #setCacheControl(value) { 5730 setMetaContent("turbo-cache-control", value); 5731 } 5732}; 5733var Session = class { 5734 navigator = new Navigator(this); 5735 history = new History(this); 5736 view = new PageView(this, document.documentElement); 5737 adapter = new BrowserAdapter(this); 5738 pageObserver = new PageObserver(this); 5739 cacheObserver = new CacheObserver(); 5740 linkPrefetchObserver = new LinkPrefetchObserver(this, document); 5741 linkClickObserver = new LinkClickObserver(this, window); 5742 formSubmitObserver = new FormSubmitObserver(this, document); 5743 scrollObserver = new ScrollObserver(this); 5744 streamObserver = new StreamObserver(this); 5745 formLinkClickObserver = new FormLinkClickObserver(this, document.documentElement); 5746 frameRedirector = new FrameRedirector(this, document.documentElement); 5747 streamMessageRenderer = new StreamMessageRenderer(); 5748 cache = new Cache(this); 5749 enabled = true; 5750 started = false; 5751 #pageRefreshDebouncePeriod = 150; 5752 constructor(recentRequests2) { 5753 this.recentRequests = recentRequests2; 5754 this.preloader = new Preloader(this, this.view.snapshotCache); 5755 this.debouncedRefresh = this.refresh; 5756 this.pageRefreshDebouncePeriod = this.pageRefreshDebouncePeriod; 5757 } 5758 start() { 5759 if (!this.started) { 5760 this.pageObserver.start(); 5761 this.cacheObserver.start(); 5762 this.linkPrefetchObserver.start(); 5763 this.formLinkClickObserver.start(); 5764 this.linkClickObserver.start(); 5765 this.formSubmitObserver.start(); 5766 this.scrollObserver.start(); 5767 this.streamObserver.start(); 5768 this.frameRedirector.start(); 5769 this.history.start(); 5770 this.preloader.start(); 5771 this.started = true; 5772 this.enabled = true; 5773 } 5774 } 5775 disable() { 5776 this.enabled = false; 5777 } 5778 stop() { 5779 if (this.started) { 5780 this.pageObserver.stop(); 5781 this.cacheObserver.stop(); 5782 this.linkPrefetchObserver.stop(); 5783 this.formLinkClickObserver.stop(); 5784 this.linkClickObserver.stop(); 5785 this.formSubmitObserver.stop(); 5786 this.scrollObserver.stop(); 5787 this.streamObserver.stop(); 5788 this.frameRedirector.stop(); 5789 this.history.stop(); 5790 this.preloader.stop(); 5791 this.started = false; 5792 } 5793 } 5794 registerAdapter(adapter) { 5795 this.adapter = adapter; 5796 } 5797 visit(location2, options = {}) { 5798 const frameElement = options.frame ? document.getElementById(options.frame) : null; 5799 if (frameElement instanceof FrameElement) { 5800 const action = options.action || getVisitAction(frameElement); 5801 frameElement.delegate.proposeVisitIfNavigatedWithAction(frameElement, action); 5802 frameElement.src = location2.toString(); 5803 } else { 5804 this.navigator.proposeVisit(expandURL(location2), options); 5805 } 5806 } 5807 refresh(url, requestId) { 5808 const isRecentRequest = requestId && this.recentRequests.has(requestId); 5809 if (!isRecentRequest && !this.navigator.currentVisit) { 5810 this.visit(url, { action: "replace", shouldCacheSnapshot: false }); 5811 } 5812 } 5813 connectStreamSource(source) { 5814 this.streamObserver.connectStreamSource(source); 5815 } 5816 disconnectStreamSource(source) { 5817 this.streamObserver.disconnectStreamSource(source); 5818 } 5819 renderStreamMessage(message) { 5820 this.streamMessageRenderer.render(StreamMessage.wrap(message)); 5821 } 5822 clearCache() { 5823 this.view.clearSnapshotCache(); 5824 } 5825 setProgressBarDelay(delay) { 5826 console.warn( 5827 "Please replace `session.setProgressBarDelay(delay)` with `session.progressBarDelay = delay`. The function is deprecated and will be removed in a future version of Turbo.`" 5828 ); 5829 this.progressBarDelay = delay; 5830 } 5831 set progressBarDelay(delay) { 5832 config.drive.progressBarDelay = delay; 5833 } 5834 get progressBarDelay() { 5835 return config.drive.progressBarDelay; 5836 } 5837 set drive(value) { 5838 config.drive.enabled = value; 5839 } 5840 get drive() { 5841 return config.drive.enabled; 5842 } 5843 set formMode(value) { 5844 config.forms.mode = value; 5845 } 5846 get formMode() { 5847 return config.forms.mode; 5848 } 5849 get location() { 5850 return this.history.location; 5851 } 5852 get restorationIdentifier() { 5853 return this.history.restorationIdentifier; 5854 } 5855 get pageRefreshDebouncePeriod() { 5856 return this.#pageRefreshDebouncePeriod; 5857 } 5858 set pageRefreshDebouncePeriod(value) { 5859 this.refresh = debounce(this.debouncedRefresh.bind(this), value); 5860 this.#pageRefreshDebouncePeriod = value; 5861 } 5862 // Preloader delegate 5863 shouldPreloadLink(element) { 5864 const isUnsafe = element.hasAttribute("data-turbo-method"); 5865 const isStream = element.hasAttribute("data-turbo-stream"); 5866 const frameTarget = element.getAttribute("data-turbo-frame"); 5867 const frame = frameTarget == "_top" ? null : document.getElementById(frameTarget) || findClosestRecursively(element, "turbo-frame:not([disabled])"); 5868 if (isUnsafe || isStream || frame instanceof FrameElement) { 5869 return false; 5870 } else { 5871 const location2 = new URL(element.href); 5872 return this.elementIsNavigatable(element) && locationIsVisitable(location2, this.snapshot.rootLocation); 5873 } 5874 } 5875 // History delegate 5876 historyPoppedToLocationWithRestorationIdentifierAndDirection(location2, restorationIdentifier, direction) { 5877 if (this.enabled) { 5878 this.navigator.startVisit(location2, restorationIdentifier, { 5879 action: "restore", 5880 historyChanged: true, 5881 direction 5882 }); 5883 } else { 5884 this.adapter.pageInvalidated({ 5885 reason: "turbo_disabled" 5886 }); 5887 } 5888 } 5889 // Scroll observer delegate 5890 scrollPositionChanged(position) { 5891 this.history.updateRestorationData({ scrollPosition: position }); 5892 } 5893 // Form click observer delegate 5894 willSubmitFormLinkToLocation(link, location2) { 5895 return this.elementIsNavigatable(link) && locationIsVisitable(location2, this.snapshot.rootLocation); 5896 } 5897 submittedFormLinkToLocation() { 5898 } 5899 // Link hover observer delegate 5900 canPrefetchRequestToLocation(link, location2) { 5901 return this.elementIsNavigatable(link) && locationIsVisitable(location2, this.snapshot.rootLocation); 5902 } 5903 // Link click observer delegate 5904 willFollowLinkToLocation(link, location2, event) { 5905 return this.elementIsNavigatable(link) && locationIsVisitable(location2, this.snapshot.rootLocation) && this.applicationAllowsFollowingLinkToLocation(link, location2, event); 5906 } 5907 followedLinkToLocation(link, location2) { 5908 const action = this.getActionForLink(link); 5909 const acceptsStreamResponse = link.hasAttribute("data-turbo-stream"); 5910 this.visit(location2.href, { action, acceptsStreamResponse }); 5911 } 5912 // Navigator delegate 5913 allowsVisitingLocationWithAction(location2, action) { 5914 return this.locationWithActionIsSamePage(location2, action) || this.applicationAllowsVisitingLocation(location2); 5915 } 5916 visitProposedToLocation(location2, options) { 5917 extendURLWithDeprecatedProperties(location2); 5918 this.adapter.visitProposedToLocation(location2, options); 5919 } 5920 // Visit delegate 5921 visitStarted(visit2) { 5922 if (!visit2.acceptsStreamResponse) { 5923 markAsBusy(document.documentElement); 5924 this.view.markVisitDirection(visit2.direction); 5925 } 5926 extendURLWithDeprecatedProperties(visit2.location); 5927 if (!visit2.silent) { 5928 this.notifyApplicationAfterVisitingLocation(visit2.location, visit2.action); 5929 } 5930 } 5931 visitCompleted(visit2) { 5932 this.view.unmarkVisitDirection(); 5933 clearBusyState(document.documentElement); 5934 this.notifyApplicationAfterPageLoad(visit2.getTimingMetrics()); 5935 } 5936 locationWithActionIsSamePage(location2, action) { 5937 return this.navigator.locationWithActionIsSamePage(location2, action); 5938 } 5939 visitScrolledToSamePageLocation(oldURL, newURL) { 5940 this.notifyApplicationAfterVisitingSamePageLocation(oldURL, newURL); 5941 } 5942 // Form submit observer delegate 5943 willSubmitForm(form, submitter2) { 5944 const action = getAction$1(form, submitter2); 5945 return this.submissionIsNavigatable(form, submitter2) && locationIsVisitable(expandURL(action), this.snapshot.rootLocation); 5946 } 5947 formSubmitted(form, submitter2) { 5948 this.navigator.submitForm(form, submitter2); 5949 } 5950 // Page observer delegate 5951 pageBecameInteractive() { 5952 this.view.lastRenderedLocation = this.location; 5953 this.notifyApplicationAfterPageLoad(); 5954 } 5955 pageLoaded() { 5956 this.history.assumeControlOfScrollRestoration(); 5957 } 5958 pageWillUnload() { 5959 this.history.relinquishControlOfScrollRestoration(); 5960 } 5961 // Stream observer delegate 5962 receivedMessageFromStream(message) { 5963 this.renderStreamMessage(message); 5964 } 5965 // Page view delegate 5966 viewWillCacheSnapshot() { 5967 if (!this.navigator.currentVisit?.silent) { 5968 this.notifyApplicationBeforeCachingSnapshot(); 5969 } 5970 } 5971 allowsImmediateRender({ element }, options) { 5972 const event = this.notifyApplicationBeforeRender(element, options); 5973 const { 5974 defaultPrevented, 5975 detail: { render } 5976 } = event; 5977 if (this.view.renderer && render) { 5978 this.view.renderer.renderElement = render; 5979 } 5980 return !defaultPrevented; 5981 } 5982 viewRenderedSnapshot(_snapshot, _isPreview, renderMethod) { 5983 this.view.lastRenderedLocation = this.history.location; 5984 this.notifyApplicationAfterRender(renderMethod); 5985 } 5986 preloadOnLoadLinksForView(element) { 5987 this.preloader.preloadOnLoadLinksForView(element); 5988 } 5989 viewInvalidated(reason) { 5990 this.adapter.pageInvalidated(reason); 5991 } 5992 // Frame element 5993 frameLoaded(frame) { 5994 this.notifyApplicationAfterFrameLoad(frame); 5995 } 5996 frameRendered(fetchResponse, frame) { 5997 this.notifyApplicationAfterFrameRender(fetchResponse, frame); 5998 } 5999 // Application events 6000 applicationAllowsFollowingLinkToLocation(link, location2, ev) { 6001 const event = this.notifyApplicationAfterClickingLinkToLocation(link, location2, ev); 6002 return !event.defaultPrevented; 6003 } 6004 applicationAllowsVisitingLocation(location2) { 6005 const event = this.notifyApplicationBeforeVisitingLocation(location2); 6006 return !event.defaultPrevented; 6007 } 6008 notifyApplicationAfterClickingLinkToLocation(link, location2, event) { 6009 return dispatch("turbo:click", { 6010 target: link, 6011 detail: { url: location2.href, originalEvent: event }, 6012 cancelable: true 6013 }); 6014 } 6015 notifyApplicationBeforeVisitingLocation(location2) { 6016 return dispatch("turbo:before-visit", { 6017 detail: { url: location2.href }, 6018 cancelable: true 6019 }); 6020 } 6021 notifyApplicationAfterVisitingLocation(location2, action) { 6022 return dispatch("turbo:visit", { detail: { url: location2.href, action } }); 6023 } 6024 notifyApplicationBeforeCachingSnapshot() { 6025 return dispatch("turbo:before-cache"); 6026 } 6027 notifyApplicationBeforeRender(newBody, options) { 6028 return dispatch("turbo:before-render", { 6029 detail: { newBody, ...options }, 6030 cancelable: true 6031 }); 6032 } 6033 notifyApplicationAfterRender(renderMethod) { 6034 return dispatch("turbo:render", { detail: { renderMethod } }); 6035 } 6036 notifyApplicationAfterPageLoad(timing = {}) { 6037 return dispatch("turbo:load", { 6038 detail: { url: this.location.href, timing } 6039 }); 6040 } 6041 notifyApplicationAfterVisitingSamePageLocation(oldURL, newURL) { 6042 dispatchEvent( 6043 new HashChangeEvent("hashchange", { 6044 oldURL: oldURL.toString(), 6045 newURL: newURL.toString() 6046 }) 6047 ); 6048 } 6049 notifyApplicationAfterFrameLoad(frame) { 6050 return dispatch("turbo:frame-load", { target: frame }); 6051 } 6052 notifyApplicationAfterFrameRender(fetchResponse, frame) { 6053 return dispatch("turbo:frame-render", { 6054 detail: { fetchResponse }, 6055 target: frame, 6056 cancelable: true 6057 }); 6058 } 6059 // Helpers 6060 submissionIsNavigatable(form, submitter2) { 6061 if (config.forms.mode == "off") { 6062 return false; 6063 } else { 6064 const submitterIsNavigatable = submitter2 ? this.elementIsNavigatable(submitter2) : true; 6065 if (config.forms.mode == "optin") { 6066 return submitterIsNavigatable && form.closest('[data-turbo="true"]') != null; 6067 } else { 6068 return submitterIsNavigatable && this.elementIsNavigatable(form); 6069 } 6070 } 6071 } 6072 elementIsNavigatable(element) { 6073 const container = findClosestRecursively(element, "[data-turbo]"); 6074 const withinFrame = findClosestRecursively(element, "turbo-frame"); 6075 if (config.drive.enabled || withinFrame) { 6076 if (container) { 6077 return container.getAttribute("data-turbo") != "false"; 6078 } else { 6079 return true; 6080 } 6081 } else { 6082 if (container) { 6083 return container.getAttribute("data-turbo") == "true"; 6084 } else { 6085 return false; 6086 } 6087 } 6088 } 6089 // Private 6090 getActionForLink(link) { 6091 return getVisitAction(link) || "advance"; 6092 } 6093 get snapshot() { 6094 return this.view.snapshot; 6095 } 6096}; 6097function extendURLWithDeprecatedProperties(url) { 6098 Object.defineProperties(url, deprecatedLocationPropertyDescriptors); 6099} 6100var deprecatedLocationPropertyDescriptors = { 6101 absoluteURL: { 6102 get() { 6103 return this.toString(); 6104 } 6105 } 6106}; 6107var session = new Session(recentRequests); 6108var { cache, navigator: navigator$1 } = session; 6109function start() { 6110 session.start(); 6111} 6112function registerAdapter(adapter) { 6113 session.registerAdapter(adapter); 6114} 6115function visit(location2, options) { 6116 session.visit(location2, options); 6117} 6118function connectStreamSource(source) { 6119 session.connectStreamSource(source); 6120} 6121function disconnectStreamSource(source) { 6122 session.disconnectStreamSource(source); 6123} 6124function renderStreamMessage(message) { 6125 session.renderStreamMessage(message); 6126} 6127function clearCache() { 6128 console.warn( 6129 "Please replace `Turbo.clearCache()` with `Turbo.cache.clear()`. The top-level function is deprecated and will be removed in a future version of Turbo.`" 6130 ); 6131 session.clearCache(); 6132} 6133function setProgressBarDelay(delay) { 6134 console.warn( 6135 "Please replace `Turbo.setProgressBarDelay(delay)` with `Turbo.config.drive.progressBarDelay = delay`. The top-level function is deprecated and will be removed in a future version of Turbo.`" 6136 ); 6137 config.drive.progressBarDelay = delay; 6138} 6139function setConfirmMethod(confirmMethod) { 6140 console.warn( 6141 "Please replace `Turbo.setConfirmMethod(confirmMethod)` with `Turbo.config.forms.confirm = confirmMethod`. The top-level function is deprecated and will be removed in a future version of Turbo.`" 6142 ); 6143 config.forms.confirm = confirmMethod; 6144} 6145function setFormMode(mode) { 6146 console.warn( 6147 "Please replace `Turbo.setFormMode(mode)` with `Turbo.config.forms.mode = mode`. The top-level function is deprecated and will be removed in a future version of Turbo.`" 6148 ); 6149 config.forms.mode = mode; 6150} 6151var Turbo2 = /* @__PURE__ */ Object.freeze({ 6152 __proto__: null, 6153 navigator: navigator$1, 6154 session, 6155 cache, 6156 PageRenderer, 6157 PageSnapshot, 6158 FrameRenderer, 6159 fetch: fetchWithTurboHeaders, 6160 config, 6161 start, 6162 registerAdapter, 6163 visit, 6164 connectStreamSource, 6165 disconnectStreamSource, 6166 renderStreamMessage, 6167 clearCache, 6168 setProgressBarDelay, 6169 setConfirmMethod, 6170 setFormMode 6171}); 6172var TurboFrameMissingError = class extends Error { 6173}; 6174var FrameController = class { 6175 fetchResponseLoaded = (_fetchResponse) => Promise.resolve(); 6176 #currentFetchRequest = null; 6177 #resolveVisitPromise = () => { 6178 }; 6179 #connected = false; 6180 #hasBeenLoaded = false; 6181 #ignoredAttributes = /* @__PURE__ */ new Set(); 6182 #shouldMorphFrame = false; 6183 action = null; 6184 constructor(element) { 6185 this.element = element; 6186 this.view = new FrameView(this, this.element); 6187 this.appearanceObserver = new AppearanceObserver(this, this.element); 6188 this.formLinkClickObserver = new FormLinkClickObserver(this, this.element); 6189 this.linkInterceptor = new LinkInterceptor(this, this.element); 6190 this.restorationIdentifier = uuid(); 6191 this.formSubmitObserver = new FormSubmitObserver(this, this.element); 6192 } 6193 // Frame delegate 6194 connect() { 6195 if (!this.#connected) { 6196 this.#connected = true; 6197 if (this.loadingStyle == FrameLoadingStyle.lazy) { 6198 this.appearanceObserver.start(); 6199 } else { 6200 this.#loadSourceURL(); 6201 } 6202 this.formLinkClickObserver.start(); 6203 this.linkInterceptor.start(); 6204 this.formSubmitObserver.start(); 6205 } 6206 } 6207 disconnect() { 6208 if (this.#connected) { 6209 this.#connected = false; 6210 this.appearanceObserver.stop(); 6211 this.formLinkClickObserver.stop(); 6212 this.linkInterceptor.stop(); 6213 this.formSubmitObserver.stop(); 6214 } 6215 } 6216 disabledChanged() { 6217 if (this.loadingStyle == FrameLoadingStyle.eager) { 6218 this.#loadSourceURL(); 6219 } 6220 } 6221 sourceURLChanged() { 6222 if (this.#isIgnoringChangesTo("src")) return; 6223 if (this.element.isConnected) { 6224 this.complete = false; 6225 } 6226 if (this.loadingStyle == FrameLoadingStyle.eager || this.#hasBeenLoaded) { 6227 this.#loadSourceURL(); 6228 } 6229 } 6230 sourceURLReloaded() { 6231 const { refresh, src } = this.element; 6232 this.#shouldMorphFrame = src && refresh === "morph"; 6233 this.element.removeAttribute("complete"); 6234 this.element.src = null; 6235 this.element.src = src; 6236 return this.element.loaded; 6237 } 6238 loadingStyleChanged() { 6239 if (this.loadingStyle == FrameLoadingStyle.lazy) { 6240 this.appearanceObserver.start(); 6241 } else { 6242 this.appearanceObserver.stop(); 6243 this.#loadSourceURL(); 6244 } 6245 } 6246 async #loadSourceURL() { 6247 if (this.enabled && this.isActive && !this.complete && this.sourceURL) { 6248 this.element.loaded = this.#visit(expandURL(this.sourceURL)); 6249 this.appearanceObserver.stop(); 6250 await this.element.loaded; 6251 this.#hasBeenLoaded = true; 6252 } 6253 } 6254 async loadResponse(fetchResponse) { 6255 if (fetchResponse.redirected || fetchResponse.succeeded && fetchResponse.isHTML) { 6256 this.sourceURL = fetchResponse.response.url; 6257 } 6258 try { 6259 const html = await fetchResponse.responseHTML; 6260 if (html) { 6261 const document2 = parseHTMLDocument(html); 6262 const pageSnapshot = PageSnapshot.fromDocument(document2); 6263 if (pageSnapshot.isVisitable) { 6264 await this.#loadFrameResponse(fetchResponse, document2); 6265 } else { 6266 await this.#handleUnvisitableFrameResponse(fetchResponse); 6267 } 6268 } 6269 } finally { 6270 this.#shouldMorphFrame = false; 6271 this.fetchResponseLoaded = () => Promise.resolve(); 6272 } 6273 } 6274 // Appearance observer delegate 6275 elementAppearedInViewport(element) { 6276 this.proposeVisitIfNavigatedWithAction(element, getVisitAction(element)); 6277 this.#loadSourceURL(); 6278 } 6279 // Form link click observer delegate 6280 willSubmitFormLinkToLocation(link) { 6281 return this.#shouldInterceptNavigation(link); 6282 } 6283 submittedFormLinkToLocation(link, _location, form) { 6284 const frame = this.#findFrameElement(link); 6285 if (frame) form.setAttribute("data-turbo-frame", frame.id); 6286 } 6287 // Link interceptor delegate 6288 shouldInterceptLinkClick(element, _location, _event) { 6289 return this.#shouldInterceptNavigation(element); 6290 } 6291 linkClickIntercepted(element, location2) { 6292 this.#navigateFrame(element, location2); 6293 } 6294 // Form submit observer delegate 6295 willSubmitForm(element, submitter2) { 6296 return element.closest("turbo-frame") == this.element && this.#shouldInterceptNavigation(element, submitter2); 6297 } 6298 formSubmitted(element, submitter2) { 6299 if (this.formSubmission) { 6300 this.formSubmission.stop(); 6301 } 6302 this.formSubmission = new FormSubmission(this, element, submitter2); 6303 const { fetchRequest } = this.formSubmission; 6304 this.prepareRequest(fetchRequest); 6305 this.formSubmission.start(); 6306 } 6307 // Fetch request delegate 6308 prepareRequest(request) { 6309 request.headers["Turbo-Frame"] = this.id; 6310 if (this.currentNavigationElement?.hasAttribute("data-turbo-stream")) { 6311 request.acceptResponseType(StreamMessage.contentType); 6312 } 6313 } 6314 requestStarted(_request) { 6315 markAsBusy(this.element); 6316 } 6317 requestPreventedHandlingResponse(_request, _response) { 6318 this.#resolveVisitPromise(); 6319 } 6320 async requestSucceededWithResponse(request, response) { 6321 await this.loadResponse(response); 6322 this.#resolveVisitPromise(); 6323 } 6324 async requestFailedWithResponse(request, response) { 6325 await this.loadResponse(response); 6326 this.#resolveVisitPromise(); 6327 } 6328 requestErrored(request, error2) { 6329 console.error(error2); 6330 this.#resolveVisitPromise(); 6331 } 6332 requestFinished(_request) { 6333 clearBusyState(this.element); 6334 } 6335 // Form submission delegate 6336 formSubmissionStarted({ formElement }) { 6337 markAsBusy(formElement, this.#findFrameElement(formElement)); 6338 } 6339 formSubmissionSucceededWithResponse(formSubmission, response) { 6340 const frame = this.#findFrameElement(formSubmission.formElement, formSubmission.submitter); 6341 frame.delegate.proposeVisitIfNavigatedWithAction(frame, getVisitAction(formSubmission.submitter, formSubmission.formElement, frame)); 6342 frame.delegate.loadResponse(response); 6343 if (!formSubmission.isSafe) { 6344 session.clearCache(); 6345 } 6346 } 6347 formSubmissionFailedWithResponse(formSubmission, fetchResponse) { 6348 this.element.delegate.loadResponse(fetchResponse); 6349 session.clearCache(); 6350 } 6351 formSubmissionErrored(formSubmission, error2) { 6352 console.error(error2); 6353 } 6354 formSubmissionFinished({ formElement }) { 6355 clearBusyState(formElement, this.#findFrameElement(formElement)); 6356 } 6357 // View delegate 6358 allowsImmediateRender({ element: newFrame }, options) { 6359 const event = dispatch("turbo:before-frame-render", { 6360 target: this.element, 6361 detail: { newFrame, ...options }, 6362 cancelable: true 6363 }); 6364 const { 6365 defaultPrevented, 6366 detail: { render } 6367 } = event; 6368 if (this.view.renderer && render) { 6369 this.view.renderer.renderElement = render; 6370 } 6371 return !defaultPrevented; 6372 } 6373 viewRenderedSnapshot(_snapshot, _isPreview, _renderMethod) { 6374 } 6375 preloadOnLoadLinksForView(element) { 6376 session.preloadOnLoadLinksForView(element); 6377 } 6378 viewInvalidated() { 6379 } 6380 // Frame renderer delegate 6381 willRenderFrame(currentElement, _newElement) { 6382 this.previousFrameElement = currentElement.cloneNode(true); 6383 } 6384 visitCachedSnapshot = ({ element }) => { 6385 const frame = element.querySelector("#" + this.element.id); 6386 if (frame && this.previousFrameElement) { 6387 frame.replaceChildren(...this.previousFrameElement.children); 6388 } 6389 delete this.previousFrameElement; 6390 }; 6391 // Private 6392 async #loadFrameResponse(fetchResponse, document2) { 6393 const newFrameElement = await this.extractForeignFrameElement(document2.body); 6394 const rendererClass = this.#shouldMorphFrame ? MorphingFrameRenderer : FrameRenderer; 6395 if (newFrameElement) { 6396 const snapshot = new Snapshot(newFrameElement); 6397 const renderer = new rendererClass(this, this.view.snapshot, snapshot, false, false); 6398 if (this.view.renderPromise) await this.view.renderPromise; 6399 this.changeHistory(); 6400 await this.view.render(renderer); 6401 this.complete = true; 6402 session.frameRendered(fetchResponse, this.element); 6403 session.frameLoaded(this.element); 6404 await this.fetchResponseLoaded(fetchResponse); 6405 } else if (this.#willHandleFrameMissingFromResponse(fetchResponse)) { 6406 this.#handleFrameMissingFromResponse(fetchResponse); 6407 } 6408 } 6409 async #visit(url) { 6410 const request = new FetchRequest(this, FetchMethod.get, url, new URLSearchParams(), this.element); 6411 this.#currentFetchRequest?.cancel(); 6412 this.#currentFetchRequest = request; 6413 return new Promise((resolve) => { 6414 this.#resolveVisitPromise = () => { 6415 this.#resolveVisitPromise = () => { 6416 }; 6417 this.#currentFetchRequest = null; 6418 resolve(); 6419 }; 6420 request.perform(); 6421 }); 6422 } 6423 #navigateFrame(element, url, submitter2) { 6424 const frame = this.#findFrameElement(element, submitter2); 6425 frame.delegate.proposeVisitIfNavigatedWithAction(frame, getVisitAction(submitter2, element, frame)); 6426 this.#withCurrentNavigationElement(element, () => { 6427 frame.src = url; 6428 }); 6429 } 6430 proposeVisitIfNavigatedWithAction(frame, action = null) { 6431 this.action = action; 6432 if (this.action) { 6433 const pageSnapshot = PageSnapshot.fromElement(frame).clone(); 6434 const { visitCachedSnapshot } = frame.delegate; 6435 frame.delegate.fetchResponseLoaded = async (fetchResponse) => { 6436 if (frame.src) { 6437 const { statusCode, redirected } = fetchResponse; 6438 const responseHTML = await fetchResponse.responseHTML; 6439 const response = { statusCode, redirected, responseHTML }; 6440 const options = { 6441 response, 6442 visitCachedSnapshot, 6443 willRender: false, 6444 updateHistory: false, 6445 restorationIdentifier: this.restorationIdentifier, 6446 snapshot: pageSnapshot 6447 }; 6448 if (this.action) options.action = this.action; 6449 session.visit(frame.src, options); 6450 } 6451 }; 6452 } 6453 } 6454 changeHistory() { 6455 if (this.action) { 6456 const method = getHistoryMethodForAction(this.action); 6457 session.history.update(method, expandURL(this.element.src || ""), this.restorationIdentifier); 6458 } 6459 } 6460 async #handleUnvisitableFrameResponse(fetchResponse) { 6461 console.warn( 6462 `The response (${fetchResponse.statusCode}) from <turbo-frame id="${this.element.id}"> is performing a full page visit due to turbo-visit-control.` 6463 ); 6464 await this.#visitResponse(fetchResponse.response); 6465 } 6466 #willHandleFrameMissingFromResponse(fetchResponse) { 6467 this.element.setAttribute("complete", ""); 6468 const response = fetchResponse.response; 6469 const visit2 = async (url, options) => { 6470 if (url instanceof Response) { 6471 this.#visitResponse(url); 6472 } else { 6473 session.visit(url, options); 6474 } 6475 }; 6476 const event = dispatch("turbo:frame-missing", { 6477 target: this.element, 6478 detail: { response, visit: visit2 }, 6479 cancelable: true 6480 }); 6481 return !event.defaultPrevented; 6482 } 6483 #handleFrameMissingFromResponse(fetchResponse) { 6484 this.view.missing(); 6485 this.#throwFrameMissingError(fetchResponse); 6486 } 6487 #throwFrameMissingError(fetchResponse) { 6488 const message = `The response (${fetchResponse.statusCode}) did not contain the expected <turbo-frame id="${this.element.id}"> and will be ignored. To perform a full page visit instead, set turbo-visit-control to reload.`; 6489 throw new TurboFrameMissingError(message); 6490 } 6491 async #visitResponse(response) { 6492 const wrapped = new FetchResponse(response); 6493 const responseHTML = await wrapped.responseHTML; 6494 const { location: location2, redirected, statusCode } = wrapped; 6495 return session.visit(location2, { response: { redirected, statusCode, responseHTML } }); 6496 } 6497 #findFrameElement(element, submitter2) { 6498 const id = getAttribute("data-turbo-frame", submitter2, element) || this.element.getAttribute("target"); 6499 return getFrameElementById(id) ?? this.element; 6500 } 6501 async extractForeignFrameElement(container) { 6502 let element; 6503 const id = CSS.escape(this.id); 6504 try { 6505 element = activateElement(container.querySelector(`turbo-frame#${id}`), this.sourceURL); 6506 if (element) { 6507 return element; 6508 } 6509 element = activateElement(container.querySelector(`turbo-frame[src][recurse~=${id}]`), this.sourceURL); 6510 if (element) { 6511 await element.loaded; 6512 return await this.extractForeignFrameElement(element); 6513 } 6514 } catch (error2) { 6515 console.error(error2); 6516 return new FrameElement(); 6517 } 6518 return null; 6519 } 6520 #formActionIsVisitable(form, submitter2) { 6521 const action = getAction$1(form, submitter2); 6522 return locationIsVisitable(expandURL(action), this.rootLocation); 6523 } 6524 #shouldInterceptNavigation(element, submitter2) { 6525 const id = getAttribute("data-turbo-frame", submitter2, element) || this.element.getAttribute("target"); 6526 if (element instanceof HTMLFormElement && !this.#formActionIsVisitable(element, submitter2)) { 6527 return false; 6528 } 6529 if (!this.enabled || id == "_top") { 6530 return false; 6531 } 6532 if (id) { 6533 const frameElement = getFrameElementById(id); 6534 if (frameElement) { 6535 return !frameElement.disabled; 6536 } 6537 } 6538 if (!session.elementIsNavigatable(element)) { 6539 return false; 6540 } 6541 if (submitter2 && !session.elementIsNavigatable(submitter2)) { 6542 return false; 6543 } 6544 return true; 6545 } 6546 // Computed properties 6547 get id() { 6548 return this.element.id; 6549 } 6550 get enabled() { 6551 return !this.element.disabled; 6552 } 6553 get sourceURL() { 6554 if (this.element.src) { 6555 return this.element.src; 6556 } 6557 } 6558 set sourceURL(sourceURL) { 6559 this.#ignoringChangesToAttribute("src", () => { 6560 this.element.src = sourceURL ?? null; 6561 }); 6562 } 6563 get loadingStyle() { 6564 return this.element.loading; 6565 } 6566 get isLoading() { 6567 return this.formSubmission !== void 0 || this.#resolveVisitPromise() !== void 0; 6568 } 6569 get complete() { 6570 return this.element.hasAttribute("complete"); 6571 } 6572 set complete(value) { 6573 if (value) { 6574 this.element.setAttribute("complete", ""); 6575 } else { 6576 this.element.removeAttribute("complete"); 6577 } 6578 } 6579 get isActive() { 6580 return this.element.isActive && this.#connected; 6581 } 6582 get rootLocation() { 6583 const meta = this.element.ownerDocument.querySelector(`meta[name="turbo-root"]`); 6584 const root = meta?.content ?? "/"; 6585 return expandURL(root); 6586 } 6587 #isIgnoringChangesTo(attributeName) { 6588 return this.#ignoredAttributes.has(attributeName); 6589 } 6590 #ignoringChangesToAttribute(attributeName, callback) { 6591 this.#ignoredAttributes.add(attributeName); 6592 callback(); 6593 this.#ignoredAttributes.delete(attributeName); 6594 } 6595 #withCurrentNavigationElement(element, callback) { 6596 this.currentNavigationElement = element; 6597 callback(); 6598 delete this.currentNavigationElement; 6599 } 6600}; 6601function getFrameElementById(id) { 6602 if (id != null) { 6603 const element = document.getElementById(id); 6604 if (element instanceof FrameElement) { 6605 return element; 6606 } 6607 } 6608} 6609function activateElement(element, currentURL) { 6610 if (element) { 6611 const src = element.getAttribute("src"); 6612 if (src != null && currentURL != null && urlsAreEqual(src, currentURL)) { 6613 throw new Error(`Matching <turbo-frame id="${element.id}"> element has a source URL which references itself`); 6614 } 6615 if (element.ownerDocument !== document) { 6616 element = document.importNode(element, true); 6617 } 6618 if (element instanceof FrameElement) { 6619 element.connectedCallback(); 6620 element.disconnectedCallback(); 6621 return element; 6622 } 6623 } 6624} 6625var StreamActions = { 6626 after() { 6627 this.targetElements.forEach((e) => e.parentElement?.insertBefore(this.templateContent, e.nextSibling)); 6628 }, 6629 append() { 6630 this.removeDuplicateTargetChildren(); 6631 this.targetElements.forEach((e) => e.append(this.templateContent)); 6632 }, 6633 before() { 6634 this.targetElements.forEach((e) => e.parentElement?.insertBefore(this.templateContent, e)); 6635 }, 6636 prepend() { 6637 this.removeDuplicateTargetChildren(); 6638 this.targetElements.forEach((e) => e.prepend(this.templateContent)); 6639 }, 6640 remove() { 6641 this.targetElements.forEach((e) => e.remove()); 6642 }, 6643 replace() { 6644 const method = this.getAttribute("method"); 6645 this.targetElements.forEach((targetElement) => { 6646 if (method === "morph") { 6647 morphElements(targetElement, this.templateContent); 6648 } else { 6649 targetElement.replaceWith(this.templateContent); 6650 } 6651 }); 6652 }, 6653 update() { 6654 const method = this.getAttribute("method"); 6655 this.targetElements.forEach((targetElement) => { 6656 if (method === "morph") { 6657 morphChildren(targetElement, this.templateContent); 6658 } else { 6659 targetElement.innerHTML = ""; 6660 targetElement.append(this.templateContent); 6661 } 6662 }); 6663 }, 6664 refresh() { 6665 session.refresh(this.baseURI, this.requestId); 6666 } 6667}; 6668var StreamElement = class _StreamElement extends HTMLElement { 6669 static async renderElement(newElement) { 6670 await newElement.performAction(); 6671 } 6672 async connectedCallback() { 6673 try { 6674 await this.render(); 6675 } catch (error2) { 6676 console.error(error2); 6677 } finally { 6678 this.disconnect(); 6679 } 6680 } 6681 async render() { 6682 return this.renderPromise ??= (async () => { 6683 const event = this.beforeRenderEvent; 6684 if (this.dispatchEvent(event)) { 6685 await nextRepaint(); 6686 await event.detail.render(this); 6687 } 6688 })(); 6689 } 6690 disconnect() { 6691 try { 6692 this.remove(); 6693 } catch { 6694 } 6695 } 6696 /** 6697 * Removes duplicate children (by ID) 6698 */ 6699 removeDuplicateTargetChildren() { 6700 this.duplicateChildren.forEach((c) => c.remove()); 6701 } 6702 /** 6703 * Gets the list of duplicate children (i.e. those with the same ID) 6704 */ 6705 get duplicateChildren() { 6706 const existingChildren = this.targetElements.flatMap((e) => [...e.children]).filter((c) => !!c.id); 6707 const newChildrenIds = [...this.templateContent?.children || []].filter((c) => !!c.id).map((c) => c.id); 6708 return existingChildren.filter((c) => newChildrenIds.includes(c.id)); 6709 } 6710 /** 6711 * Gets the action function to be performed. 6712 */ 6713 get performAction() { 6714 if (this.action) { 6715 const actionFunction = StreamActions[this.action]; 6716 if (actionFunction) { 6717 return actionFunction; 6718 } 6719 this.#raise("unknown action"); 6720 } 6721 this.#raise("action attribute is missing"); 6722 } 6723 /** 6724 * Gets the target elements which the template will be rendered to. 6725 */ 6726 get targetElements() { 6727 if (this.target) { 6728 return this.targetElementsById; 6729 } else if (this.targets) { 6730 return this.targetElementsByQuery; 6731 } else { 6732 this.#raise("target or targets attribute is missing"); 6733 } 6734 } 6735 /** 6736 * Gets the contents of the main `<template>`. 6737 */ 6738 get templateContent() { 6739 return this.templateElement.content.cloneNode(true); 6740 } 6741 /** 6742 * Gets the main `<template>` used for rendering 6743 */ 6744 get templateElement() { 6745 if (this.firstElementChild === null) { 6746 const template = this.ownerDocument.createElement("template"); 6747 this.appendChild(template); 6748 return template; 6749 } else if (this.firstElementChild instanceof HTMLTemplateElement) { 6750 return this.firstElementChild; 6751 } 6752 this.#raise("first child element must be a <template> element"); 6753 } 6754 /** 6755 * Gets the current action. 6756 */ 6757 get action() { 6758 return this.getAttribute("action"); 6759 } 6760 /** 6761 * Gets the current target (an element ID) to which the result will 6762 * be rendered. 6763 */ 6764 get target() { 6765 return this.getAttribute("target"); 6766 } 6767 /** 6768 * Gets the current "targets" selector (a CSS selector) 6769 */ 6770 get targets() { 6771 return this.getAttribute("targets"); 6772 } 6773 /** 6774 * Reads the request-id attribute 6775 */ 6776 get requestId() { 6777 return this.getAttribute("request-id"); 6778 } 6779 #raise(message) { 6780 throw new Error(`${this.description}: ${message}`); 6781 } 6782 get description() { 6783 return (this.outerHTML.match(/<[^>]+>/) ?? [])[0] ?? "<turbo-stream>"; 6784 } 6785 get beforeRenderEvent() { 6786 return new CustomEvent("turbo:before-stream-render", { 6787 bubbles: true, 6788 cancelable: true, 6789 detail: { newStream: this, render: _StreamElement.renderElement } 6790 }); 6791 } 6792 get targetElementsById() { 6793 const element = this.ownerDocument?.getElementById(this.target); 6794 if (element !== null) { 6795 return [element]; 6796 } else { 6797 return []; 6798 } 6799 } 6800 get targetElementsByQuery() { 6801 const elements = this.ownerDocument?.querySelectorAll(this.targets); 6802 if (elements.length !== 0) { 6803 return Array.prototype.slice.call(elements); 6804 } else { 6805 return []; 6806 } 6807 } 6808}; 6809var StreamSourceElement = class extends HTMLElement { 6810 streamSource = null; 6811 connectedCallback() { 6812 this.streamSource = this.src.match(/^ws{1,2}:/) ? new WebSocket(this.src) : new EventSource(this.src); 6813 connectStreamSource(this.streamSource); 6814 } 6815 disconnectedCallback() { 6816 if (this.streamSource) { 6817 this.streamSource.close(); 6818 disconnectStreamSource(this.streamSource); 6819 } 6820 } 6821 get src() { 6822 return this.getAttribute("src") || ""; 6823 } 6824}; 6825FrameElement.delegateConstructor = FrameController; 6826if (customElements.get("turbo-frame") === void 0) { 6827 customElements.define("turbo-frame", FrameElement); 6828} 6829if (customElements.get("turbo-stream") === void 0) { 6830 customElements.define("turbo-stream", StreamElement); 6831} 6832if (customElements.get("turbo-stream-source") === void 0) { 6833 customElements.define("turbo-stream-source", StreamSourceElement); 6834} 6835(() => { 6836 let element = document.currentScript; 6837 if (!element) return; 6838 if (element.hasAttribute("data-turbo-suppress-warning")) return; 6839 element = element.parentElement; 6840 while (element) { 6841 if (element == document.body) { 6842 return console.warn( 6843 unindent` 6844 You are loading Turbo from a <script> element inside the <body> element. This is probably not what you meant to do! 6845 6846 Load your applicationâs JavaScript bundle inside the <head> element instead. <script> elements in <body> are evaluated with each page change. 6847 6848 For more information, see: https://turbo.hotwired.dev/handbook/building#working-with-script-elements 6849 6850 ââ 6851 Suppress this warning by adding a "data-turbo-suppress-warning" attribute to: %s 6852 `, 6853 element.outerHTML 6854 ); 6855 } 6856 element = element.parentElement; 6857 } 6858})(); 6859window.Turbo = { ...Turbo2, StreamActions }; 6860start(); 6861
vendor: 575 bytes, lines 6862-6878
6862// node_modules/@hotwired/turbo-rails/app/javascript/turbo/cable.js 6863var consumer; 6864async function getConsumer() { 6865 return consumer || setConsumer(createConsumer2().then(setConsumer)); 6866} 6867function setConsumer(newConsumer) { 6868 return consumer = newConsumer; 6869} 6870async function createConsumer2() { 6871 const { createConsumer: createConsumer3 } = await Promise.resolve().then(() => (init_src(), src_exports)); 6872 return createConsumer3(); 6873} 6874async function subscribeTo(channel, mixin) { 6875 const { subscriptions } = await getConsumer(); 6876 return subscriptions.create(channel, mixin); 6877} 6878
vendor: 505 bytes, lines 6879-6892
6879// node_modules/@hotwired/turbo-rails/app/javascript/turbo/snakeize.js 6880function walk(obj) { 6881 if (!obj || typeof obj !== "object") return obj; 6882 if (obj instanceof Date || obj instanceof RegExp) return obj; 6883 if (Array.isArray(obj)) return obj.map(walk); 6884 return Object.keys(obj).reduce(function(acc, key) { 6885 var camel = key[0].toLowerCase() + key.slice(1).replace(/([A-Z]+)/g, function(m, x) { 6886 return "_" + x.toLowerCase(); 6887 }); 6888 acc[camel] = walk(obj[key]); 6889 return acc; 6890 }, {}); 6891} 6892
vendor: 1,471 bytes, lines 6893-6934
6893// node_modules/@hotwired/turbo-rails/app/javascript/turbo/cable_stream_source_element.js 6894var TurboCableStreamSourceElement = class extends HTMLElement { 6895 static observedAttributes = ["channel", "signed-stream-name"]; 6896 async connectedCallback() { 6897 connectStreamSource(this); 6898 this.subscription = await subscribeTo(this.channel, { 6899 received: this.dispatchMessageEvent.bind(this), 6900 connected: this.subscriptionConnected.bind(this), 6901 disconnected: this.subscriptionDisconnected.bind(this) 6902 }); 6903 } 6904 disconnectedCallback() { 6905 disconnectStreamSource(this); 6906 if (this.subscription) this.subscription.unsubscribe(); 6907 this.subscriptionDisconnected(); 6908 } 6909 attributeChangedCallback() { 6910 if (this.subscription) { 6911 this.disconnectedCallback(); 6912 this.connectedCallback(); 6913 } 6914 } 6915 dispatchMessageEvent(data) { 6916 const event = new MessageEvent("message", { data }); 6917 return this.dispatchEvent(event); 6918 } 6919 subscriptionConnected() { 6920 this.setAttribute("connected", ""); 6921 } 6922 subscriptionDisconnected() { 6923 this.removeAttribute("connected"); 6924 } 6925 get channel() { 6926 const channel = this.getAttribute("channel"); 6927 const signed_stream_name = this.getAttribute("signed-stream-name"); 6928 return { channel, signed_stream_name, ...walk({ ...this.dataset }) }; 6929 } 6930}; 6931if (customElements.get("turbo-cable-stream-source") === void 0) { 6932 customElements.define("turbo-cable-stream-source", TurboCableStreamSourceElement); 6933} 6934
vendor: 1,611 bytes, lines 6935-6981
6935// node_modules/@hotwired/turbo-rails/app/javascript/turbo/fetch_requests.js 6936function encodeMethodIntoRequestBody(event) { 6937 if (event.target instanceof HTMLFormElement) { 6938 const { target: form, detail: { fetchOptions } } = event; 6939 form.addEventListener("turbo:submit-start", ({ detail: { formSubmission: { submitter: submitter2 } } }) => { 6940 const body = isBodyInit(fetchOptions.body) ? fetchOptions.body : new URLSearchParams(); 6941 const method = determineFetchMethod(submitter2, body, form); 6942 if (!/get/i.test(method)) { 6943 if (/post/i.test(method)) { 6944 body.delete("_method"); 6945 } else { 6946 body.set("_method", method); 6947 } 6948 fetchOptions.method = "post"; 6949 } 6950 }, { once: true }); 6951 } 6952} 6953function determineFetchMethod(submitter2, body, form) { 6954 const formMethod = determineFormMethod(submitter2); 6955 const overrideMethod = body.get("_method"); 6956 const method = form.getAttribute("method") || "get"; 6957 if (typeof formMethod == "string") { 6958 return formMethod; 6959 } else if (typeof overrideMethod == "string") { 6960 return overrideMethod; 6961 } else { 6962 return method; 6963 } 6964} 6965function determineFormMethod(submitter2) { 6966 if (submitter2 instanceof HTMLButtonElement || submitter2 instanceof HTMLInputElement) { 6967 if (submitter2.name === "_method") { 6968 return submitter2.value; 6969 } else if (submitter2.hasAttribute("formmethod")) { 6970 return submitter2.formMethod; 6971 } else { 6972 return null; 6973 } 6974 } else { 6975 return null; 6976 } 6977} 6978function isBodyInit(body) { 6979 return body instanceof FormData || body instanceof URLSearchParams; 6980} 6981
vendor: 187 bytes, lines 6982-6985
6982// node_modules/@hotwired/turbo-rails/app/javascript/turbo/index.js 6983window.Turbo = turbo_es2017_esm_exports; 6984addEventListener("turbo:before-fetch-request", encodeMethodIntoRequestBody); 6985
vendor: 79,408 bytes, lines 6986-9433
6986// node_modules/@hotwired/stimulus/dist/stimulus.js 6987var EventListener = class { 6988 constructor(eventTarget, eventName, eventOptions) { 6989 this.eventTarget = eventTarget; 6990 this.eventName = eventName; 6991 this.eventOptions = eventOptions; 6992 this.unorderedBindings = /* @__PURE__ */ new Set(); 6993 } 6994 connect() { 6995 this.eventTarget.addEventListener(this.eventName, this, this.eventOptions); 6996 } 6997 disconnect() { 6998 this.eventTarget.removeEventListener(this.eventName, this, this.eventOptions); 6999 } 7000 bindingConnected(binding) { 7001 this.unorderedBindings.add(binding); 7002 } 7003 bindingDisconnected(binding) { 7004 this.unorderedBindings.delete(binding); 7005 } 7006 handleEvent(event) { 7007 const extendedEvent = extendEvent(event); 7008 for (const binding of this.bindings) { 7009 if (extendedEvent.immediatePropagationStopped) { 7010 break; 7011 } else { 7012 binding.handleEvent(extendedEvent); 7013 } 7014 } 7015 } 7016 hasBindings() { 7017 return this.unorderedBindings.size > 0; 7018 } 7019 get bindings() { 7020 return Array.from(this.unorderedBindings).sort((left, right) => { 7021 const leftIndex = left.index, rightIndex = right.index; 7022 return leftIndex < rightIndex ? -1 : leftIndex > rightIndex ? 1 : 0; 7023 }); 7024 } 7025}; 7026function extendEvent(event) { 7027 if ("immediatePropagationStopped" in event) { 7028 return event; 7029 } else { 7030 const { stopImmediatePropagation } = event; 7031 return Object.assign(event, { 7032 immediatePropagationStopped: false, 7033 stopImmediatePropagation() { 7034 this.immediatePropagationStopped = true; 7035 stopImmediatePropagation.call(this); 7036 } 7037 }); 7038 } 7039} 7040var Dispatcher = class { 7041 constructor(application2) { 7042 this.application = application2; 7043 this.eventListenerMaps = /* @__PURE__ */ new Map(); 7044 this.started = false; 7045 } 7046 start() { 7047 if (!this.started) { 7048 this.started = true; 7049 this.eventListeners.forEach((eventListener) => eventListener.connect()); 7050 } 7051 } 7052 stop() { 7053 if (this.started) { 7054 this.started = false; 7055 this.eventListeners.forEach((eventListener) => eventListener.disconnect()); 7056 } 7057 } 7058 get eventListeners() { 7059 return Array.from(this.eventListenerMaps.values()).reduce((listeners, map) => listeners.concat(Array.from(map.values())), []); 7060 } 7061 bindingConnected(binding) { 7062 this.fetchEventListenerForBinding(binding).bindingConnected(binding); 7063 } 7064 bindingDisconnected(binding, clearEventListeners = false) { 7065 this.fetchEventListenerForBinding(binding).bindingDisconnected(binding); 7066 if (clearEventListeners) 7067 this.clearEventListenersForBinding(binding); 7068 } 7069 handleError(error2, message, detail = {}) { 7070 this.application.handleError(error2, `Error ${message}`, detail); 7071 } 7072 clearEventListenersForBinding(binding) { 7073 const eventListener = this.fetchEventListenerForBinding(binding); 7074 if (!eventListener.hasBindings()) { 7075 eventListener.disconnect(); 7076 this.removeMappedEventListenerFor(binding); 7077 } 7078 } 7079 removeMappedEventListenerFor(binding) { 7080 const { eventTarget, eventName, eventOptions } = binding; 7081 const eventListenerMap = this.fetchEventListenerMapForEventTarget(eventTarget); 7082 const cacheKey = this.cacheKey(eventName, eventOptions); 7083 eventListenerMap.delete(cacheKey); 7084 if (eventListenerMap.size == 0) 7085 this.eventListenerMaps.delete(eventTarget); 7086 } 7087 fetchEventListenerForBinding(binding) { 7088 const { eventTarget, eventName, eventOptions } = binding; 7089 return this.fetchEventListener(eventTarget, eventName, eventOptions); 7090 } 7091 fetchEventListener(eventTarget, eventName, eventOptions) { 7092 const eventListenerMap = this.fetchEventListenerMapForEventTarget(eventTarget); 7093 const cacheKey = this.cacheKey(eventName, eventOptions); 7094 let eventListener = eventListenerMap.get(cacheKey); 7095 if (!eventListener) { 7096 eventListener = this.createEventListener(eventTarget, eventName, eventOptions); 7097 eventListenerMap.set(cacheKey, eventListener); 7098 } 7099 return eventListener; 7100 } 7101 createEventListener(eventTarget, eventName, eventOptions) { 7102 const eventListener = new EventListener(eventTarget, eventName, eventOptions); 7103 if (this.started) { 7104 eventListener.connect(); 7105 } 7106 return eventListener; 7107 } 7108 fetchEventListenerMapForEventTarget(eventTarget) { 7109 let eventListenerMap = this.eventListenerMaps.get(eventTarget); 7110 if (!eventListenerMap) { 7111 eventListenerMap = /* @__PURE__ */ new Map(); 7112 this.eventListenerMaps.set(eventTarget, eventListenerMap); 7113 } 7114 return eventListenerMap; 7115 } 7116 cacheKey(eventName, eventOptions) { 7117 const parts = [eventName]; 7118 Object.keys(eventOptions).sort().forEach((key) => { 7119 parts.push(`${eventOptions[key] ? "" : "!"}${key}`); 7120 }); 7121 return parts.join(":"); 7122 } 7123}; 7124var defaultActionDescriptorFilters = { 7125 stop({ event, value }) { 7126 if (value) 7127 event.stopPropagation(); 7128 return true; 7129 }, 7130 prevent({ event, value }) { 7131 if (value) 7132 event.preventDefault(); 7133 return true; 7134 }, 7135 self({ event, value, element }) { 7136 if (value) { 7137 return element === event.target; 7138 } else { 7139 return true; 7140 } 7141 } 7142}; 7143var descriptorPattern = /^(?:(?:([^.]+?)\+)?(.+?)(?:\.(.+?))?(?:@(window|document))?->)?(.+?)(?:#([^:]+?))(?::(.+))?$/; 7144function parseActionDescriptorString(descriptorString) { 7145 const source = descriptorString.trim(); 7146 const matches = source.match(descriptorPattern) || []; 7147 let eventName = matches[2]; 7148 let keyFilter = matches[3]; 7149 if (keyFilter && !["keydown", "keyup", "keypress"].includes(eventName)) { 7150 eventName += `.${keyFilter}`; 7151 keyFilter = ""; 7152 } 7153 return { 7154 eventTarget: parseEventTarget(matches[4]), 7155 eventName, 7156 eventOptions: matches[7] ? parseEventOptions(matches[7]) : {}, 7157 identifier: matches[5], 7158 methodName: matches[6], 7159 keyFilter: matches[1] || keyFilter 7160 }; 7161} 7162function parseEventTarget(eventTargetName) { 7163 if (eventTargetName == "window") { 7164 return window; 7165 } else if (eventTargetName == "document") { 7166 return document; 7167 } 7168} 7169function parseEventOptions(eventOptions) { 7170 return eventOptions.split(":").reduce((options, token) => Object.assign(options, { [token.replace(/^!/, "")]: !/^!/.test(token) }), {}); 7171} 7172function stringifyEventTarget(eventTarget) { 7173 if (eventTarget == window) { 7174 return "window"; 7175 } else if (eventTarget == document) { 7176 return "document"; 7177 } 7178} 7179function camelize(value) { 7180 return value.replace(/(?:[_-])([a-z0-9])/g, (_, char) => char.toUpperCase()); 7181} 7182function namespaceCamelize(value) { 7183 return camelize(value.replace(/--/g, "-").replace(/__/g, "_")); 7184} 7185function capitalize(value) { 7186 return value.charAt(0).toUpperCase() + value.slice(1); 7187} 7188function dasherize(value) { 7189 return value.replace(/([A-Z])/g, (_, char) => `-${char.toLowerCase()}`); 7190} 7191function tokenize(value) { 7192 return value.match(/[^\s]+/g) || []; 7193} 7194function isSomething(object) { 7195 return object !== null && object !== void 0; 7196} 7197function hasProperty(object, property) { 7198 return Object.prototype.hasOwnProperty.call(object, property); 7199} 7200var allModifiers = ["meta", "ctrl", "alt", "shift"]; 7201var Action = class { 7202 constructor(element, index, descriptor, schema) { 7203 this.element = element; 7204 this.index = index; 7205 this.eventTarget = descriptor.eventTarget || element; 7206 this.eventName = descriptor.eventName || getDefaultEventNameForElement(element) || error("missing event name"); 7207 this.eventOptions = descriptor.eventOptions || {}; 7208 this.identifier = descriptor.identifier || error("missing identifier"); 7209 this.methodName = descriptor.methodName || error("missing method name"); 7210 this.keyFilter = descriptor.keyFilter || ""; 7211 this.schema = schema; 7212 } 7213 static forToken(token, schema) { 7214 return new this(token.element, token.index, parseActionDescriptorString(token.content), schema); 7215 } 7216 toString() { 7217 const eventFilter = this.keyFilter ? `.${this.keyFilter}` : ""; 7218 const eventTarget = this.eventTargetName ? `@${this.eventTargetName}` : ""; 7219 return `${this.eventName}${eventFilter}${eventTarget}->${this.identifier}#${this.methodName}`; 7220 } 7221 shouldIgnoreKeyboardEvent(event) { 7222 if (!this.keyFilter) { 7223 return false; 7224 } 7225 const filters = this.keyFilter.split("+"); 7226 if (this.keyFilterDissatisfied(event, filters)) { 7227 return true; 7228 } 7229 const standardFilter = filters.filter((key) => !allModifiers.includes(key))[0]; 7230 if (!standardFilter) { 7231 return false; 7232 } 7233 if (!hasProperty(this.keyMappings, standardFilter)) { 7234 error(`contains unknown key filter: ${this.keyFilter}`); 7235 } 7236 return this.keyMappings[standardFilter].toLowerCase() !== event.key.toLowerCase(); 7237 } 7238 shouldIgnoreMouseEvent(event) { 7239 if (!this.keyFilter) { 7240 return false; 7241 } 7242 const filters = [this.keyFilter]; 7243 if (this.keyFilterDissatisfied(event, filters)) { 7244 return true; 7245 } 7246 return false; 7247 } 7248 get params() { 7249 const params = {}; 7250 const pattern = new RegExp(`^data-${this.identifier}-(.+)-param$`, "i"); 7251 for (const { name, value } of Array.from(this.element.attributes)) { 7252 const match = name.match(pattern); 7253 const key = match && match[1]; 7254 if (key) { 7255 params[camelize(key)] = typecast(value); 7256 } 7257 } 7258 return params; 7259 } 7260 get eventTargetName() { 7261 return stringifyEventTarget(this.eventTarget); 7262 } 7263 get keyMappings() { 7264 return this.schema.keyMappings; 7265 } 7266 keyFilterDissatisfied(event, filters) { 7267 const [meta, ctrl, alt, shift] = allModifiers.map((modifier) => filters.includes(modifier)); 7268 return event.metaKey !== meta || event.ctrlKey !== ctrl || event.altKey !== alt || event.shiftKey !== shift; 7269 } 7270}; 7271var defaultEventNames = { 7272 a: () => "click", 7273 button: () => "click", 7274 form: () => "submit", 7275 details: () => "toggle", 7276 input: (e) => e.getAttribute("type") == "submit" ? "click" : "input", 7277 select: () => "change", 7278 textarea: () => "input" 7279}; 7280function getDefaultEventNameForElement(element) { 7281 const tagName = element.tagName.toLowerCase(); 7282 if (tagName in defaultEventNames) { 7283 return defaultEventNames[tagName](element); 7284 } 7285} 7286function error(message) { 7287 throw new Error(message); 7288} 7289function typecast(value) { 7290 try { 7291 return JSON.parse(value); 7292 } catch (o_O) { 7293 return value; 7294 } 7295} 7296var Binding = class { 7297 constructor(context, action) { 7298 this.context = context; 7299 this.action = action; 7300 } 7301 get index() { 7302 return this.action.index; 7303 } 7304 get eventTarget() { 7305 return this.action.eventTarget; 7306 } 7307 get eventOptions() { 7308 return this.action.eventOptions; 7309 } 7310 get identifier() { 7311 return this.context.identifier; 7312 } 7313 handleEvent(event) { 7314 const actionEvent = this.prepareActionEvent(event); 7315 if (this.willBeInvokedByEvent(event) && this.applyEventModifiers(actionEvent)) { 7316 this.invokeWithEvent(actionEvent); 7317 } 7318 } 7319 get eventName() { 7320 return this.action.eventName; 7321 } 7322 get method() { 7323 const method = this.controller[this.methodName]; 7324 if (typeof method == "function") { 7325 return method; 7326 } 7327 throw new Error(`Action "${this.action}" references undefined method "${this.methodName}"`); 7328 } 7329 applyEventModifiers(event) { 7330 const { element } = this.action; 7331 const { actionDescriptorFilters } = this.context.application; 7332 const { controller } = this.context; 7333 let passes = true; 7334 for (const [name, value] of Object.entries(this.eventOptions)) { 7335 if (name in actionDescriptorFilters) { 7336 const filter = actionDescriptorFilters[name]; 7337 passes = passes && filter({ name, value, event, element, controller }); 7338 } else { 7339 continue; 7340 } 7341 } 7342 return passes; 7343 } 7344 prepareActionEvent(event) { 7345 return Object.assign(event, { params: this.action.params }); 7346 } 7347 invokeWithEvent(event) { 7348 const { target, currentTarget } = event; 7349 try { 7350 this.method.call(this.controller, event); 7351 this.context.logDebugActivity(this.methodName, { event, target, currentTarget, action: this.methodName }); 7352 } catch (error2) { 7353 const { identifier, controller, element, index } = this; 7354 const detail = { identifier, controller, element, index, event }; 7355 this.context.handleError(error2, `invoking action "${this.action}"`, detail); 7356 } 7357 } 7358 willBeInvokedByEvent(event) { 7359 const eventTarget = event.target; 7360 if (event instanceof KeyboardEvent && this.action.shouldIgnoreKeyboardEvent(event)) { 7361 return false; 7362 } 7363 if (event instanceof MouseEvent && this.action.shouldIgnoreMouseEvent(event)) { 7364 return false; 7365 } 7366 if (this.element === eventTarget) { 7367 return true; 7368 } else if (eventTarget instanceof Element && this.element.contains(eventTarget)) { 7369 return this.scope.containsElement(eventTarget); 7370 } else { 7371 return this.scope.containsElement(this.action.element); 7372 } 7373 } 7374 get controller() { 7375 return this.context.controller; 7376 } 7377 get methodName() { 7378 return this.action.methodName; 7379 } 7380 get element() { 7381 return this.scope.element; 7382 } 7383 get scope() { 7384 return this.context.scope; 7385 } 7386}; 7387var ElementObserver = class { 7388 constructor(element, delegate) { 7389 this.mutationObserverInit = { attributes: true, childList: true, subtree: true }; 7390 this.element = element; 7391 this.started = false; 7392 this.delegate = delegate; 7393 this.elements = /* @__PURE__ */ new Set(); 7394 this.mutationObserver = new MutationObserver((mutations) => this.processMutations(mutations)); 7395 } 7396 start() { 7397 if (!this.started) { 7398 this.started = true; 7399 this.mutationObserver.observe(this.element, this.mutationObserverInit); 7400 this.refresh(); 7401 } 7402 } 7403 pause(callback) { 7404 if (this.started) { 7405 this.mutationObserver.disconnect(); 7406 this.started = false; 7407 } 7408 callback(); 7409 if (!this.started) { 7410 this.mutationObserver.observe(this.element, this.mutationObserverInit); 7411 this.started = true; 7412 } 7413 } 7414 stop() { 7415 if (this.started) { 7416 this.mutationObserver.takeRecords(); 7417 this.mutationObserver.disconnect(); 7418 this.started = false; 7419 } 7420 } 7421 refresh() { 7422 if (this.started) { 7423 const matches = new Set(this.matchElementsInTree()); 7424 for (const element of Array.from(this.elements)) { 7425 if (!matches.has(element)) { 7426 this.removeElement(element); 7427 } 7428 } 7429 for (const element of Array.from(matches)) { 7430 this.addElement(element); 7431 } 7432 } 7433 } 7434 processMutations(mutations) { 7435 if (this.started) { 7436 for (const mutation of mutations) { 7437 this.processMutation(mutation); 7438 } 7439 } 7440 } 7441 processMutation(mutation) { 7442 if (mutation.type == "attributes") { 7443 this.processAttributeChange(mutation.target, mutation.attributeName); 7444 } else if (mutation.type == "childList") { 7445 this.processRemovedNodes(mutation.removedNodes); 7446 this.processAddedNodes(mutation.addedNodes); 7447 } 7448 } 7449 processAttributeChange(element, attributeName) { 7450 if (this.elements.has(element)) { 7451 if (this.delegate.elementAttributeChanged && this.matchElement(element)) { 7452 this.delegate.elementAttributeChanged(element, attributeName); 7453 } else { 7454 this.removeElement(element); 7455 } 7456 } else if (this.matchElement(element)) { 7457 this.addElement(element); 7458 } 7459 } 7460 processRemovedNodes(nodes) { 7461 for (const node of Array.from(nodes)) { 7462 const element = this.elementFromNode(node); 7463 if (element) { 7464 this.processTree(element, this.removeElement); 7465 } 7466 } 7467 } 7468 processAddedNodes(nodes) { 7469 for (const node of Array.from(nodes)) { 7470 const element = this.elementFromNode(node); 7471 if (element && this.elementIsActive(element)) { 7472 this.processTree(element, this.addElement); 7473 } 7474 } 7475 } 7476 matchElement(element) { 7477 return this.delegate.matchElement(element); 7478 } 7479 matchElementsInTree(tree = this.element) { 7480 return this.delegate.matchElementsInTree(tree); 7481 } 7482 processTree(tree, processor) { 7483 for (const element of this.matchElementsInTree(tree)) { 7484 processor.call(this, element); 7485 } 7486 } 7487 elementFromNode(node) { 7488 if (node.nodeType == Node.ELEMENT_NODE) { 7489 return node; 7490 } 7491 } 7492 elementIsActive(element) { 7493 if (element.isConnected != this.element.isConnected) { 7494 return false; 7495 } else { 7496 return this.element.contains(element); 7497 } 7498 } 7499 addElement(element) { 7500 if (!this.elements.has(element)) { 7501 if (this.elementIsActive(element)) { 7502 this.elements.add(element); 7503 if (this.delegate.elementMatched) { 7504 this.delegate.elementMatched(element); 7505 } 7506 } 7507 } 7508 } 7509 removeElement(element) { 7510 if (this.elements.has(element)) { 7511 this.elements.delete(element); 7512 if (this.delegate.elementUnmatched) { 7513 this.delegate.elementUnmatched(element); 7514 } 7515 } 7516 } 7517}; 7518var AttributeObserver = class { 7519 constructor(element, attributeName, delegate) { 7520 this.attributeName = attributeName; 7521 this.delegate = delegate; 7522 this.elementObserver = new ElementObserver(element, this); 7523 } 7524 get element() { 7525 return this.elementObserver.element; 7526 } 7527 get selector() { 7528 return `[${this.attributeName}]`; 7529 } 7530 start() { 7531 this.elementObserver.start(); 7532 } 7533 pause(callback) { 7534 this.elementObserver.pause(callback); 7535 } 7536 stop() { 7537 this.elementObserver.stop(); 7538 } 7539 refresh() { 7540 this.elementObserver.refresh(); 7541 } 7542 get started() { 7543 return this.elementObserver.started; 7544 } 7545 matchElement(element) { 7546 return element.hasAttribute(this.attributeName); 7547 } 7548 matchElementsInTree(tree) { 7549 const match = this.matchElement(tree) ? [tree] : []; 7550 const matches = Array.from(tree.querySelectorAll(this.selector)); 7551 return match.concat(matches); 7552 } 7553 elementMatched(element) { 7554 if (this.delegate.elementMatchedAttribute) { 7555 this.delegate.elementMatchedAttribute(element, this.attributeName); 7556 } 7557 } 7558 elementUnmatched(element) { 7559 if (this.delegate.elementUnmatchedAttribute) { 7560 this.delegate.elementUnmatchedAttribute(element, this.attributeName); 7561 } 7562 } 7563 elementAttributeChanged(element, attributeName) { 7564 if (this.delegate.elementAttributeValueChanged && this.attributeName == attributeName) { 7565 this.delegate.elementAttributeValueChanged(element, attributeName); 7566 } 7567 } 7568}; 7569function add(map, key, value) { 7570 fetch2(map, key).add(value); 7571} 7572function del(map, key, value) { 7573 fetch2(map, key).delete(value); 7574 prune(map, key); 7575} 7576function fetch2(map, key) { 7577 let values = map.get(key); 7578 if (!values) { 7579 values = /* @__PURE__ */ new Set(); 7580 map.set(key, values); 7581 } 7582 return values; 7583} 7584function prune(map, key) { 7585 const values = map.get(key); 7586 if (values != null && values.size == 0) { 7587 map.delete(key); 7588 } 7589} 7590var Multimap = class { 7591 constructor() { 7592 this.valuesByKey = /* @__PURE__ */ new Map(); 7593 } 7594 get keys() { 7595 return Array.from(this.valuesByKey.keys()); 7596 } 7597 get values() { 7598 const sets = Array.from(this.valuesByKey.values()); 7599 return sets.reduce((values, set) => values.concat(Array.from(set)), []); 7600 } 7601 get size() { 7602 const sets = Array.from(this.valuesByKey.values()); 7603 return sets.reduce((size, set) => size + set.size, 0); 7604 } 7605 add(key, value) { 7606 add(this.valuesByKey, key, value); 7607 } 7608 delete(key, value) { 7609 del(this.valuesByKey, key, value); 7610 } 7611 has(key, value) { 7612 const values = this.valuesByKey.get(key); 7613 return values != null && values.has(value); 7614 } 7615 hasKey(key) { 7616 return this.valuesByKey.has(key); 7617 } 7618 hasValue(value) { 7619 const sets = Array.from(this.valuesByKey.values()); 7620 return sets.some((set) => set.has(value)); 7621 } 7622 getValuesForKey(key) { 7623 const values = this.valuesByKey.get(key); 7624 return values ? Array.from(values) : []; 7625 } 7626 getKeysForValue(value) { 7627 return Array.from(this.valuesByKey).filter(([_key, values]) => values.has(value)).map(([key, _values]) => key); 7628 } 7629}; 7630var SelectorObserver = class { 7631 constructor(element, selector, delegate, details) { 7632 this._selector = selector; 7633 this.details = details; 7634 this.elementObserver = new ElementObserver(element, this); 7635 this.delegate = delegate; 7636 this.matchesByElement = new Multimap(); 7637 } 7638 get started() { 7639 return this.elementObserver.started; 7640 } 7641 get selector() { 7642 return this._selector; 7643 } 7644 set selector(selector) { 7645 this._selector = selector; 7646 this.refresh(); 7647 } 7648 start() { 7649 this.elementObserver.start(); 7650 } 7651 pause(callback) { 7652 this.elementObserver.pause(callback); 7653 } 7654 stop() { 7655 this.elementObserver.stop(); 7656 } 7657 refresh() { 7658 this.elementObserver.refresh(); 7659 } 7660 get element() { 7661 return this.elementObserver.element; 7662 } 7663 matchElement(element) { 7664 const { selector } = this; 7665 if (selector) { 7666 const matches = element.matches(selector); 7667 if (this.delegate.selectorMatchElement) { 7668 return matches && this.delegate.selectorMatchElement(element, this.details); 7669 } 7670 return matches; 7671 } else { 7672 return false; 7673 } 7674 } 7675 matchElementsInTree(tree) { 7676 const { selector } = this; 7677 if (selector) { 7678 const match = this.matchElement(tree) ? [tree] : []; 7679 const matches = Array.from(tree.querySelectorAll(selector)).filter((match2) => this.matchElement(match2)); 7680 return match.concat(matches); 7681 } else { 7682 return []; 7683 } 7684 } 7685 elementMatched(element) { 7686 const { selector } = this; 7687 if (selector) { 7688 this.selectorMatched(element, selector); 7689 } 7690 } 7691 elementUnmatched(element) { 7692 const selectors = this.matchesByElement.getKeysForValue(element); 7693 for (const selector of selectors) { 7694 this.selectorUnmatched(element, selector); 7695 } 7696 } 7697 elementAttributeChanged(element, _attributeName) { 7698 const { selector } = this; 7699 if (selector) { 7700 const matches = this.matchElement(element); 7701 const matchedBefore = this.matchesByElement.has(selector, element); 7702 if (matches && !matchedBefore) { 7703 this.selectorMatched(element, selector); 7704 } else if (!matches && matchedBefore) { 7705 this.selectorUnmatched(element, selector); 7706 } 7707 } 7708 } 7709 selectorMatched(element, selector) { 7710 this.delegate.selectorMatched(element, selector, this.details); 7711 this.matchesByElement.add(selector, element); 7712 } 7713 selectorUnmatched(element, selector) { 7714 this.delegate.selectorUnmatched(element, selector, this.details); 7715 this.matchesByElement.delete(selector, element); 7716 } 7717}; 7718var StringMapObserver = class { 7719 constructor(element, delegate) { 7720 this.element = element; 7721 this.delegate = delegate; 7722 this.started = false; 7723 this.stringMap = /* @__PURE__ */ new Map(); 7724 this.mutationObserver = new MutationObserver((mutations) => this.processMutations(mutations)); 7725 } 7726 start() { 7727 if (!this.started) { 7728 this.started = true; 7729 this.mutationObserver.observe(this.element, { attributes: true, attributeOldValue: true }); 7730 this.refresh(); 7731 } 7732 } 7733 stop() { 7734 if (this.started) { 7735 this.mutationObserver.takeRecords(); 7736 this.mutationObserver.disconnect(); 7737 this.started = false; 7738 } 7739 } 7740 refresh() { 7741 if (this.started) { 7742 for (const attributeName of this.knownAttributeNames) { 7743 this.refreshAttribute(attributeName, null); 7744 } 7745 } 7746 } 7747 processMutations(mutations) { 7748 if (this.started) { 7749 for (const mutation of mutations) { 7750 this.processMutation(mutation); 7751 } 7752 } 7753 } 7754 processMutation(mutation) { 7755 const attributeName = mutation.attributeName; 7756 if (attributeName) { 7757 this.refreshAttribute(attributeName, mutation.oldValue); 7758 } 7759 } 7760 refreshAttribute(attributeName, oldValue) { 7761 const key = this.delegate.getStringMapKeyForAttribute(attributeName); 7762 if (key != null) { 7763 if (!this.stringMap.has(attributeName)) { 7764 this.stringMapKeyAdded(key, attributeName); 7765 } 7766 const value = this.element.getAttribute(attributeName); 7767 if (this.stringMap.get(attributeName) != value) { 7768 this.stringMapValueChanged(value, key, oldValue); 7769 } 7770 if (value == null) { 7771 const oldValue2 = this.stringMap.get(attributeName); 7772 this.stringMap.delete(attributeName); 7773 if (oldValue2) 7774 this.stringMapKeyRemoved(key, attributeName, oldValue2); 7775 } else { 7776 this.stringMap.set(attributeName, value); 7777 } 7778 } 7779 } 7780 stringMapKeyAdded(key, attributeName) { 7781 if (this.delegate.stringMapKeyAdded) { 7782 this.delegate.stringMapKeyAdded(key, attributeName); 7783 } 7784 } 7785 stringMapValueChanged(value, key, oldValue) { 7786 if (this.delegate.stringMapValueChanged) { 7787 this.delegate.stringMapValueChanged(value, key, oldValue); 7788 } 7789 } 7790 stringMapKeyRemoved(key, attributeName, oldValue) { 7791 if (this.delegate.stringMapKeyRemoved) { 7792 this.delegate.stringMapKeyRemoved(key, attributeName, oldValue); 7793 } 7794 } 7795 get knownAttributeNames() { 7796 return Array.from(new Set(this.currentAttributeNames.concat(this.recordedAttributeNames))); 7797 } 7798 get currentAttributeNames() { 7799 return Array.from(this.element.attributes).map((attribute) => attribute.name); 7800 } 7801 get recordedAttributeNames() { 7802 return Array.from(this.stringMap.keys()); 7803 } 7804}; 7805var TokenListObserver = class { 7806 constructor(element, attributeName, delegate) { 7807 this.attributeObserver = new AttributeObserver(element, attributeName, this); 7808 this.delegate = delegate; 7809 this.tokensByElement = new Multimap(); 7810 } 7811 get started() { 7812 return this.attributeObserver.started; 7813 } 7814 start() { 7815 this.attributeObserver.start(); 7816 } 7817 pause(callback) { 7818 this.attributeObserver.pause(callback); 7819 } 7820 stop() { 7821 this.attributeObserver.stop(); 7822 } 7823 refresh() { 7824 this.attributeObserver.refresh(); 7825 } 7826 get element() { 7827 return this.attributeObserver.element; 7828 } 7829 get attributeName() { 7830 return this.attributeObserver.attributeName; 7831 } 7832 elementMatchedAttribute(element) { 7833 this.tokensMatched(this.readTokensForElement(element)); 7834 } 7835 elementAttributeValueChanged(element) { 7836 const [unmatchedTokens, matchedTokens] = this.refreshTokensForElement(element); 7837 this.tokensUnmatched(unmatchedTokens); 7838 this.tokensMatched(matchedTokens); 7839 } 7840 elementUnmatchedAttribute(element) { 7841 this.tokensUnmatched(this.tokensByElement.getValuesForKey(element)); 7842 } 7843 tokensMatched(tokens) { 7844 tokens.forEach((token) => this.tokenMatched(token)); 7845 } 7846 tokensUnmatched(tokens) { 7847 tokens.forEach((token) => this.tokenUnmatched(token)); 7848 } 7849 tokenMatched(token) { 7850 this.delegate.tokenMatched(token); 7851 this.tokensByElement.add(token.element, token); 7852 } 7853 tokenUnmatched(token) { 7854 this.delegate.tokenUnmatched(token); 7855 this.tokensByElement.delete(token.element, token); 7856 } 7857 refreshTokensForElement(element) { 7858 const previousTokens = this.tokensByElement.getValuesForKey(element); 7859 const currentTokens = this.readTokensForElement(element); 7860 const firstDifferingIndex = zip(previousTokens, currentTokens).findIndex(([previousToken, currentToken]) => !tokensAreEqual(previousToken, currentToken)); 7861 if (firstDifferingIndex == -1) { 7862 return [[], []]; 7863 } else { 7864 return [previousTokens.slice(firstDifferingIndex), currentTokens.slice(firstDifferingIndex)]; 7865 } 7866 } 7867 readTokensForElement(element) { 7868 const attributeName = this.attributeName; 7869 const tokenString = element.getAttribute(attributeName) || ""; 7870 return parseTokenString(tokenString, element, attributeName); 7871 } 7872}; 7873function parseTokenString(tokenString, element, attributeName) { 7874 return tokenString.trim().split(/\s+/).filter((content) => content.length).map((content, index) => ({ element, attributeName, content, index })); 7875} 7876function zip(left, right) { 7877 const length = Math.max(left.length, right.length); 7878 return Array.from({ length }, (_, index) => [left[index], right[index]]); 7879} 7880function tokensAreEqual(left, right) { 7881 return left && right && left.index == right.index && left.content == right.content; 7882} 7883var ValueListObserver = class { 7884 constructor(element, attributeName, delegate) { 7885 this.tokenListObserver = new TokenListObserver(element, attributeName, this); 7886 this.delegate = delegate; 7887 this.parseResultsByToken = /* @__PURE__ */ new WeakMap(); 7888 this.valuesByTokenByElement = /* @__PURE__ */ new WeakMap(); 7889 } 7890 get started() { 7891 return this.tokenListObserver.started; 7892 } 7893 start() { 7894 this.tokenListObserver.start(); 7895 } 7896 stop() { 7897 this.tokenListObserver.stop(); 7898 } 7899 refresh() { 7900 this.tokenListObserver.refresh(); 7901 } 7902 get element() { 7903 return this.tokenListObserver.element; 7904 } 7905 get attributeName() { 7906 return this.tokenListObserver.attributeName; 7907 } 7908 tokenMatched(token) { 7909 const { element } = token; 7910 const { value } = this.fetchParseResultForToken(token); 7911 if (value) { 7912 this.fetchValuesByTokenForElement(element).set(token, value); 7913 this.delegate.elementMatchedValue(element, value); 7914 } 7915 } 7916 tokenUnmatched(token) { 7917 const { element } = token; 7918 const { value } = this.fetchParseResultForToken(token); 7919 if (value) { 7920 this.fetchValuesByTokenForElement(element).delete(token); 7921 this.delegate.elementUnmatchedValue(element, value); 7922 } 7923 } 7924 fetchParseResultForToken(token) { 7925 let parseResult = this.parseResultsByToken.get(token); 7926 if (!parseResult) { 7927 parseResult = this.parseToken(token); 7928 this.parseResultsByToken.set(token, parseResult); 7929 } 7930 return parseResult; 7931 } 7932 fetchValuesByTokenForElement(element) { 7933 let valuesByToken = this.valuesByTokenByElement.get(element); 7934 if (!valuesByToken) { 7935 valuesByToken = /* @__PURE__ */ new Map(); 7936 this.valuesByTokenByElement.set(element, valuesByToken); 7937 } 7938 return valuesByToken; 7939 } 7940 parseToken(token) { 7941 try { 7942 const value = this.delegate.parseValueForToken(token); 7943 return { value }; 7944 } catch (error2) { 7945 return { error: error2 }; 7946 } 7947 } 7948}; 7949var BindingObserver = class { 7950 constructor(context, delegate) { 7951 this.context = context; 7952 this.delegate = delegate; 7953 this.bindingsByAction = /* @__PURE__ */ new Map(); 7954 } 7955 start() { 7956 if (!this.valueListObserver) { 7957 this.valueListObserver = new ValueListObserver(this.element, this.actionAttribute, this); 7958 this.valueListObserver.start(); 7959 } 7960 } 7961 stop() { 7962 if (this.valueListObserver) { 7963 this.valueListObserver.stop(); 7964 delete this.valueListObserver; 7965 this.disconnectAllActions(); 7966 } 7967 } 7968 get element() { 7969 return this.context.element; 7970 } 7971 get identifier() { 7972 return this.context.identifier; 7973 } 7974 get actionAttribute() { 7975 return this.schema.actionAttribute; 7976 } 7977 get schema() { 7978 return this.context.schema; 7979 } 7980 get bindings() { 7981 return Array.from(this.bindingsByAction.values()); 7982 } 7983 connectAction(action) { 7984 const binding = new Binding(this.context, action); 7985 this.bindingsByAction.set(action, binding); 7986 this.delegate.bindingConnected(binding); 7987 } 7988 disconnectAction(action) { 7989 const binding = this.bindingsByAction.get(action); 7990 if (binding) { 7991 this.bindingsByAction.delete(action); 7992 this.delegate.bindingDisconnected(binding); 7993 } 7994 } 7995 disconnectAllActions() { 7996 this.bindings.forEach((binding) => this.delegate.bindingDisconnected(binding, true)); 7997 this.bindingsByAction.clear(); 7998 } 7999 parseValueForToken(token) { 8000 const action = Action.forToken(token, this.schema); 8001 if (action.identifier == this.identifier) { 8002 return action; 8003 } 8004 } 8005 elementMatchedValue(element, action) { 8006 this.connectAction(action); 8007 } 8008 elementUnmatchedValue(element, action) { 8009 this.disconnectAction(action); 8010 } 8011}; 8012var ValueObserver = class { 8013 constructor(context, receiver) { 8014 this.context = context; 8015 this.receiver = receiver; 8016 this.stringMapObserver = new StringMapObserver(this.element, this); 8017 this.valueDescriptorMap = this.controller.valueDescriptorMap; 8018 } 8019 start() { 8020 this.stringMapObserver.start(); 8021 this.invokeChangedCallbacksForDefaultValues(); 8022 } 8023 stop() { 8024 this.stringMapObserver.stop(); 8025 } 8026 get element() { 8027 return this.context.element; 8028 } 8029 get controller() { 8030 return this.context.controller; 8031 } 8032 getStringMapKeyForAttribute(attributeName) { 8033 if (attributeName in this.valueDescriptorMap) { 8034 return this.valueDescriptorMap[attributeName].name; 8035 } 8036 } 8037 stringMapKeyAdded(key, attributeName) { 8038 const descriptor = this.valueDescriptorMap[attributeName]; 8039 if (!this.hasValue(key)) { 8040 this.invokeChangedCallback(key, descriptor.writer(this.receiver[key]), descriptor.writer(descriptor.defaultValue)); 8041 } 8042 } 8043 stringMapValueChanged(value, name, oldValue) { 8044 const descriptor = this.valueDescriptorNameMap[name]; 8045 if (value === null) 8046 return; 8047 if (oldValue === null) { 8048 oldValue = descriptor.writer(descriptor.defaultValue); 8049 } 8050 this.invokeChangedCallback(name, value, oldValue); 8051 } 8052 stringMapKeyRemoved(key, attributeName, oldValue) { 8053 const descriptor = this.valueDescriptorNameMap[key]; 8054 if (this.hasValue(key)) { 8055 this.invokeChangedCallback(key, descriptor.writer(this.receiver[key]), oldValue); 8056 } else { 8057 this.invokeChangedCallback(key, descriptor.writer(descriptor.defaultValue), oldValue); 8058 } 8059 } 8060 invokeChangedCallbacksForDefaultValues() { 8061 for (const { key, name, defaultValue, writer } of this.valueDescriptors) { 8062 if (defaultValue != void 0 && !this.controller.data.has(key)) { 8063 this.invokeChangedCallback(name, writer(defaultValue), void 0); 8064 } 8065 } 8066 } 8067 invokeChangedCallback(name, rawValue, rawOldValue) { 8068 const changedMethodName = `${name}Changed`; 8069 const changedMethod = this.receiver[changedMethodName]; 8070 if (typeof changedMethod == "function") { 8071 const descriptor = this.valueDescriptorNameMap[name]; 8072 try { 8073 const value = descriptor.reader(rawValue); 8074 let oldValue = rawOldValue; 8075 if (rawOldValue) { 8076 oldValue = descriptor.reader(rawOldValue); 8077 } 8078 changedMethod.call(this.receiver, value, oldValue); 8079 } catch (error2) { 8080 if (error2 instanceof TypeError) { 8081 error2.message = `Stimulus Value "${this.context.identifier}.${descriptor.name}" - ${error2.message}`; 8082 } 8083 throw error2; 8084 } 8085 } 8086 } 8087 get valueDescriptors() { 8088 const { valueDescriptorMap } = this; 8089 return Object.keys(valueDescriptorMap).map((key) => valueDescriptorMap[key]); 8090 } 8091 get valueDescriptorNameMap() { 8092 const descriptors = {}; 8093 Object.keys(this.valueDescriptorMap).forEach((key) => { 8094 const descriptor = this.valueDescriptorMap[key]; 8095 descriptors[descriptor.name] = descriptor; 8096 }); 8097 return descriptors; 8098 } 8099 hasValue(attributeName) { 8100 const descriptor = this.valueDescriptorNameMap[attributeName]; 8101 const hasMethodName = `has${capitalize(descriptor.name)}`; 8102 return this.receiver[hasMethodName]; 8103 } 8104}; 8105var TargetObserver = class { 8106 constructor(context, delegate) { 8107 this.context = context; 8108 this.delegate = delegate; 8109 this.targetsByName = new Multimap(); 8110 } 8111 start() { 8112 if (!this.tokenListObserver) { 8113 this.tokenListObserver = new TokenListObserver(this.element, this.attributeName, this); 8114 this.tokenListObserver.start(); 8115 } 8116 } 8117 stop() { 8118 if (this.tokenListObserver) { 8119 this.disconnectAllTargets(); 8120 this.tokenListObserver.stop(); 8121 delete this.tokenListObserver; 8122 } 8123 } 8124 tokenMatched({ element, content: name }) { 8125 if (this.scope.containsElement(element)) { 8126 this.connectTarget(element, name); 8127 } 8128 } 8129 tokenUnmatched({ element, content: name }) { 8130 this.disconnectTarget(element, name); 8131 } 8132 connectTarget(element, name) { 8133 var _a; 8134 if (!this.targetsByName.has(name, element)) { 8135 this.targetsByName.add(name, element); 8136 (_a = this.tokenListObserver) === null || _a === void 0 ? void 0 : _a.pause(() => this.delegate.targetConnected(element, name)); 8137 } 8138 } 8139 disconnectTarget(element, name) { 8140 var _a; 8141 if (this.targetsByName.has(name, element)) { 8142 this.targetsByName.delete(name, element); 8143 (_a = this.tokenListObserver) === null || _a === void 0 ? void 0 : _a.pause(() => this.delegate.targetDisconnected(element, name)); 8144 } 8145 } 8146 disconnectAllTargets() { 8147 for (const name of this.targetsByName.keys) { 8148 for (const element of this.targetsByName.getValuesForKey(name)) { 8149 this.disconnectTarget(element, name); 8150 } 8151 } 8152 } 8153 get attributeName() { 8154 return `data-${this.context.identifier}-target`; 8155 } 8156 get element() { 8157 return this.context.element; 8158 } 8159 get scope() { 8160 return this.context.scope; 8161 } 8162}; 8163function readInheritableStaticArrayValues(constructor, propertyName) { 8164 const ancestors = getAncestorsForConstructor(constructor); 8165 return Array.from(ancestors.reduce((values, constructor2) => { 8166 getOwnStaticArrayValues(constructor2, propertyName).forEach((name) => values.add(name)); 8167 return values; 8168 }, /* @__PURE__ */ new Set())); 8169} 8170function readInheritableStaticObjectPairs(constructor, propertyName) { 8171 const ancestors = getAncestorsForConstructor(constructor); 8172 return ancestors.reduce((pairs, constructor2) => { 8173 pairs.push(...getOwnStaticObjectPairs(constructor2, propertyName)); 8174 return pairs; 8175 }, []); 8176} 8177function getAncestorsForConstructor(constructor) { 8178 const ancestors = []; 8179 while (constructor) { 8180 ancestors.push(constructor); 8181 constructor = Object.getPrototypeOf(constructor); 8182 } 8183 return ancestors.reverse(); 8184} 8185function getOwnStaticArrayValues(constructor, propertyName) { 8186 const definition = constructor[propertyName]; 8187 return Array.isArray(definition) ? definition : []; 8188} 8189function getOwnStaticObjectPairs(constructor, propertyName) { 8190 const definition = constructor[propertyName]; 8191 return definition ? Object.keys(definition).map((key) => [key, definition[key]]) : []; 8192} 8193var OutletObserver = class { 8194 constructor(context, delegate) { 8195 this.started = false; 8196 this.context = context; 8197 this.delegate = delegate; 8198 this.outletsByName = new Multimap(); 8199 this.outletElementsByName = new Multimap(); 8200 this.selectorObserverMap = /* @__PURE__ */ new Map(); 8201 this.attributeObserverMap = /* @__PURE__ */ new Map(); 8202 } 8203 start() { 8204 if (!this.started) { 8205 this.outletDefinitions.forEach((outletName) => { 8206 this.setupSelectorObserverForOutlet(outletName); 8207 this.setupAttributeObserverForOutlet(outletName); 8208 }); 8209 this.started = true; 8210 this.dependentContexts.forEach((context) => context.refresh()); 8211 } 8212 } 8213 refresh() { 8214 this.selectorObserverMap.forEach((observer) => observer.refresh()); 8215 this.attributeObserverMap.forEach((observer) => observer.refresh()); 8216 } 8217 stop() { 8218 if (this.started) { 8219 this.started = false; 8220 this.disconnectAllOutlets(); 8221 this.stopSelectorObservers(); 8222 this.stopAttributeObservers(); 8223 } 8224 } 8225 stopSelectorObservers() { 8226 if (this.selectorObserverMap.size > 0) { 8227 this.selectorObserverMap.forEach((observer) => observer.stop()); 8228 this.selectorObserverMap.clear(); 8229 } 8230 } 8231 stopAttributeObservers() { 8232 if (this.attributeObserverMap.size > 0) { 8233 this.attributeObserverMap.forEach((observer) => observer.stop()); 8234 this.attributeObserverMap.clear(); 8235 } 8236 } 8237 selectorMatched(element, _selector, { outletName }) { 8238 const outlet = this.getOutlet(element, outletName); 8239 if (outlet) { 8240 this.connectOutlet(outlet, element, outletName); 8241 } 8242 } 8243 selectorUnmatched(element, _selector, { outletName }) { 8244 const outlet = this.getOutletFromMap(element, outletName); 8245 if (outlet) { 8246 this.disconnectOutlet(outlet, element, outletName); 8247 } 8248 } 8249 selectorMatchElement(element, { outletName }) { 8250 const selector = this.selector(outletName); 8251 const hasOutlet = this.hasOutlet(element, outletName); 8252 const hasOutletController = element.matches(`[${this.schema.controllerAttribute}~=${outletName}]`); 8253 if (selector) { 8254 return hasOutlet && hasOutletController && element.matches(selector); 8255 } else { 8256 return false; 8257 } 8258 } 8259 elementMatchedAttribute(_element, attributeName) { 8260 const outletName = this.getOutletNameFromOutletAttributeName(attributeName); 8261 if (outletName) { 8262 this.updateSelectorObserverForOutlet(outletName); 8263 } 8264 } 8265 elementAttributeValueChanged(_element, attributeName) { 8266 const outletName = this.getOutletNameFromOutletAttributeName(attributeName); 8267 if (outletName) { 8268 this.updateSelectorObserverForOutlet(outletName); 8269 } 8270 } 8271 elementUnmatchedAttribute(_element, attributeName) { 8272 const outletName = this.getOutletNameFromOutletAttributeName(attributeName); 8273 if (outletName) { 8274 this.updateSelectorObserverForOutlet(outletName); 8275 } 8276 } 8277 connectOutlet(outlet, element, outletName) { 8278 var _a; 8279 if (!this.outletElementsByName.has(outletName, element)) { 8280 this.outletsByName.add(outletName, outlet); 8281 this.outletElementsByName.add(outletName, element); 8282 (_a = this.selectorObserverMap.get(outletName)) === null || _a === void 0 ? void 0 : _a.pause(() => this.delegate.outletConnected(outlet, element, outletName)); 8283 } 8284 } 8285 disconnectOutlet(outlet, element, outletName) { 8286 var _a; 8287 if (this.outletElementsByName.has(outletName, element)) { 8288 this.outletsByName.delete(outletName, outlet); 8289 this.outletElementsByName.delete(outletName, element); 8290 (_a = this.selectorObserverMap.get(outletName)) === null || _a === void 0 ? void 0 : _a.pause(() => this.delegate.outletDisconnected(outlet, element, outletName)); 8291 } 8292 } 8293 disconnectAllOutlets() { 8294 for (const outletName of this.outletElementsByName.keys) { 8295 for (const element of this.outletElementsByName.getValuesForKey(outletName)) { 8296 for (const outlet of this.outletsByName.getValuesForKey(outletName)) { 8297 this.disconnectOutlet(outlet, element, outletName); 8298 } 8299 } 8300 } 8301 } 8302 updateSelectorObserverForOutlet(outletName) { 8303 const observer = this.selectorObserverMap.get(outletName); 8304 if (observer) { 8305 observer.selector = this.selector(outletName); 8306 } 8307 } 8308 setupSelectorObserverForOutlet(outletName) { 8309 const selector = this.selector(outletName); 8310 const selectorObserver = new SelectorObserver(document.body, selector, this, { outletName }); 8311 this.selectorObserverMap.set(outletName, selectorObserver); 8312 selectorObserver.start(); 8313 } 8314 setupAttributeObserverForOutlet(outletName) { 8315 const attributeName = this.attributeNameForOutletName(outletName); 8316 const attributeObserver = new AttributeObserver(this.scope.element, attributeName, this); 8317 this.attributeObserverMap.set(outletName, attributeObserver); 8318 attributeObserver.start(); 8319 } 8320 selector(outletName) { 8321 return this.scope.outlets.getSelectorForOutletName(outletName); 8322 } 8323 attributeNameForOutletName(outletName) { 8324 return this.scope.schema.outletAttributeForScope(this.identifier, outletName); 8325 } 8326 getOutletNameFromOutletAttributeName(attributeName) { 8327 return this.outletDefinitions.find((outletName) => this.attributeNameForOutletName(outletName) === attributeName); 8328 } 8329 get outletDependencies() { 8330 const dependencies = new Multimap(); 8331 this.router.modules.forEach((module) => { 8332 const constructor = module.definition.controllerConstructor; 8333 const outlets = readInheritableStaticArrayValues(constructor, "outlets"); 8334 outlets.forEach((outlet) => dependencies.add(outlet, module.identifier)); 8335 }); 8336 return dependencies; 8337 } 8338 get outletDefinitions() { 8339 return this.outletDependencies.getKeysForValue(this.identifier); 8340 } 8341 get dependentControllerIdentifiers() { 8342 return this.outletDependencies.getValuesForKey(this.identifier); 8343 } 8344 get dependentContexts() { 8345 const identifiers = this.dependentControllerIdentifiers; 8346 return this.router.contexts.filter((context) => identifiers.includes(context.identifier)); 8347 } 8348 hasOutlet(element, outletName) { 8349 return !!this.getOutlet(element, outletName) || !!this.getOutletFromMap(element, outletName); 8350 } 8351 getOutlet(element, outletName) { 8352 return this.application.getControllerForElementAndIdentifier(element, outletName); 8353 } 8354 getOutletFromMap(element, outletName) { 8355 return this.outletsByName.getValuesForKey(outletName).find((outlet) => outlet.element === element); 8356 } 8357 get scope() { 8358 return this.context.scope; 8359 } 8360 get schema() { 8361 return this.context.schema; 8362 } 8363 get identifier() { 8364 return this.context.identifier; 8365 } 8366 get application() { 8367 return this.context.application; 8368 } 8369 get router() { 8370 return this.application.router; 8371 } 8372}; 8373var Context = class { 8374 constructor(module, scope) { 8375 this.logDebugActivity = (functionName, detail = {}) => { 8376 const { identifier, controller, element } = this; 8377 detail = Object.assign({ identifier, controller, element }, detail); 8378 this.application.logDebugActivity(this.identifier, functionName, detail); 8379 }; 8380 this.module = module; 8381 this.scope = scope; 8382 this.controller = new module.controllerConstructor(this); 8383 this.bindingObserver = new BindingObserver(this, this.dispatcher); 8384 this.valueObserver = new ValueObserver(this, this.controller); 8385 this.targetObserver = new TargetObserver(this, this); 8386 this.outletObserver = new OutletObserver(this, this); 8387 try { 8388 this.controller.initialize(); 8389 this.logDebugActivity("initialize"); 8390 } catch (error2) { 8391 this.handleError(error2, "initializing controller"); 8392 } 8393 } 8394 connect() { 8395 this.bindingObserver.start(); 8396 this.valueObserver.start(); 8397 this.targetObserver.start(); 8398 this.outletObserver.start(); 8399 try { 8400 this.controller.connect(); 8401 this.logDebugActivity("connect"); 8402 } catch (error2) { 8403 this.handleError(error2, "connecting controller"); 8404 } 8405 } 8406 refresh() { 8407 this.outletObserver.refresh(); 8408 } 8409 disconnect() { 8410 try { 8411 this.controller.disconnect(); 8412 this.logDebugActivity("disconnect"); 8413 } catch (error2) { 8414 this.handleError(error2, "disconnecting controller"); 8415 } 8416 this.outletObserver.stop(); 8417 this.targetObserver.stop(); 8418 this.valueObserver.stop(); 8419 this.bindingObserver.stop(); 8420 } 8421 get application() { 8422 return this.module.application; 8423 } 8424 get identifier() { 8425 return this.module.identifier; 8426 } 8427 get schema() { 8428 return this.application.schema; 8429 } 8430 get dispatcher() { 8431 return this.application.dispatcher; 8432 } 8433 get element() { 8434 return this.scope.element; 8435 } 8436 get parentElement() { 8437 return this.element.parentElement; 8438 } 8439 handleError(error2, message, detail = {}) { 8440 const { identifier, controller, element } = this; 8441 detail = Object.assign({ identifier, controller, element }, detail); 8442 this.application.handleError(error2, `Error ${message}`, detail); 8443 } 8444 targetConnected(element, name) { 8445 this.invokeControllerMethod(`${name}TargetConnected`, element); 8446 } 8447 targetDisconnected(element, name) { 8448 this.invokeControllerMethod(`${name}TargetDisconnected`, element); 8449 } 8450 outletConnected(outlet, element, name) { 8451 this.invokeControllerMethod(`${namespaceCamelize(name)}OutletConnected`, outlet, element); 8452 } 8453 outletDisconnected(outlet, element, name) { 8454 this.invokeControllerMethod(`${namespaceCamelize(name)}OutletDisconnected`, outlet, element); 8455 } 8456 invokeControllerMethod(methodName, ...args) { 8457 const controller = this.controller; 8458 if (typeof controller[methodName] == "function") { 8459 controller[methodName](...args); 8460 } 8461 } 8462}; 8463function bless(constructor) { 8464 return shadow(constructor, getBlessedProperties(constructor)); 8465} 8466function shadow(constructor, properties) { 8467 const shadowConstructor = extend2(constructor); 8468 const shadowProperties = getShadowProperties(constructor.prototype, properties); 8469 Object.defineProperties(shadowConstructor.prototype, shadowProperties); 8470 return shadowConstructor; 8471} 8472function getBlessedProperties(constructor) { 8473 const blessings = readInheritableStaticArrayValues(constructor, "blessings"); 8474 return blessings.reduce((blessedProperties, blessing) => { 8475 const properties = blessing(constructor); 8476 for (const key in properties) { 8477 const descriptor = blessedProperties[key] || {}; 8478 blessedProperties[key] = Object.assign(descriptor, properties[key]); 8479 } 8480 return blessedProperties; 8481 }, {}); 8482} 8483function getShadowProperties(prototype, properties) { 8484 return getOwnKeys(properties).reduce((shadowProperties, key) => { 8485 const descriptor = getShadowedDescriptor(prototype, properties, key); 8486 if (descriptor) { 8487 Object.assign(shadowProperties, { [key]: descriptor }); 8488 } 8489 return shadowProperties; 8490 }, {}); 8491} 8492function getShadowedDescriptor(prototype, properties, key) { 8493 const shadowingDescriptor = Object.getOwnPropertyDescriptor(prototype, key); 8494 const shadowedByValue = shadowingDescriptor && "value" in shadowingDescriptor; 8495 if (!shadowedByValue) { 8496 const descriptor = Object.getOwnPropertyDescriptor(properties, key).value; 8497 if (shadowingDescriptor) { 8498 descriptor.get = shadowingDescriptor.get || descriptor.get; 8499 descriptor.set = shadowingDescriptor.set || descriptor.set; 8500 } 8501 return descriptor; 8502 } 8503} 8504var getOwnKeys = (() => { 8505 if (typeof Object.getOwnPropertySymbols == "function") { 8506 return (object) => [...Object.getOwnPropertyNames(object), ...Object.getOwnPropertySymbols(object)]; 8507 } else { 8508 return Object.getOwnPropertyNames; 8509 } 8510})(); 8511var extend2 = (() => { 8512 function extendWithReflect(constructor) { 8513 function extended() { 8514 return Reflect.construct(constructor, arguments, new.target); 8515 } 8516 extended.prototype = Object.create(constructor.prototype, { 8517 constructor: { value: extended } 8518 }); 8519 Reflect.setPrototypeOf(extended, constructor); 8520 return extended; 8521 } 8522 function testReflectExtension() { 8523 const a = function() { 8524 this.a.call(this); 8525 }; 8526 const b = extendWithReflect(a); 8527 b.prototype.a = function() { 8528 }; 8529 return new b(); 8530 } 8531 try { 8532 testReflectExtension(); 8533 return extendWithReflect; 8534 } catch (error2) { 8535 return (constructor) => class extended extends constructor { 8536 }; 8537 } 8538})(); 8539function blessDefinition(definition) { 8540 return { 8541 identifier: definition.identifier, 8542 controllerConstructor: bless(definition.controllerConstructor) 8543 }; 8544} 8545var Module = class { 8546 constructor(application2, definition) { 8547 this.application = application2; 8548 this.definition = blessDefinition(definition); 8549 this.contextsByScope = /* @__PURE__ */ new WeakMap(); 8550 this.connectedContexts = /* @__PURE__ */ new Set(); 8551 } 8552 get identifier() { 8553 return this.definition.identifier; 8554 } 8555 get controllerConstructor() { 8556 return this.definition.controllerConstructor; 8557 } 8558 get contexts() { 8559 return Array.from(this.connectedContexts); 8560 } 8561 connectContextForScope(scope) { 8562 const context = this.fetchContextForScope(scope); 8563 this.connectedContexts.add(context); 8564 context.connect(); 8565 } 8566 disconnectContextForScope(scope) { 8567 const context = this.contextsByScope.get(scope); 8568 if (context) { 8569 this.connectedContexts.delete(context); 8570 context.disconnect(); 8571 } 8572 } 8573 fetchContextForScope(scope) { 8574 let context = this.contextsByScope.get(scope); 8575 if (!context) { 8576 context = new Context(this, scope); 8577 this.contextsByScope.set(scope, context); 8578 } 8579 return context; 8580 } 8581}; 8582var ClassMap = class { 8583 constructor(scope) { 8584 this.scope = scope; 8585 } 8586 has(name) { 8587 return this.data.has(this.getDataKey(name)); 8588 } 8589 get(name) { 8590 return this.getAll(name)[0]; 8591 } 8592 getAll(name) { 8593 const tokenString = this.data.get(this.getDataKey(name)) || ""; 8594 return tokenize(tokenString); 8595 } 8596 getAttributeName(name) { 8597 return this.data.getAttributeNameForKey(this.getDataKey(name)); 8598 } 8599 getDataKey(name) { 8600 return `${name}-class`; 8601 } 8602 get data() { 8603 return this.scope.data; 8604 } 8605}; 8606var DataMap = class { 8607 constructor(scope) { 8608 this.scope = scope; 8609 } 8610 get element() { 8611 return this.scope.element; 8612 } 8613 get identifier() { 8614 return this.scope.identifier; 8615 } 8616 get(key) { 8617 const name = this.getAttributeNameForKey(key); 8618 return this.element.getAttribute(name); 8619 } 8620 set(key, value) { 8621 const name = this.getAttributeNameForKey(key); 8622 this.element.setAttribute(name, value); 8623 return this.get(key); 8624 } 8625 has(key) { 8626 const name = this.getAttributeNameForKey(key); 8627 return this.element.hasAttribute(name); 8628 } 8629 delete(key) { 8630 if (this.has(key)) { 8631 const name = this.getAttributeNameForKey(key); 8632 this.element.removeAttribute(name); 8633 return true; 8634 } else { 8635 return false; 8636 } 8637 } 8638 getAttributeNameForKey(key) { 8639 return `data-${this.identifier}-${dasherize(key)}`; 8640 } 8641}; 8642var Guide = class { 8643 constructor(logger) { 8644 this.warnedKeysByObject = /* @__PURE__ */ new WeakMap(); 8645 this.logger = logger; 8646 } 8647 warn(object, key, message) { 8648 let warnedKeys = this.warnedKeysByObject.get(object); 8649 if (!warnedKeys) { 8650 warnedKeys = /* @__PURE__ */ new Set(); 8651 this.warnedKeysByObject.set(object, warnedKeys); 8652 } 8653 if (!warnedKeys.has(key)) { 8654 warnedKeys.add(key); 8655 this.logger.warn(message, object); 8656 } 8657 } 8658}; 8659function attributeValueContainsToken(attributeName, token) { 8660 return `[${attributeName}~="${token}"]`; 8661} 8662var TargetSet = class { 8663 constructor(scope) { 8664 this.scope = scope; 8665 } 8666 get element() { 8667 return this.scope.element; 8668 } 8669 get identifier() { 8670 return this.scope.identifier; 8671 } 8672 get schema() { 8673 return this.scope.schema; 8674 } 8675 has(targetName) { 8676 return this.find(targetName) != null; 8677 } 8678 find(...targetNames) { 8679 return targetNames.reduce((target, targetName) => target || this.findTarget(targetName) || this.findLegacyTarget(targetName), void 0); 8680 } 8681 findAll(...targetNames) { 8682 return targetNames.reduce((targets, targetName) => [ 8683 ...targets, 8684 ...this.findAllTargets(targetName), 8685 ...this.findAllLegacyTargets(targetName) 8686 ], []); 8687 } 8688 findTarget(targetName) { 8689 const selector = this.getSelectorForTargetName(targetName); 8690 return this.scope.findElement(selector); 8691 } 8692 findAllTargets(targetName) { 8693 const selector = this.getSelectorForTargetName(targetName); 8694 return this.scope.findAllElements(selector); 8695 } 8696 getSelectorForTargetName(targetName) { 8697 const attributeName = this.schema.targetAttributeForScope(this.identifier); 8698 return attributeValueContainsToken(attributeName, targetName); 8699 } 8700 findLegacyTarget(targetName) { 8701 const selector = this.getLegacySelectorForTargetName(targetName); 8702 return this.deprecate(this.scope.findElement(selector), targetName); 8703 } 8704 findAllLegacyTargets(targetName) { 8705 const selector = this.getLegacySelectorForTargetName(targetName); 8706 return this.scope.findAllElements(selector).map((element) => this.deprecate(element, targetName)); 8707 } 8708 getLegacySelectorForTargetName(targetName) { 8709 const targetDescriptor = `${this.identifier}.${targetName}`; 8710 return attributeValueContainsToken(this.schema.targetAttribute, targetDescriptor); 8711 } 8712 deprecate(element, targetName) { 8713 if (element) { 8714 const { identifier } = this; 8715 const attributeName = this.schema.targetAttribute; 8716 const revisedAttributeName = this.schema.targetAttributeForScope(identifier); 8717 this.guide.warn(element, `target:${targetName}`, `Please replace ${attributeName}="${identifier}.${targetName}" with ${revisedAttributeName}="${targetName}". The ${attributeName} attribute is deprecated and will be removed in a future version of Stimulus.`); 8718 } 8719 return element; 8720 } 8721 get guide() { 8722 return this.scope.guide; 8723 } 8724}; 8725var OutletSet = class { 8726 constructor(scope, controllerElement) { 8727 this.scope = scope; 8728 this.controllerElement = controllerElement; 8729 } 8730 get element() { 8731 return this.scope.element; 8732 } 8733 get identifier() { 8734 return this.scope.identifier; 8735 } 8736 get schema() { 8737 return this.scope.schema; 8738 } 8739 has(outletName) { 8740 return this.find(outletName) != null; 8741 } 8742 find(...outletNames) { 8743 return outletNames.reduce((outlet, outletName) => outlet || this.findOutlet(outletName), void 0); 8744 } 8745 findAll(...outletNames) { 8746 return outletNames.reduce((outlets, outletName) => [...outlets, ...this.findAllOutlets(outletName)], []); 8747 } 8748 getSelectorForOutletName(outletName) { 8749 const attributeName = this.schema.outletAttributeForScope(this.identifier, outletName); 8750 return this.controllerElement.getAttribute(attributeName); 8751 } 8752 findOutlet(outletName) { 8753 const selector = this.getSelectorForOutletName(outletName); 8754 if (selector) 8755 return this.findElement(selector, outletName); 8756 } 8757 findAllOutlets(outletName) { 8758 const selector = this.getSelectorForOutletName(outletName); 8759 return selector ? this.findAllElements(selector, outletName) : []; 8760 } 8761 findElement(selector, outletName) { 8762 const elements = this.scope.queryElements(selector); 8763 return elements.filter((element) => this.matchesElement(element, selector, outletName))[0]; 8764 } 8765 findAllElements(selector, outletName) { 8766 const elements = this.scope.queryElements(selector); 8767 return elements.filter((element) => this.matchesElement(element, selector, outletName)); 8768 } 8769 matchesElement(element, selector, outletName) { 8770 const controllerAttribute = element.getAttribute(this.scope.schema.controllerAttribute) || ""; 8771 return element.matches(selector) && controllerAttribute.split(" ").includes(outletName); 8772 } 8773}; 8774var Scope = class _Scope { 8775 constructor(schema, element, identifier, logger) { 8776 this.targets = new TargetSet(this); 8777 this.classes = new ClassMap(this); 8778 this.data = new DataMap(this); 8779 this.containsElement = (element2) => { 8780 return element2.closest(this.controllerSelector) === this.element; 8781 }; 8782 this.schema = schema; 8783 this.element = element; 8784 this.identifier = identifier; 8785 this.guide = new Guide(logger); 8786 this.outlets = new OutletSet(this.documentScope, element); 8787 } 8788 findElement(selector) { 8789 return this.element.matches(selector) ? this.element : this.queryElements(selector).find(this.containsElement); 8790 } 8791 findAllElements(selector) { 8792 return [ 8793 ...this.element.matches(selector) ? [this.element] : [], 8794 ...this.queryElements(selector).filter(this.containsElement) 8795 ]; 8796 } 8797 queryElements(selector) { 8798 return Array.from(this.element.querySelectorAll(selector)); 8799 } 8800 get controllerSelector() { 8801 return attributeValueContainsToken(this.schema.controllerAttribute, this.identifier); 8802 } 8803 get isDocumentScope() { 8804 return this.element === document.documentElement; 8805 } 8806 get documentScope() { 8807 return this.isDocumentScope ? this : new _Scope(this.schema, document.documentElement, this.identifier, this.guide.logger); 8808 } 8809}; 8810var ScopeObserver = class { 8811 constructor(element, schema, delegate) { 8812 this.element = element; 8813 this.schema = schema; 8814 this.delegate = delegate; 8815 this.valueListObserver = new ValueListObserver(this.element, this.controllerAttribute, this); 8816 this.scopesByIdentifierByElement = /* @__PURE__ */ new WeakMap(); 8817 this.scopeReferenceCounts = /* @__PURE__ */ new WeakMap(); 8818 } 8819 start() { 8820 this.valueListObserver.start(); 8821 } 8822 stop() { 8823 this.valueListObserver.stop(); 8824 } 8825 get controllerAttribute() { 8826 return this.schema.controllerAttribute; 8827 } 8828 parseValueForToken(token) { 8829 const { element, content: identifier } = token; 8830 return this.parseValueForElementAndIdentifier(element, identifier); 8831 } 8832 parseValueForElementAndIdentifier(element, identifier) { 8833 const scopesByIdentifier = this.fetchScopesByIdentifierForElement(element); 8834 let scope = scopesByIdentifier.get(identifier); 8835 if (!scope) { 8836 scope = this.delegate.createScopeForElementAndIdentifier(element, identifier); 8837 scopesByIdentifier.set(identifier, scope); 8838 } 8839 return scope; 8840 } 8841 elementMatchedValue(element, value) { 8842 const referenceCount = (this.scopeReferenceCounts.get(value) || 0) + 1; 8843 this.scopeReferenceCounts.set(value, referenceCount); 8844 if (referenceCount == 1) { 8845 this.delegate.scopeConnected(value); 8846 } 8847 } 8848 elementUnmatchedValue(element, value) { 8849 const referenceCount = this.scopeReferenceCounts.get(value); 8850 if (referenceCount) { 8851 this.scopeReferenceCounts.set(value, referenceCount - 1); 8852 if (referenceCount == 1) { 8853 this.delegate.scopeDisconnected(value); 8854 } 8855 } 8856 } 8857 fetchScopesByIdentifierForElement(element) { 8858 let scopesByIdentifier = this.scopesByIdentifierByElement.get(element); 8859 if (!scopesByIdentifier) { 8860 scopesByIdentifier = /* @__PURE__ */ new Map(); 8861 this.scopesByIdentifierByElement.set(element, scopesByIdentifier); 8862 } 8863 return scopesByIdentifier; 8864 } 8865}; 8866var Router = class { 8867 constructor(application2) { 8868 this.application = application2; 8869 this.scopeObserver = new ScopeObserver(this.element, this.schema, this); 8870 this.scopesByIdentifier = new Multimap(); 8871 this.modulesByIdentifier = /* @__PURE__ */ new Map(); 8872 } 8873 get element() { 8874 return this.application.element; 8875 } 8876 get schema() { 8877 return this.application.schema; 8878 } 8879 get logger() { 8880 return this.application.logger; 8881 } 8882 get controllerAttribute() { 8883 return this.schema.controllerAttribute; 8884 } 8885 get modules() { 8886 return Array.from(this.modulesByIdentifier.values()); 8887 } 8888 get contexts() { 8889 return this.modules.reduce((contexts, module) => contexts.concat(module.contexts), []); 8890 } 8891 start() { 8892 this.scopeObserver.start(); 8893 } 8894 stop() { 8895 this.scopeObserver.stop(); 8896 } 8897 loadDefinition(definition) { 8898 this.unloadIdentifier(definition.identifier); 8899 const module = new Module(this.application, definition); 8900 this.connectModule(module); 8901 const afterLoad = definition.controllerConstructor.afterLoad; 8902 if (afterLoad) { 8903 afterLoad.call(definition.controllerConstructor, definition.identifier, this.application); 8904 } 8905 } 8906 unloadIdentifier(identifier) { 8907 const module = this.modulesByIdentifier.get(identifier); 8908 if (module) { 8909 this.disconnectModule(module); 8910 } 8911 } 8912 getContextForElementAndIdentifier(element, identifier) { 8913 const module = this.modulesByIdentifier.get(identifier); 8914 if (module) { 8915 return module.contexts.find((context) => context.element == element); 8916 } 8917 } 8918 proposeToConnectScopeForElementAndIdentifier(element, identifier) { 8919 const scope = this.scopeObserver.parseValueForElementAndIdentifier(element, identifier); 8920 if (scope) { 8921 this.scopeObserver.elementMatchedValue(scope.element, scope); 8922 } else { 8923 console.error(`Couldn't find or create scope for identifier: "${identifier}" and element:`, element); 8924 } 8925 } 8926 handleError(error2, message, detail) { 8927 this.application.handleError(error2, message, detail); 8928 } 8929 createScopeForElementAndIdentifier(element, identifier) { 8930 return new Scope(this.schema, element, identifier, this.logger); 8931 } 8932 scopeConnected(scope) { 8933 this.scopesByIdentifier.add(scope.identifier, scope); 8934 const module = this.modulesByIdentifier.get(scope.identifier); 8935 if (module) { 8936 module.connectContextForScope(scope); 8937 } 8938 } 8939 scopeDisconnected(scope) { 8940 this.scopesByIdentifier.delete(scope.identifier, scope); 8941 const module = this.modulesByIdentifier.get(scope.identifier); 8942 if (module) { 8943 module.disconnectContextForScope(scope); 8944 } 8945 } 8946 connectModule(module) { 8947 this.modulesByIdentifier.set(module.identifier, module); 8948 const scopes = this.scopesByIdentifier.getValuesForKey(module.identifier); 8949 scopes.forEach((scope) => module.connectContextForScope(scope)); 8950 } 8951 disconnectModule(module) { 8952 this.modulesByIdentifier.delete(module.identifier); 8953 const scopes = this.scopesByIdentifier.getValuesForKey(module.identifier); 8954 scopes.forEach((scope) => module.disconnectContextForScope(scope)); 8955 } 8956}; 8957var defaultSchema = { 8958 controllerAttribute: "data-controller", 8959 actionAttribute: "data-action", 8960 targetAttribute: "data-target", 8961 targetAttributeForScope: (identifier) => `data-${identifier}-target`, 8962 outletAttributeForScope: (identifier, outlet) => `data-${identifier}-${outlet}-outlet`, 8963 keyMappings: Object.assign(Object.assign({ enter: "Enter", tab: "Tab", esc: "Escape", space: " ", up: "ArrowUp", down: "ArrowDown", left: "ArrowLeft", right: "ArrowRight", home: "Home", end: "End", page_up: "PageUp", page_down: "PageDown" }, objectFromEntries("abcdefghijklmnopqrstuvwxyz".split("").map((c) => [c, c]))), objectFromEntries("0123456789".split("").map((n) => [n, n]))) 8964}; 8965function objectFromEntries(array) { 8966 return array.reduce((memo, [k, v]) => Object.assign(Object.assign({}, memo), { [k]: v }), {}); 8967} 8968var Application = class { 8969 constructor(element = document.documentElement, schema = defaultSchema) { 8970 this.logger = console; 8971 this.debug = false; 8972 this.logDebugActivity = (identifier, functionName, detail = {}) => { 8973 if (this.debug) { 8974 this.logFormattedMessage(identifier, functionName, detail); 8975 } 8976 }; 8977 this.element = element; 8978 this.schema = schema; 8979 this.dispatcher = new Dispatcher(this); 8980 this.router = new Router(this); 8981 this.actionDescriptorFilters = Object.assign({}, defaultActionDescriptorFilters); 8982 } 8983 static start(element, schema) { 8984 const application2 = new this(element, schema); 8985 application2.start(); 8986 return application2; 8987 } 8988 async start() { 8989 await domReady(); 8990 this.logDebugActivity("application", "starting"); 8991 this.dispatcher.start(); 8992 this.router.start(); 8993 this.logDebugActivity("application", "start"); 8994 } 8995 stop() { 8996 this.logDebugActivity("application", "stopping"); 8997 this.dispatcher.stop(); 8998 this.router.stop(); 8999 this.logDebugActivity("application", "stop"); 9000 } 9001 register(identifier, controllerConstructor) { 9002 this.load({ identifier, controllerConstructor }); 9003 } 9004 registerActionOption(name, filter) { 9005 this.actionDescriptorFilters[name] = filter; 9006 } 9007 load(head, ...rest) { 9008 const definitions = Array.isArray(head) ? head : [head, ...rest]; 9009 definitions.forEach((definition) => { 9010 if (definition.controllerConstructor.shouldLoad) { 9011 this.router.loadDefinition(definition); 9012 } 9013 }); 9014 } 9015 unload(head, ...rest) { 9016 const identifiers = Array.isArray(head) ? head : [head, ...rest]; 9017 identifiers.forEach((identifier) => this.router.unloadIdentifier(identifier)); 9018 } 9019 get controllers() { 9020 return this.router.contexts.map((context) => context.controller); 9021 } 9022 getControllerForElementAndIdentifier(element, identifier) { 9023 const context = this.router.getContextForElementAndIdentifier(element, identifier); 9024 return context ? context.controller : null; 9025 } 9026 handleError(error2, message, detail) { 9027 var _a; 9028 this.logger.error(`%s 9029 9030%o 9031 9032%o`, message, error2, detail); 9033 (_a = window.onerror) === null || _a === void 0 ? void 0 : _a.call(window, message, "", 0, 0, error2); 9034 } 9035 logFormattedMessage(identifier, functionName, detail = {}) { 9036 detail = Object.assign({ application: this }, detail); 9037 this.logger.groupCollapsed(`${identifier} #${functionName}`); 9038 this.logger.log("details:", Object.assign({}, detail)); 9039 this.logger.groupEnd(); 9040 } 9041}; 9042function domReady() { 9043 return new Promise((resolve) => { 9044 if (document.readyState == "loading") { 9045 document.addEventListener("DOMContentLoaded", () => resolve()); 9046 } else { 9047 resolve(); 9048 } 9049 }); 9050} 9051function ClassPropertiesBlessing(constructor) { 9052 const classes = readInheritableStaticArrayValues(constructor, "classes"); 9053 return classes.reduce((properties, classDefinition) => { 9054 return Object.assign(properties, propertiesForClassDefinition(classDefinition)); 9055 }, {}); 9056} 9057function propertiesForClassDefinition(key) { 9058 return { 9059 [`${key}Class`]: { 9060 get() { 9061 const { classes } = this; 9062 if (classes.has(key)) { 9063 return classes.get(key); 9064 } else { 9065 const attribute = classes.getAttributeName(key); 9066 throw new Error(`Missing attribute "${attribute}"`); 9067 } 9068 } 9069 }, 9070 [`${key}Classes`]: { 9071 get() { 9072 return this.classes.getAll(key); 9073 } 9074 }, 9075 [`has${capitalize(key)}Class`]: { 9076 get() { 9077 return this.classes.has(key); 9078 } 9079 } 9080 }; 9081} 9082function OutletPropertiesBlessing(constructor) { 9083 const outlets = readInheritableStaticArrayValues(constructor, "outlets"); 9084 return outlets.reduce((properties, outletDefinition) => { 9085 return Object.assign(properties, propertiesForOutletDefinition(outletDefinition)); 9086 }, {}); 9087} 9088function getOutletController(controller, element, identifier) { 9089 return controller.application.getControllerForElementAndIdentifier(element, identifier); 9090} 9091function getControllerAndEnsureConnectedScope(controller, element, outletName) { 9092 let outletController = getOutletController(controller, element, outletName); 9093 if (outletController) 9094 return outletController; 9095 controller.application.router.proposeToConnectScopeForElementAndIdentifier(element, outletName); 9096 outletController = getOutletController(controller, element, outletName); 9097 if (outletController) 9098 return outletController; 9099} 9100function propertiesForOutletDefinition(name) { 9101 const camelizedName = namespaceCamelize(name); 9102 return { 9103 [`${camelizedName}Outlet`]: { 9104 get() { 9105 const outletElement = this.outlets.find(name); 9106 const selector = this.outlets.getSelectorForOutletName(name); 9107 if (outletElement) { 9108 const outletController = getControllerAndEnsureConnectedScope(this, outletElement, name); 9109 if (outletController) 9110 return outletController; 9111 throw new Error(`The provided outlet element is missing an outlet controller "${name}" instance for host controller "${this.identifier}"`); 9112 } 9113 throw new Error(`Missing outlet element "${name}" for host controller "${this.identifier}". Stimulus couldn't find a matching outlet element using selector "${selector}".`); 9114 } 9115 }, 9116 [`${camelizedName}Outlets`]: { 9117 get() { 9118 const outlets = this.outlets.findAll(name); 9119 if (outlets.length > 0) { 9120 return outlets.map((outletElement) => { 9121 const outletController = getControllerAndEnsureConnectedScope(this, outletElement, name); 9122 if (outletController) 9123 return outletController; 9124 console.warn(`The provided outlet element is missing an outlet controller "${name}" instance for host controller "${this.identifier}"`, outletElement); 9125 }).filter((controller) => controller); 9126 } 9127 return []; 9128 } 9129 }, 9130 [`${camelizedName}OutletElement`]: { 9131 get() { 9132 const outletElement = this.outlets.find(name); 9133 const selector = this.outlets.getSelectorForOutletName(name); 9134 if (outletElement) { 9135 return outletElement; 9136 } else { 9137 throw new Error(`Missing outlet element "${name}" for host controller "${this.identifier}". Stimulus couldn't find a matching outlet element using selector "${selector}".`); 9138 } 9139 } 9140 }, 9141 [`${camelizedName}OutletElements`]: { 9142 get() { 9143 return this.outlets.findAll(name); 9144 } 9145 }, 9146 [`has${capitalize(camelizedName)}Outlet`]: { 9147 get() { 9148 return this.outlets.has(name); 9149 } 9150 } 9151 }; 9152} 9153function TargetPropertiesBlessing(constructor) { 9154 const targets = readInheritableStaticArrayValues(constructor, "targets"); 9155 return targets.reduce((properties, targetDefinition) => { 9156 return Object.assign(properties, propertiesForTargetDefinition(targetDefinition)); 9157 }, {}); 9158} 9159function propertiesForTargetDefinition(name) { 9160 return { 9161 [`${name}Target`]: { 9162 get() { 9163 const target = this.targets.find(name); 9164 if (target) { 9165 return target; 9166 } else { 9167 throw new Error(`Missing target element "${name}" for "${this.identifier}" controller`); 9168 } 9169 } 9170 }, 9171 [`${name}Targets`]: { 9172 get() { 9173 return this.targets.findAll(name); 9174 } 9175 }, 9176 [`has${capitalize(name)}Target`]: { 9177 get() { 9178 return this.targets.has(name); 9179 } 9180 } 9181 }; 9182} 9183function ValuePropertiesBlessing(constructor) { 9184 const valueDefinitionPairs = readInheritableStaticObjectPairs(constructor, "values"); 9185 const propertyDescriptorMap = { 9186 valueDescriptorMap: { 9187 get() { 9188 return valueDefinitionPairs.reduce((result, valueDefinitionPair) => { 9189 const valueDescriptor = parseValueDefinitionPair(valueDefinitionPair, this.identifier); 9190 const attributeName = this.data.getAttributeNameForKey(valueDescriptor.key); 9191 return Object.assign(result, { [attributeName]: valueDescriptor }); 9192 }, {}); 9193 } 9194 } 9195 }; 9196 return valueDefinitionPairs.reduce((properties, valueDefinitionPair) => { 9197 return Object.assign(properties, propertiesForValueDefinitionPair(valueDefinitionPair)); 9198 }, propertyDescriptorMap); 9199} 9200function propertiesForValueDefinitionPair(valueDefinitionPair, controller) { 9201 const definition = parseValueDefinitionPair(valueDefinitionPair, controller); 9202 const { key, name, reader: read, writer: write } = definition; 9203 return { 9204 [name]: { 9205 get() { 9206 const value = this.data.get(key); 9207 if (value !== null) { 9208 return read(value); 9209 } else { 9210 return definition.defaultValue; 9211 } 9212 }, 9213 set(value) { 9214 if (value === void 0) { 9215 this.data.delete(key); 9216 } else { 9217 this.data.set(key, write(value)); 9218 } 9219 } 9220 }, 9221 [`has${capitalize(name)}`]: { 9222 get() { 9223 return this.data.has(key) || definition.hasCustomDefaultValue; 9224 } 9225 } 9226 }; 9227} 9228function parseValueDefinitionPair([token, typeDefinition], controller) { 9229 return valueDescriptorForTokenAndTypeDefinition({ 9230 controller, 9231 token, 9232 typeDefinition 9233 }); 9234} 9235function parseValueTypeConstant(constant) { 9236 switch (constant) { 9237 case Array: 9238 return "array"; 9239 case Boolean: 9240 return "boolean"; 9241 case Number: 9242 return "number"; 9243 case Object: 9244 return "object"; 9245 case String: 9246 return "string"; 9247 } 9248} 9249function parseValueTypeDefault(defaultValue) { 9250 switch (typeof defaultValue) { 9251 case "boolean": 9252 return "boolean"; 9253 case "number": 9254 return "number"; 9255 case "string": 9256 return "string"; 9257 } 9258 if (Array.isArray(defaultValue)) 9259 return "array"; 9260 if (Object.prototype.toString.call(defaultValue) === "[object Object]") 9261 return "object"; 9262} 9263function parseValueTypeObject(payload) { 9264 const { controller, token, typeObject } = payload; 9265 const hasType = isSomething(typeObject.type); 9266 const hasDefault = isSomething(typeObject.default); 9267 const fullObject = hasType && hasDefault; 9268 const onlyType = hasType && !hasDefault; 9269 const onlyDefault = !hasType && hasDefault; 9270 const typeFromObject = parseValueTypeConstant(typeObject.type); 9271 const typeFromDefaultValue = parseValueTypeDefault(payload.typeObject.default); 9272 if (onlyType) 9273 return typeFromObject; 9274 if (onlyDefault) 9275 return typeFromDefaultValue; 9276 if (typeFromObject !== typeFromDefaultValue) { 9277 const propertyPath = controller ? `${controller}.${token}` : token; 9278 throw new Error(`The specified default value for the Stimulus Value "${propertyPath}" must match the defined type "${typeFromObject}". The provided default value of "${typeObject.default}" is of type "${typeFromDefaultValue}".`); 9279 } 9280 if (fullObject) 9281 return typeFromObject; 9282} 9283function parseValueTypeDefinition(payload) { 9284 const { controller, token, typeDefinition } = payload; 9285 const typeObject = { controller, token, typeObject: typeDefinition }; 9286 const typeFromObject = parseValueTypeObject(typeObject); 9287 const typeFromDefaultValue = parseValueTypeDefault(typeDefinition); 9288 const typeFromConstant = parseValueTypeConstant(typeDefinition); 9289 const type = typeFromObject || typeFromDefaultValue || typeFromConstant; 9290 if (type) 9291 return type; 9292 const propertyPath = controller ? `${controller}.${typeDefinition}` : token; 9293 throw new Error(`Unknown value type "${propertyPath}" for "${token}" value`); 9294} 9295function defaultValueForDefinition(typeDefinition) { 9296 const constant = parseValueTypeConstant(typeDefinition); 9297 if (constant) 9298 return defaultValuesByType[constant]; 9299 const hasDefault = hasProperty(typeDefinition, "default"); 9300 const hasType = hasProperty(typeDefinition, "type"); 9301 const typeObject = typeDefinition; 9302 if (hasDefault) 9303 return typeObject.default; 9304 if (hasType) { 9305 const { type } = typeObject; 9306 const constantFromType = parseValueTypeConstant(type); 9307 if (constantFromType) 9308 return defaultValuesByType[constantFromType]; 9309 } 9310 return typeDefinition; 9311} 9312function valueDescriptorForTokenAndTypeDefinition(payload) { 9313 const { token, typeDefinition } = payload; 9314 const key = `${dasherize(token)}-value`; 9315 const type = parseValueTypeDefinition(payload); 9316 return { 9317 type, 9318 key, 9319 name: camelize(key), 9320 get defaultValue() { 9321 return defaultValueForDefinition(typeDefinition); 9322 }, 9323 get hasCustomDefaultValue() { 9324 return parseValueTypeDefault(typeDefinition) !== void 0; 9325 }, 9326 reader: readers[type], 9327 writer: writers[type] || writers.default 9328 }; 9329} 9330var defaultValuesByType = { 9331 get array() { 9332 return []; 9333 }, 9334 boolean: false, 9335 number: 0, 9336 get object() { 9337 return {}; 9338 }, 9339 string: "" 9340}; 9341var readers = { 9342 array(value) { 9343 const array = JSON.parse(value); 9344 if (!Array.isArray(array)) { 9345 throw new TypeError(`expected value of type "array" but instead got value "${value}" of type "${parseValueTypeDefault(array)}"`); 9346 } 9347 return array; 9348 }, 9349 boolean(value) { 9350 return !(value == "0" || String(value).toLowerCase() == "false"); 9351 }, 9352 number(value) { 9353 return Number(value.replace(/_/g, "")); 9354 }, 9355 object(value) { 9356 const object = JSON.parse(value); 9357 if (object === null || typeof object != "object" || Array.isArray(object)) { 9358 throw new TypeError(`expected value of type "object" but instead got value "${value}" of type "${parseValueTypeDefault(object)}"`); 9359 } 9360 return object; 9361 }, 9362 string(value) { 9363 return value; 9364 } 9365}; 9366var writers = { 9367 default: writeString, 9368 array: writeJSON, 9369 object: writeJSON 9370}; 9371function writeJSON(value) { 9372 return JSON.stringify(value); 9373} 9374function writeString(value) { 9375 return `${value}`; 9376} 9377var Controller = class { 9378 constructor(context) { 9379 this.context = context; 9380 } 9381 static get shouldLoad() { 9382 return true; 9383 } 9384 static afterLoad(_identifier, _application) { 9385 return; 9386 } 9387 get application() { 9388 return this.context.application; 9389 } 9390 get scope() { 9391 return this.context.scope; 9392 } 9393 get element() { 9394 return this.scope.element; 9395 } 9396 get identifier() { 9397 return this.scope.identifier; 9398 } 9399 get targets() { 9400 return this.scope.targets; 9401 } 9402 get outlets() { 9403 return this.scope.outlets; 9404 } 9405 get classes() { 9406 return this.scope.classes; 9407 } 9408 get data() { 9409 return this.scope.data; 9410 } 9411 initialize() { 9412 } 9413 connect() { 9414 } 9415 disconnect() { 9416 } 9417 dispatch(eventName, { target = this.element, detail = {}, prefix = this.identifier, bubbles = true, cancelable = true } = {}) { 9418 const type = prefix ? `${prefix}:${eventName}` : eventName; 9419 const event = new CustomEvent(type, { detail, bubbles, cancelable }); 9420 target.dispatchEvent(event); 9421 return event; 9422 } 9423}; 9424Controller.blessings = [ 9425 ClassPropertiesBlessing, 9426 TargetPropertiesBlessing, 9427 ValuePropertiesBlessing, 9428 OutletPropertiesBlessing 9429]; 9430Controller.targets = []; 9431Controller.outlets = []; 9432Controller.values = {}; 9433
9434// app/javascript/controllers/application.js 9435var application = Application.start(); 9436application.debug = false; 9437window.Stimulus = application; 9438
9439// app/javascript/controllers/address_controller.js 9440var address_controller_default = class extends Controller { 9441 static targets = ["address", "output"]; 9442 setAddress(e) { 9443 const { address } = e.detail; 9444 this.address = address; 9445 } 9446 set address(value) { 9447 this.addressTarget.value = value; 9448 } 9449}; 9450
9451// app/javascript/controllers/country-state_controller.js 9452var JAPAN_ID = 145; 9453var country_state_controller_default = class extends Controller { 9454 static targets = [ 9455 "countryId", 9456 "countryStateId", 9457 "state", 9458 "stateOption", 9459 "countryStateLabel", 9460 "addressLabel", 9461 "furigana", 9462 "furiganaField", 9463 "output" 9464 ]; 9465 countryIdTargetConnected(target) { 9466 const value = target.value; 9467 if (value) { 9468 this.setOptions({ target }); 9469 } 9470 } 9471 setOptions(e) { 9472 const options = this.stateOptionTargets.filter((option) => { 9473 return option.dataset.countryId == e.target.value; 9474 }); 9475 const selected = this.stateOptionTargets.find((option) => { 9476 return option.selected; 9477 }); 9478 if (selected && selected.dataset.countryId != e.target.value) { 9479 this.countryStateIdTarget.value = ""; 9480 selected.selected = false; 9481 } 9482 this.stateOptionTargets.forEach((option) => { 9483 option.hidden = true; 9484 }); 9485 if (options.length == 0) { 9486 this.stateTarget.hidden = true; 9487 } else { 9488 this.stateTarget.hidden = false; 9489 options.forEach((option) => { 9490 option.hidden = false; 9491 }); 9492 } 9493 if (e.target.value != JAPAN_ID) { 9494 this.furiganaTarget.value = ""; 9495 this.furiganaFieldTarget.hidden = true; 9496 this.addressLabelTarget.textContent = "\u4F4F\u6240"; 9497 this.countryStateLabelTarget.textContent = "\u5DDE\u30FB\u770C\u30FB\u7701"; 9498 } else { 9499 this.furiganaFieldTarget.hidden = false; 9500 this.addressLabelTarget.textContent = "\u5E02\u533A\u753A\u6751\u30FB\u756A\u5730"; 9501 this.countryStateLabelTarget.textContent = "\u90FD\u9053\u5E9C\u770C"; 9502 } 9503 } 9504}; 9505
9506// app/javascript/controllers/fincode-card_controller.js 9507var DEFAULT_FORM_WIDTH = 400; 9508var MIN_FORM_WIDTH = 250; 9509var FORM_EXTRA_WIDTH = 30; 9510var IFRAME_HEIGHT_SLACK = 60; 9511var fincode_card_controller_default = class extends Controller { 9512 static targets = ["mount", "submit", "error"]; 9513 static values = { 9514 publicKey: String, 9515 jsUrl: String, 9516 checkUrl: String, 9517 cardId: String, 9518 csrf: String, 9519 submittingText: String, 9520 iframeTitle: String 9521 }; 9522 connect() { 9523 if (this.hasSubmitTarget) this.defaultSubmitText = this.submitTarget.textContent; 9524 if (this.hasErrorTarget) this.defaultErrorText = this.errorTarget.textContent; 9525 this.loadFincodeJs().then(() => this.initUi()).catch((error2) => { 9526 console.error("fincode WEBUI init failed:", error2); 9527 this.showError(); 9528 }); 9529 } 9530 loadFincodeJs() { 9531 if (window.Fincode) return Promise.resolve(); 9532 return new Promise((resolve, reject) => { 9533 const script = document.createElement("script"); 9534 script.src = this.jsUrlValue; 9535 script.onload = () => resolve(); 9536 script.onerror = () => reject(new Error("failed to load fincode.js")); 9537 document.head.appendChild(script); 9538 }); 9539 } 9540 initUi() { 9541 this.fincode = window.Fincode(this.publicKeyValue); 9542 this.ui = this.fincode.ui({ layout: "vertical" }); 9543 this.ui.create("payments", { layout: "vertical" }); 9544 this.ui.mount(this.mountTarget.id, this.mountWidth()); 9545 this.iframeSizeListener = (event) => this.resizeIframe(event); 9546 window.addEventListener("message", this.iframeSizeListener); 9547 } 9548 disconnect() { 9549 if (this.iframeSizeListener) window.removeEventListener("message", this.iframeSizeListener); 9550 } 9551 resizeIframe(event) { 9552 if (event.origin !== new URL(this.jsUrlValue).origin) return; 9553 if (event.data?.action !== "iframeSize") return; 9554 const iframe = document.getElementById(`${this.mountTarget.id}-ui`); 9555 if (!iframe) return; 9556 if (this.hasIframeTitleValue) iframe.title = this.iframeTitleValue; 9557 const height = parseInt(event.data.size?.height, 10); 9558 if (Number.isFinite(height)) iframe.style.height = `${height + IFRAME_HEIGHT_SLACK}px`; 9559 } 9560 // åºå®å¹ ãæ¸¡ãã¨çãç»é¢ã§æ¨ªã¹ã¯ãã¼ã«ãåºãããã表示é åããéç®ããã 9561 mountWidth() { 9562 const available = this.element.clientWidth - FORM_EXTRA_WIDTH; 9563 return String(Math.min(DEFAULT_FORM_WIDTH, Math.max(MIN_FORM_WIDTH, available))); 9564 } 9565 submit(event) { 9566 event.preventDefault(); 9567 if (!this.ui) { 9568 this.showError(); 9569 return; 9570 } 9571 this.disableSubmit(); 9572 this.ui.getFormData().then((formData) => this.run(formData)).catch((e) => { 9573 console.error("getFormData failed:", e); 9574 this.showError(); 9575 }); 9576 } 9577 async run(formData) {
9578 let check; 9579 try { 9580 const token = await this.tokenizeCard(formData); 9581 check = await this.createCheck(token); 9582 } catch (e) { 9583 console.error("fincode card change failed before 3DS:", e); 9584 this.showError(e.userMessage); 9585 return; 9586 } 9587 this.proceed(check); 9588 } 9589 // fincode.tokens() ã§ã«ã¼ãããã¼ã¯ã³åããï¼PAN ã¯èªç¤¾ãµã¼ãã«éããªãï¼ã 9590 tokenizeCard(formData) { 9591 return new Promise((resolve, reject) => { 9592 this.fincode.tokens( 9593 { 9594 card_no: formData.cardNo, 9595 expire: formData.expire, 9596 security_code: formData.CVC, 9597 holder_name: formData.holderName, 9598 number: "1" 9599 }, 9600 (status, response) => { 9601 const token = status === 200 && response.list && response.list[0] && response.list[0].token; 9602 token ? resolve(token) : reject(response); 9603 }, 9604 () => reject(new Error("fincode.tokens communication error")) 9605 ); 9606 }); 9607 } 9608 // colorme-api çµç±ã§ã«ã¼ãç»é² + CHECK 決æ¸ï¼auto-3DSï¼ãå®è¡ããã 9609 // æ»ã: { redirect_urlï¼ãã£ã¬ã³ã¸æã®ã¿ï¼, complete_urlï¼ããªã¯ã·ã§ã³ã¬ã¹æã®é·ç§»å ï¼ } 9610 async createCheck(token) { 9611 const res = await fetch(this.checkUrlValue, { 9612 method: "POST", 9613 headers: { 9614 "Content-Type": "application/json", 9615 Accept: "application/json", 9616 "X-CSRF-Token": this.csrfValue 9617 }, 9618 body: JSON.stringify({ token, card_id: this.cardIdValue }) 9619 }); 9620 if (!res.ok) { 9621 const error2 = new Error(`check create failed: ${res.status}`); 9622 error2.userMessage = await res.json().then((body) => body.error).catch(() => void 0); 9623 throw error2; 9624 } 9625 const data = await res.json(); 9626 if (!data.complete_url) throw new Error("invalid check response: missing complete_url"); 9627 return data; 9628 } 9629 proceed(check) { 9630 if (check.redirect_url) { 9631 if (this.fincodeUrl(check.redirect_url)) { 9632 window.location.href = check.redirect_url; 9633 } else { 9634 console.error("unexpected 3DS redirect domain:", check.redirect_url); 9635 this.showError(); 9636 } 9637 } else { 9638 window.location.href = check.complete_url; 9639 } 9640 } 9641 // fincodeï¼https ã® *.fincode.jpï¼é ä¸ã® URL ãã©ããã3DS ãã£ã¬ã³ã¸é·ç§»å ã®æ¤è¨¼ã«ä½¿ãã 9642 // HTTP ã¸ã®ãã¦ã³ã°ã¬ã¼ããé²ãããããããã³ã«ã https ã§ãããã¨ãæ¤è¨¼ããã 9643 fincodeUrl(url) { 9644 try { 9645 const parsed = new URL(url); 9646 if (parsed.protocol !== "https:") return false; 9647 const host = parsed.hostname; 9648 return host === "fincode.jp" || host.endsWith(".fincode.jp"); 9649 } catch { 9650 return false; 9651 } 9652 } 9653 disableSubmit() { 9654 if (!this.hasSubmitTarget) return; 9655 this.submitTarget.disabled = true; 9656 if (this.hasSubmittingTextValue) this.submitTarget.textContent = this.submittingTextValue; 9657 } 9658 enableSubmit() { 9659 if (!this.hasSubmitTarget) return; 9660 this.submitTarget.disabled = false; 9661 if (this.defaultSubmitText) this.submitTarget.textContent = this.defaultSubmitText; 9662 } 9663 // message ãç¡ããã°æ¢å®ã®æè¨ã«æ»ãï¼ååã®å¶éä¸ã®æè¨ãªã©ãæ®ããªãï¼ã 9664 showError(message) { 9665 if (this.hasErrorTarget) { 9666 this.errorTarget.textContent = message || this.defaultErrorText; 9667 this.errorTarget.hidden = false; 9668 } 9669 this.enableSubmit(); 9670 } 9671}; 9672
9673// app/javascript/postal-code.js 9674var import_fetch_jsonp = __toESM(require_fetch_jsonp()); 9675var JSONDATA = "https://yubinbango.github.io/yubinbango-data/data"; 9676var CACHE = {}; 9677var PREFMAP = [ 9678 "", 9679 "\u5317\u6D77\u9053", 9680 "\u9752\u68EE\u770C", 9681 "\u5CA9\u624B\u770C", 9682 "\u5BAE\u57CE\u770C", 9683 "\u79CB\u7530\u770C", 9684 "\u5C71\u5F62\u770C", 9685 "\u798F\u5CF6\u770C", 9686 "\u8328\u57CE\u770C", 9687 "\u6803\u6728\u770C", 9688 "\u7FA4\u99AC\u770C", 9689 "\u57FC\u7389\u770C", 9690 "\u5343\u8449\u770C", 9691 "\u6771\u4EAC\u90FD", 9692 "\u795E\u5948\u5DDD\u770C", 9693 "\u65B0\u6F5F\u770C", 9694 "\u5BCC\u5C71\u770C", 9695 "\u77F3\u5DDD\u770C", 9696 "\u798F\u4E95\u770C", 9697 "\u5C71\u68A8\u770C", 9698 "\u9577\u91CE\u770C", 9699 "\u5C90\u961C\u770C", 9700 "\u9759\u5CA1\u770C", 9701 "\u611B\u77E5\u770C", 9702 "\u4E09\u91CD\u770C", 9703 "\u6ECB\u8CC0\u770C", 9704 "\u4EAC\u90FD\u5E9C", 9705 "\u5927\u962A\u5E9C", 9706 "\u5175\u5EAB\u770C", 9707 "\u5948\u826F\u770C", 9708 "\u548C\u6B4C\u5C71\u770C", 9709 "\u9CE5\u53D6\u770C", 9710 "\u5CF6\u6839\u770C", 9711 "\u5CA1\u5C71\u770C", 9712 "\u5E83\u5CF6\u770C", 9713 "\u5C71\u53E3\u770C", 9714 "\u5FB3\u5CF6\u770C", 9715 "\u9999\u5DDD\u770C", 9716 "\u611B\u5A9B\u770C", 9717 "\u9AD8\u77E5\u770C", 9718 "\u798F\u5CA1\u770C", 9719 "\u4F50\u8CC0\u770C", 9720 "\u9577\u5D0E\u770C", 9721 "\u718A\u672C\u770C", 9722 "\u5927\u5206\u770C", 9723 "\u5BAE\u5D0E\u770C", 9724 "\u9E7F\u5150\u5CF6\u770C", 9725 "\u6C96\u7E04\u770C" 9726]; 9727var getJapanPostalCode = (zip_code, callback) => { 9728 const vzip = zip_code; 9729 if (!vzip) return; 9730 let nzip = ""; 9731 for (let i = 0; i < vzip.length; i++) { 9732 const chr = vzip.charCodeAt(i); 9733 if (chr < 48) continue; 9734 if (chr > 57) continue; 9735 nzip += vzip.charAt(i); 9736 } 9737 if (nzip.length < 7) return; 9738 const zip3 = nzip.substr(0, 3); 9739 const data = CACHE[zip3]; 9740 if (data) return parse(nzip, data, callback); 9741 fetchRemote(nzip, callback); 9742}; 9743var parse = (nzip, data, callback) => { 9744 let array = data[nzip]; 9745 const opera = (parseInt(nzip, 10) - 0 + 4278190080).toString(); 9746 if (!array && data[opera]) { 9747 array = data[opera]; 9748 } 9749 if (!array) { 9750 throw new Error("Failed to parse address data"); 9751 } 9752 const prefId = array[0]; 9753 if (!prefId) { 9754 throw new Error("Failed to parse address data"); 9755 } 9756 const jpref = PREFMAP[prefId]; 9757 if (!jpref) { 9758 throw new Error("Failed to parse address data"); 9759 } 9760 const prefecture = jpref; 9761 const jcity = array[1] || ""; 9762 const jarea = array[2] || ""; 9763 const jstrt = array[3] || ""; 9764 callback({ 9765 prefecture, 9766 address: jcity + jarea + jstrt 9767 }); 9768}; 9769var fetchRemote = (nzip, callback) => { 9770 const zip3 = nzip.substr(0, 3); 9771 const url = JSONDATA + "/" + zip3 + ".js"; 9772 (0, import_fetch_jsonp.default)(url, { jsonpCallbackFunction: "$yubin" }).then((response) => { 9773 return response.json(); 9774 }).then((data) => { 9775 CACHE[zip3] = data; 9776 parse(nzip, data, callback); 9777 }).catch(() => { 9778 }); 9779}; 9780
9781// app/javascript/controllers/postal-code_controller.js 9782var postal_code_controller_default = class extends Controller { 9783 static targets = ["postalCode", "output"]; 9784 search() { 9785 getJapanPostalCode(this.postalCode, (data) => { 9786 this.dispatch("search", { detail: data }); 9787 }); 9788 } 9789 get postalCode() { 9790 return this.postalCodeTarget.value; 9791 } 9792}; 9793
9794// app/javascript/controllers/prefecture_controller.js 9795var prefecture_controller_default = class extends Controller { 9796 static targets = ["prefecture", "output"]; 9797 setPrefectureId(e) { 9798 const { prefecture } = e.detail; 9799 const prefectureId = Array.from(this.prefectureTarget).find((o) => o.text === prefecture).value; 9800 this.prefecture = prefectureId; 9801 } 9802 set prefecture(value) { 9803 this.prefectureTarget.value = value; 9804 } 9805}; 9806
9807// app/javascript/controllers/star_rating_controller.js 9808var star_rating_controller_default = class extends Controller { 9809 static targets = ["star", "input"]; 9810 static values = { 9811 unfilledStarUrl: String, 9812 filledStarUrl: String 9813 }; 9814 connect() { 9815 this.starNum = null; 9816 this.loadStar(this.inputTarget.value); 9817 } 9818 highlight({ params: { index } }) { 9819 this.updateStars(index); 9820 } 9821 select({ params: { index } }) { 9822 if (this.starNum === index) { 9823 this.starNum = null; 9824 this.inputTarget.value = 0; 9825 } else { 9826 this.starNum = index; 9827 this.inputTarget.value = this.starNum; 9828 } 9829 this.updateStars(this.starNum); 9830 } 9831 reset() { 9832 this.updateStars(this.starNum); 9833 } 9834 loadStar(num) { 9835 this.starNum = num ? parseInt(num) : null; 9836 this.updateStars(this.starNum); 9837 } 9838 updateStars(index) { 9839 this.starTargets.forEach((star, i) => { 9840 if (i < index) { 9841 star.style.backgroundImage = `url(${this.filledStarUrlValue})`; 9842 } else { 9843 star.style.backgroundImage = `url(${this.unfilledStarUrlValue})`; 9844 } 9845 }); 9846 } 9847}; 9848
9849// app/javascript/controllers/submit_guard_controller.js 9850var submit_guard_controller_default = class extends Controller { 9851 connect() { 9852 this.submitted = false; 9853 this.onPageShow = (event) => { 9854 if (event.persisted) this.reset(); 9855 }; 9856 window.addEventListener("pageshow", this.onPageShow); 9857 } 9858 disconnect() { 9859 window.removeEventListener("pageshow", this.onPageShow); 9860 } 9861 submit(event) { 9862 if (this.submitted) { 9863 event.preventDefault(); 9864 return; 9865 } 9866 this.submitted = true; 9867 requestAnimationFrame(() => { 9868 this.submitButtons().forEach((button) => { 9869 button.disabled = true; 9870 }); 9871 }); 9872 } 9873 reset() { 9874 this.submitted = false; 9875 this.submitButtons().forEach((button) => { 9876 button.disabled = false; 9877 }); 9878 } 9879 submitButtons() { 9880 return this.element.querySelectorAll("[type=submit]"); 9881 } 9882}; 9883
9884// app/javascript/controllers/index.js 9885application.register("address", address_controller_default); 9886application.register("country-state", country_state_controller_default); 9887application.register("fincode-card", fincode_card_controller_default); 9888application.register("postal-code", postal_code_controller_default); 9889application.register("prefecture", prefecture_controller_default); 9890application.register("star-rating", star_rating_controller_default); 9891application.register("submit-guard", submit_guard_controller_default); 9892
9893// app/javascript/pikaday.js 9894var import_pikaday = __toESM(require_pikaday()); 9895function initializePikadayFields() { 9896 const dateInput = document.querySelector(".pikaday"); 9897 if (dateInput) { 9898 if (dateInput.pikaday) { 9899 dateInput.pikaday.destroy(); 9900 } 9901 const picker = new import_pikaday.default({ 9902 field: dateInput, 9903 format: "YYYY-MM-DD", 9904 i18n: { 9905 previousMonth: "\u524D\u6708", 9906 nextMonth: "\u6B21\u6708", 9907 months: ["1\u6708", "2\u6708", "3\u6708", "4\u6708", "5\u6708", "6\u6708", "7\u6708", "8\u6708", "9\u6708", "10\u6708", "11\u6708", "12\u6708"], 9908 weekdays: ["\u65E5\u66DC\u65E5", "\u6708\u66DC\u65E5", "\u706B\u66DC\u65E5", "\u6C34\u66DC\u65E5", "\u6728\u66DC\u65E5", "\u91D1\u66DC\u65E5", "\u571F\u66DC\u65E5"], 9909 weekdaysShort: ["\u65E5", "\u6708", "\u706B", "\u6C34", "\u6728", "\u91D1", "\u571F"] 9910 }, 9911 yearRange: [1900, (/* @__PURE__ */ new Date()).getFullYear()], 9912 toString(date) { 9913 const day = date.getDate(); 9914 const month = date.getMonth() + 1; 9915 const year = date.getFullYear(); 9916 return `${year}-${month.toString().padStart(2, "0")}-${day.toString().padStart(2, "0")}`; 9917 } 9918 }); 9919 dateInput.pikaday = picker; 9920 } 9921} 9922document.addEventListener("turbo:load", initializePikadayFields); 9923document.addEventListener("turbo:render", initializePikadayFields); 9924
9925// app/javascript/application.js 9926var Colorme = { getJapanPostalCode }; 9927window.Colorme = Colorme; 9928window.addEventListener("turbo:load", () => { 9929 let s = document.createElement("script"); 9930 s.src = "https://seal.atlas.globalsign.com/gss/one/seal?image=seal_115-57_ja.png"; 9931 document.body.appendChild(s); 9932}); 9933Turbo.StreamActions.redirect = function() { 9934 Turbo.visit(this.target); 9935}; 9936/*! Bundled license information: 9937 9938pikaday/pikaday.js: 9939 (*! 9940 * Pikaday 9941 * 9942 * Copyright © 2014 David Bushell | BSD & MIT license | https://github.com/Pikaday/Pikaday 9943 *) 9944 9945@hotwired/turbo/dist/turbo.es2017-esm.js: 9946 (*! 9947 Turbo 8.0.10 9948 Copyright © 2024 37signals LLC 9949 *) 9950*/
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.