1
0
Fork 0
mirror of https://github.com/archtechx/laravel-tips.git synced 2025-12-12 05:14:04 +00:00
laravel-tips/test/js/app.js
2021-04-06 18:27:18 +02:00

4907 lines
No EOL
172 KiB
JavaScript
Vendored
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/******/ (() => { // webpackBootstrap
/******/ var __webpack_modules__ = ({
/***/ "./node_modules/@hotwired/turbo/dist/turbo.es2017-esm.js":
/*!***************************************************************!*\
!*** ./node_modules/@hotwired/turbo/dist/turbo.es2017-esm.js ***!
\***************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "clearCache": () => (/* binding */ clearCache),
/* harmony export */ "connectStreamSource": () => (/* binding */ connectStreamSource),
/* harmony export */ "disconnectStreamSource": () => (/* binding */ disconnectStreamSource),
/* harmony export */ "navigator": () => (/* binding */ navigator),
/* harmony export */ "registerAdapter": () => (/* binding */ registerAdapter),
/* harmony export */ "renderStreamMessage": () => (/* binding */ renderStreamMessage),
/* harmony export */ "setProgressBarDelay": () => (/* binding */ setProgressBarDelay),
/* harmony export */ "start": () => (/* binding */ start),
/* harmony export */ "visit": () => (/* binding */ visit)
/* harmony export */ });
/*
Turbo 7.0.0-beta.4
Copyright © 2021 Basecamp, LLC
*/
(function () {
if (window.Reflect === undefined || window.customElements === undefined ||
window.customElements.polyfillWrapFlushCallback) {
return;
}
const BuiltInHTMLElement = HTMLElement;
const wrapperForTheName = {
'HTMLElement': function HTMLElement() {
return Reflect.construct(BuiltInHTMLElement, [], this.constructor);
}
};
window.HTMLElement =
wrapperForTheName['HTMLElement'];
HTMLElement.prototype = BuiltInHTMLElement.prototype;
HTMLElement.prototype.constructor = HTMLElement;
Object.setPrototypeOf(HTMLElement, BuiltInHTMLElement);
})();
const submittersByForm = new WeakMap;
function findSubmitterFromClickTarget(target) {
const element = target instanceof Element ? target : target instanceof Node ? target.parentElement : null;
const candidate = element ? element.closest("input, button") : null;
return (candidate === null || candidate === void 0 ? void 0 : candidate.type) == "submit" ? candidate : null;
}
function clickCaptured(event) {
const submitter = findSubmitterFromClickTarget(event.target);
if (submitter && submitter.form) {
submittersByForm.set(submitter.form, submitter);
}
}
(function () {
if ("SubmitEvent" in window)
return;
addEventListener("click", clickCaptured, true);
Object.defineProperty(Event.prototype, "submitter", {
get() {
if (this.type == "submit" && this.target instanceof HTMLFormElement) {
return submittersByForm.get(this.target);
}
}
});
})();
var FrameLoadingStyle;
(function (FrameLoadingStyle) {
FrameLoadingStyle["eager"] = "eager";
FrameLoadingStyle["lazy"] = "lazy";
})(FrameLoadingStyle || (FrameLoadingStyle = {}));
class FrameElement extends HTMLElement {
constructor() {
super();
this.loaded = Promise.resolve();
this.delegate = new FrameElement.delegateConstructor(this);
}
static get observedAttributes() {
return ["loading", "src"];
}
connectedCallback() {
this.delegate.connect();
}
disconnectedCallback() {
this.delegate.disconnect();
}
attributeChangedCallback(name) {
if (name == "loading") {
this.delegate.loadingStyleChanged();
}
else if (name == "src") {
this.delegate.sourceURLChanged();
}
}
get src() {
return this.getAttribute("src");
}
set src(value) {
if (value) {
this.setAttribute("src", value);
}
else {
this.removeAttribute("src");
}
}
get loading() {
return frameLoadingStyleFromString(this.getAttribute("loading") || "");
}
set loading(value) {
if (value) {
this.setAttribute("loading", value);
}
else {
this.removeAttribute("loading");
}
}
get disabled() {
return this.hasAttribute("disabled");
}
set disabled(value) {
if (value) {
this.setAttribute("disabled", "");
}
else {
this.removeAttribute("disabled");
}
}
get autoscroll() {
return this.hasAttribute("autoscroll");
}
set autoscroll(value) {
if (value) {
this.setAttribute("autoscroll", "");
}
else {
this.removeAttribute("autoscroll");
}
}
get complete() {
return !this.delegate.isLoading;
}
get isActive() {
return this.ownerDocument === document && !this.isPreview;
}
get isPreview() {
var _a, _b;
return (_b = (_a = this.ownerDocument) === null || _a === void 0 ? void 0 : _a.documentElement) === null || _b === void 0 ? void 0 : _b.hasAttribute("data-turbo-preview");
}
}
function frameLoadingStyleFromString(style) {
switch (style.toLowerCase()) {
case "lazy": return FrameLoadingStyle.lazy;
default: return FrameLoadingStyle.eager;
}
}
function expandURL(locatable) {
const anchor = document.createElement("a");
anchor.href = locatable.toString();
return new URL(anchor.href);
}
function getAnchor(url) {
let anchorMatch;
if (url.hash) {
return url.hash.slice(1);
}
else if (anchorMatch = url.href.match(/#(.*)$/)) {
return anchorMatch[1];
}
else {
return "";
}
}
function getExtension(url) {
return (getLastPathComponent(url).match(/\.[^.]*$/) || [])[0] || "";
}
function isHTML(url) {
return !!getExtension(url).match(/^(?:|\.(?:htm|html|xhtml))$/);
}
function isPrefixedBy(baseURL, url) {
const prefix = getPrefix(url);
return baseURL.href === expandURL(prefix).href || baseURL.href.startsWith(prefix);
}
function toCacheKey(url) {
const anchorLength = url.hash.length;
if (anchorLength < 2) {
return url.href;
}
else {
return url.href.slice(0, -anchorLength);
}
}
function getPathComponents(url) {
return url.pathname.split("/").slice(1);
}
function getLastPathComponent(url) {
return getPathComponents(url).slice(-1)[0];
}
function getPrefix(url) {
return addTrailingSlash(url.origin + url.pathname);
}
function addTrailingSlash(value) {
return value.endsWith("/") ? value : value + "/";
}
class FetchResponse {
constructor(response) {
this.response = response;
}
get succeeded() {
return this.response.ok;
}
get failed() {
return !this.succeeded;
}
get clientError() {
return this.statusCode >= 400 && this.statusCode <= 499;
}
get serverError() {
return this.statusCode >= 500 && this.statusCode <= 599;
}
get redirected() {
return this.response.redirected;
}
get location() {
return expandURL(this.response.url);
}
get isHTML() {
return this.contentType && this.contentType.match(/^(?:text\/([^\s;,]+\b)?html|application\/xhtml\+xml)\b/);
}
get statusCode() {
return this.response.status;
}
get contentType() {
return this.header("Content-Type");
}
get responseText() {
return this.response.text();
}
get responseHTML() {
if (this.isHTML) {
return this.response.text();
}
else {
return Promise.resolve(undefined);
}
}
header(name) {
return this.response.headers.get(name);
}
}
function dispatch(eventName, { target, cancelable, detail } = {}) {
const event = new CustomEvent(eventName, { cancelable, bubbles: true, detail });
void (target || document.documentElement).dispatchEvent(event);
return event;
}
function nextAnimationFrame() {
return new Promise(resolve => requestAnimationFrame(() => resolve()));
}
function nextEventLoopTick() {
return new Promise(resolve => setTimeout(() => resolve(), 0));
}
function nextMicrotask() {
return Promise.resolve();
}
function parseHTMLDocument(html = "") {
return new DOMParser().parseFromString(html, "text/html");
}
function unindent(strings, ...values) {
const lines = interpolate(strings, values).replace(/^\n/, "").split("\n");
const match = lines[0].match(/^\s+/);
const indent = match ? match[0].length : 0;
return lines.map(line => line.slice(indent)).join("\n");
}
function interpolate(strings, values) {
return strings.reduce((result, string, i) => {
const value = values[i] == undefined ? "" : values[i];
return result + string + value;
}, "");
}
function uuid() {
return Array.apply(null, { length: 36 }).map((_, i) => {
if (i == 8 || i == 13 || i == 18 || i == 23) {
return "-";
}
else if (i == 14) {
return "4";
}
else if (i == 19) {
return (Math.floor(Math.random() * 4) + 8).toString(16);
}
else {
return Math.floor(Math.random() * 15).toString(16);
}
}).join("");
}
var FetchMethod;
(function (FetchMethod) {
FetchMethod[FetchMethod["get"] = 0] = "get";
FetchMethod[FetchMethod["post"] = 1] = "post";
FetchMethod[FetchMethod["put"] = 2] = "put";
FetchMethod[FetchMethod["patch"] = 3] = "patch";
FetchMethod[FetchMethod["delete"] = 4] = "delete";
})(FetchMethod || (FetchMethod = {}));
function fetchMethodFromString(method) {
switch (method.toLowerCase()) {
case "get": return FetchMethod.get;
case "post": return FetchMethod.post;
case "put": return FetchMethod.put;
case "patch": return FetchMethod.patch;
case "delete": return FetchMethod.delete;
}
}
class FetchRequest {
constructor(delegate, method, location, body = new URLSearchParams) {
this.abortController = new AbortController;
this.delegate = delegate;
this.method = method;
if (this.isIdempotent) {
this.url = mergeFormDataEntries(location, [...body.entries()]);
}
else {
this.body = body;
this.url = location;
}
}
get location() {
return this.url;
}
get params() {
return this.url.searchParams;
}
get entries() {
return this.body ? Array.from(this.body.entries()) : [];
}
cancel() {
this.abortController.abort();
}
async perform() {
const { fetchOptions } = this;
dispatch("turbo:before-fetch-request", { detail: { fetchOptions } });
try {
this.delegate.requestStarted(this);
const response = await fetch(this.url.href, fetchOptions);
return await this.receive(response);
}
catch (error) {
this.delegate.requestErrored(this, error);
throw error;
}
finally {
this.delegate.requestFinished(this);
}
}
async receive(response) {
const fetchResponse = new FetchResponse(response);
const event = dispatch("turbo:before-fetch-response", { cancelable: true, detail: { fetchResponse } });
if (event.defaultPrevented) {
this.delegate.requestPreventedHandlingResponse(this, fetchResponse);
}
else if (fetchResponse.succeeded) {
this.delegate.requestSucceededWithResponse(this, fetchResponse);
}
else {
this.delegate.requestFailedWithResponse(this, fetchResponse);
}
return fetchResponse;
}
get fetchOptions() {
return {
method: FetchMethod[this.method].toUpperCase(),
credentials: "same-origin",
headers: this.headers,
redirect: "follow",
body: this.body,
signal: this.abortSignal
};
}
get isIdempotent() {
return this.method == FetchMethod.get;
}
get headers() {
const headers = Object.assign({}, this.defaultHeaders);
if (typeof this.delegate.prepareHeadersForRequest == "function") {
this.delegate.prepareHeadersForRequest(headers, this);
}
return headers;
}
get abortSignal() {
return this.abortController.signal;
}
get defaultHeaders() {
return {
"Accept": "text/html, application/xhtml+xml"
};
}
}
function mergeFormDataEntries(url, entries) {
const currentSearchParams = new URLSearchParams(url.search);
for (const [name, value] of entries) {
if (value instanceof File)
continue;
if (currentSearchParams.has(name)) {
currentSearchParams.delete(name);
url.searchParams.set(name, value);
}
else {
url.searchParams.append(name, value);
}
}
return url;
}
class AppearanceObserver {
constructor(delegate, element) {
this.started = false;
this.intersect = entries => {
const lastEntry = entries.slice(-1)[0];
if (lastEntry === null || lastEntry === void 0 ? void 0 : lastEntry.isIntersecting) {
this.delegate.elementAppearedInViewport(this.element);
}
};
this.delegate = delegate;
this.element = element;
this.intersectionObserver = new IntersectionObserver(this.intersect);
}
start() {
if (!this.started) {
this.started = true;
this.intersectionObserver.observe(this.element);
}
}
stop() {
if (this.started) {
this.started = false;
this.intersectionObserver.unobserve(this.element);
}
}
}
class StreamMessage {
constructor(html) {
this.templateElement = document.createElement("template");
this.templateElement.innerHTML = html;
}
static wrap(message) {
if (typeof message == "string") {
return new this(message);
}
else {
return message;
}
}
get fragment() {
const fragment = document.createDocumentFragment();
for (const element of this.foreignElements) {
fragment.appendChild(document.importNode(element, true));
}
return fragment;
}
get foreignElements() {
return this.templateChildren.reduce((streamElements, child) => {
if (child.tagName.toLowerCase() == "turbo-stream") {
return [...streamElements, child];
}
else {
return streamElements;
}
}, []);
}
get templateChildren() {
return Array.from(this.templateElement.content.children);
}
}
StreamMessage.contentType = "text/vnd.turbo-stream.html";
var FormSubmissionState;
(function (FormSubmissionState) {
FormSubmissionState[FormSubmissionState["initialized"] = 0] = "initialized";
FormSubmissionState[FormSubmissionState["requesting"] = 1] = "requesting";
FormSubmissionState[FormSubmissionState["waiting"] = 2] = "waiting";
FormSubmissionState[FormSubmissionState["receiving"] = 3] = "receiving";
FormSubmissionState[FormSubmissionState["stopping"] = 4] = "stopping";
FormSubmissionState[FormSubmissionState["stopped"] = 5] = "stopped";
})(FormSubmissionState || (FormSubmissionState = {}));
var FormEnctype;
(function (FormEnctype) {
FormEnctype["urlEncoded"] = "application/x-www-form-urlencoded";
FormEnctype["multipart"] = "multipart/form-data";
FormEnctype["plain"] = "text/plain";
})(FormEnctype || (FormEnctype = {}));
function formEnctypeFromString(encoding) {
switch (encoding.toLowerCase()) {
case FormEnctype.multipart: return FormEnctype.multipart;
case FormEnctype.plain: return FormEnctype.plain;
default: return FormEnctype.urlEncoded;
}
}
class FormSubmission {
constructor(delegate, formElement, submitter, mustRedirect = false) {
this.state = FormSubmissionState.initialized;
this.delegate = delegate;
this.formElement = formElement;
this.submitter = submitter;
this.formData = buildFormData(formElement, submitter);
this.fetchRequest = new FetchRequest(this, this.method, this.location, this.body);
this.mustRedirect = mustRedirect;
}
get method() {
var _a;
const method = ((_a = this.submitter) === null || _a === void 0 ? void 0 : _a.getAttribute("formmethod")) || this.formElement.getAttribute("method") || "";
return fetchMethodFromString(method.toLowerCase()) || FetchMethod.get;
}
get action() {
var _a;
return ((_a = this.submitter) === null || _a === void 0 ? void 0 : _a.getAttribute("formaction")) || this.formElement.action;
}
get location() {
return expandURL(this.action);
}
get body() {
if (this.enctype == FormEnctype.urlEncoded || this.method == FetchMethod.get) {
return new URLSearchParams(this.stringFormData);
}
else {
return this.formData;
}
}
get enctype() {
var _a;
return formEnctypeFromString(((_a = this.submitter) === null || _a === void 0 ? void 0 : _a.getAttribute("formenctype")) || this.formElement.enctype);
}
get stringFormData() {
return [...this.formData].reduce((entries, [name, value]) => {
return entries.concat(typeof value == "string" ? [[name, value]] : []);
}, []);
}
async start() {
const { initialized, requesting } = FormSubmissionState;
if (this.state == initialized) {
this.state = requesting;
return this.fetchRequest.perform();
}
}
stop() {
const { stopping, stopped } = FormSubmissionState;
if (this.state != stopping && this.state != stopped) {
this.state = stopping;
this.fetchRequest.cancel();
return true;
}
}
prepareHeadersForRequest(headers, request) {
if (!request.isIdempotent) {
const token = getCookieValue(getMetaContent("csrf-param")) || getMetaContent("csrf-token");
if (token) {
headers["X-CSRF-Token"] = token;
}
headers["Accept"] = [StreamMessage.contentType, headers["Accept"]].join(", ");
}
}
requestStarted(request) {
this.state = FormSubmissionState.waiting;
dispatch("turbo:submit-start", { target: this.formElement, detail: { formSubmission: this } });
this.delegate.formSubmissionStarted(this);
}
requestPreventedHandlingResponse(request, response) {
this.result = { success: response.succeeded, fetchResponse: response };
}
requestSucceededWithResponse(request, response) {
if (response.clientError || response.serverError) {
this.delegate.formSubmissionFailedWithResponse(this, response);
}
else if (this.requestMustRedirect(request) && responseSucceededWithoutRedirect(response)) {
const error = new Error("Form responses must redirect to another location");
this.delegate.formSubmissionErrored(this, error);
}
else {
this.state = FormSubmissionState.receiving;
this.result = { success: true, fetchResponse: response };
this.delegate.formSubmissionSucceededWithResponse(this, response);
}
}
requestFailedWithResponse(request, response) {
this.result = { success: false, fetchResponse: response };
this.delegate.formSubmissionFailedWithResponse(this, response);
}
requestErrored(request, error) {
this.result = { success: false, error };
this.delegate.formSubmissionErrored(this, error);
}
requestFinished(request) {
this.state = FormSubmissionState.stopped;
dispatch("turbo:submit-end", { target: this.formElement, detail: Object.assign({ formSubmission: this }, this.result) });
this.delegate.formSubmissionFinished(this);
}
requestMustRedirect(request) {
return !request.isIdempotent && this.mustRedirect;
}
}
function buildFormData(formElement, submitter) {
const formData = new FormData(formElement);
const name = submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("name");
const value = submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("value");
if (name && formData.get(name) != value) {
formData.append(name, value || "");
}
return formData;
}
function getCookieValue(cookieName) {
if (cookieName != null) {
const cookies = document.cookie ? document.cookie.split("; ") : [];
const cookie = cookies.find((cookie) => cookie.startsWith(cookieName));
if (cookie) {
const value = cookie.split("=").slice(1).join("=");
return value ? decodeURIComponent(value) : undefined;
}
}
}
function getMetaContent(name) {
const element = document.querySelector(`meta[name="${name}"]`);
return element && element.content;
}
function responseSucceededWithoutRedirect(response) {
return response.statusCode == 200 && !response.redirected;
}
class Snapshot {
constructor(element) {
this.element = element;
}
get children() {
return [...this.element.children];
}
hasAnchor(anchor) {
return this.getElementForAnchor(anchor) != null;
}
getElementForAnchor(anchor) {
try {
return this.element.querySelector(`[id='${anchor}'], a[name='${anchor}']`);
}
catch (_a) {
return null;
}
}
get firstAutofocusableElement() {
return this.element.querySelector("[autofocus]");
}
get permanentElements() {
return [...this.element.querySelectorAll("[id][data-turbo-permanent]")];
}
getPermanentElementById(id) {
return this.element.querySelector(`#${id}[data-turbo-permanent]`);
}
getPermanentElementsPresentInSnapshot(snapshot) {
return this.permanentElements.filter(({ id }) => snapshot.getPermanentElementById(id));
}
}
class FormInterceptor {
constructor(delegate, element) {
this.submitBubbled = ((event) => {
if (event.target instanceof HTMLFormElement) {
const form = event.target;
const submitter = event.submitter || undefined;
if (this.delegate.shouldInterceptFormSubmission(form, submitter)) {
event.preventDefault();
event.stopImmediatePropagation();
this.delegate.formSubmissionIntercepted(form, submitter);
}
}
});
this.delegate = delegate;
this.element = element;
}
start() {
this.element.addEventListener("submit", this.submitBubbled);
}
stop() {
this.element.removeEventListener("submit", this.submitBubbled);
}
}
class View {
constructor(delegate, element) {
this.delegate = delegate;
this.element = element;
}
scrollToAnchor(anchor) {
const element = this.snapshot.getElementForAnchor(anchor);
if (element) {
this.scrollToElement(element);
}
else {
this.scrollToPosition({ x: 0, y: 0 });
}
}
scrollToElement(element) {
element.scrollIntoView();
}
scrollToPosition({ x, y }) {
this.scrollRoot.scrollTo(x, y);
}
get scrollRoot() {
return window;
}
async render(renderer) {
if (this.renderer) {
throw new Error("rendering is already in progress");
}
const { isPreview, shouldRender, newSnapshot: snapshot } = renderer;
if (shouldRender) {
try {
this.renderer = renderer;
this.prepareToRenderSnapshot(renderer);
this.delegate.viewWillRenderSnapshot(snapshot, isPreview);
await this.renderSnapshot(renderer);
this.delegate.viewRenderedSnapshot(snapshot, isPreview);
this.finishRenderingSnapshot(renderer);
}
finally {
delete this.renderer;
}
}
else {
this.invalidate();
}
}
invalidate() {
this.delegate.viewInvalidated();
}
prepareToRenderSnapshot(renderer) {
this.markAsPreview(renderer.isPreview);
renderer.prepareToRender();
}
markAsPreview(isPreview) {
if (isPreview) {
this.element.setAttribute("data-turbo-preview", "");
}
else {
this.element.removeAttribute("data-turbo-preview");
}
}
async renderSnapshot(renderer) {
await renderer.render();
}
finishRenderingSnapshot(renderer) {
renderer.finishRendering();
}
}
class FrameView extends View {
invalidate() {
this.element.innerHTML = "";
}
get snapshot() {
return new Snapshot(this.element);
}
}
class LinkInterceptor {
constructor(delegate, element) {
this.clickBubbled = (event) => {
if (this.respondsToEventTarget(event.target)) {
this.clickEvent = event;
}
else {
delete this.clickEvent;
}
};
this.linkClicked = ((event) => {
if (this.clickEvent && this.respondsToEventTarget(event.target) && event.target instanceof Element) {
if (this.delegate.shouldInterceptLinkClick(event.target, event.detail.url)) {
this.clickEvent.preventDefault();
event.preventDefault();
this.delegate.linkClickIntercepted(event.target, event.detail.url);
}
}
delete this.clickEvent;
});
this.willVisit = () => {
delete this.clickEvent;
};
this.delegate = delegate;
this.element = element;
}
start() {
this.element.addEventListener("click", this.clickBubbled);
document.addEventListener("turbo:click", this.linkClicked);
document.addEventListener("turbo:before-visit", this.willVisit);
}
stop() {
this.element.removeEventListener("click", this.clickBubbled);
document.removeEventListener("turbo:click", this.linkClicked);
document.removeEventListener("turbo:before-visit", this.willVisit);
}
respondsToEventTarget(target) {
const element = target instanceof Element
? target
: target instanceof Node
? target.parentElement
: null;
return element && element.closest("turbo-frame, html") == this.element;
}
}
class Renderer {
constructor(currentSnapshot, newSnapshot, isPreview) {
this.currentSnapshot = currentSnapshot;
this.newSnapshot = newSnapshot;
this.isPreview = isPreview;
this.promise = new Promise((resolve, reject) => this.resolvingFunctions = { resolve, reject });
}
get shouldRender() {
return true;
}
prepareToRender() {
return;
}
finishRendering() {
if (this.resolvingFunctions) {
this.resolvingFunctions.resolve();
delete this.resolvingFunctions;
}
}
createScriptElement(element) {
if (element.getAttribute("data-turbo-eval") == "false") {
return element;
}
else {
const createdScriptElement = document.createElement("script");
createdScriptElement.textContent = element.textContent;
createdScriptElement.async = false;
copyElementAttributes(createdScriptElement, element);
return createdScriptElement;
}
}
preservingPermanentElements(callback) {
const placeholders = relocatePermanentElements(this.currentSnapshot, this.newSnapshot);
callback();
replacePlaceholderElementsWithClonedPermanentElements(placeholders);
}
focusFirstAutofocusableElement() {
const element = this.newSnapshot.firstAutofocusableElement;
if (elementIsFocusable(element)) {
element.focus();
}
}
get currentElement() {
return this.currentSnapshot.element;
}
get newElement() {
return this.newSnapshot.element;
}
}
function replaceElementWithElement(fromElement, toElement) {
const parentElement = fromElement.parentElement;
if (parentElement) {
return parentElement.replaceChild(toElement, fromElement);
}
}
function copyElementAttributes(destinationElement, sourceElement) {
for (const { name, value } of [...sourceElement.attributes]) {
destinationElement.setAttribute(name, value);
}
}
function createPlaceholderForPermanentElement(permanentElement) {
const element = document.createElement("meta");
element.setAttribute("name", "turbo-permanent-placeholder");
element.setAttribute("content", permanentElement.id);
return { element, permanentElement };
}
function replacePlaceholderElementsWithClonedPermanentElements(placeholders) {
for (const { element, permanentElement } of placeholders) {
const clonedElement = permanentElement.cloneNode(true);
replaceElementWithElement(element, clonedElement);
}
}
function relocatePermanentElements(currentSnapshot, newSnapshot) {
return currentSnapshot.getPermanentElementsPresentInSnapshot(newSnapshot).reduce((placeholders, permanentElement) => {
const newElement = newSnapshot.getPermanentElementById(permanentElement.id);
if (newElement) {
const placeholder = createPlaceholderForPermanentElement(permanentElement);
replaceElementWithElement(permanentElement, placeholder.element);
replaceElementWithElement(newElement, permanentElement);
return [...placeholders, placeholder];
}
else {
return placeholders;
}
}, []);
}
function elementIsFocusable(element) {
return element && typeof element.focus == "function";
}
class FrameRenderer extends Renderer {
get shouldRender() {
return true;
}
async render() {
await nextAnimationFrame();
this.preservingPermanentElements(() => {
this.loadFrameElement();
});
this.scrollFrameIntoView();
await nextAnimationFrame();
this.focusFirstAutofocusableElement();
}
loadFrameElement() {
var _a;
const destinationRange = document.createRange();
destinationRange.selectNodeContents(this.currentElement);
destinationRange.deleteContents();
const frameElement = this.newElement;
const sourceRange = (_a = frameElement.ownerDocument) === null || _a === void 0 ? void 0 : _a.createRange();
if (sourceRange) {
sourceRange.selectNodeContents(frameElement);
this.currentElement.appendChild(sourceRange.extractContents());
}
}
scrollFrameIntoView() {
if (this.currentElement.autoscroll || this.newElement.autoscroll) {
const element = this.currentElement.firstElementChild;
const block = readScrollLogicalPosition(this.currentElement.getAttribute("data-autoscroll-block"), "end");
if (element) {
element.scrollIntoView({ block });
return true;
}
}
return false;
}
}
function readScrollLogicalPosition(value, defaultValue) {
if (value == "end" || value == "start" || value == "center" || value == "nearest") {
return value;
}
else {
return defaultValue;
}
}
class FrameController {
constructor(element) {
this.resolveVisitPromise = () => { };
this.element = element;
this.view = new FrameView(this, this.element);
this.appearanceObserver = new AppearanceObserver(this, this.element);
this.linkInterceptor = new LinkInterceptor(this, this.element);
this.formInterceptor = new FormInterceptor(this, this.element);
}
connect() {
if (this.loadingStyle == FrameLoadingStyle.lazy) {
this.appearanceObserver.start();
}
this.linkInterceptor.start();
this.formInterceptor.start();
}
disconnect() {
this.appearanceObserver.stop();
this.linkInterceptor.stop();
this.formInterceptor.stop();
}
sourceURLChanged() {
if (this.loadingStyle == FrameLoadingStyle.eager) {
this.loadSourceURL();
}
}
loadingStyleChanged() {
if (this.loadingStyle == FrameLoadingStyle.lazy) {
this.appearanceObserver.start();
}
else {
this.appearanceObserver.stop();
this.loadSourceURL();
}
}
async loadSourceURL() {
if (this.isActive && this.sourceURL && this.sourceURL != this.loadingURL) {
try {
this.loadingURL = this.sourceURL;
this.element.loaded = this.visit(this.sourceURL);
this.appearanceObserver.stop();
await this.element.loaded;
}
finally {
delete this.loadingURL;
}
}
}
async loadResponse(response) {
try {
const html = await response.responseHTML;
if (html) {
const { body } = parseHTMLDocument(html);
const snapshot = new Snapshot(await this.extractForeignFrameElement(body));
const renderer = new FrameRenderer(this.view.snapshot, snapshot, false);
await this.view.render(renderer);
}
}
catch (error) {
console.error(error);
this.view.invalidate();
}
}
elementAppearedInViewport(element) {
this.loadSourceURL();
}
shouldInterceptLinkClick(element, url) {
return this.shouldInterceptNavigation(element);
}
linkClickIntercepted(element, url) {
this.navigateFrame(element, url);
}
shouldInterceptFormSubmission(element) {
return this.shouldInterceptNavigation(element);
}
formSubmissionIntercepted(element, submitter) {
if (this.formSubmission) {
this.formSubmission.stop();
}
this.formSubmission = new FormSubmission(this, element, submitter);
if (this.formSubmission.fetchRequest.isIdempotent) {
this.navigateFrame(element, this.formSubmission.fetchRequest.url.href);
}
else {
this.formSubmission.start();
}
}
prepareHeadersForRequest(headers, request) {
headers["Turbo-Frame"] = this.id;
}
requestStarted(request) {
this.element.setAttribute("busy", "");
}
requestPreventedHandlingResponse(request, response) {
this.resolveVisitPromise();
}
async requestSucceededWithResponse(request, response) {
await this.loadResponse(response);
this.resolveVisitPromise();
}
requestFailedWithResponse(request, response) {
console.error(response);
this.resolveVisitPromise();
}
requestErrored(request, error) {
console.error(error);
this.resolveVisitPromise();
}
requestFinished(request) {
this.element.removeAttribute("busy");
}
formSubmissionStarted(formSubmission) {
}
formSubmissionSucceededWithResponse(formSubmission, response) {
const frame = this.findFrameElement(formSubmission.formElement);
frame.delegate.loadResponse(response);
}
formSubmissionFailedWithResponse(formSubmission, fetchResponse) {
this.element.delegate.loadResponse(fetchResponse);
}
formSubmissionErrored(formSubmission, error) {
}
formSubmissionFinished(formSubmission) {
}
viewWillRenderSnapshot(snapshot, isPreview) {
}
viewRenderedSnapshot(snapshot, isPreview) {
}
viewInvalidated() {
}
async visit(url) {
const request = new FetchRequest(this, FetchMethod.get, expandURL(url));
return new Promise(resolve => {
this.resolveVisitPromise = () => {
this.resolveVisitPromise = () => { };
resolve();
};
request.perform();
});
}
navigateFrame(element, url) {
const frame = this.findFrameElement(element);
frame.src = url;
}
findFrameElement(element) {
var _a;
const id = element.getAttribute("data-turbo-frame") || this.element.getAttribute("target");
return (_a = getFrameElementById(id)) !== null && _a !== void 0 ? _a : this.element;
}
async extractForeignFrameElement(container) {
let element;
const id = CSS.escape(this.id);
if (element = activateElement(container.querySelector(`turbo-frame#${id}`))) {
return element;
}
if (element = activateElement(container.querySelector(`turbo-frame[src][recurse~=${id}]`))) {
await element.loaded;
return await this.extractForeignFrameElement(element);
}
console.error(`Response has no matching <turbo-frame id="${id}"> element`);
return new FrameElement();
}
shouldInterceptNavigation(element) {
const id = element.getAttribute("data-turbo-frame") || this.element.getAttribute("target");
if (!this.enabled || id == "_top") {
return false;
}
if (id) {
const frameElement = getFrameElementById(id);
if (frameElement) {
return !frameElement.disabled;
}
}
return true;
}
get id() {
return this.element.id;
}
get enabled() {
return !this.element.disabled;
}
get sourceURL() {
return this.element.src;
}
get loadingStyle() {
return this.element.loading;
}
get isLoading() {
return this.formSubmission !== undefined || this.loadingURL !== undefined;
}
get isActive() {
return this.element.isActive;
}
}
function getFrameElementById(id) {
if (id != null) {
const element = document.getElementById(id);
if (element instanceof FrameElement) {
return element;
}
}
}
function activateElement(element) {
if (element && element.ownerDocument !== document) {
element = document.importNode(element, true);
}
if (element instanceof FrameElement) {
return element;
}
}
const StreamActions = {
append() {
var _a;
(_a = this.targetElement) === null || _a === void 0 ? void 0 : _a.append(this.templateContent);
},
prepend() {
var _a;
(_a = this.targetElement) === null || _a === void 0 ? void 0 : _a.prepend(this.templateContent);
},
remove() {
var _a;
(_a = this.targetElement) === null || _a === void 0 ? void 0 : _a.remove();
},
replace() {
var _a;
(_a = this.targetElement) === null || _a === void 0 ? void 0 : _a.replaceWith(this.templateContent);
},
update() {
if (this.targetElement) {
this.targetElement.innerHTML = "";
this.targetElement.append(this.templateContent);
}
}
};
class StreamElement extends HTMLElement {
async connectedCallback() {
try {
await this.render();
}
catch (error) {
console.error(error);
}
finally {
this.disconnect();
}
}
async render() {
var _a;
return (_a = this.renderPromise) !== null && _a !== void 0 ? _a : (this.renderPromise = (async () => {
if (this.dispatchEvent(this.beforeRenderEvent)) {
await nextAnimationFrame();
this.performAction();
}
})());
}
disconnect() {
try {
this.remove();
}
catch (_a) { }
}
get performAction() {
if (this.action) {
const actionFunction = StreamActions[this.action];
if (actionFunction) {
return actionFunction;
}
this.raise("unknown action");
}
this.raise("action attribute is missing");
}
get targetElement() {
var _a;
if (this.target) {
return (_a = this.ownerDocument) === null || _a === void 0 ? void 0 : _a.getElementById(this.target);
}
this.raise("target attribute is missing");
}
get templateContent() {
return this.templateElement.content;
}
get templateElement() {
if (this.firstElementChild instanceof HTMLTemplateElement) {
return this.firstElementChild;
}
this.raise("first child element must be a <template> element");
}
get action() {
return this.getAttribute("action");
}
get target() {
return this.getAttribute("target");
}
raise(message) {
throw new Error(`${this.description}: ${message}`);
}
get description() {
var _a, _b;
return (_b = ((_a = this.outerHTML.match(/<[^>]+>/)) !== null && _a !== void 0 ? _a : [])[0]) !== null && _b !== void 0 ? _b : "<turbo-stream>";
}
get beforeRenderEvent() {
return new CustomEvent("turbo:before-stream-render", { bubbles: true, cancelable: true });
}
}
FrameElement.delegateConstructor = FrameController;
customElements.define("turbo-frame", FrameElement);
customElements.define("turbo-stream", StreamElement);
(() => {
let element = document.currentScript;
if (!element)
return;
if (element.hasAttribute("data-turbo-suppress-warning"))
return;
while (element = element.parentElement) {
if (element == document.body) {
return console.warn(unindent `
You are loading Turbo from a <script> element inside the <body> element. This is probably not what you meant to do!
Load your applications JavaScript bundle inside the <head> element instead. <script> elements in <body> are evaluated with each page change.
For more information, see: https://turbo.hotwire.dev/handbook/building#working-with-script-elements
——
Suppress this warning by adding a "data-turbo-suppress-warning" attribute to: %s
`, element.outerHTML);
}
}
})();
class ProgressBar {
constructor() {
this.hiding = false;
this.value = 0;
this.visible = false;
this.trickle = () => {
this.setValue(this.value + Math.random() / 100);
};
this.stylesheetElement = this.createStylesheetElement();
this.progressElement = this.createProgressElement();
this.installStylesheetElement();
this.setValue(0);
}
static get defaultCSS() {
return unindent `
.turbo-progress-bar {
position: fixed;
display: block;
top: 0;
left: 0;
height: 3px;
background: #0076ff;
z-index: 9999;
transition:
width ${ProgressBar.animationDuration}ms ease-out,
opacity ${ProgressBar.animationDuration / 2}ms ${ProgressBar.animationDuration / 2}ms ease-in;
transform: translate3d(0, 0, 0);
}
`;
}
show() {
if (!this.visible) {
this.visible = true;
this.installProgressElement();
this.startTrickling();
}
}
hide() {
if (this.visible && !this.hiding) {
this.hiding = true;
this.fadeProgressElement(() => {
this.uninstallProgressElement();
this.stopTrickling();
this.visible = false;
this.hiding = false;
});
}
}
setValue(value) {
this.value = value;
this.refresh();
}
installStylesheetElement() {
document.head.insertBefore(this.stylesheetElement, document.head.firstChild);
}
installProgressElement() {
this.progressElement.style.width = "0";
this.progressElement.style.opacity = "1";
document.documentElement.insertBefore(this.progressElement, document.body);
this.refresh();
}
fadeProgressElement(callback) {
this.progressElement.style.opacity = "0";
setTimeout(callback, ProgressBar.animationDuration * 1.5);
}
uninstallProgressElement() {
if (this.progressElement.parentNode) {
document.documentElement.removeChild(this.progressElement);
}
}
startTrickling() {
if (!this.trickleInterval) {
this.trickleInterval = window.setInterval(this.trickle, ProgressBar.animationDuration);
}
}
stopTrickling() {
window.clearInterval(this.trickleInterval);
delete this.trickleInterval;
}
refresh() {
requestAnimationFrame(() => {
this.progressElement.style.width = `${10 + (this.value * 90)}%`;
});
}
createStylesheetElement() {
const element = document.createElement("style");
element.type = "text/css";
element.textContent = ProgressBar.defaultCSS;
return element;
}
createProgressElement() {
const element = document.createElement("div");
element.className = "turbo-progress-bar";
return element;
}
}
ProgressBar.animationDuration = 300;
class HeadSnapshot extends Snapshot {
constructor() {
super(...arguments);
this.detailsByOuterHTML = this.children.reduce((result, element) => {
const { outerHTML } = element;
const details = outerHTML in result
? result[outerHTML]
: {
type: elementType(element),
tracked: elementIsTracked(element),
elements: []
};
return Object.assign(Object.assign({}, result), { [outerHTML]: Object.assign(Object.assign({}, details), { elements: [...details.elements, element] }) });
}, {});
}
get trackedElementSignature() {
return Object.keys(this.detailsByOuterHTML)
.filter(outerHTML => this.detailsByOuterHTML[outerHTML].tracked)
.join("");
}
getScriptElementsNotInSnapshot(snapshot) {
return this.getElementsMatchingTypeNotInSnapshot("script", snapshot);
}
getStylesheetElementsNotInSnapshot(snapshot) {
return this.getElementsMatchingTypeNotInSnapshot("stylesheet", snapshot);
}
getElementsMatchingTypeNotInSnapshot(matchedType, snapshot) {
return Object.keys(this.detailsByOuterHTML)
.filter(outerHTML => !(outerHTML in snapshot.detailsByOuterHTML))
.map(outerHTML => this.detailsByOuterHTML[outerHTML])
.filter(({ type }) => type == matchedType)
.map(({ elements: [element] }) => element);
}
get provisionalElements() {
return Object.keys(this.detailsByOuterHTML).reduce((result, outerHTML) => {
const { type, tracked, elements } = this.detailsByOuterHTML[outerHTML];
if (type == null && !tracked) {
return [...result, ...elements];
}
else if (elements.length > 1) {
return [...result, ...elements.slice(1)];
}
else {
return result;
}
}, []);
}
getMetaValue(name) {
const element = this.findMetaElementByName(name);
return element
? element.getAttribute("content")
: null;
}
findMetaElementByName(name) {
return Object.keys(this.detailsByOuterHTML).reduce((result, outerHTML) => {
const { elements: [element] } = this.detailsByOuterHTML[outerHTML];
return elementIsMetaElementWithName(element, name) ? element : result;
}, undefined);
}
}
function elementType(element) {
if (elementIsScript(element)) {
return "script";
}
else if (elementIsStylesheet(element)) {
return "stylesheet";
}
}
function elementIsTracked(element) {
return element.getAttribute("data-turbo-track") == "reload";
}
function elementIsScript(element) {
const tagName = element.tagName.toLowerCase();
return tagName == "script";
}
function elementIsStylesheet(element) {
const tagName = element.tagName.toLowerCase();
return tagName == "style" || (tagName == "link" && element.getAttribute("rel") == "stylesheet");
}
function elementIsMetaElementWithName(element, name) {
const tagName = element.tagName.toLowerCase();
return tagName == "meta" && element.getAttribute("name") == name;
}
class PageSnapshot extends Snapshot {
constructor(element, headSnapshot) {
super(element);
this.headSnapshot = headSnapshot;
}
static fromHTMLString(html = "") {
return this.fromDocument(parseHTMLDocument(html));
}
static fromElement(element) {
return this.fromDocument(element.ownerDocument);
}
static fromDocument({ head, body }) {
return new this(body, new HeadSnapshot(head));
}
clone() {
return new PageSnapshot(this.element.cloneNode(true), this.headSnapshot);
}
get headElement() {
return this.headSnapshot.element;
}
get rootLocation() {
var _a;
const root = (_a = this.getSetting("root")) !== null && _a !== void 0 ? _a : "/";
return expandURL(root);
}
get cacheControlValue() {
return this.getSetting("cache-control");
}
get isPreviewable() {
return this.cacheControlValue != "no-preview";
}
get isCacheable() {
return this.cacheControlValue != "no-cache";
}
get isVisitable() {
return this.getSetting("visit-control") != "reload";
}
getSetting(name) {
return this.headSnapshot.getMetaValue(`turbo-${name}`);
}
}
var TimingMetric;
(function (TimingMetric) {
TimingMetric["visitStart"] = "visitStart";
TimingMetric["requestStart"] = "requestStart";
TimingMetric["requestEnd"] = "requestEnd";
TimingMetric["visitEnd"] = "visitEnd";
})(TimingMetric || (TimingMetric = {}));
var VisitState;
(function (VisitState) {
VisitState["initialized"] = "initialized";
VisitState["started"] = "started";
VisitState["canceled"] = "canceled";
VisitState["failed"] = "failed";
VisitState["completed"] = "completed";
})(VisitState || (VisitState = {}));
const defaultOptions = {
action: "advance",
historyChanged: false
};
var SystemStatusCode;
(function (SystemStatusCode) {
SystemStatusCode[SystemStatusCode["networkFailure"] = 0] = "networkFailure";
SystemStatusCode[SystemStatusCode["timeoutFailure"] = -1] = "timeoutFailure";
SystemStatusCode[SystemStatusCode["contentTypeMismatch"] = -2] = "contentTypeMismatch";
})(SystemStatusCode || (SystemStatusCode = {}));
class Visit {
constructor(delegate, location, restorationIdentifier, options = {}) {
this.identifier = uuid();
this.timingMetrics = {};
this.followedRedirect = false;
this.historyChanged = false;
this.scrolled = false;
this.snapshotCached = false;
this.state = VisitState.initialized;
this.delegate = delegate;
this.location = location;
this.restorationIdentifier = restorationIdentifier || uuid();
const { action, historyChanged, referrer, snapshotHTML, response } = Object.assign(Object.assign({}, defaultOptions), options);
this.action = action;
this.historyChanged = historyChanged;
this.referrer = referrer;
this.snapshotHTML = snapshotHTML;
this.response = response;
}
get adapter() {
return this.delegate.adapter;
}
get view() {
return this.delegate.view;
}
get history() {
return this.delegate.history;
}
get restorationData() {
return this.history.getRestorationDataForIdentifier(this.restorationIdentifier);
}
start() {
if (this.state == VisitState.initialized) {
this.recordTimingMetric(TimingMetric.visitStart);
this.state = VisitState.started;
this.adapter.visitStarted(this);
this.delegate.visitStarted(this);
}
}
cancel() {
if (this.state == VisitState.started) {
if (this.request) {
this.request.cancel();
}
this.cancelRender();
this.state = VisitState.canceled;
}
}
complete() {
if (this.state == VisitState.started) {
this.recordTimingMetric(TimingMetric.visitEnd);
this.state = VisitState.completed;
this.adapter.visitCompleted(this);
this.delegate.visitCompleted(this);
}
}
fail() {
if (this.state == VisitState.started) {
this.state = VisitState.failed;
this.adapter.visitFailed(this);
}
}
changeHistory() {
var _a;
if (!this.historyChanged) {
const actionForHistory = this.location.href === ((_a = this.referrer) === null || _a === void 0 ? void 0 : _a.href) ? "replace" : this.action;
const method = this.getHistoryMethodForAction(actionForHistory);
this.history.update(method, this.location, this.restorationIdentifier);
this.historyChanged = true;
}
}
issueRequest() {
if (this.hasPreloadedResponse()) {
this.simulateRequest();
}
else if (this.shouldIssueRequest() && !this.request) {
this.request = new FetchRequest(this, FetchMethod.get, this.location);
this.request.perform();
}
}
simulateRequest() {
if (this.response) {
this.startRequest();
this.recordResponse();
this.finishRequest();
}
}
startRequest() {
this.recordTimingMetric(TimingMetric.requestStart);
this.adapter.visitRequestStarted(this);
}
recordResponse(response = this.response) {
this.response = response;
if (response) {
const { statusCode } = response;
if (isSuccessful(statusCode)) {
this.adapter.visitRequestCompleted(this);
}
else {
this.adapter.visitRequestFailedWithStatusCode(this, statusCode);
}
}
}
finishRequest() {
this.recordTimingMetric(TimingMetric.requestEnd);
this.adapter.visitRequestFinished(this);
}
loadResponse() {
if (this.response) {
const { statusCode, responseHTML } = this.response;
this.render(async () => {
this.cacheSnapshot();
if (isSuccessful(statusCode) && responseHTML != null) {
await this.view.renderPage(PageSnapshot.fromHTMLString(responseHTML));
this.adapter.visitRendered(this);
this.complete();
}
else {
await this.view.renderError(PageSnapshot.fromHTMLString(responseHTML));
this.adapter.visitRendered(this);
this.fail();
}
});
}
}
getCachedSnapshot() {
const snapshot = this.view.getCachedSnapshotForLocation(this.location) || this.getPreloadedSnapshot();
if (snapshot && (!getAnchor(this.location) || snapshot.hasAnchor(getAnchor(this.location)))) {
if (this.action == "restore" || snapshot.isPreviewable) {
return snapshot;
}
}
}
getPreloadedSnapshot() {
if (this.snapshotHTML) {
return PageSnapshot.fromHTMLString(this.snapshotHTML);
}
}
hasCachedSnapshot() {
return this.getCachedSnapshot() != null;
}
loadCachedSnapshot() {
const snapshot = this.getCachedSnapshot();
if (snapshot) {
const isPreview = this.shouldIssueRequest();
this.render(async () => {
this.cacheSnapshot();
await this.view.renderPage(snapshot);
this.adapter.visitRendered(this);
if (!isPreview) {
this.complete();
}
});
}
}
followRedirect() {
if (this.redirectedToLocation && !this.followedRedirect) {
this.location = this.redirectedToLocation;
this.history.replace(this.redirectedToLocation, this.restorationIdentifier);
this.followedRedirect = true;
}
}
requestStarted() {
this.startRequest();
}
requestPreventedHandlingResponse(request, response) {
}
async requestSucceededWithResponse(request, response) {
const responseHTML = await response.responseHTML;
if (responseHTML == undefined) {
this.recordResponse({ statusCode: SystemStatusCode.contentTypeMismatch });
}
else {
this.redirectedToLocation = response.redirected ? response.location : undefined;
this.recordResponse({ statusCode: response.statusCode, responseHTML });
}
}
async requestFailedWithResponse(request, response) {
const responseHTML = await response.responseHTML;
if (responseHTML == undefined) {
this.recordResponse({ statusCode: SystemStatusCode.contentTypeMismatch });
}
else {
this.recordResponse({ statusCode: response.statusCode, responseHTML });
}
}
requestErrored(request, error) {
this.recordResponse({ statusCode: SystemStatusCode.networkFailure });
}
requestFinished() {
this.finishRequest();
}
performScroll() {
if (!this.scrolled) {
if (this.action == "restore") {
this.scrollToRestoredPosition() || this.scrollToTop();
}
else {
this.scrollToAnchor() || this.scrollToTop();
}
this.scrolled = true;
}
}
scrollToRestoredPosition() {
const { scrollPosition } = this.restorationData;
if (scrollPosition) {
this.view.scrollToPosition(scrollPosition);
return true;
}
}
scrollToAnchor() {
if (getAnchor(this.location) != null) {
this.view.scrollToAnchor(getAnchor(this.location));
return true;
}
}
scrollToTop() {
this.view.scrollToPosition({ x: 0, y: 0 });
}
recordTimingMetric(metric) {
this.timingMetrics[metric] = new Date().getTime();
}
getTimingMetrics() {
return Object.assign({}, this.timingMetrics);
}
getHistoryMethodForAction(action) {
switch (action) {
case "replace": return history.replaceState;
case "advance":
case "restore": return history.pushState;
}
}
hasPreloadedResponse() {
return typeof this.response == "object";
}
shouldIssueRequest() {
return this.action == "restore"
? !this.hasCachedSnapshot()
: true;
}
cacheSnapshot() {
if (!this.snapshotCached) {
this.view.cacheSnapshot();
this.snapshotCached = true;
}
}
async render(callback) {
this.cancelRender();
await new Promise(resolve => {
this.frame = requestAnimationFrame(() => resolve());
});
callback();
delete this.frame;
this.performScroll();
}
cancelRender() {
if (this.frame) {
cancelAnimationFrame(this.frame);
delete this.frame;
}
}
}
function isSuccessful(statusCode) {
return statusCode >= 200 && statusCode < 300;
}
class BrowserAdapter {
constructor(session) {
this.progressBar = new ProgressBar;
this.showProgressBar = () => {
this.progressBar.show();
};
this.session = session;
}
visitProposedToLocation(location, options) {
this.navigator.startVisit(location, uuid(), options);
}
visitStarted(visit) {
visit.issueRequest();
visit.changeHistory();
visit.loadCachedSnapshot();
}
visitRequestStarted(visit) {
this.progressBar.setValue(0);
if (visit.hasCachedSnapshot() || visit.action != "restore") {
this.showProgressBarAfterDelay();
}
else {
this.showProgressBar();
}
}
visitRequestCompleted(visit) {
visit.loadResponse();
}
visitRequestFailedWithStatusCode(visit, statusCode) {
switch (statusCode) {
case SystemStatusCode.networkFailure:
case SystemStatusCode.timeoutFailure:
case SystemStatusCode.contentTypeMismatch:
return this.reload();
default:
return visit.loadResponse();
}
}
visitRequestFinished(visit) {
this.progressBar.setValue(1);
this.hideProgressBar();
}
visitCompleted(visit) {
visit.followRedirect();
}
pageInvalidated() {
this.reload();
}
visitFailed(visit) {
}
visitRendered(visit) {
}
showProgressBarAfterDelay() {
this.progressBarTimeout = window.setTimeout(this.showProgressBar, this.session.progressBarDelay);
}
hideProgressBar() {
this.progressBar.hide();
if (this.progressBarTimeout != null) {
window.clearTimeout(this.progressBarTimeout);
delete this.progressBarTimeout;
}
}
reload() {
window.location.reload();
}
get navigator() {
return this.session.navigator;
}
}
class FormSubmitObserver {
constructor(delegate) {
this.started = false;
this.submitCaptured = () => {
removeEventListener("submit", this.submitBubbled, false);
addEventListener("submit", this.submitBubbled, false);
};
this.submitBubbled = ((event) => {
if (!event.defaultPrevented) {
const form = event.target instanceof HTMLFormElement ? event.target : undefined;
const submitter = event.submitter || undefined;
if (form) {
const method = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("formmethod")) || form.method;
if (method != "dialog" && this.delegate.willSubmitForm(form, submitter)) {
event.preventDefault();
this.delegate.formSubmitted(form, submitter);
}
}
}
});
this.delegate = delegate;
}
start() {
if (!this.started) {
addEventListener("submit", this.submitCaptured, true);
this.started = true;
}
}
stop() {
if (this.started) {
removeEventListener("submit", this.submitCaptured, true);
this.started = false;
}
}
}
class FrameRedirector {
constructor(element) {
this.element = element;
this.linkInterceptor = new LinkInterceptor(this, element);
this.formInterceptor = new FormInterceptor(this, element);
}
start() {
this.linkInterceptor.start();
this.formInterceptor.start();
}
stop() {
this.linkInterceptor.stop();
this.formInterceptor.stop();
}
shouldInterceptLinkClick(element, url) {
return this.shouldRedirect(element);
}
linkClickIntercepted(element, url) {
const frame = this.findFrameElement(element);
if (frame) {
frame.src = url;
}
}
shouldInterceptFormSubmission(element, submitter) {
return this.shouldRedirect(element, submitter);
}
formSubmissionIntercepted(element, submitter) {
const frame = this.findFrameElement(element);
if (frame) {
frame.delegate.formSubmissionIntercepted(element, submitter);
}
}
shouldRedirect(element, submitter) {
const frame = this.findFrameElement(element);
return frame ? frame != element.closest("turbo-frame") : false;
}
findFrameElement(element) {
const id = element.getAttribute("data-turbo-frame");
if (id && id != "_top") {
const frame = this.element.querySelector(`#${id}:not([disabled])`);
if (frame instanceof FrameElement) {
return frame;
}
}
}
}
class History {
constructor(delegate) {
this.restorationIdentifier = uuid();
this.restorationData = {};
this.started = false;
this.pageLoaded = false;
this.onPopState = (event) => {
if (this.shouldHandlePopState()) {
const { turbo } = event.state || {};
if (turbo) {
this.location = new URL(window.location.href);
const { restorationIdentifier } = turbo;
this.restorationIdentifier = restorationIdentifier;
this.delegate.historyPoppedToLocationWithRestorationIdentifier(this.location, restorationIdentifier);
}
}
};
this.onPageLoad = async (event) => {
await nextMicrotask();
this.pageLoaded = true;
};
this.delegate = delegate;
}
start() {
if (!this.started) {
addEventListener("popstate", this.onPopState, false);
addEventListener("load", this.onPageLoad, false);
this.started = true;
this.replace(new URL(window.location.href));
}
}
stop() {
if (this.started) {
removeEventListener("popstate", this.onPopState, false);
removeEventListener("load", this.onPageLoad, false);
this.started = false;
}
}
push(location, restorationIdentifier) {
this.update(history.pushState, location, restorationIdentifier);
}
replace(location, restorationIdentifier) {
this.update(history.replaceState, location, restorationIdentifier);
}
update(method, location, restorationIdentifier = uuid()) {
const state = { turbo: { restorationIdentifier } };
method.call(history, state, "", location.href);
this.location = location;
this.restorationIdentifier = restorationIdentifier;
}
getRestorationDataForIdentifier(restorationIdentifier) {
return this.restorationData[restorationIdentifier] || {};
}
updateRestorationData(additionalData) {
const { restorationIdentifier } = this;
const restorationData = this.restorationData[restorationIdentifier];
this.restorationData[restorationIdentifier] = Object.assign(Object.assign({}, restorationData), additionalData);
}
assumeControlOfScrollRestoration() {
var _a;
if (!this.previousScrollRestoration) {
this.previousScrollRestoration = (_a = history.scrollRestoration) !== null && _a !== void 0 ? _a : "auto";
history.scrollRestoration = "manual";
}
}
relinquishControlOfScrollRestoration() {
if (this.previousScrollRestoration) {
history.scrollRestoration = this.previousScrollRestoration;
delete this.previousScrollRestoration;
}
}
shouldHandlePopState() {
return this.pageIsLoaded();
}
pageIsLoaded() {
return this.pageLoaded || document.readyState == "complete";
}
}
class LinkClickObserver {
constructor(delegate) {
this.started = false;
this.clickCaptured = () => {
removeEventListener("click", this.clickBubbled, false);
addEventListener("click", this.clickBubbled, false);
};
this.clickBubbled = (event) => {
if (this.clickEventIsSignificant(event)) {
const link = this.findLinkFromClickTarget(event.target);
if (link) {
const location = this.getLocationForLink(link);
if (this.delegate.willFollowLinkToLocation(link, location)) {
event.preventDefault();
this.delegate.followedLinkToLocation(link, location);
}
}
}
};
this.delegate = delegate;
}
start() {
if (!this.started) {
addEventListener("click", this.clickCaptured, true);
this.started = true;
}
}
stop() {
if (this.started) {
removeEventListener("click", this.clickCaptured, true);
this.started = false;
}
}
clickEventIsSignificant(event) {
return !((event.target && event.target.isContentEditable)
|| event.defaultPrevented
|| event.which > 1
|| event.altKey
|| event.ctrlKey
|| event.metaKey
|| event.shiftKey);
}
findLinkFromClickTarget(target) {
if (target instanceof Element) {
return target.closest("a[href]:not([target^=_]):not([download])");
}
}
getLocationForLink(link) {
return expandURL(link.getAttribute("href") || "");
}
}
class Navigator {
constructor(delegate) {
this.delegate = delegate;
}
proposeVisit(location, options = {}) {
if (this.delegate.allowsVisitingLocation(location)) {
this.delegate.visitProposedToLocation(location, options);
}
}
startVisit(locatable, restorationIdentifier, options = {}) {
this.stop();
this.currentVisit = new Visit(this, expandURL(locatable), restorationIdentifier, Object.assign({ referrer: this.location }, options));
this.currentVisit.start();
}
submitForm(form, submitter) {
this.stop();
this.formSubmission = new FormSubmission(this, form, submitter, true);
if (this.formSubmission.fetchRequest.isIdempotent) {
this.proposeVisit(this.formSubmission.fetchRequest.url);
}
else {
this.formSubmission.start();
}
}
stop() {
if (this.formSubmission) {
this.formSubmission.stop();
delete this.formSubmission;
}
if (this.currentVisit) {
this.currentVisit.cancel();
delete this.currentVisit;
}
}
get adapter() {
return this.delegate.adapter;
}
get view() {
return this.delegate.view;
}
get history() {
return this.delegate.history;
}
formSubmissionStarted(formSubmission) {
}
async formSubmissionSucceededWithResponse(formSubmission, fetchResponse) {
if (formSubmission == this.formSubmission) {
const responseHTML = await fetchResponse.responseHTML;
if (responseHTML) {
if (formSubmission.method != FetchMethod.get) {
this.view.clearSnapshotCache();
}
const { statusCode } = fetchResponse;
const visitOptions = { response: { statusCode, responseHTML } };
this.proposeVisit(fetchResponse.location, visitOptions);
}
}
}
async formSubmissionFailedWithResponse(formSubmission, fetchResponse) {
const responseHTML = await fetchResponse.responseHTML;
if (responseHTML) {
const snapshot = PageSnapshot.fromHTMLString(responseHTML);
await this.view.renderPage(snapshot);
this.view.clearSnapshotCache();
}
}
formSubmissionErrored(formSubmission, error) {
}
formSubmissionFinished(formSubmission) {
}
visitStarted(visit) {
this.delegate.visitStarted(visit);
}
visitCompleted(visit) {
this.delegate.visitCompleted(visit);
}
get location() {
return this.history.location;
}
get restorationIdentifier() {
return this.history.restorationIdentifier;
}
}
var PageStage;
(function (PageStage) {
PageStage[PageStage["initial"] = 0] = "initial";
PageStage[PageStage["loading"] = 1] = "loading";
PageStage[PageStage["interactive"] = 2] = "interactive";
PageStage[PageStage["complete"] = 3] = "complete";
})(PageStage || (PageStage = {}));
class PageObserver {
constructor(delegate) {
this.stage = PageStage.initial;
this.started = false;
this.interpretReadyState = () => {
const { readyState } = this;
if (readyState == "interactive") {
this.pageIsInteractive();
}
else if (readyState == "complete") {
this.pageIsComplete();
}
};
this.pageWillUnload = () => {
this.delegate.pageWillUnload();
};
this.delegate = delegate;
}
start() {
if (!this.started) {
if (this.stage == PageStage.initial) {
this.stage = PageStage.loading;
}
document.addEventListener("readystatechange", this.interpretReadyState, false);
addEventListener("pagehide", this.pageWillUnload, false);
this.started = true;
}
}
stop() {
if (this.started) {
document.removeEventListener("readystatechange", this.interpretReadyState, false);
removeEventListener("pagehide", this.pageWillUnload, false);
this.started = false;
}
}
pageIsInteractive() {
if (this.stage == PageStage.loading) {
this.stage = PageStage.interactive;
this.delegate.pageBecameInteractive();
}
}
pageIsComplete() {
this.pageIsInteractive();
if (this.stage == PageStage.interactive) {
this.stage = PageStage.complete;
this.delegate.pageLoaded();
}
}
get readyState() {
return document.readyState;
}
}
class ScrollObserver {
constructor(delegate) {
this.started = false;
this.onScroll = () => {
this.updatePosition({ x: window.pageXOffset, y: window.pageYOffset });
};
this.delegate = delegate;
}
start() {
if (!this.started) {
addEventListener("scroll", this.onScroll, false);
this.onScroll();
this.started = true;
}
}
stop() {
if (this.started) {
removeEventListener("scroll", this.onScroll, false);
this.started = false;
}
}
updatePosition(position) {
this.delegate.scrollPositionChanged(position);
}
}
class StreamObserver {
constructor(delegate) {
this.sources = new Set;
this.started = false;
this.inspectFetchResponse = ((event) => {
const response = fetchResponseFromEvent(event);
if (response && fetchResponseIsStream(response)) {
event.preventDefault();
this.receiveMessageResponse(response);
}
});
this.receiveMessageEvent = (event) => {
if (this.started && typeof event.data == "string") {
this.receiveMessageHTML(event.data);
}
};
this.delegate = delegate;
}
start() {
if (!this.started) {
this.started = true;
addEventListener("turbo:before-fetch-response", this.inspectFetchResponse, false);
}
}
stop() {
if (this.started) {
this.started = false;
removeEventListener("turbo:before-fetch-response", this.inspectFetchResponse, false);
}
}
connectStreamSource(source) {
if (!this.streamSourceIsConnected(source)) {
this.sources.add(source);
source.addEventListener("message", this.receiveMessageEvent, false);
}
}
disconnectStreamSource(source) {
if (this.streamSourceIsConnected(source)) {
this.sources.delete(source);
source.removeEventListener("message", this.receiveMessageEvent, false);
}
}
streamSourceIsConnected(source) {
return this.sources.has(source);
}
async receiveMessageResponse(response) {
const html = await response.responseHTML;
if (html) {
this.receiveMessageHTML(html);
}
}
receiveMessageHTML(html) {
this.delegate.receivedMessageFromStream(new StreamMessage(html));
}
}
function fetchResponseFromEvent(event) {
var _a;
const fetchResponse = (_a = event.detail) === null || _a === void 0 ? void 0 : _a.fetchResponse;
if (fetchResponse instanceof FetchResponse) {
return fetchResponse;
}
}
function fetchResponseIsStream(response) {
var _a;
const contentType = (_a = response.contentType) !== null && _a !== void 0 ? _a : "";
return contentType.startsWith(StreamMessage.contentType);
}
function isAction(action) {
return action == "advance" || action == "replace" || action == "restore";
}
class ErrorRenderer extends Renderer {
async render() {
this.replaceHeadAndBody();
this.activateScriptElements();
}
replaceHeadAndBody() {
const { documentElement, head, body } = document;
documentElement.replaceChild(this.newHead, head);
documentElement.replaceChild(this.newElement, body);
}
activateScriptElements() {
for (const replaceableElement of this.scriptElements) {
const parentNode = replaceableElement.parentNode;
if (parentNode) {
const element = this.createScriptElement(replaceableElement);
parentNode.replaceChild(element, replaceableElement);
}
}
}
get newHead() {
return this.newSnapshot.headSnapshot.element;
}
get scriptElements() {
return [...document.documentElement.querySelectorAll("script")];
}
}
class PageRenderer extends Renderer {
get shouldRender() {
return this.newSnapshot.isVisitable && this.trackedElementsAreIdentical;
}
prepareToRender() {
this.mergeHead();
}
async render() {
this.replaceBody();
}
finishRendering() {
super.finishRendering();
if (this.isPreview) {
this.focusFirstAutofocusableElement();
}
}
get currentHeadSnapshot() {
return this.currentSnapshot.headSnapshot;
}
get newHeadSnapshot() {
return this.newSnapshot.headSnapshot;
}
get newElement() {
return this.newSnapshot.element;
}
mergeHead() {
this.copyNewHeadStylesheetElements();
this.copyNewHeadScriptElements();
this.removeCurrentHeadProvisionalElements();
this.copyNewHeadProvisionalElements();
}
replaceBody() {
this.preservingPermanentElements(() => {
this.activateNewBody();
this.assignNewBody();
});
}
get trackedElementsAreIdentical() {
return this.currentHeadSnapshot.trackedElementSignature == this.newHeadSnapshot.trackedElementSignature;
}
copyNewHeadStylesheetElements() {
for (const element of this.newHeadStylesheetElements) {
document.head.appendChild(element);
}
}
copyNewHeadScriptElements() {
for (const element of this.newHeadScriptElements) {
document.head.appendChild(this.createScriptElement(element));
}
}
removeCurrentHeadProvisionalElements() {
for (const element of this.currentHeadProvisionalElements) {
document.head.removeChild(element);
}
}
copyNewHeadProvisionalElements() {
for (const element of this.newHeadProvisionalElements) {
document.head.appendChild(element);
}
}
activateNewBody() {
document.adoptNode(this.newElement);
this.activateNewBodyScriptElements();
}
activateNewBodyScriptElements() {
for (const inertScriptElement of this.newBodyScriptElements) {
const activatedScriptElement = this.createScriptElement(inertScriptElement);
replaceElementWithElement(inertScriptElement, activatedScriptElement);
}
}
assignNewBody() {
if (document.body && this.newElement instanceof HTMLBodyElement) {
replaceElementWithElement(document.body, this.newElement);
}
else {
document.documentElement.appendChild(this.newElement);
}
}
get newHeadStylesheetElements() {
return this.newHeadSnapshot.getStylesheetElementsNotInSnapshot(this.currentHeadSnapshot);
}
get newHeadScriptElements() {
return this.newHeadSnapshot.getScriptElementsNotInSnapshot(this.currentHeadSnapshot);
}
get currentHeadProvisionalElements() {
return this.currentHeadSnapshot.provisionalElements;
}
get newHeadProvisionalElements() {
return this.newHeadSnapshot.provisionalElements;
}
get newBodyScriptElements() {
return [...this.newElement.querySelectorAll("script")];
}
}
class SnapshotCache {
constructor(size) {
this.keys = [];
this.snapshots = {};
this.size = size;
}
has(location) {
return toCacheKey(location) in this.snapshots;
}
get(location) {
if (this.has(location)) {
const snapshot = this.read(location);
this.touch(location);
return snapshot;
}
}
put(location, snapshot) {
this.write(location, snapshot);
this.touch(location);
return snapshot;
}
clear() {
this.snapshots = {};
}
read(location) {
return this.snapshots[toCacheKey(location)];
}
write(location, snapshot) {
this.snapshots[toCacheKey(location)] = snapshot;
}
touch(location) {
const key = toCacheKey(location);
const index = this.keys.indexOf(key);
if (index > -1)
this.keys.splice(index, 1);
this.keys.unshift(key);
this.trim();
}
trim() {
for (const key of this.keys.splice(this.size)) {
delete this.snapshots[key];
}
}
}
class PageView extends View {
constructor() {
super(...arguments);
this.snapshotCache = new SnapshotCache(10);
this.lastRenderedLocation = new URL(location.href);
}
renderPage(snapshot, isPreview = false) {
const renderer = new PageRenderer(this.snapshot, snapshot, isPreview);
return this.render(renderer);
}
renderError(snapshot) {
const renderer = new ErrorRenderer(this.snapshot, snapshot, false);
this.render(renderer);
}
clearSnapshotCache() {
this.snapshotCache.clear();
}
async cacheSnapshot() {
if (this.shouldCacheSnapshot) {
this.delegate.viewWillCacheSnapshot();
const { snapshot, lastRenderedLocation: location } = this;
await nextEventLoopTick();
this.snapshotCache.put(location, snapshot.clone());
}
}
getCachedSnapshotForLocation(location) {
return this.snapshotCache.get(location);
}
get snapshot() {
return PageSnapshot.fromElement(this.element);
}
get shouldCacheSnapshot() {
return this.snapshot.isCacheable;
}
}
class Session {
constructor() {
this.navigator = new Navigator(this);
this.history = new History(this);
this.view = new PageView(this, document.documentElement);
this.adapter = new BrowserAdapter(this);
this.pageObserver = new PageObserver(this);
this.linkClickObserver = new LinkClickObserver(this);
this.formSubmitObserver = new FormSubmitObserver(this);
this.scrollObserver = new ScrollObserver(this);
this.streamObserver = new StreamObserver(this);
this.frameRedirector = new FrameRedirector(document.documentElement);
this.enabled = true;
this.progressBarDelay = 500;
this.started = false;
}
start() {
if (!this.started) {
this.pageObserver.start();
this.linkClickObserver.start();
this.formSubmitObserver.start();
this.scrollObserver.start();
this.streamObserver.start();
this.frameRedirector.start();
this.history.start();
this.started = true;
this.enabled = true;
}
}
disable() {
this.enabled = false;
}
stop() {
if (this.started) {
this.pageObserver.stop();
this.linkClickObserver.stop();
this.formSubmitObserver.stop();
this.scrollObserver.stop();
this.streamObserver.stop();
this.frameRedirector.stop();
this.history.stop();
this.started = false;
}
}
registerAdapter(adapter) {
this.adapter = adapter;
}
visit(location, options = {}) {
this.navigator.proposeVisit(expandURL(location), options);
}
connectStreamSource(source) {
this.streamObserver.connectStreamSource(source);
}
disconnectStreamSource(source) {
this.streamObserver.disconnectStreamSource(source);
}
renderStreamMessage(message) {
document.documentElement.appendChild(StreamMessage.wrap(message).fragment);
}
clearCache() {
this.view.clearSnapshotCache();
}
setProgressBarDelay(delay) {
this.progressBarDelay = delay;
}
get location() {
return this.history.location;
}
get restorationIdentifier() {
return this.history.restorationIdentifier;
}
historyPoppedToLocationWithRestorationIdentifier(location) {
if (this.enabled) {
this.navigator.proposeVisit(location, { action: "restore", historyChanged: true });
}
else {
this.adapter.pageInvalidated();
}
}
scrollPositionChanged(position) {
this.history.updateRestorationData({ scrollPosition: position });
}
willFollowLinkToLocation(link, location) {
return this.elementIsNavigable(link)
&& this.locationIsVisitable(location)
&& this.applicationAllowsFollowingLinkToLocation(link, location);
}
followedLinkToLocation(link, location) {
const action = this.getActionForLink(link);
this.visit(location.href, { action });
}
allowsVisitingLocation(location) {
return this.applicationAllowsVisitingLocation(location);
}
visitProposedToLocation(location, options) {
extendURLWithDeprecatedProperties(location);
this.adapter.visitProposedToLocation(location, options);
}
visitStarted(visit) {
extendURLWithDeprecatedProperties(visit.location);
this.notifyApplicationAfterVisitingLocation(visit.location);
}
visitCompleted(visit) {
this.notifyApplicationAfterPageLoad(visit.getTimingMetrics());
}
willSubmitForm(form, submitter) {
return this.elementIsNavigable(form) && this.elementIsNavigable(submitter);
}
formSubmitted(form, submitter) {
this.navigator.submitForm(form, submitter);
}
pageBecameInteractive() {
this.view.lastRenderedLocation = this.location;
this.notifyApplicationAfterPageLoad();
}
pageLoaded() {
this.history.assumeControlOfScrollRestoration();
}
pageWillUnload() {
this.history.relinquishControlOfScrollRestoration();
}
receivedMessageFromStream(message) {
this.renderStreamMessage(message);
}
viewWillCacheSnapshot() {
this.notifyApplicationBeforeCachingSnapshot();
}
viewWillRenderSnapshot({ element }, isPreview) {
this.notifyApplicationBeforeRender(element);
}
viewRenderedSnapshot(snapshot, isPreview) {
this.view.lastRenderedLocation = this.history.location;
this.notifyApplicationAfterRender();
}
viewInvalidated() {
this.adapter.pageInvalidated();
}
applicationAllowsFollowingLinkToLocation(link, location) {
const event = this.notifyApplicationAfterClickingLinkToLocation(link, location);
return !event.defaultPrevented;
}
applicationAllowsVisitingLocation(location) {
const event = this.notifyApplicationBeforeVisitingLocation(location);
return !event.defaultPrevented;
}
notifyApplicationAfterClickingLinkToLocation(link, location) {
return dispatch("turbo:click", { target: link, detail: { url: location.href }, cancelable: true });
}
notifyApplicationBeforeVisitingLocation(location) {
return dispatch("turbo:before-visit", { detail: { url: location.href }, cancelable: true });
}
notifyApplicationAfterVisitingLocation(location) {
return dispatch("turbo:visit", { detail: { url: location.href } });
}
notifyApplicationBeforeCachingSnapshot() {
return dispatch("turbo:before-cache");
}
notifyApplicationBeforeRender(newBody) {
return dispatch("turbo:before-render", { detail: { newBody } });
}
notifyApplicationAfterRender() {
return dispatch("turbo:render");
}
notifyApplicationAfterPageLoad(timing = {}) {
return dispatch("turbo:load", { detail: { url: this.location.href, timing } });
}
getActionForLink(link) {
const action = link.getAttribute("data-turbo-action");
return isAction(action) ? action : "advance";
}
elementIsNavigable(element) {
const container = element === null || element === void 0 ? void 0 : element.closest("[data-turbo]");
if (container) {
return container.getAttribute("data-turbo") != "false";
}
else {
return true;
}
}
locationIsVisitable(location) {
return isPrefixedBy(location, this.snapshot.rootLocation) && isHTML(location);
}
get snapshot() {
return this.view.snapshot;
}
}
function extendURLWithDeprecatedProperties(url) {
Object.defineProperties(url, deprecatedLocationPropertyDescriptors);
}
const deprecatedLocationPropertyDescriptors = {
absoluteURL: {
get() {
return this.toString();
}
}
};
const session = new Session;
const { navigator } = session;
function start() {
session.start();
}
function registerAdapter(adapter) {
session.registerAdapter(adapter);
}
function visit(location, options) {
session.visit(location, options);
}
function connectStreamSource(source) {
session.connectStreamSource(source);
}
function disconnectStreamSource(source) {
session.disconnectStreamSource(source);
}
function renderStreamMessage(message) {
session.renderStreamMessage(message);
}
function clearCache() {
session.clearCache();
}
function setProgressBarDelay(delay) {
session.setProgressBarDelay(delay);
}
start();
//# sourceMappingURL=turbo.es2017-esm.js.map
/***/ }),
/***/ "./node_modules/alpinejs/dist/alpine.js":
/*!**********************************************!*\
!*** ./node_modules/alpinejs/dist/alpine.js ***!
\**********************************************/
/***/ (function(module) {
(function (global, factory) {
true ? module.exports = factory() :
0;
}(this, (function () { 'use strict';
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function ownKeys(object, enumerableOnly) {
var keys = Object.keys(object);
if (Object.getOwnPropertySymbols) {
var symbols = Object.getOwnPropertySymbols(object);
if (enumerableOnly) symbols = symbols.filter(function (sym) {
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
});
keys.push.apply(keys, symbols);
}
return keys;
}
function _objectSpread2(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i] != null ? arguments[i] : {};
if (i % 2) {
ownKeys(Object(source), true).forEach(function (key) {
_defineProperty(target, key, source[key]);
});
} else if (Object.getOwnPropertyDescriptors) {
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
} else {
ownKeys(Object(source)).forEach(function (key) {
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
});
}
}
return target;
}
// Thanks @stimulus:
// https://github.com/stimulusjs/stimulus/blob/master/packages/%40stimulus/core/src/application.ts
function domReady() {
return new Promise(resolve => {
if (document.readyState == "loading") {
document.addEventListener("DOMContentLoaded", resolve);
} else {
resolve();
}
});
}
function arrayUnique(array) {
return Array.from(new Set(array));
}
function isTesting() {
return navigator.userAgent.includes("Node.js") || navigator.userAgent.includes("jsdom");
}
function checkedAttrLooseCompare(valueA, valueB) {
return valueA == valueB;
}
function warnIfMalformedTemplate(el, directive) {
if (el.tagName.toLowerCase() !== 'template') {
console.warn(`Alpine: [${directive}] directive should only be added to <template> tags. See https://github.com/alpinejs/alpine#${directive}`);
} else if (el.content.childElementCount !== 1) {
console.warn(`Alpine: <template> tag with [${directive}] encountered with an unexpected number of root elements. Make sure <template> has a single root element. `);
}
}
function kebabCase(subject) {
return subject.replace(/([a-z])([A-Z])/g, '$1-$2').replace(/[_\s]/, '-').toLowerCase();
}
function camelCase(subject) {
return subject.toLowerCase().replace(/-(\w)/g, (match, char) => char.toUpperCase());
}
function walk(el, callback) {
if (callback(el) === false) return;
let node = el.firstElementChild;
while (node) {
walk(node, callback);
node = node.nextElementSibling;
}
}
function debounce(func, wait) {
var timeout;
return function () {
var context = this,
args = arguments;
var later = function later() {
timeout = null;
func.apply(context, args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
const handleError = (el, expression, error) => {
console.warn(`Alpine Error: "${error}"\n\nExpression: "${expression}"\nElement:`, el);
if (!isTesting()) {
Object.assign(error, {
el,
expression
});
throw error;
}
};
function tryCatch(cb, {
el,
expression
}) {
try {
const value = cb();
return value instanceof Promise ? value.catch(e => handleError(el, expression, e)) : value;
} catch (e) {
handleError(el, expression, e);
}
}
function saferEval(el, expression, dataContext, additionalHelperVariables = {}) {
return tryCatch(() => {
if (typeof expression === 'function') {
return expression.call(dataContext);
}
return new Function(['$data', ...Object.keys(additionalHelperVariables)], `var __alpine_result; with($data) { __alpine_result = ${expression} }; return __alpine_result`)(dataContext, ...Object.values(additionalHelperVariables));
}, {
el,
expression
});
}
function saferEvalNoReturn(el, expression, dataContext, additionalHelperVariables = {}) {
return tryCatch(() => {
if (typeof expression === 'function') {
return Promise.resolve(expression.call(dataContext, additionalHelperVariables['$event']));
}
let AsyncFunction = Function;
/* MODERN-ONLY:START */
AsyncFunction = Object.getPrototypeOf(async function () {}).constructor;
/* MODERN-ONLY:END */
// For the cases when users pass only a function reference to the caller: `x-on:click="foo"`
// Where "foo" is a function. Also, we'll pass the function the event instance when we call it.
if (Object.keys(dataContext).includes(expression)) {
let methodReference = new Function(['dataContext', ...Object.keys(additionalHelperVariables)], `with(dataContext) { return ${expression} }`)(dataContext, ...Object.values(additionalHelperVariables));
if (typeof methodReference === 'function') {
return Promise.resolve(methodReference.call(dataContext, additionalHelperVariables['$event']));
} else {
return Promise.resolve();
}
}
return Promise.resolve(new AsyncFunction(['dataContext', ...Object.keys(additionalHelperVariables)], `with(dataContext) { ${expression} }`)(dataContext, ...Object.values(additionalHelperVariables)));
}, {
el,
expression
});
}
const xAttrRE = /^x-(on|bind|data|text|html|model|if|for|show|cloak|transition|ref|spread)\b/;
function isXAttr(attr) {
const name = replaceAtAndColonWithStandardSyntax(attr.name);
return xAttrRE.test(name);
}
function getXAttrs(el, component, type) {
let directives = Array.from(el.attributes).filter(isXAttr).map(parseHtmlAttribute); // Get an object of directives from x-spread.
let spreadDirective = directives.filter(directive => directive.type === 'spread')[0];
if (spreadDirective) {
let spreadObject = saferEval(el, spreadDirective.expression, component.$data); // Add x-spread directives to the pile of existing directives.
directives = directives.concat(Object.entries(spreadObject).map(([name, value]) => parseHtmlAttribute({
name,
value
})));
}
if (type) return directives.filter(i => i.type === type);
return sortDirectives(directives);
}
function sortDirectives(directives) {
let directiveOrder = ['bind', 'model', 'show', 'catch-all'];
return directives.sort((a, b) => {
let typeA = directiveOrder.indexOf(a.type) === -1 ? 'catch-all' : a.type;
let typeB = directiveOrder.indexOf(b.type) === -1 ? 'catch-all' : b.type;
return directiveOrder.indexOf(typeA) - directiveOrder.indexOf(typeB);
});
}
function parseHtmlAttribute({
name,
value
}) {
const normalizedName = replaceAtAndColonWithStandardSyntax(name);
const typeMatch = normalizedName.match(xAttrRE);
const valueMatch = normalizedName.match(/:([a-zA-Z0-9\-:]+)/);
const modifiers = normalizedName.match(/\.[^.\]]+(?=[^\]]*$)/g) || [];
return {
type: typeMatch ? typeMatch[1] : null,
value: valueMatch ? valueMatch[1] : null,
modifiers: modifiers.map(i => i.replace('.', '')),
expression: value
};
}
function isBooleanAttr(attrName) {
// As per HTML spec table https://html.spec.whatwg.org/multipage/indices.html#attributes-3:boolean-attribute
// Array roughly ordered by estimated usage
const booleanAttributes = ['disabled', 'checked', 'required', 'readonly', 'hidden', 'open', 'selected', 'autofocus', 'itemscope', 'multiple', 'novalidate', 'allowfullscreen', 'allowpaymentrequest', 'formnovalidate', 'autoplay', 'controls', 'loop', 'muted', 'playsinline', 'default', 'ismap', 'reversed', 'async', 'defer', 'nomodule'];
return booleanAttributes.includes(attrName);
}
function replaceAtAndColonWithStandardSyntax(name) {
if (name.startsWith('@')) {
return name.replace('@', 'x-on:');
} else if (name.startsWith(':')) {
return name.replace(':', 'x-bind:');
}
return name;
}
function convertClassStringToArray(classList, filterFn = Boolean) {
return classList.split(' ').filter(filterFn);
}
const TRANSITION_TYPE_IN = 'in';
const TRANSITION_TYPE_OUT = 'out';
const TRANSITION_CANCELLED = 'cancelled';
function transitionIn(el, show, reject, component, forceSkip = false) {
// We don't want to transition on the initial page load.
if (forceSkip) return show();
if (el.__x_transition && el.__x_transition.type === TRANSITION_TYPE_IN) {
// there is already a similar transition going on, this was probably triggered by
// a change in a different property, let's just leave the previous one doing its job
return;
}
const attrs = getXAttrs(el, component, 'transition');
const showAttr = getXAttrs(el, component, 'show')[0]; // If this is triggered by a x-show.transition.
if (showAttr && showAttr.modifiers.includes('transition')) {
let modifiers = showAttr.modifiers; // If x-show.transition.out, we'll skip the "in" transition.
if (modifiers.includes('out') && !modifiers.includes('in')) return show();
const settingBothSidesOfTransition = modifiers.includes('in') && modifiers.includes('out'); // If x-show.transition.in...out... only use "in" related modifiers for this transition.
modifiers = settingBothSidesOfTransition ? modifiers.filter((i, index) => index < modifiers.indexOf('out')) : modifiers;
transitionHelperIn(el, modifiers, show, reject); // Otherwise, we can assume x-transition:enter.
} else if (attrs.some(attr => ['enter', 'enter-start', 'enter-end'].includes(attr.value))) {
transitionClassesIn(el, component, attrs, show, reject);
} else {
// If neither, just show that damn thing.
show();
}
}
function transitionOut(el, hide, reject, component, forceSkip = false) {
// We don't want to transition on the initial page load.
if (forceSkip) return hide();
if (el.__x_transition && el.__x_transition.type === TRANSITION_TYPE_OUT) {
// there is already a similar transition going on, this was probably triggered by
// a change in a different property, let's just leave the previous one doing its job
return;
}
const attrs = getXAttrs(el, component, 'transition');
const showAttr = getXAttrs(el, component, 'show')[0];
if (showAttr && showAttr.modifiers.includes('transition')) {
let modifiers = showAttr.modifiers;
if (modifiers.includes('in') && !modifiers.includes('out')) return hide();
const settingBothSidesOfTransition = modifiers.includes('in') && modifiers.includes('out');
modifiers = settingBothSidesOfTransition ? modifiers.filter((i, index) => index > modifiers.indexOf('out')) : modifiers;
transitionHelperOut(el, modifiers, settingBothSidesOfTransition, hide, reject);
} else if (attrs.some(attr => ['leave', 'leave-start', 'leave-end'].includes(attr.value))) {
transitionClassesOut(el, component, attrs, hide, reject);
} else {
hide();
}
}
function transitionHelperIn(el, modifiers, showCallback, reject) {
// Default values inspired by: https://material.io/design/motion/speed.html#duration
const styleValues = {
duration: modifierValue(modifiers, 'duration', 150),
origin: modifierValue(modifiers, 'origin', 'center'),
first: {
opacity: 0,
scale: modifierValue(modifiers, 'scale', 95)
},
second: {
opacity: 1,
scale: 100
}
};
transitionHelper(el, modifiers, showCallback, () => {}, reject, styleValues, TRANSITION_TYPE_IN);
}
function transitionHelperOut(el, modifiers, settingBothSidesOfTransition, hideCallback, reject) {
// Make the "out" transition .5x slower than the "in". (Visually better)
// HOWEVER, if they explicitly set a duration for the "out" transition,
// use that.
const duration = settingBothSidesOfTransition ? modifierValue(modifiers, 'duration', 150) : modifierValue(modifiers, 'duration', 150) / 2;
const styleValues = {
duration: duration,
origin: modifierValue(modifiers, 'origin', 'center'),
first: {
opacity: 1,
scale: 100
},
second: {
opacity: 0,
scale: modifierValue(modifiers, 'scale', 95)
}
};
transitionHelper(el, modifiers, () => {}, hideCallback, reject, styleValues, TRANSITION_TYPE_OUT);
}
function modifierValue(modifiers, key, fallback) {
// If the modifier isn't present, use the default.
if (modifiers.indexOf(key) === -1) return fallback; // If it IS present, grab the value after it: x-show.transition.duration.500ms
const rawValue = modifiers[modifiers.indexOf(key) + 1];
if (!rawValue) return fallback;
if (key === 'scale') {
// Check if the very next value is NOT a number and return the fallback.
// If x-show.transition.scale, we'll use the default scale value.
// That is how a user opts out of the opacity transition.
if (!isNumeric(rawValue)) return fallback;
}
if (key === 'duration') {
// Support x-show.transition.duration.500ms && duration.500
let match = rawValue.match(/([0-9]+)ms/);
if (match) return match[1];
}
if (key === 'origin') {
// Support chaining origin directions: x-show.transition.top.right
if (['top', 'right', 'left', 'center', 'bottom'].includes(modifiers[modifiers.indexOf(key) + 2])) {
return [rawValue, modifiers[modifiers.indexOf(key) + 2]].join(' ');
}
}
return rawValue;
}
function transitionHelper(el, modifiers, hook1, hook2, reject, styleValues, type) {
// clear the previous transition if exists to avoid caching the wrong styles
if (el.__x_transition) {
el.__x_transition.cancel && el.__x_transition.cancel();
} // If the user set these style values, we'll put them back when we're done with them.
const opacityCache = el.style.opacity;
const transformCache = el.style.transform;
const transformOriginCache = el.style.transformOrigin; // If no modifiers are present: x-show.transition, we'll default to both opacity and scale.
const noModifiers = !modifiers.includes('opacity') && !modifiers.includes('scale');
const transitionOpacity = noModifiers || modifiers.includes('opacity');
const transitionScale = noModifiers || modifiers.includes('scale'); // These are the explicit stages of a transition (same stages for in and for out).
// This way you can get a birds eye view of the hooks, and the differences
// between them.
const stages = {
start() {
if (transitionOpacity) el.style.opacity = styleValues.first.opacity;
if (transitionScale) el.style.transform = `scale(${styleValues.first.scale / 100})`;
},
during() {
if (transitionScale) el.style.transformOrigin = styleValues.origin;
el.style.transitionProperty = [transitionOpacity ? `opacity` : ``, transitionScale ? `transform` : ``].join(' ').trim();
el.style.transitionDuration = `${styleValues.duration / 1000}s`;
el.style.transitionTimingFunction = `cubic-bezier(0.4, 0.0, 0.2, 1)`;
},
show() {
hook1();
},
end() {
if (transitionOpacity) el.style.opacity = styleValues.second.opacity;
if (transitionScale) el.style.transform = `scale(${styleValues.second.scale / 100})`;
},
hide() {
hook2();
},
cleanup() {
if (transitionOpacity) el.style.opacity = opacityCache;
if (transitionScale) el.style.transform = transformCache;
if (transitionScale) el.style.transformOrigin = transformOriginCache;
el.style.transitionProperty = null;
el.style.transitionDuration = null;
el.style.transitionTimingFunction = null;
}
};
transition(el, stages, type, reject);
}
const ensureStringExpression = (expression, el, component) => {
return typeof expression === 'function' ? component.evaluateReturnExpression(el, expression) : expression;
};
function transitionClassesIn(el, component, directives, showCallback, reject) {
const enter = convertClassStringToArray(ensureStringExpression((directives.find(i => i.value === 'enter') || {
expression: ''
}).expression, el, component));
const enterStart = convertClassStringToArray(ensureStringExpression((directives.find(i => i.value === 'enter-start') || {
expression: ''
}).expression, el, component));
const enterEnd = convertClassStringToArray(ensureStringExpression((directives.find(i => i.value === 'enter-end') || {
expression: ''
}).expression, el, component));
transitionClasses(el, enter, enterStart, enterEnd, showCallback, () => {}, TRANSITION_TYPE_IN, reject);
}
function transitionClassesOut(el, component, directives, hideCallback, reject) {
const leave = convertClassStringToArray(ensureStringExpression((directives.find(i => i.value === 'leave') || {
expression: ''
}).expression, el, component));
const leaveStart = convertClassStringToArray(ensureStringExpression((directives.find(i => i.value === 'leave-start') || {
expression: ''
}).expression, el, component));
const leaveEnd = convertClassStringToArray(ensureStringExpression((directives.find(i => i.value === 'leave-end') || {
expression: ''
}).expression, el, component));
transitionClasses(el, leave, leaveStart, leaveEnd, () => {}, hideCallback, TRANSITION_TYPE_OUT, reject);
}
function transitionClasses(el, classesDuring, classesStart, classesEnd, hook1, hook2, type, reject) {
// clear the previous transition if exists to avoid caching the wrong classes
if (el.__x_transition) {
el.__x_transition.cancel && el.__x_transition.cancel();
}
const originalClasses = el.__x_original_classes || [];
const stages = {
start() {
el.classList.add(...classesStart);
},
during() {
el.classList.add(...classesDuring);
},
show() {
hook1();
},
end() {
// Don't remove classes that were in the original class attribute.
el.classList.remove(...classesStart.filter(i => !originalClasses.includes(i)));
el.classList.add(...classesEnd);
},
hide() {
hook2();
},
cleanup() {
el.classList.remove(...classesDuring.filter(i => !originalClasses.includes(i)));
el.classList.remove(...classesEnd.filter(i => !originalClasses.includes(i)));
}
};
transition(el, stages, type, reject);
}
function transition(el, stages, type, reject) {
const finish = once(() => {
stages.hide(); // Adding an "isConnected" check, in case the callback
// removed the element from the DOM.
if (el.isConnected) {
stages.cleanup();
}
delete el.__x_transition;
});
el.__x_transition = {
// Set transition type so we can avoid clearing transition if the direction is the same
type: type,
// create a callback for the last stages of the transition so we can call it
// from different point and early terminate it. Once will ensure that function
// is only called one time.
cancel: once(() => {
reject(TRANSITION_CANCELLED);
finish();
}),
finish,
// This store the next animation frame so we can cancel it
nextFrame: null
};
stages.start();
stages.during();
el.__x_transition.nextFrame = requestAnimationFrame(() => {
// Note: Safari's transitionDuration property will list out comma separated transition durations
// for every single transition property. Let's grab the first one and call it a day.
let duration = Number(getComputedStyle(el).transitionDuration.replace(/,.*/, '').replace('s', '')) * 1000;
if (duration === 0) {
duration = Number(getComputedStyle(el).animationDuration.replace('s', '')) * 1000;
}
stages.show();
el.__x_transition.nextFrame = requestAnimationFrame(() => {
stages.end();
setTimeout(el.__x_transition.finish, duration);
});
});
}
function isNumeric(subject) {
return !Array.isArray(subject) && !isNaN(subject);
} // Thanks @vuejs
// https://github.com/vuejs/vue/blob/4de4649d9637262a9b007720b59f80ac72a5620c/src/shared/util.js
function once(callback) {
let called = false;
return function () {
if (!called) {
called = true;
callback.apply(this, arguments);
}
};
}
function handleForDirective(component, templateEl, expression, initialUpdate, extraVars) {
warnIfMalformedTemplate(templateEl, 'x-for');
let iteratorNames = typeof expression === 'function' ? parseForExpression(component.evaluateReturnExpression(templateEl, expression)) : parseForExpression(expression);
let items = evaluateItemsAndReturnEmptyIfXIfIsPresentAndFalseOnElement(component, templateEl, iteratorNames, extraVars); // As we walk the array, we'll also walk the DOM (updating/creating as we go).
let currentEl = templateEl;
items.forEach((item, index) => {
let iterationScopeVariables = getIterationScopeVariables(iteratorNames, item, index, items, extraVars());
let currentKey = generateKeyForIteration(component, templateEl, index, iterationScopeVariables);
let nextEl = lookAheadForMatchingKeyedElementAndMoveItIfFound(currentEl.nextElementSibling, currentKey); // If we haven't found a matching key, insert the element at the current position.
if (!nextEl) {
nextEl = addElementInLoopAfterCurrentEl(templateEl, currentEl); // And transition it in if it's not the first page load.
transitionIn(nextEl, () => {}, () => {}, component, initialUpdate);
nextEl.__x_for = iterationScopeVariables;
component.initializeElements(nextEl, () => nextEl.__x_for); // Otherwise update the element we found.
} else {
// Temporarily remove the key indicator to allow the normal "updateElements" to work.
delete nextEl.__x_for_key;
nextEl.__x_for = iterationScopeVariables;
component.updateElements(nextEl, () => nextEl.__x_for);
}
currentEl = nextEl;
currentEl.__x_for_key = currentKey;
});
removeAnyLeftOverElementsFromPreviousUpdate(currentEl, component);
} // This was taken from VueJS 2.* core. Thanks Vue!
function parseForExpression(expression) {
let forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/;
let stripParensRE = /^\(|\)$/g;
let forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/;
let inMatch = String(expression).match(forAliasRE);
if (!inMatch) return;
let res = {};
res.items = inMatch[2].trim();
let item = inMatch[1].trim().replace(stripParensRE, '');
let iteratorMatch = item.match(forIteratorRE);
if (iteratorMatch) {
res.item = item.replace(forIteratorRE, '').trim();
res.index = iteratorMatch[1].trim();
if (iteratorMatch[2]) {
res.collection = iteratorMatch[2].trim();
}
} else {
res.item = item;
}
return res;
}
function getIterationScopeVariables(iteratorNames, item, index, items, extraVars) {
// We must create a new object, so each iteration has a new scope
let scopeVariables = extraVars ? _objectSpread2({}, extraVars) : {};
scopeVariables[iteratorNames.item] = item;
if (iteratorNames.index) scopeVariables[iteratorNames.index] = index;
if (iteratorNames.collection) scopeVariables[iteratorNames.collection] = items;
return scopeVariables;
}
function generateKeyForIteration(component, el, index, iterationScopeVariables) {
let bindKeyAttribute = getXAttrs(el, component, 'bind').filter(attr => attr.value === 'key')[0]; // If the dev hasn't specified a key, just return the index of the iteration.
if (!bindKeyAttribute) return index;
return component.evaluateReturnExpression(el, bindKeyAttribute.expression, () => iterationScopeVariables);
}
function evaluateItemsAndReturnEmptyIfXIfIsPresentAndFalseOnElement(component, el, iteratorNames, extraVars) {
let ifAttribute = getXAttrs(el, component, 'if')[0];
if (ifAttribute && !component.evaluateReturnExpression(el, ifAttribute.expression)) {
return [];
}
let items = component.evaluateReturnExpression(el, iteratorNames.items, extraVars); // This adds support for the `i in n` syntax.
if (isNumeric(items) && items >= 0) {
items = Array.from(Array(items).keys(), i => i + 1);
}
return items;
}
function addElementInLoopAfterCurrentEl(templateEl, currentEl) {
let clone = document.importNode(templateEl.content, true);
currentEl.parentElement.insertBefore(clone, currentEl.nextElementSibling);
return currentEl.nextElementSibling;
}
function lookAheadForMatchingKeyedElementAndMoveItIfFound(nextEl, currentKey) {
if (!nextEl) return; // If we are already past the x-for generated elements, we don't need to look ahead.
if (nextEl.__x_for_key === undefined) return; // If the the key's DO match, no need to look ahead.
if (nextEl.__x_for_key === currentKey) return nextEl; // If they don't, we'll look ahead for a match.
// If we find it, we'll move it to the current position in the loop.
let tmpNextEl = nextEl;
while (tmpNextEl) {
if (tmpNextEl.__x_for_key === currentKey) {
return tmpNextEl.parentElement.insertBefore(tmpNextEl, nextEl);
}
tmpNextEl = tmpNextEl.nextElementSibling && tmpNextEl.nextElementSibling.__x_for_key !== undefined ? tmpNextEl.nextElementSibling : false;
}
}
function removeAnyLeftOverElementsFromPreviousUpdate(currentEl, component) {
var nextElementFromOldLoop = currentEl.nextElementSibling && currentEl.nextElementSibling.__x_for_key !== undefined ? currentEl.nextElementSibling : false;
while (nextElementFromOldLoop) {
let nextElementFromOldLoopImmutable = nextElementFromOldLoop;
let nextSibling = nextElementFromOldLoop.nextElementSibling;
transitionOut(nextElementFromOldLoop, () => {
nextElementFromOldLoopImmutable.remove();
}, () => {}, component);
nextElementFromOldLoop = nextSibling && nextSibling.__x_for_key !== undefined ? nextSibling : false;
}
}
function handleAttributeBindingDirective(component, el, attrName, expression, extraVars, attrType, modifiers) {
var value = component.evaluateReturnExpression(el, expression, extraVars);
if (attrName === 'value') {
if (Alpine.ignoreFocusedForValueBinding && document.activeElement.isSameNode(el)) return; // If nested model key is undefined, set the default value to empty string.
if (value === undefined && String(expression).match(/\./)) {
value = '';
}
if (el.type === 'radio') {
// Set radio value from x-bind:value, if no "value" attribute exists.
// If there are any initial state values, radio will have a correct
// "checked" value since x-bind:value is processed before x-model.
if (el.attributes.value === undefined && attrType === 'bind') {
el.value = value;
} else if (attrType !== 'bind') {
el.checked = checkedAttrLooseCompare(el.value, value);
}
} else if (el.type === 'checkbox') {
// If we are explicitly binding a string to the :value, set the string,
// If the value is a boolean, leave it alone, it will be set to "on"
// automatically.
if (typeof value !== 'boolean' && ![null, undefined].includes(value) && attrType === 'bind') {
el.value = String(value);
} else if (attrType !== 'bind') {
if (Array.isArray(value)) {
// I'm purposely not using Array.includes here because it's
// strict, and because of Numeric/String mis-casting, I
// want the "includes" to be "fuzzy".
el.checked = value.some(val => checkedAttrLooseCompare(val, el.value));
} else {
el.checked = !!value;
}
}
} else if (el.tagName === 'SELECT') {
updateSelect(el, value);
} else {
if (el.value === value) return;
el.value = value;
}
} else if (attrName === 'class') {
if (Array.isArray(value)) {
const originalClasses = el.__x_original_classes || [];
el.setAttribute('class', arrayUnique(originalClasses.concat(value)).join(' '));
} else if (typeof value === 'object') {
// Sorting the keys / class names by their boolean value will ensure that
// anything that evaluates to `false` and needs to remove classes is run first.
const keysSortedByBooleanValue = Object.keys(value).sort((a, b) => value[a] - value[b]);
keysSortedByBooleanValue.forEach(classNames => {
if (value[classNames]) {
convertClassStringToArray(classNames).forEach(className => el.classList.add(className));
} else {
convertClassStringToArray(classNames).forEach(className => el.classList.remove(className));
}
});
} else {
const originalClasses = el.__x_original_classes || [];
const newClasses = value ? convertClassStringToArray(value) : [];
el.setAttribute('class', arrayUnique(originalClasses.concat(newClasses)).join(' '));
}
} else {
attrName = modifiers.includes('camel') ? camelCase(attrName) : attrName; // If an attribute's bound value is null, undefined or false, remove the attribute
if ([null, undefined, false].includes(value)) {
el.removeAttribute(attrName);
} else {
isBooleanAttr(attrName) ? setIfChanged(el, attrName, attrName) : setIfChanged(el, attrName, value);
}
}
}
function setIfChanged(el, attrName, value) {
if (el.getAttribute(attrName) != value) {
el.setAttribute(attrName, value);
}
}
function updateSelect(el, value) {
const arrayWrappedValue = [].concat(value).map(value => {
return value + '';
});
Array.from(el.options).forEach(option => {
option.selected = arrayWrappedValue.includes(option.value || option.text);
});
}
function handleTextDirective(el, output, expression) {
// If nested model key is undefined, set the default value to empty string.
if (output === undefined && String(expression).match(/\./)) {
output = '';
}
el.textContent = output;
}
function handleHtmlDirective(component, el, expression, extraVars) {
el.innerHTML = component.evaluateReturnExpression(el, expression, extraVars);
}
function handleShowDirective(component, el, value, modifiers, initialUpdate = false) {
const hide = () => {
el.style.display = 'none';
el.__x_is_shown = false;
};
const show = () => {
if (el.style.length === 1 && el.style.display === 'none') {
el.removeAttribute('style');
} else {
el.style.removeProperty('display');
}
el.__x_is_shown = true;
};
if (initialUpdate === true) {
if (value) {
show();
} else {
hide();
}
return;
}
const handle = (resolve, reject) => {
if (value) {
if (el.style.display === 'none' || el.__x_transition) {
transitionIn(el, () => {
show();
}, reject, component);
}
resolve(() => {});
} else {
if (el.style.display !== 'none') {
transitionOut(el, () => {
resolve(() => {
hide();
});
}, reject, component);
} else {
resolve(() => {});
}
}
}; // The working of x-show is a bit complex because we need to
// wait for any child transitions to finish before hiding
// some element. Also, this has to be done recursively.
// If x-show.immediate, foregoe the waiting.
if (modifiers.includes('immediate')) {
handle(finish => finish(), () => {});
return;
} // x-show is encountered during a DOM tree walk. If an element
// we encounter is NOT a child of another x-show element we
// can execute the previous x-show stack (if one exists).
if (component.showDirectiveLastElement && !component.showDirectiveLastElement.contains(el)) {
component.executeAndClearRemainingShowDirectiveStack();
}
component.showDirectiveStack.push(handle);
component.showDirectiveLastElement = el;
}
function handleIfDirective(component, el, expressionResult, initialUpdate, extraVars) {
warnIfMalformedTemplate(el, 'x-if');
const elementHasAlreadyBeenAdded = el.nextElementSibling && el.nextElementSibling.__x_inserted_me === true;
if (expressionResult && (!elementHasAlreadyBeenAdded || el.__x_transition)) {
const clone = document.importNode(el.content, true);
el.parentElement.insertBefore(clone, el.nextElementSibling);
transitionIn(el.nextElementSibling, () => {}, () => {}, component, initialUpdate);
component.initializeElements(el.nextElementSibling, extraVars);
el.nextElementSibling.__x_inserted_me = true;
} else if (!expressionResult && elementHasAlreadyBeenAdded) {
transitionOut(el.nextElementSibling, () => {
el.nextElementSibling.remove();
}, () => {}, component, initialUpdate);
}
}
function registerListener(component, el, event, modifiers, expression, extraVars = {}) {
const options = {
passive: modifiers.includes('passive')
};
if (modifiers.includes('camel')) {
event = camelCase(event);
}
let handler, listenerTarget;
if (modifiers.includes('away')) {
listenerTarget = document;
handler = e => {
// Don't do anything if the click came from the element or within it.
if (el.contains(e.target)) return; // Don't do anything if this element isn't currently visible.
if (el.offsetWidth < 1 && el.offsetHeight < 1) return; // Now that we are sure the element is visible, AND the click
// is from outside it, let's run the expression.
runListenerHandler(component, expression, e, extraVars);
if (modifiers.includes('once')) {
document.removeEventListener(event, handler, options);
}
};
} else {
listenerTarget = modifiers.includes('window') ? window : modifiers.includes('document') ? document : el;
handler = e => {
// Remove this global event handler if the element that declared it
// has been removed. It's now stale.
if (listenerTarget === window || listenerTarget === document) {
if (!document.body.contains(el)) {
listenerTarget.removeEventListener(event, handler, options);
return;
}
}
if (isKeyEvent(event)) {
if (isListeningForASpecificKeyThatHasntBeenPressed(e, modifiers)) {
return;
}
}
if (modifiers.includes('prevent')) e.preventDefault();
if (modifiers.includes('stop')) e.stopPropagation(); // If the .self modifier isn't present, or if it is present and
// the target element matches the element we are registering the
// event on, run the handler
if (!modifiers.includes('self') || e.target === el) {
const returnValue = runListenerHandler(component, expression, e, extraVars);
returnValue.then(value => {
if (value === false) {
e.preventDefault();
} else {
if (modifiers.includes('once')) {
listenerTarget.removeEventListener(event, handler, options);
}
}
});
}
};
}
if (modifiers.includes('debounce')) {
let nextModifier = modifiers[modifiers.indexOf('debounce') + 1] || 'invalid-wait';
let wait = isNumeric(nextModifier.split('ms')[0]) ? Number(nextModifier.split('ms')[0]) : 250;
handler = debounce(handler, wait);
}
listenerTarget.addEventListener(event, handler, options);
}
function runListenerHandler(component, expression, e, extraVars) {
return component.evaluateCommandExpression(e.target, expression, () => {
return _objectSpread2(_objectSpread2({}, extraVars()), {}, {
'$event': e
});
});
}
function isKeyEvent(event) {
return ['keydown', 'keyup'].includes(event);
}
function isListeningForASpecificKeyThatHasntBeenPressed(e, modifiers) {
let keyModifiers = modifiers.filter(i => {
return !['window', 'document', 'prevent', 'stop'].includes(i);
});
if (keyModifiers.includes('debounce')) {
let debounceIndex = keyModifiers.indexOf('debounce');
keyModifiers.splice(debounceIndex, isNumeric((keyModifiers[debounceIndex + 1] || 'invalid-wait').split('ms')[0]) ? 2 : 1);
} // If no modifier is specified, we'll call it a press.
if (keyModifiers.length === 0) return false; // If one is passed, AND it matches the key pressed, we'll call it a press.
if (keyModifiers.length === 1 && keyModifiers[0] === keyToModifier(e.key)) return false; // The user is listening for key combinations.
const systemKeyModifiers = ['ctrl', 'shift', 'alt', 'meta', 'cmd', 'super'];
const selectedSystemKeyModifiers = systemKeyModifiers.filter(modifier => keyModifiers.includes(modifier));
keyModifiers = keyModifiers.filter(i => !selectedSystemKeyModifiers.includes(i));
if (selectedSystemKeyModifiers.length > 0) {
const activelyPressedKeyModifiers = selectedSystemKeyModifiers.filter(modifier => {
// Alias "cmd" and "super" to "meta"
if (modifier === 'cmd' || modifier === 'super') modifier = 'meta';
return e[`${modifier}Key`];
}); // If all the modifiers selected are pressed, ...
if (activelyPressedKeyModifiers.length === selectedSystemKeyModifiers.length) {
// AND the remaining key is pressed as well. It's a press.
if (keyModifiers[0] === keyToModifier(e.key)) return false;
}
} // We'll call it NOT a valid keypress.
return true;
}
function keyToModifier(key) {
switch (key) {
case '/':
return 'slash';
case ' ':
case 'Spacebar':
return 'space';
default:
return key && kebabCase(key);
}
}
function registerModelListener(component, el, modifiers, expression, extraVars) {
// If the element we are binding to is a select, a radio, or checkbox
// we'll listen for the change event instead of the "input" event.
var event = el.tagName.toLowerCase() === 'select' || ['checkbox', 'radio'].includes(el.type) || modifiers.includes('lazy') ? 'change' : 'input';
const listenerExpression = `${expression} = rightSideOfExpression($event, ${expression})`;
registerListener(component, el, event, modifiers, listenerExpression, () => {
return _objectSpread2(_objectSpread2({}, extraVars()), {}, {
rightSideOfExpression: generateModelAssignmentFunction(el, modifiers, expression)
});
});
}
function generateModelAssignmentFunction(el, modifiers, expression) {
if (el.type === 'radio') {
// Radio buttons only work properly when they share a name attribute.
// People might assume we take care of that for them, because
// they already set a shared "x-model" attribute.
if (!el.hasAttribute('name')) el.setAttribute('name', expression);
}
return (event, currentValue) => {
// Check for event.detail due to an issue where IE11 handles other events as a CustomEvent.
if (event instanceof CustomEvent && event.detail) {
return event.detail;
} else if (el.type === 'checkbox') {
// If the data we are binding to is an array, toggle its value inside the array.
if (Array.isArray(currentValue)) {
const newValue = modifiers.includes('number') ? safeParseNumber(event.target.value) : event.target.value;
return event.target.checked ? currentValue.concat([newValue]) : currentValue.filter(el => !checkedAttrLooseCompare(el, newValue));
} else {
return event.target.checked;
}
} else if (el.tagName.toLowerCase() === 'select' && el.multiple) {
return modifiers.includes('number') ? Array.from(event.target.selectedOptions).map(option => {
const rawValue = option.value || option.text;
return safeParseNumber(rawValue);
}) : Array.from(event.target.selectedOptions).map(option => {
return option.value || option.text;
});
} else {
const rawValue = event.target.value;
return modifiers.includes('number') ? safeParseNumber(rawValue) : modifiers.includes('trim') ? rawValue.trim() : rawValue;
}
};
}
function safeParseNumber(rawValue) {
const number = rawValue ? parseFloat(rawValue) : null;
return isNumeric(number) ? number : rawValue;
}
/**
* Copyright (C) 2017 salesforce.com, inc.
*/
const { isArray } = Array;
const { getPrototypeOf, create: ObjectCreate, defineProperty: ObjectDefineProperty, defineProperties: ObjectDefineProperties, isExtensible, getOwnPropertyDescriptor, getOwnPropertyNames, getOwnPropertySymbols, preventExtensions, hasOwnProperty, } = Object;
const { push: ArrayPush, concat: ArrayConcat, map: ArrayMap, } = Array.prototype;
function isUndefined(obj) {
return obj === undefined;
}
function isFunction(obj) {
return typeof obj === 'function';
}
function isObject(obj) {
return typeof obj === 'object';
}
const proxyToValueMap = new WeakMap();
function registerProxy(proxy, value) {
proxyToValueMap.set(proxy, value);
}
const unwrap = (replicaOrAny) => proxyToValueMap.get(replicaOrAny) || replicaOrAny;
function wrapValue(membrane, value) {
return membrane.valueIsObservable(value) ? membrane.getProxy(value) : value;
}
/**
* Unwrap property descriptors will set value on original descriptor
* We only need to unwrap if value is specified
* @param descriptor external descrpitor provided to define new property on original value
*/
function unwrapDescriptor(descriptor) {
if (hasOwnProperty.call(descriptor, 'value')) {
descriptor.value = unwrap(descriptor.value);
}
return descriptor;
}
function lockShadowTarget(membrane, shadowTarget, originalTarget) {
const targetKeys = ArrayConcat.call(getOwnPropertyNames(originalTarget), getOwnPropertySymbols(originalTarget));
targetKeys.forEach((key) => {
let descriptor = getOwnPropertyDescriptor(originalTarget, key);
// We do not need to wrap the descriptor if configurable
// Because we can deal with wrapping it when user goes through
// Get own property descriptor. There is also a chance that this descriptor
// could change sometime in the future, so we can defer wrapping
// until we need to
if (!descriptor.configurable) {
descriptor = wrapDescriptor(membrane, descriptor, wrapValue);
}
ObjectDefineProperty(shadowTarget, key, descriptor);
});
preventExtensions(shadowTarget);
}
class ReactiveProxyHandler {
constructor(membrane, value) {
this.originalTarget = value;
this.membrane = membrane;
}
get(shadowTarget, key) {
const { originalTarget, membrane } = this;
const value = originalTarget[key];
const { valueObserved } = membrane;
valueObserved(originalTarget, key);
return membrane.getProxy(value);
}
set(shadowTarget, key, value) {
const { originalTarget, membrane: { valueMutated } } = this;
const oldValue = originalTarget[key];
if (oldValue !== value) {
originalTarget[key] = value;
valueMutated(originalTarget, key);
}
else if (key === 'length' && isArray(originalTarget)) {
// fix for issue #236: push will add the new index, and by the time length
// is updated, the internal length is already equal to the new length value
// therefore, the oldValue is equal to the value. This is the forking logic
// to support this use case.
valueMutated(originalTarget, key);
}
return true;
}
deleteProperty(shadowTarget, key) {
const { originalTarget, membrane: { valueMutated } } = this;
delete originalTarget[key];
valueMutated(originalTarget, key);
return true;
}
apply(shadowTarget, thisArg, argArray) {
/* No op */
}
construct(target, argArray, newTarget) {
/* No op */
}
has(shadowTarget, key) {
const { originalTarget, membrane: { valueObserved } } = this;
valueObserved(originalTarget, key);
return key in originalTarget;
}
ownKeys(shadowTarget) {
const { originalTarget } = this;
return ArrayConcat.call(getOwnPropertyNames(originalTarget), getOwnPropertySymbols(originalTarget));
}
isExtensible(shadowTarget) {
const shadowIsExtensible = isExtensible(shadowTarget);
if (!shadowIsExtensible) {
return shadowIsExtensible;
}
const { originalTarget, membrane } = this;
const targetIsExtensible = isExtensible(originalTarget);
if (!targetIsExtensible) {
lockShadowTarget(membrane, shadowTarget, originalTarget);
}
return targetIsExtensible;
}
setPrototypeOf(shadowTarget, prototype) {
}
getPrototypeOf(shadowTarget) {
const { originalTarget } = this;
return getPrototypeOf(originalTarget);
}
getOwnPropertyDescriptor(shadowTarget, key) {
const { originalTarget, membrane } = this;
const { valueObserved } = this.membrane;
// keys looked up via hasOwnProperty need to be reactive
valueObserved(originalTarget, key);
let desc = getOwnPropertyDescriptor(originalTarget, key);
if (isUndefined(desc)) {
return desc;
}
const shadowDescriptor = getOwnPropertyDescriptor(shadowTarget, key);
if (!isUndefined(shadowDescriptor)) {
return shadowDescriptor;
}
// Note: by accessing the descriptor, the key is marked as observed
// but access to the value, setter or getter (if available) cannot observe
// mutations, just like regular methods, in which case we just do nothing.
desc = wrapDescriptor(membrane, desc, wrapValue);
if (!desc.configurable) {
// If descriptor from original target is not configurable,
// We must copy the wrapped descriptor over to the shadow target.
// Otherwise, proxy will throw an invariant error.
// This is our last chance to lock the value.
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/getOwnPropertyDescriptor#Invariants
ObjectDefineProperty(shadowTarget, key, desc);
}
return desc;
}
preventExtensions(shadowTarget) {
const { originalTarget, membrane } = this;
lockShadowTarget(membrane, shadowTarget, originalTarget);
preventExtensions(originalTarget);
return true;
}
defineProperty(shadowTarget, key, descriptor) {
const { originalTarget, membrane } = this;
const { valueMutated } = membrane;
const { configurable } = descriptor;
// We have to check for value in descriptor
// because Object.freeze(proxy) calls this method
// with only { configurable: false, writeable: false }
// Additionally, method will only be called with writeable:false
// if the descriptor has a value, as opposed to getter/setter
// So we can just check if writable is present and then see if
// value is present. This eliminates getter and setter descriptors
if (hasOwnProperty.call(descriptor, 'writable') && !hasOwnProperty.call(descriptor, 'value')) {
const originalDescriptor = getOwnPropertyDescriptor(originalTarget, key);
descriptor.value = originalDescriptor.value;
}
ObjectDefineProperty(originalTarget, key, unwrapDescriptor(descriptor));
if (configurable === false) {
ObjectDefineProperty(shadowTarget, key, wrapDescriptor(membrane, descriptor, wrapValue));
}
valueMutated(originalTarget, key);
return true;
}
}
function wrapReadOnlyValue(membrane, value) {
return membrane.valueIsObservable(value) ? membrane.getReadOnlyProxy(value) : value;
}
class ReadOnlyHandler {
constructor(membrane, value) {
this.originalTarget = value;
this.membrane = membrane;
}
get(shadowTarget, key) {
const { membrane, originalTarget } = this;
const value = originalTarget[key];
const { valueObserved } = membrane;
valueObserved(originalTarget, key);
return membrane.getReadOnlyProxy(value);
}
set(shadowTarget, key, value) {
return false;
}
deleteProperty(shadowTarget, key) {
return false;
}
apply(shadowTarget, thisArg, argArray) {
/* No op */
}
construct(target, argArray, newTarget) {
/* No op */
}
has(shadowTarget, key) {
const { originalTarget, membrane: { valueObserved } } = this;
valueObserved(originalTarget, key);
return key in originalTarget;
}
ownKeys(shadowTarget) {
const { originalTarget } = this;
return ArrayConcat.call(getOwnPropertyNames(originalTarget), getOwnPropertySymbols(originalTarget));
}
setPrototypeOf(shadowTarget, prototype) {
}
getOwnPropertyDescriptor(shadowTarget, key) {
const { originalTarget, membrane } = this;
const { valueObserved } = membrane;
// keys looked up via hasOwnProperty need to be reactive
valueObserved(originalTarget, key);
let desc = getOwnPropertyDescriptor(originalTarget, key);
if (isUndefined(desc)) {
return desc;
}
const shadowDescriptor = getOwnPropertyDescriptor(shadowTarget, key);
if (!isUndefined(shadowDescriptor)) {
return shadowDescriptor;
}
// Note: by accessing the descriptor, the key is marked as observed
// but access to the value or getter (if available) cannot be observed,
// just like regular methods, in which case we just do nothing.
desc = wrapDescriptor(membrane, desc, wrapReadOnlyValue);
if (hasOwnProperty.call(desc, 'set')) {
desc.set = undefined; // readOnly membrane does not allow setters
}
if (!desc.configurable) {
// If descriptor from original target is not configurable,
// We must copy the wrapped descriptor over to the shadow target.
// Otherwise, proxy will throw an invariant error.
// This is our last chance to lock the value.
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/getOwnPropertyDescriptor#Invariants
ObjectDefineProperty(shadowTarget, key, desc);
}
return desc;
}
preventExtensions(shadowTarget) {
return false;
}
defineProperty(shadowTarget, key, descriptor) {
return false;
}
}
function createShadowTarget(value) {
let shadowTarget = undefined;
if (isArray(value)) {
shadowTarget = [];
}
else if (isObject(value)) {
shadowTarget = {};
}
return shadowTarget;
}
const ObjectDotPrototype = Object.prototype;
function defaultValueIsObservable(value) {
// intentionally checking for null
if (value === null) {
return false;
}
// treat all non-object types, including undefined, as non-observable values
if (typeof value !== 'object') {
return false;
}
if (isArray(value)) {
return true;
}
const proto = getPrototypeOf(value);
return (proto === ObjectDotPrototype || proto === null || getPrototypeOf(proto) === null);
}
const defaultValueObserved = (obj, key) => {
/* do nothing */
};
const defaultValueMutated = (obj, key) => {
/* do nothing */
};
const defaultValueDistortion = (value) => value;
function wrapDescriptor(membrane, descriptor, getValue) {
const { set, get } = descriptor;
if (hasOwnProperty.call(descriptor, 'value')) {
descriptor.value = getValue(membrane, descriptor.value);
}
else {
if (!isUndefined(get)) {
descriptor.get = function () {
// invoking the original getter with the original target
return getValue(membrane, get.call(unwrap(this)));
};
}
if (!isUndefined(set)) {
descriptor.set = function (value) {
// At this point we don't have a clear indication of whether
// or not a valid mutation will occur, we don't have the key,
// and we are not sure why and how they are invoking this setter.
// Nevertheless we preserve the original semantics by invoking the
// original setter with the original target and the unwrapped value
set.call(unwrap(this), membrane.unwrapProxy(value));
};
}
}
return descriptor;
}
class ReactiveMembrane {
constructor(options) {
this.valueDistortion = defaultValueDistortion;
this.valueMutated = defaultValueMutated;
this.valueObserved = defaultValueObserved;
this.valueIsObservable = defaultValueIsObservable;
this.objectGraph = new WeakMap();
if (!isUndefined(options)) {
const { valueDistortion, valueMutated, valueObserved, valueIsObservable } = options;
this.valueDistortion = isFunction(valueDistortion) ? valueDistortion : defaultValueDistortion;
this.valueMutated = isFunction(valueMutated) ? valueMutated : defaultValueMutated;
this.valueObserved = isFunction(valueObserved) ? valueObserved : defaultValueObserved;
this.valueIsObservable = isFunction(valueIsObservable) ? valueIsObservable : defaultValueIsObservable;
}
}
getProxy(value) {
const unwrappedValue = unwrap(value);
const distorted = this.valueDistortion(unwrappedValue);
if (this.valueIsObservable(distorted)) {
const o = this.getReactiveState(unwrappedValue, distorted);
// when trying to extract the writable version of a readonly
// we return the readonly.
return o.readOnly === value ? value : o.reactive;
}
return distorted;
}
getReadOnlyProxy(value) {
value = unwrap(value);
const distorted = this.valueDistortion(value);
if (this.valueIsObservable(distorted)) {
return this.getReactiveState(value, distorted).readOnly;
}
return distorted;
}
unwrapProxy(p) {
return unwrap(p);
}
getReactiveState(value, distortedValue) {
const { objectGraph, } = this;
let reactiveState = objectGraph.get(distortedValue);
if (reactiveState) {
return reactiveState;
}
const membrane = this;
reactiveState = {
get reactive() {
const reactiveHandler = new ReactiveProxyHandler(membrane, distortedValue);
// caching the reactive proxy after the first time it is accessed
const proxy = new Proxy(createShadowTarget(distortedValue), reactiveHandler);
registerProxy(proxy, value);
ObjectDefineProperty(this, 'reactive', { value: proxy });
return proxy;
},
get readOnly() {
const readOnlyHandler = new ReadOnlyHandler(membrane, distortedValue);
// caching the readOnly proxy after the first time it is accessed
const proxy = new Proxy(createShadowTarget(distortedValue), readOnlyHandler);
registerProxy(proxy, value);
ObjectDefineProperty(this, 'readOnly', { value: proxy });
return proxy;
}
};
objectGraph.set(distortedValue, reactiveState);
return reactiveState;
}
}
/** version: 0.26.0 */
function wrap(data, mutationCallback) {
let membrane = new ReactiveMembrane({
valueMutated(target, key) {
mutationCallback(target, key);
}
});
return {
data: membrane.getProxy(data),
membrane: membrane
};
}
function unwrap$1(membrane, observable) {
let unwrappedData = membrane.unwrapProxy(observable);
let copy = {};
Object.keys(unwrappedData).forEach(key => {
if (['$el', '$refs', '$nextTick', '$watch'].includes(key)) return;
copy[key] = unwrappedData[key];
});
return copy;
}
class Component {
constructor(el, componentForClone = null) {
this.$el = el;
const dataAttr = this.$el.getAttribute('x-data');
const dataExpression = dataAttr === '' ? '{}' : dataAttr;
const initExpression = this.$el.getAttribute('x-init');
let dataExtras = {
$el: this.$el
};
let canonicalComponentElementReference = componentForClone ? componentForClone.$el : this.$el;
Object.entries(Alpine.magicProperties).forEach(([name, callback]) => {
Object.defineProperty(dataExtras, `$${name}`, {
get: function get() {
return callback(canonicalComponentElementReference);
}
});
});
this.unobservedData = componentForClone ? componentForClone.getUnobservedData() : saferEval(el, dataExpression, dataExtras);
// Construct a Proxy-based observable. This will be used to handle reactivity.
let {
membrane,
data
} = this.wrapDataInObservable(this.unobservedData);
this.$data = data;
this.membrane = membrane; // After making user-supplied data methods reactive, we can now add
// our magic properties to the original data for access.
this.unobservedData.$el = this.$el;
this.unobservedData.$refs = this.getRefsProxy();
this.nextTickStack = [];
this.unobservedData.$nextTick = callback => {
this.nextTickStack.push(callback);
};
this.watchers = {};
this.unobservedData.$watch = (property, callback) => {
if (!this.watchers[property]) this.watchers[property] = [];
this.watchers[property].push(callback);
};
/* MODERN-ONLY:START */
// We remove this piece of code from the legacy build.
// In IE11, we have already defined our helpers at this point.
// Register custom magic properties.
Object.entries(Alpine.magicProperties).forEach(([name, callback]) => {
Object.defineProperty(this.unobservedData, `$${name}`, {
get: function get() {
return callback(canonicalComponentElementReference, this.$el);
}
});
});
/* MODERN-ONLY:END */
this.showDirectiveStack = [];
this.showDirectiveLastElement;
componentForClone || Alpine.onBeforeComponentInitializeds.forEach(callback => callback(this));
var initReturnedCallback; // If x-init is present AND we aren't cloning (skip x-init on clone)
if (initExpression && !componentForClone) {
// We want to allow data manipulation, but not trigger DOM updates just yet.
// We haven't even initialized the elements with their Alpine bindings. I mean c'mon.
this.pauseReactivity = true;
initReturnedCallback = this.evaluateReturnExpression(this.$el, initExpression);
this.pauseReactivity = false;
} // Register all our listeners and set all our attribute bindings.
// If we're cloning a component, the third parameter ensures no duplicate
// event listeners are registered (the mutation observer will take care of them)
this.initializeElements(this.$el, () => {}, componentForClone); // Use mutation observer to detect new elements being added within this component at run-time.
// Alpine's just so darn flexible amirite?
this.listenForNewElementsToInitialize();
if (typeof initReturnedCallback === 'function') {
// Run the callback returned from the "x-init" hook to allow the user to do stuff after
// Alpine's got it's grubby little paws all over everything.
initReturnedCallback.call(this.$data);
}
componentForClone || setTimeout(() => {
Alpine.onComponentInitializeds.forEach(callback => callback(this));
}, 0);
}
getUnobservedData() {
return unwrap$1(this.membrane, this.$data);
}
wrapDataInObservable(data) {
var self = this;
let updateDom = debounce(function () {
self.updateElements(self.$el);
}, 0);
return wrap(data, (target, key) => {
if (self.watchers[key]) {
// If there's a watcher for this specific key, run it.
self.watchers[key].forEach(callback => callback(target[key]));
} else if (Array.isArray(target)) {
// Arrays are special cases, if any of the items change, we consider the array as mutated.
Object.keys(self.watchers).forEach(fullDotNotationKey => {
let dotNotationParts = fullDotNotationKey.split('.'); // Ignore length mutations since they would result in duplicate calls.
// For example, when calling push, we would get a mutation for the item's key
// and a second mutation for the length property.
if (key === 'length') return;
dotNotationParts.reduce((comparisonData, part) => {
if (Object.is(target, comparisonData[part])) {
self.watchers[fullDotNotationKey].forEach(callback => callback(target));
}
return comparisonData[part];
}, self.unobservedData);
});
} else {
// Let's walk through the watchers with "dot-notation" (foo.bar) and see
// if this mutation fits any of them.
Object.keys(self.watchers).filter(i => i.includes('.')).forEach(fullDotNotationKey => {
let dotNotationParts = fullDotNotationKey.split('.'); // If this dot-notation watcher's last "part" doesn't match the current
// key, then skip it early for performance reasons.
if (key !== dotNotationParts[dotNotationParts.length - 1]) return; // Now, walk through the dot-notation "parts" recursively to find
// a match, and call the watcher if one's found.
dotNotationParts.reduce((comparisonData, part) => {
if (Object.is(target, comparisonData)) {
// Run the watchers.
self.watchers[fullDotNotationKey].forEach(callback => callback(target[key]));
}
return comparisonData[part];
}, self.unobservedData);
});
} // Don't react to data changes for cases like the `x-created` hook.
if (self.pauseReactivity) return;
updateDom();
});
}
walkAndSkipNestedComponents(el, callback, initializeComponentCallback = () => {}) {
walk(el, el => {
// We've hit a component.
if (el.hasAttribute('x-data')) {
// If it's not the current one.
if (!el.isSameNode(this.$el)) {
// Initialize it if it's not.
if (!el.__x) initializeComponentCallback(el); // Now we'll let that sub-component deal with itself.
return false;
}
}
return callback(el);
});
}
initializeElements(rootEl, extraVars = () => {}, componentForClone = false) {
this.walkAndSkipNestedComponents(rootEl, el => {
// Don't touch spawns from for loop
if (el.__x_for_key !== undefined) return false; // Don't touch spawns from if directives
if (el.__x_inserted_me !== undefined) return false;
this.initializeElement(el, extraVars, componentForClone ? false : true);
}, el => {
if (!componentForClone) el.__x = new Component(el);
});
this.executeAndClearRemainingShowDirectiveStack();
this.executeAndClearNextTickStack(rootEl);
}
initializeElement(el, extraVars, shouldRegisterListeners = true) {
// To support class attribute merging, we have to know what the element's
// original class attribute looked like for reference.
if (el.hasAttribute('class') && getXAttrs(el, this).length > 0) {
el.__x_original_classes = convertClassStringToArray(el.getAttribute('class'));
}
shouldRegisterListeners && this.registerListeners(el, extraVars);
this.resolveBoundAttributes(el, true, extraVars);
}
updateElements(rootEl, extraVars = () => {}) {
this.walkAndSkipNestedComponents(rootEl, el => {
// Don't touch spawns from for loop (and check if the root is actually a for loop in a parent, don't skip it.)
if (el.__x_for_key !== undefined && !el.isSameNode(this.$el)) return false;
this.updateElement(el, extraVars);
}, el => {
el.__x = new Component(el);
});
this.executeAndClearRemainingShowDirectiveStack();
this.executeAndClearNextTickStack(rootEl);
}
executeAndClearNextTickStack(el) {
// Skip spawns from alpine directives
if (el === this.$el && this.nextTickStack.length > 0) {
// We run the tick stack after the next frame to allow any
// running transitions to pass the initial show stage.
requestAnimationFrame(() => {
while (this.nextTickStack.length > 0) {
this.nextTickStack.shift()();
}
});
}
}
executeAndClearRemainingShowDirectiveStack() {
// The goal here is to start all the x-show transitions
// and build a nested promise chain so that elements
// only hide when the children are finished hiding.
this.showDirectiveStack.reverse().map(handler => {
return new Promise((resolve, reject) => {
handler(resolve, reject);
});
}).reduce((promiseChain, promise) => {
return promiseChain.then(() => {
return promise.then(finishElement => {
finishElement();
});
});
}, Promise.resolve(() => {})).catch(e => {
if (e !== TRANSITION_CANCELLED) throw e;
}); // We've processed the handler stack. let's clear it.
this.showDirectiveStack = [];
this.showDirectiveLastElement = undefined;
}
updateElement(el, extraVars) {
this.resolveBoundAttributes(el, false, extraVars);
}
registerListeners(el, extraVars) {
getXAttrs(el, this).forEach(({
type,
value,
modifiers,
expression
}) => {
switch (type) {
case 'on':
registerListener(this, el, value, modifiers, expression, extraVars);
break;
case 'model':
registerModelListener(this, el, modifiers, expression, extraVars);
break;
}
});
}
resolveBoundAttributes(el, initialUpdate = false, extraVars) {
let attrs = getXAttrs(el, this);
attrs.forEach(({
type,
value,
modifiers,
expression
}) => {
switch (type) {
case 'model':
handleAttributeBindingDirective(this, el, 'value', expression, extraVars, type, modifiers);
break;
case 'bind':
// The :key binding on an x-for is special, ignore it.
if (el.tagName.toLowerCase() === 'template' && value === 'key') return;
handleAttributeBindingDirective(this, el, value, expression, extraVars, type, modifiers);
break;
case 'text':
var output = this.evaluateReturnExpression(el, expression, extraVars);
handleTextDirective(el, output, expression);
break;
case 'html':
handleHtmlDirective(this, el, expression, extraVars);
break;
case 'show':
var output = this.evaluateReturnExpression(el, expression, extraVars);
handleShowDirective(this, el, output, modifiers, initialUpdate);
break;
case 'if':
// If this element also has x-for on it, don't process x-if.
// We will let the "x-for" directive handle the "if"ing.
if (attrs.some(i => i.type === 'for')) return;
var output = this.evaluateReturnExpression(el, expression, extraVars);
handleIfDirective(this, el, output, initialUpdate, extraVars);
break;
case 'for':
handleForDirective(this, el, expression, initialUpdate, extraVars);
break;
case 'cloak':
el.removeAttribute('x-cloak');
break;
}
});
}
evaluateReturnExpression(el, expression, extraVars = () => {}) {
return saferEval(el, expression, this.$data, _objectSpread2(_objectSpread2({}, extraVars()), {}, {
$dispatch: this.getDispatchFunction(el)
}));
}
evaluateCommandExpression(el, expression, extraVars = () => {}) {
return saferEvalNoReturn(el, expression, this.$data, _objectSpread2(_objectSpread2({}, extraVars()), {}, {
$dispatch: this.getDispatchFunction(el)
}));
}
getDispatchFunction(el) {
return (event, detail = {}) => {
el.dispatchEvent(new CustomEvent(event, {
detail,
bubbles: true
}));
};
}
listenForNewElementsToInitialize() {
const targetNode = this.$el;
const observerOptions = {
childList: true,
attributes: true,
subtree: true
};
const observer = new MutationObserver(mutations => {
for (let i = 0; i < mutations.length; i++) {
// Filter out mutations triggered from child components.
const closestParentComponent = mutations[i].target.closest('[x-data]');
if (!(closestParentComponent && closestParentComponent.isSameNode(this.$el))) continue;
if (mutations[i].type === 'attributes' && mutations[i].attributeName === 'x-data') {
const xAttr = mutations[i].target.getAttribute('x-data') || '{}';
const rawData = saferEval(this.$el, xAttr, {
$el: this.$el
});
Object.keys(rawData).forEach(key => {
if (this.$data[key] !== rawData[key]) {
this.$data[key] = rawData[key];
}
});
}
if (mutations[i].addedNodes.length > 0) {
mutations[i].addedNodes.forEach(node => {
if (node.nodeType !== 1 || node.__x_inserted_me) return;
if (node.matches('[x-data]') && !node.__x) {
node.__x = new Component(node);
return;
}
this.initializeElements(node);
});
}
}
});
observer.observe(targetNode, observerOptions);
}
getRefsProxy() {
var self = this;
var refObj = {};
// One of the goals of this is to not hold elements in memory, but rather re-evaluate
// the DOM when the system needs something from it. This way, the framework is flexible and
// friendly to outside DOM changes from libraries like Vue/Livewire.
// For this reason, I'm using an "on-demand" proxy to fake a "$refs" object.
return new Proxy(refObj, {
get(object, property) {
if (property === '$isAlpineProxy') return true;
var ref; // We can't just query the DOM because it's hard to filter out refs in
// nested components.
self.walkAndSkipNestedComponents(self.$el, el => {
if (el.hasAttribute('x-ref') && el.getAttribute('x-ref') === property) {
ref = el;
}
});
return ref;
}
});
}
}
const Alpine = {
version: "2.8.2",
pauseMutationObserver: false,
magicProperties: {},
onComponentInitializeds: [],
onBeforeComponentInitializeds: [],
ignoreFocusedForValueBinding: false,
start: async function start() {
if (!isTesting()) {
await domReady();
}
this.discoverComponents(el => {
this.initializeComponent(el);
}); // It's easier and more performant to just support Turbolinks than listen
// to MutationObserver mutations at the document level.
document.addEventListener("turbolinks:load", () => {
this.discoverUninitializedComponents(el => {
this.initializeComponent(el);
});
});
this.listenForNewUninitializedComponentsAtRunTime();
},
discoverComponents: function discoverComponents(callback) {
const rootEls = document.querySelectorAll('[x-data]');
rootEls.forEach(rootEl => {
callback(rootEl);
});
},
discoverUninitializedComponents: function discoverUninitializedComponents(callback, el = null) {
const rootEls = (el || document).querySelectorAll('[x-data]');
Array.from(rootEls).filter(el => el.__x === undefined).forEach(rootEl => {
callback(rootEl);
});
},
listenForNewUninitializedComponentsAtRunTime: function listenForNewUninitializedComponentsAtRunTime() {
const targetNode = document.querySelector('body');
const observerOptions = {
childList: true,
attributes: true,
subtree: true
};
const observer = new MutationObserver(mutations => {
if (this.pauseMutationObserver) return;
for (let i = 0; i < mutations.length; i++) {
if (mutations[i].addedNodes.length > 0) {
mutations[i].addedNodes.forEach(node => {
// Discard non-element nodes (like line-breaks)
if (node.nodeType !== 1) return; // Discard any changes happening within an existing component.
// They will take care of themselves.
if (node.parentElement && node.parentElement.closest('[x-data]')) return;
this.discoverUninitializedComponents(el => {
this.initializeComponent(el);
}, node.parentElement);
});
}
}
});
observer.observe(targetNode, observerOptions);
},
initializeComponent: function initializeComponent(el) {
if (!el.__x) {
// Wrap in a try/catch so that we don't prevent other components
// from initializing when one component contains an error.
try {
el.__x = new Component(el);
} catch (error) {
setTimeout(() => {
throw error;
}, 0);
}
}
},
clone: function clone(component, newEl) {
if (!newEl.__x) {
newEl.__x = new Component(newEl, component);
}
},
addMagicProperty: function addMagicProperty(name, callback) {
this.magicProperties[name] = callback;
},
onComponentInitialized: function onComponentInitialized(callback) {
this.onComponentInitializeds.push(callback);
},
onBeforeComponentInitialized: function onBeforeComponentInitialized(callback) {
this.onBeforeComponentInitializeds.push(callback);
}
};
if (!isTesting()) {
window.Alpine = Alpine;
if (window.deferLoadingAlpine) {
window.deferLoadingAlpine(function () {
window.Alpine.start();
});
} else {
window.Alpine.start();
}
}
return Alpine;
})));
/***/ }),
/***/ "./resources/js/app.js":
/*!*****************************!*\
!*** ./resources/js/app.js ***!
\*****************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _hotwired_turbo__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @hotwired/turbo */ "./node_modules/@hotwired/turbo/dist/turbo.es2017-esm.js");
/* harmony import */ var alpinejs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! alpinejs */ "./node_modules/alpinejs/dist/alpine.js");
/* harmony import */ var alpinejs__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(alpinejs__WEBPACK_IMPORTED_MODULE_1__);
/***/ }),
/***/ "./resources/css/app.css":
/*!*******************************!*\
!*** ./resources/css/app.css ***!
\*******************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
// extracted by mini-css-extract-plugin
/***/ })
/******/ });
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = __webpack_modules__;
/******/
/************************************************************************/
/******/ /* webpack/runtime/chunk loaded */
/******/ (() => {
/******/ var deferred = [];
/******/ __webpack_require__.O = (result, chunkIds, fn, priority) => {
/******/ if(chunkIds) {
/******/ priority = priority || 0;
/******/ for(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];
/******/ deferred[i] = [chunkIds, fn, priority];
/******/ return;
/******/ }
/******/ var notFulfilled = Infinity;
/******/ for (var i = 0; i < deferred.length; i++) {
/******/ var [chunkIds, fn, priority] = deferred[i];
/******/ var fulfilled = true;
/******/ for (var j = 0; j < chunkIds.length; j++) {
/******/ if ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {
/******/ chunkIds.splice(j--, 1);
/******/ } else {
/******/ fulfilled = false;
/******/ if(priority < notFulfilled) notFulfilled = priority;
/******/ }
/******/ }
/******/ if(fulfilled) {
/******/ deferred.splice(i--, 1)
/******/ result = fn();
/******/ }
/******/ }
/******/ return result;
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/compat get default export */
/******/ (() => {
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = (module) => {
/******/ var getter = module && module.__esModule ?
/******/ () => (module['default']) :
/******/ () => (module);
/******/ __webpack_require__.d(getter, { a: getter });
/******/ return getter;
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ (() => {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = (exports) => {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/jsonp chunk loading */
/******/ (() => {
/******/ // no baseURI
/******/
/******/ // object to store loaded and loading chunks
/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched
/******/ // [resolve, reject, Promise] = chunk loading, 0 = chunk loaded
/******/ var installedChunks = {
/******/ "/js/app": 0,
/******/ "css/app": 0
/******/ };
/******/
/******/ // no chunk on demand loading
/******/
/******/ // no prefetching
/******/
/******/ // no preloaded
/******/
/******/ // no HMR
/******/
/******/ // no HMR manifest
/******/
/******/ __webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);
/******/
/******/ // install a JSONP callback for chunk loading
/******/ var webpackJsonpCallback = (parentChunkLoadingFunction, data) => {
/******/ var [chunkIds, moreModules, runtime] = data;
/******/ // add "moreModules" to the modules object,
/******/ // then flag all "chunkIds" as loaded and fire callback
/******/ var moduleId, chunkId, i = 0;
/******/ for(moduleId in moreModules) {
/******/ if(__webpack_require__.o(moreModules, moduleId)) {
/******/ __webpack_require__.m[moduleId] = moreModules[moduleId];
/******/ }
/******/ }
/******/ if(runtime) runtime(__webpack_require__);
/******/ if(parentChunkLoadingFunction) parentChunkLoadingFunction(data);
/******/ for(;i < chunkIds.length; i++) {
/******/ chunkId = chunkIds[i];
/******/ if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {
/******/ installedChunks[chunkId][0]();
/******/ }
/******/ installedChunks[chunkIds[i]] = 0;
/******/ }
/******/ __webpack_require__.O();
/******/ }
/******/
/******/ var chunkLoadingGlobal = self["webpackChunk"] = self["webpackChunk"] || [];
/******/ chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));
/******/ chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));
/******/ })();
/******/
/************************************************************************/
/******/
/******/ // startup
/******/ // Load entry module and return exports
/******/ // This entry module depends on other loaded chunks and execution need to be delayed
/******/ __webpack_require__.O(undefined, ["css/app"], () => (__webpack_require__("./resources/js/app.js")))
/******/ var __webpack_exports__ = __webpack_require__.O(undefined, ["css/app"], () => (__webpack_require__("./resources/css/app.css")))
/******/ __webpack_exports__ = __webpack_require__.O(__webpack_exports__);
/******/
/******/ })()
;