Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/gohugoio/hugo-mod-jslibs-dist.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2022-03-04 11:21:47 +0300
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2022-03-04 19:11:14 +0300
commitac6c92c0bf6650220371c2dfc18ad0513d9a3a87 (patch)
treee144431034ca772059df3ed2404f5205f14d958f
parent7c4d83e324c73bb3dc1209ddefef733c5144424e (diff)
Update to Alpine 3.9.1v391
-rw-r--r--alpinejs/packages/alpinejs/builds/cdn.js7
-rw-r--r--alpinejs/packages/alpinejs/builds/module.js3
-rw-r--r--alpinejs/packages/alpinejs/dist/cdn.js655
-rw-r--r--alpinejs/packages/alpinejs/dist/cdn.min.js4
-rw-r--r--alpinejs/packages/alpinejs/dist/module.cjs.js657
-rw-r--r--alpinejs/packages/alpinejs/dist/module.esm.js657
-rw-r--r--alpinejs/packages/alpinejs/package.json13
-rw-r--r--alpinejs/packages/alpinejs/src/alpine.js67
-rw-r--r--alpinejs/packages/alpinejs/src/binds.js20
-rw-r--r--alpinejs/packages/alpinejs/src/clone.js61
-rw-r--r--alpinejs/packages/alpinejs/src/datas.js22
-rw-r--r--alpinejs/packages/alpinejs/src/directives.js188
-rw-r--r--alpinejs/packages/alpinejs/src/directives/index.js18
-rw-r--r--alpinejs/packages/alpinejs/src/directives/x-bind.js63
-rw-r--r--alpinejs/packages/alpinejs/src/directives/x-cloak.js4
-rw-r--r--alpinejs/packages/alpinejs/src/directives/x-data.js45
-rw-r--r--alpinejs/packages/alpinejs/src/directives/x-effect.js4
-rw-r--r--alpinejs/packages/alpinejs/src/directives/x-for.js273
-rw-r--r--alpinejs/packages/alpinejs/src/directives/x-html.js13
-rw-r--r--alpinejs/packages/alpinejs/src/directives/x-id.js8
-rw-r--r--alpinejs/packages/alpinejs/src/directives/x-if.js55
-rw-r--r--alpinejs/packages/alpinejs/src/directives/x-ignore.js17
-rw-r--r--alpinejs/packages/alpinejs/src/directives/x-init.js13
-rw-r--r--alpinejs/packages/alpinejs/src/directives/x-model.js120
-rw-r--r--alpinejs/packages/alpinejs/src/directives/x-modelable.js26
-rw-r--r--alpinejs/packages/alpinejs/src/directives/x-on.js22
-rw-r--r--alpinejs/packages/alpinejs/src/directives/x-ref.js16
-rw-r--r--alpinejs/packages/alpinejs/src/directives/x-show.js56
-rw-r--r--alpinejs/packages/alpinejs/src/directives/x-teleport.js42
-rw-r--r--alpinejs/packages/alpinejs/src/directives/x-text.js14
-rw-r--r--alpinejs/packages/alpinejs/src/directives/x-transition.js334
-rw-r--r--alpinejs/packages/alpinejs/src/evaluator.js132
-rw-r--r--alpinejs/packages/alpinejs/src/ids.js20
-rw-r--r--alpinejs/packages/alpinejs/src/index.js74
-rw-r--r--alpinejs/packages/alpinejs/src/interceptor.js77
-rw-r--r--alpinejs/packages/alpinejs/src/lifecycle.js84
-rw-r--r--alpinejs/packages/alpinejs/src/magics.js36
-rw-r--r--alpinejs/packages/alpinejs/src/magics/$data.js4
-rw-r--r--alpinejs/packages/alpinejs/src/magics/$dispatch.js4
-rw-r--r--alpinejs/packages/alpinejs/src/magics/$el.js3
-rw-r--r--alpinejs/packages/alpinejs/src/magics/$id.js14
-rw-r--r--alpinejs/packages/alpinejs/src/magics/$nextTick.js4
-rw-r--r--alpinejs/packages/alpinejs/src/magics/$refs.js25
-rw-r--r--alpinejs/packages/alpinejs/src/magics/$root.js4
-rw-r--r--alpinejs/packages/alpinejs/src/magics/$store.js4
-rw-r--r--alpinejs/packages/alpinejs/src/magics/$watch.js28
-rw-r--r--alpinejs/packages/alpinejs/src/magics/index.js9
-rw-r--r--alpinejs/packages/alpinejs/src/mutation.js217
-rw-r--r--alpinejs/packages/alpinejs/src/nextTick.js24
-rw-r--r--alpinejs/packages/alpinejs/src/plugin.js5
-rw-r--r--alpinejs/packages/alpinejs/src/reactivity.js62
-rw-r--r--alpinejs/packages/alpinejs/src/scheduler.js38
-rw-r--r--alpinejs/packages/alpinejs/src/scope.js105
-rw-r--r--alpinejs/packages/alpinejs/src/store.js23
-rw-r--r--alpinejs/packages/alpinejs/src/utils/bind.js149
-rw-r--r--alpinejs/packages/alpinejs/src/utils/classes.js58
-rw-r--r--alpinejs/packages/alpinejs/src/utils/debounce.js18
-rw-r--r--alpinejs/packages/alpinejs/src/utils/dispatch.js12
-rw-r--r--alpinejs/packages/alpinejs/src/utils/error.js15
-rw-r--r--alpinejs/packages/alpinejs/src/utils/on.js167
-rw-r--r--alpinejs/packages/alpinejs/src/utils/once.js14
-rw-r--r--alpinejs/packages/alpinejs/src/utils/styles.js50
-rw-r--r--alpinejs/packages/alpinejs/src/utils/throttle.js16
-rw-r--r--alpinejs/packages/alpinejs/src/utils/walk.js38
-rw-r--r--alpinejs/packages/alpinejs/src/utils/warn.js4
-rw-r--r--alpinejs/packages/collapse/builds/cdn.js5
-rw-r--r--alpinejs/packages/collapse/builds/module.js3
-rw-r--r--alpinejs/packages/collapse/dist/cdn.js23
-rw-r--r--alpinejs/packages/collapse/dist/cdn.min.js2
-rw-r--r--alpinejs/packages/collapse/dist/module.cjs.js23
-rw-r--r--alpinejs/packages/collapse/dist/module.esm.js23
-rw-r--r--alpinejs/packages/collapse/package.json11
-rw-r--r--alpinejs/packages/collapse/src/index.js90
-rw-r--r--alpinejs/packages/csp/builds/cdn.js7
-rw-r--r--alpinejs/packages/csp/builds/module.js3
-rw-r--r--alpinejs/packages/csp/dist/cdn.js659
-rw-r--r--alpinejs/packages/csp/dist/cdn.min.js4
-rw-r--r--alpinejs/packages/csp/dist/module.cjs.js661
-rw-r--r--alpinejs/packages/csp/dist/module.esm.js661
-rw-r--r--alpinejs/packages/csp/package.json12
-rw-r--r--alpinejs/packages/csp/src/index.js38
-rw-r--r--alpinejs/packages/docs/package.json7
-rw-r--r--alpinejs/packages/docs/src/en/advanced.md5
-rw-r--r--alpinejs/packages/docs/src/en/advanced/async.md40
-rw-r--r--alpinejs/packages/docs/src/en/advanced/csp.md72
-rw-r--r--alpinejs/packages/docs/src/en/advanced/extending.md360
-rw-r--r--alpinejs/packages/docs/src/en/advanced/reactivity.md101
-rw-r--r--alpinejs/packages/docs/src/en/directives.md7
-rw-r--r--alpinejs/packages/docs/src/en/directives/bind.md197
-rw-r--r--alpinejs/packages/docs/src/en/directives/cloak.md38
-rw-r--r--alpinejs/packages/docs/src/en/directives/data.md170
-rw-r--r--alpinejs/packages/docs/src/en/directives/effect.md20
-rw-r--r--alpinejs/packages/docs/src/en/directives/for.md87
-rw-r--r--alpinejs/packages/docs/src/en/directives/html.md29
-rw-r--r--alpinejs/packages/docs/src/en/directives/id.md33
-rw-r--r--alpinejs/packages/docs/src/en/directives/if.md20
-rw-r--r--alpinejs/packages/docs/src/en/directives/ignore.md20
-rw-r--r--alpinejs/packages/docs/src/en/directives/init.md74
-rw-r--r--alpinejs/packages/docs/src/en/directives/model.md374
-rw-r--r--alpinejs/packages/docs/src/en/directives/modelable.md37
-rw-r--r--alpinejs/packages/docs/src/en/directives/on.md299
-rw-r--r--alpinejs/packages/docs/src/en/directives/ref.md24
-rw-r--r--alpinejs/packages/docs/src/en/directives/show.md39
-rw-r--r--alpinejs/packages/docs/src/en/directives/teleport.md159
-rw-r--r--alpinejs/packages/docs/src/en/directives/text.md26
-rw-r--r--alpinejs/packages/docs/src/en/directives/transition.md175
-rw-r--r--alpinejs/packages/docs/src/en/essentials.md5
-rw-r--r--alpinejs/packages/docs/src/en/essentials/events.md101
-rw-r--r--alpinejs/packages/docs/src/en/essentials/installation.md68
-rw-r--r--alpinejs/packages/docs/src/en/essentials/lifecycle.md96
-rw-r--r--alpinejs/packages/docs/src/en/essentials/state.md133
-rw-r--r--alpinejs/packages/docs/src/en/essentials/templating.md368
-rw-r--r--alpinejs/packages/docs/src/en/globals.md7
-rw-r--r--alpinejs/packages/docs/src/en/globals/alpine-bind.md36
-rw-r--r--alpinejs/packages/docs/src/en/globals/alpine-data.md136
-rw-r--r--alpinejs/packages/docs/src/en/globals/alpine-store.md115
-rw-r--r--alpinejs/packages/docs/src/en/magics.md7
-rw-r--r--alpinejs/packages/docs/src/en/magics/data.md45
-rw-r--r--alpinejs/packages/docs/src/en/magics/dispatch.md106
-rw-r--r--alpinejs/packages/docs/src/en/magics/el.md21
-rw-r--r--alpinejs/packages/docs/src/en/magics/id.md106
-rw-r--r--alpinejs/packages/docs/src/en/magics/nextTick.md23
-rw-r--r--alpinejs/packages/docs/src/en/magics/refs.md27
-rw-r--r--alpinejs/packages/docs/src/en/magics/root.md21
-rw-r--r--alpinejs/packages/docs/src/en/magics/store.md60
-rw-r--r--alpinejs/packages/docs/src/en/magics/watch.md59
-rw-r--r--alpinejs/packages/docs/src/en/plugins.md6
-rw-r--r--alpinejs/packages/docs/src/en/plugins/collapse.md109
-rw-r--r--alpinejs/packages/docs/src/en/plugins/focus.md420
-rw-r--r--alpinejs/packages/docs/src/en/plugins/intersect.md152
-rw-r--r--alpinejs/packages/docs/src/en/plugins/morph.md252
-rw-r--r--alpinejs/packages/docs/src/en/plugins/persist.md207
-rw-r--r--alpinejs/packages/docs/src/en/start-here.md326
-rw-r--r--alpinejs/packages/docs/src/en/upgrade-guide.md360
-rw-r--r--alpinejs/packages/focus/.gitignore0
-rw-r--r--alpinejs/packages/focus/builds/cdn.js5
-rw-r--r--alpinejs/packages/focus/builds/module.js3
-rw-r--r--alpinejs/packages/focus/dist/cdn.js821
-rw-r--r--alpinejs/packages/focus/dist/cdn.min.js9
-rw-r--r--alpinejs/packages/focus/dist/module.cjs.js879
-rw-r--r--alpinejs/packages/focus/dist/module.esm.js872
-rw-r--r--alpinejs/packages/focus/package.json13
-rw-r--r--alpinejs/packages/focus/src/index.js197
-rw-r--r--alpinejs/packages/history/builds/cdn.js5
-rw-r--r--alpinejs/packages/history/builds/module.js3
-rw-r--r--alpinejs/packages/history/package.json12
-rw-r--r--alpinejs/packages/history/src/index.js76
-rw-r--r--alpinejs/packages/history/src/url.js36
-rw-r--r--alpinejs/packages/intersect/builds/cdn.js5
-rw-r--r--alpinejs/packages/intersect/builds/module.js3
-rw-r--r--alpinejs/packages/intersect/dist/cdn.js20
-rw-r--r--alpinejs/packages/intersect/dist/cdn.min.js2
-rw-r--r--alpinejs/packages/intersect/dist/module.cjs.js20
-rw-r--r--alpinejs/packages/intersect/dist/module.esm.js20
-rw-r--r--alpinejs/packages/intersect/package.json11
-rw-r--r--alpinejs/packages/intersect/src/index.js60
-rw-r--r--alpinejs/packages/morph/builds/cdn.js5
-rw-r--r--alpinejs/packages/morph/builds/module.js5
-rw-r--r--alpinejs/packages/morph/dist/cdn.js247
-rw-r--r--alpinejs/packages/morph/dist/cdn.min.js3
-rw-r--r--alpinejs/packages/morph/dist/module.cjs.js254
-rw-r--r--alpinejs/packages/morph/dist/module.esm.js247
-rw-r--r--alpinejs/packages/morph/package.json9
-rw-r--r--alpinejs/packages/morph/src/index.js7
-rw-r--r--alpinejs/packages/morph/src/morph.js432
-rw-r--r--alpinejs/packages/persist/builds/cdn.js5
-rw-r--r--alpinejs/packages/persist/builds/module.js3
-rw-r--r--alpinejs/packages/persist/package.json11
-rw-r--r--alpinejs/packages/persist/src/index.js44
-rw-r--r--alpinejs/packages/portal/builds/cdn.js5
-rw-r--r--alpinejs/packages/portal/builds/module.js3
-rw-r--r--alpinejs/packages/portal/package.json11
-rw-r--r--alpinejs/packages/portal/src/index.js62
173 files changed, 15802 insertions, 1667 deletions
diff --git a/alpinejs/packages/alpinejs/builds/cdn.js b/alpinejs/packages/alpinejs/builds/cdn.js
new file mode 100644
index 0000000..a54e7e0
--- /dev/null
+++ b/alpinejs/packages/alpinejs/builds/cdn.js
@@ -0,0 +1,7 @@
+import Alpine from './../src/index'
+
+window.Alpine = Alpine
+
+queueMicrotask(() => {
+ Alpine.start()
+})
diff --git a/alpinejs/packages/alpinejs/builds/module.js b/alpinejs/packages/alpinejs/builds/module.js
new file mode 100644
index 0000000..0382080
--- /dev/null
+++ b/alpinejs/packages/alpinejs/builds/module.js
@@ -0,0 +1,3 @@
+import Alpine from './../src/index'
+
+export default Alpine
diff --git a/alpinejs/packages/alpinejs/dist/cdn.js b/alpinejs/packages/alpinejs/dist/cdn.js
index 800464c..4ba2177 100644
--- a/alpinejs/packages/alpinejs/dist/cdn.js
+++ b/alpinejs/packages/alpinejs/dist/cdn.js
@@ -11,6 +11,11 @@
queue.push(job);
queueFlush();
}
+ function dequeueJob(job) {
+ let index = queue.indexOf(job);
+ if (index !== -1)
+ queue.splice(index, 1);
+ }
function queueFlush() {
if (!flushing && !flushPending) {
flushPending = true;
@@ -84,8 +89,15 @@
function onElAdded(callback) {
onElAddeds.push(callback);
}
- function onElRemoved(callback) {
- onElRemoveds.push(callback);
+ function onElRemoved(el, callback) {
+ if (typeof callback === "function") {
+ if (!el._x_cleanups)
+ el._x_cleanups = [];
+ el._x_cleanups.push(callback);
+ } else {
+ callback = el;
+ onElRemoveds.push(callback);
+ }
}
function onAttributesAdded(callback) {
onAttributeAddeds.push(callback);
@@ -198,16 +210,34 @@
addedAttributes.forEach((attrs, el) => {
onAttributeAddeds.forEach((i) => i(el, attrs));
});
- for (let node of addedNodes) {
- if (removedNodes.includes(node))
- continue;
- onElAddeds.forEach((i) => i(node));
- }
for (let node of removedNodes) {
if (addedNodes.includes(node))
continue;
onElRemoveds.forEach((i) => i(node));
+ if (node._x_cleanups) {
+ while (node._x_cleanups.length)
+ node._x_cleanups.pop()();
+ }
+ }
+ addedNodes.forEach((node) => {
+ node._x_ignoreSelf = true;
+ node._x_ignore = true;
+ });
+ for (let node of addedNodes) {
+ if (removedNodes.includes(node))
+ continue;
+ if (!node.isConnected)
+ continue;
+ delete node._x_ignoreSelf;
+ delete node._x_ignore;
+ onElAddeds.forEach((i) => i(node));
+ node._x_ignore = true;
+ node._x_ignoreSelf = true;
}
+ addedNodes.forEach((node) => {
+ delete node._x_ignoreSelf;
+ delete node._x_ignore;
+ });
addedNodes = null;
removedNodes = null;
addedAttributes = null;
@@ -215,15 +245,18 @@
}
// packages/alpinejs/src/scope.js
+ function scope(node) {
+ return mergeProxies(closestDataStack(node));
+ }
function addScopeToNode(node, data2, referenceNode) {
node._x_dataStack = [data2, ...closestDataStack(referenceNode || node)];
return () => {
node._x_dataStack = node._x_dataStack.filter((i) => i !== data2);
};
}
- function refreshScope(element, scope) {
+ function refreshScope(element, scope2) {
let existingScope = element._x_dataStack[0];
- Object.entries(scope).forEach(([key, value]) => {
+ Object.entries(scope2).forEach(([key, value]) => {
existingScope[key] = value;
});
}
@@ -359,7 +392,10 @@
Object.entries(magics).forEach(([name, callback]) => {
Object.defineProperty(obj, `$${name}`, {
get() {
- return callback(el, {Alpine: alpine_default, interceptor});
+ let [utilities, cleanup2] = getElementBoundUtilities(el);
+ utilities = {interceptor, ...utilities};
+ onElRemoved(el, cleanup2);
+ return callback(el, utilities);
},
enumerable: false
});
@@ -416,8 +452,8 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
}
function generateEvaluatorFromFunction(dataStack, func) {
return (receiver = () => {
- }, {scope = {}, params = []} = {}) => {
- let result = func.apply(mergeProxies([scope, ...dataStack]), params);
+ }, {scope: scope2 = {}, params = []} = {}) => {
+ let result = func.apply(mergeProxies([scope2, ...dataStack]), params);
runIfTypeOfFunction(receiver, result);
};
}
@@ -444,27 +480,28 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
function generateEvaluatorFromString(dataStack, expression, el) {
let func = generateFunctionFromString(expression, el);
return (receiver = () => {
- }, {scope = {}, params = []} = {}) => {
+ }, {scope: scope2 = {}, params = []} = {}) => {
func.result = void 0;
func.finished = false;
- let completeScope = mergeProxies([scope, ...dataStack]);
+ let completeScope = mergeProxies([scope2, ...dataStack]);
if (typeof func === "function") {
let promise = func(func, completeScope).catch((error2) => handleError(error2, el, expression));
if (func.finished) {
runIfTypeOfFunction(receiver, func.result, completeScope, params, el);
+ func.result = void 0;
} else {
promise.then((result) => {
runIfTypeOfFunction(receiver, result, completeScope, params, el);
- }).catch((error2) => handleError(error2, el, expression));
+ }).catch((error2) => handleError(error2, el, expression)).finally(() => func.result = void 0);
}
}
};
}
- function runIfTypeOfFunction(receiver, value, scope, params, el) {
+ function runIfTypeOfFunction(receiver, value, scope2, params, el) {
if (typeof value === "function") {
- let result = value.apply(scope, params);
+ let result = value.apply(scope2, params);
if (result instanceof Promise) {
- result.then((i) => runIfTypeOfFunction(receiver, i, scope, params)).catch((error2) => handleError(error2, el, value));
+ result.then((i) => runIfTypeOfFunction(receiver, i, scope2, params)).catch((error2) => handleError(error2, el, value));
} else {
receiver(result);
}
@@ -515,10 +552,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
callback(flushHandlers);
stopDeferring();
}
- function getDirectiveHandler(el, directive2) {
- let noop = () => {
- };
- let handler3 = directiveHandlers[directive2.type] || noop;
+ function getElementBoundUtilities(el) {
let cleanups = [];
let cleanup2 = (callback) => cleanups.push(callback);
let [effect3, cleanupEffect] = elementBoundEffect(el);
@@ -531,7 +565,14 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
evaluate: evaluate.bind(evaluate, el)
};
let doCleanup = () => cleanups.forEach((i) => i());
- onAttributeRemoved(el, directive2.original, doCleanup);
+ return [utilities, doCleanup];
+ }
+ function getDirectiveHandler(el, directive2) {
+ let noop = () => {
+ };
+ let handler3 = directiveHandlers[directive2.type] || noop;
+ let [utilities, cleanup2] = getElementBoundUtilities(el);
+ onAttributeRemoved(el, directive2.original, cleanup2);
let fullHandler = () => {
if (el._x_ignore || el._x_ignoreSelf)
return;
@@ -539,7 +580,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
handler3 = handler3.bind(handler3, el, directive2, utilities);
isDeferringHandlers ? directiveHandlerStacks.get(currentHandlerStackKey).push(handler3) : handler3();
};
- fullHandler.runCleanups = doCleanup;
+ fullHandler.runCleanups = cleanup2;
return fullHandler;
}
var startingWith = (subject, replacement) => ({name, value}) => {
@@ -587,14 +628,17 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
"ignore",
"ref",
"data",
+ "id",
"bind",
"init",
"for",
"model",
+ "modelable",
"transition",
"show",
"if",
DEFAULT,
+ "teleport",
"element"
];
function byPriority(a, b) {
@@ -663,7 +707,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
dispatch(document, "alpine:initializing");
startObservingMutations();
onElAdded((el) => initTree(el, walk));
- onElRemoved((el) => nextTick(() => destroyTree(el)));
+ onElRemoved((el) => destroyTree(el));
onAttributesAdded((el, attrs) => {
directives(el, attrs).forEach((handle) => handle());
});
@@ -688,14 +732,22 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
initSelectorCallbacks.push(selectorCallback);
}
function closestRoot(el, includeInitSelectors = false) {
+ return findClosest(el, (element) => {
+ const selectors = includeInitSelectors ? allSelectors() : rootSelectors();
+ if (selectors.some((selector) => element.matches(selector)))
+ return true;
+ });
+ }
+ function findClosest(el, callback) {
if (!el)
return;
- const selectors = includeInitSelectors ? allSelectors() : rootSelectors();
- if (selectors.some((selector) => el.matches(selector)))
+ if (callback(el))
return el;
+ if (el._x_teleportBack)
+ el = el._x_teleportBack;
if (!el.parentElement)
return;
- return closestRoot(el.parentElement, includeInitSelectors);
+ return findClosest(el.parentElement, callback);
}
function isRoot(el) {
return rootSelectors().some((selector) => el.matches(selector));
@@ -770,7 +822,10 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
let previousStyles = {};
Object.entries(value).forEach(([key, value2]) => {
previousStyles[key] = el.style[key];
- el.style.setProperty(kebabCase(key), value2);
+ if (!key.startsWith("--")) {
+ key = kebabCase(key);
+ }
+ el.style.setProperty(key, value2);
});
setTimeout(() => {
if (el.style.length === 0) {
@@ -785,7 +840,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
let cache = el.getAttribute("style", value);
el.setAttribute("style", value);
return () => {
- el.setAttribute("style", cache);
+ el.setAttribute("style", cache || "");
};
}
function kebabCase(subject) {
@@ -1082,6 +1137,179 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
return rawValue;
}
+ // packages/alpinejs/src/clone.js
+ var isCloning = false;
+ function skipDuringClone(callback, fallback = () => {
+ }) {
+ return (...args) => isCloning ? fallback(...args) : callback(...args);
+ }
+ function clone(oldEl, newEl) {
+ if (!newEl._x_dataStack)
+ newEl._x_dataStack = oldEl._x_dataStack;
+ isCloning = true;
+ dontRegisterReactiveSideEffects(() => {
+ cloneTree(newEl);
+ });
+ isCloning = false;
+ }
+ function cloneTree(el) {
+ let hasRunThroughFirstEl = false;
+ let shallowWalker = (el2, callback) => {
+ walk(el2, (el3, skip) => {
+ if (hasRunThroughFirstEl && isRoot(el3))
+ return skip();
+ hasRunThroughFirstEl = true;
+ callback(el3, skip);
+ });
+ };
+ initTree(el, shallowWalker);
+ }
+ function dontRegisterReactiveSideEffects(callback) {
+ let cache = effect;
+ overrideEffect((callback2, el) => {
+ let storedEffect = cache(callback2);
+ release(storedEffect);
+ return () => {
+ };
+ });
+ callback();
+ overrideEffect(cache);
+ }
+
+ // packages/alpinejs/src/utils/bind.js
+ function bind(el, name, value, modifiers = []) {
+ if (!el._x_bindings)
+ el._x_bindings = reactive({});
+ el._x_bindings[name] = value;
+ name = modifiers.includes("camel") ? camelCase(name) : name;
+ switch (name) {
+ case "value":
+ bindInputValue(el, value);
+ break;
+ case "style":
+ bindStyles(el, value);
+ break;
+ case "class":
+ bindClasses(el, value);
+ break;
+ default:
+ bindAttribute(el, name, value);
+ break;
+ }
+ }
+ function bindInputValue(el, value) {
+ if (el.type === "radio") {
+ if (el.attributes.value === void 0) {
+ el.value = value;
+ }
+ if (window.fromModel) {
+ el.checked = checkedAttrLooseCompare(el.value, value);
+ }
+ } else if (el.type === "checkbox") {
+ if (Number.isInteger(value)) {
+ el.value = value;
+ } else if (!Number.isInteger(value) && !Array.isArray(value) && typeof value !== "boolean" && ![null, void 0].includes(value)) {
+ el.value = String(value);
+ } else {
+ if (Array.isArray(value)) {
+ 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;
+ }
+ }
+ function bindClasses(el, value) {
+ if (el._x_undoAddedClasses)
+ el._x_undoAddedClasses();
+ el._x_undoAddedClasses = setClasses(el, value);
+ }
+ function bindStyles(el, value) {
+ if (el._x_undoAddedStyles)
+ el._x_undoAddedStyles();
+ el._x_undoAddedStyles = setStyles(el, value);
+ }
+ function bindAttribute(el, name, value) {
+ if ([null, void 0, false].includes(value) && attributeShouldntBePreservedIfFalsy(name)) {
+ el.removeAttribute(name);
+ } else {
+ if (isBooleanAttr(name))
+ value = name;
+ setIfChanged(el, name, value);
+ }
+ }
+ function setIfChanged(el, attrName, value) {
+ if (el.getAttribute(attrName) != value) {
+ el.setAttribute(attrName, value);
+ }
+ }
+ function updateSelect(el, value) {
+ const arrayWrappedValue = [].concat(value).map((value2) => {
+ return value2 + "";
+ });
+ Array.from(el.options).forEach((option) => {
+ option.selected = arrayWrappedValue.includes(option.value);
+ });
+ }
+ function camelCase(subject) {
+ return subject.toLowerCase().replace(/-(\w)/g, (match, char) => char.toUpperCase());
+ }
+ function checkedAttrLooseCompare(valueA, valueB) {
+ return valueA == valueB;
+ }
+ function isBooleanAttr(attrName) {
+ 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 attributeShouldntBePreservedIfFalsy(name) {
+ return !["aria-pressed", "aria-checked", "aria-expanded", "aria-selected"].includes(name);
+ }
+ function getBinding(el, name, fallback) {
+ if (el._x_bindings && el._x_bindings[name] !== void 0)
+ return el._x_bindings[name];
+ let attr = el.getAttribute(name);
+ if (attr === null)
+ return typeof fallback === "function" ? fallback() : fallback;
+ if (isBooleanAttr(name)) {
+ return !![name, "true"].includes(attr);
+ }
+ if (attr === "")
+ return true;
+ return attr;
+ }
+
// packages/alpinejs/src/utils/debounce.js
function debounce(func, wait) {
var timeout;
@@ -1135,42 +1363,22 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
return stores;
}
- // packages/alpinejs/src/clone.js
- var isCloning = false;
- function skipDuringClone(callback, fallback = () => {
- }) {
- return (...args) => isCloning ? fallback(...args) : callback(...args);
+ // packages/alpinejs/src/binds.js
+ var binds = {};
+ function bind2(name, object) {
+ binds[name] = typeof object !== "function" ? () => object : object;
}
- function clone(oldEl, newEl) {
- newEl._x_dataStack = oldEl._x_dataStack;
- isCloning = true;
- dontRegisterReactiveSideEffects(() => {
- cloneTree(newEl);
- });
- isCloning = false;
- }
- function cloneTree(el) {
- let hasRunThroughFirstEl = false;
- let shallowWalker = (el2, callback) => {
- walk(el2, (el3, skip) => {
- if (hasRunThroughFirstEl && isRoot(el3))
- return skip();
- hasRunThroughFirstEl = true;
- callback(el3, skip);
+ function injectBindingProviders(obj) {
+ Object.entries(binds).forEach(([name, callback]) => {
+ Object.defineProperty(obj, name, {
+ get() {
+ return (...args) => {
+ return callback(...args);
+ };
+ }
});
- };
- initTree(el, shallowWalker);
- }
- function dontRegisterReactiveSideEffects(callback) {
- let cache = effect;
- overrideEffect((callback2, el) => {
- let storedEffect = cache(callback2);
- release(storedEffect);
- return () => {
- };
});
- callback();
- overrideEffect(cache);
+ return obj;
}
// packages/alpinejs/src/datas.js
@@ -1206,19 +1414,23 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
get raw() {
return raw;
},
- version: "3.5.1",
+ version: "3.9.1",
flushAndStopDeferringMutations,
disableEffectScheduling,
stopObservingMutations,
+ destroyTree,
setReactivityEngine,
+ closestDataStack,
skipDuringClone,
addRootSelector,
+ addInitSelector,
+ addScopeToNode,
deferMutations,
mapAttributes,
evaluateLater,
setEvaluator,
mergeProxies,
- destroyTree,
+ findClosest,
closestRoot,
interceptor,
transition,
@@ -1230,13 +1442,17 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
evaluate,
initTree,
nextTick,
+ prefixed: prefix,
prefix: setPrefix,
plugin,
magic,
store,
start,
clone,
- data
+ bound: getBinding,
+ $data: scope,
+ data,
+ bind: bind2
};
var alpine_default = Alpine;
@@ -1271,7 +1487,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
[3]: "FORWARDED"
};
var specialBooleanAttrs = `itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly`;
- var isBooleanAttr = /* @__PURE__ */ makeMap(specialBooleanAttrs + `,async,autofocus,autoplay,controls,default,defer,disabled,hidden,loop,open,required,reversed,scoped,seamless,checked,muted,multiple,selected`);
+ var isBooleanAttr2 = /* @__PURE__ */ makeMap(specialBooleanAttrs + `,async,autofocus,autoplay,controls,default,defer,disabled,hidden,loop,open,required,reversed,scoped,seamless,checked,muted,multiple,selected`);
var EMPTY_OBJ = true ? Object.freeze({}) : {};
var EMPTY_ARR = true ? Object.freeze([]) : [];
var extend = Object.assign;
@@ -1926,15 +2142,12 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
magic("dispatch", (el) => dispatch.bind(dispatch, el));
// packages/alpinejs/src/magics/$watch.js
- magic("watch", (el) => (key, callback) => {
- let evaluate2 = evaluateLater(el, key);
+ magic("watch", (el, {evaluateLater: evaluateLater2, effect: effect3}) => (key, callback) => {
+ let evaluate2 = evaluateLater2(key);
let firstTime = true;
let oldValue;
- let [effect3, cleanupEffect] = elementBoundEffect(el);
- onAttributeRemoved(el, key, cleanupEffect);
effect3(() => evaluate2((value) => {
- let div = document.createElement("div");
- div.dataset.throwAway = value;
+ JSON.stringify(value);
if (!firstTime) {
queueMicrotask(() => {
callback(value, oldValue);
@@ -1951,9 +2164,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
magic("store", getStores);
// packages/alpinejs/src/magics/$data.js
- magic("data", (el) => {
- return mergeProxies(closestDataStack(el));
- });
+ magic("data", (el) => scope(el));
// packages/alpinejs/src/magics/$root.js
magic("root", (el) => closestRoot(el));
@@ -1976,9 +2187,88 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
return refObjects;
}
+ // packages/alpinejs/src/ids.js
+ var globalIdMemo = {};
+ function findAndIncrementId(name) {
+ if (!globalIdMemo[name])
+ globalIdMemo[name] = 0;
+ return ++globalIdMemo[name];
+ }
+ function closestIdRoot(el, name) {
+ return findClosest(el, (element) => {
+ if (element._x_ids && element._x_ids[name])
+ return true;
+ });
+ }
+ function setIdRoot(el, name) {
+ if (!el._x_ids)
+ el._x_ids = {};
+ if (!el._x_ids[name])
+ el._x_ids[name] = findAndIncrementId(name);
+ }
+
+ // packages/alpinejs/src/magics/$id.js
+ magic("id", (el) => (name, key = null) => {
+ let root = closestIdRoot(el, name);
+ let id = root ? root._x_ids[name] : findAndIncrementId(name);
+ return key ? `${name}-${id}-${key}` : `${name}-${id}`;
+ });
+
// packages/alpinejs/src/magics/$el.js
magic("el", (el) => el);
+ // packages/alpinejs/src/directives/x-modelable.js
+ directive("modelable", (el, {expression}, {effect: effect3, evaluate: evaluate2, evaluateLater: evaluateLater2}) => {
+ let func = evaluateLater2(expression);
+ let innerGet = () => {
+ let result;
+ func((i) => result = i);
+ return result;
+ };
+ let evaluateInnerSet = evaluateLater2(`${expression} = __placeholder`);
+ let innerSet = (val) => evaluateInnerSet(() => {
+ }, {scope: {__placeholder: val}});
+ let initialValue = innerGet();
+ if (el._x_modelable_hook)
+ initialValue = el._x_modelable_hook(initialValue);
+ innerSet(initialValue);
+ queueMicrotask(() => {
+ if (!el._x_model)
+ return;
+ let outerGet = el._x_model.get;
+ let outerSet = el._x_model.set;
+ effect3(() => innerSet(outerGet()));
+ effect3(() => outerSet(innerGet()));
+ });
+ });
+
+ // packages/alpinejs/src/directives/x-teleport.js
+ directive("teleport", (el, {expression}, {cleanup: cleanup2}) => {
+ if (el.tagName.toLowerCase() !== "template")
+ warn("x-teleport can only be used on a <template> tag", el);
+ let target = document.querySelector(expression);
+ if (!target)
+ warn(`Cannot find x-teleport element for selector: "${expression}"`);
+ let clone2 = el.content.cloneNode(true).firstElementChild;
+ el._x_teleport = clone2;
+ clone2._x_teleportBack = el;
+ if (el._x_forwardEvents) {
+ el._x_forwardEvents.forEach((eventName) => {
+ clone2.addEventListener(eventName, (e) => {
+ e.stopPropagation();
+ el.dispatchEvent(new e.constructor(e.type, e));
+ });
+ });
+ }
+ addScopeToNode(clone2, {}, el);
+ mutateDom(() => {
+ target.appendChild(clone2);
+ initTree(clone2);
+ clone2._x_ignore = true;
+ });
+ cleanup2(() => clone2.remove());
+ });
+
// packages/alpinejs/src/directives/x-ignore.js
var handler = () => {
};
@@ -1993,127 +2283,6 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
// packages/alpinejs/src/directives/x-effect.js
directive("effect", (el, {expression}, {effect: effect3}) => effect3(evaluateLater(el, expression)));
- // packages/alpinejs/src/utils/bind.js
- function bind(el, name, value, modifiers = []) {
- if (!el._x_bindings)
- el._x_bindings = reactive({});
- el._x_bindings[name] = value;
- name = modifiers.includes("camel") ? camelCase(name) : name;
- switch (name) {
- case "value":
- bindInputValue(el, value);
- break;
- case "style":
- bindStyles(el, value);
- break;
- case "class":
- bindClasses(el, value);
- break;
- default:
- bindAttribute(el, name, value);
- break;
- }
- }
- function bindInputValue(el, value) {
- if (el.type === "radio") {
- if (el.attributes.value === void 0) {
- el.value = value;
- }
- if (window.fromModel) {
- el.checked = checkedAttrLooseCompare(el.value, value);
- }
- } else if (el.type === "checkbox") {
- if (Number.isInteger(value)) {
- el.value = value;
- } else if (!Number.isInteger(value) && !Array.isArray(value) && typeof value !== "boolean" && ![null, void 0].includes(value)) {
- el.value = String(value);
- } else {
- if (Array.isArray(value)) {
- 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;
- }
- }
- function bindClasses(el, value) {
- if (el._x_undoAddedClasses)
- el._x_undoAddedClasses();
- el._x_undoAddedClasses = setClasses(el, value);
- }
- function bindStyles(el, value) {
- if (el._x_undoAddedStyles)
- el._x_undoAddedStyles();
- el._x_undoAddedStyles = setStyles(el, value);
- }
- function bindAttribute(el, name, value) {
- if ([null, void 0, false].includes(value) && attributeShouldntBePreservedIfFalsy(name)) {
- el.removeAttribute(name);
- } else {
- if (isBooleanAttr2(name))
- value = name;
- setIfChanged(el, name, value);
- }
- }
- function setIfChanged(el, attrName, value) {
- if (el.getAttribute(attrName) != value) {
- el.setAttribute(attrName, value);
- }
- }
- function updateSelect(el, value) {
- const arrayWrappedValue = [].concat(value).map((value2) => {
- return value2 + "";
- });
- Array.from(el.options).forEach((option) => {
- option.selected = arrayWrappedValue.includes(option.value);
- });
- }
- function camelCase(subject) {
- return subject.toLowerCase().replace(/-(\w)/g, (match, char) => char.toUpperCase());
- }
- function checkedAttrLooseCompare(valueA, valueB) {
- return valueA == valueB;
- }
- function isBooleanAttr2(attrName) {
- 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 attributeShouldntBePreservedIfFalsy(name) {
- return !["aria-pressed", "aria-checked", "aria-expanded"].includes(name);
- }
-
// packages/alpinejs/src/utils/on.js
function on(el, event, modifiers, callback) {
let listenerTarget = el;
@@ -2345,11 +2514,11 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
// packages/alpinejs/src/directives/x-init.js
addInitSelector(() => `[${prefix("init")}]`);
- directive("init", skipDuringClone((el, {expression}) => {
+ directive("init", skipDuringClone((el, {expression}, {evaluate: evaluate2}) => {
if (typeof expression === "string") {
- return !!expression.trim() && evaluate(el, expression, {}, false);
+ return !!expression.trim() && evaluate2(expression, {}, false);
}
- return evaluate(el, expression, {}, false);
+ return evaluate2(expression, {}, false);
}));
// packages/alpinejs/src/directives/x-text.js
@@ -2377,8 +2546,9 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
// packages/alpinejs/src/directives/x-bind.js
mapAttributes(startingWith(":", into(prefix("bind:"))));
directive("bind", (el, {value, modifiers, expression, original}, {effect: effect3}) => {
- if (!value)
+ if (!value) {
return applyBindingsObject(el, expression, original, effect3);
+ }
if (value === "key")
return storeKeyForXFor(el, expression);
let evaluate2 = evaluateLater(el, expression);
@@ -2389,32 +2559,29 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
}));
});
function applyBindingsObject(el, expression, original, effect3) {
+ let bindingProviders = {};
+ injectBindingProviders(bindingProviders);
let getBindings = evaluateLater(el, expression);
let cleanupRunners = [];
- effect3(() => {
- while (cleanupRunners.length)
- cleanupRunners.pop()();
- getBindings((bindings) => {
- let attributes = Object.entries(bindings).map(([name, value]) => ({name, value}));
- attributes = attributes.filter((attr) => {
- return !(typeof attr.value === "object" && !Array.isArray(attr.value) && attr.value !== null);
- });
- let staticAttributes = attributesOnly(attributes);
- attributes = attributes.map((attribute) => {
- if (staticAttributes.find((attr) => attr.name === attribute.name)) {
- return {
- name: `x-bind:${attribute.name}`,
- value: `"${attribute.value}"`
- };
- }
- return attribute;
- });
- directives(el, attributes, original).map((handle) => {
- cleanupRunners.push(handle.runCleanups);
- handle();
- });
+ while (cleanupRunners.length)
+ cleanupRunners.pop()();
+ getBindings((bindings) => {
+ let attributes = Object.entries(bindings).map(([name, value]) => ({name, value}));
+ let staticAttributes = attributesOnly(attributes);
+ attributes = attributes.map((attribute) => {
+ if (staticAttributes.find((attr) => attr.name === attribute.name)) {
+ return {
+ name: `x-bind:${attribute.name}`,
+ value: `"${attribute.value}"`
+ };
+ }
+ return attribute;
});
- });
+ directives(el, attributes, original).map((handle) => {
+ cleanupRunners.push(handle.runCleanups);
+ handle();
+ });
+ }, {scope: bindingProviders});
}
function storeKeyForXFor(el, expression) {
el._x_keyExpression = expression;
@@ -2509,15 +2676,15 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
let keys = [];
if (isObject2(items)) {
items = Object.entries(items).map(([key, value]) => {
- let scope = getIterationScopeVariables(iteratorNames, value, key, items);
- evaluateKey((value2) => keys.push(value2), {scope: {index: key, ...scope}});
- scopes.push(scope);
+ let scope2 = getIterationScopeVariables(iteratorNames, value, key, items);
+ evaluateKey((value2) => keys.push(value2), {scope: {index: key, ...scope2}});
+ scopes.push(scope2);
});
} else {
for (let i = 0; i < items.length; i++) {
- let scope = getIterationScopeVariables(iteratorNames, items[i], i, items);
- evaluateKey((value) => keys.push(value), {scope: {index: i, ...scope}});
- scopes.push(scope);
+ let scope2 = getIterationScopeVariables(iteratorNames, items[i], i, items);
+ evaluateKey((value) => keys.push(value), {scope: {index: i, ...scope2}});
+ scopes.push(scope2);
}
}
let adds = [];
@@ -2550,6 +2717,9 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
}
for (let i = 0; i < removes.length; i++) {
let key = removes[i];
+ if (!!lookup[key]._x_effects) {
+ lookup[key]._x_effects.forEach(dequeueJob);
+ }
lookup[key].remove();
lookup[key] = null;
delete lookup[key];
@@ -2562,7 +2732,9 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
mutateDom(() => {
elForSpot.after(marker);
elInSpot.after(elForSpot);
+ elForSpot._x_currentIfEl && elForSpot.after(elForSpot._x_currentIfEl);
marker.before(elInSpot);
+ elInSpot._x_currentIfEl && elInSpot.after(elInSpot._x_currentIfEl);
marker.remove();
});
refreshScope(elForSpot, scopes[keys.indexOf(keyForSpot)]);
@@ -2570,10 +2742,12 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
for (let i = 0; i < adds.length; i++) {
let [lastKey2, index] = adds[i];
let lastEl = lastKey2 === "template" ? templateEl : lookup[lastKey2];
- let scope = scopes[index];
+ if (lastEl._x_currentIfEl)
+ lastEl = lastEl._x_currentIfEl;
+ let scope2 = scopes[index];
let key = keys[index];
let clone2 = document.importNode(templateEl.content, true).firstElementChild;
- addScopeToNode(clone2, reactive(scope), templateEl);
+ addScopeToNode(clone2, reactive(scope2), templateEl);
mutateDom(() => {
lastEl.after(clone2);
initTree(clone2);
@@ -2662,6 +2836,11 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
});
el._x_currentIfEl = clone2;
el._x_undoIf = () => {
+ walk(clone2, (node) => {
+ if (!!node._x_effects) {
+ node._x_effects.forEach(dequeueJob);
+ }
+ });
clone2.remove();
delete el._x_currentIfEl;
};
@@ -2679,11 +2858,23 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
cleanup2(() => el._x_undoIf && el._x_undoIf());
});
+ // packages/alpinejs/src/directives/x-id.js
+ directive("id", (el, {expression}, {evaluate: evaluate2}) => {
+ let names = evaluate2(expression);
+ names.forEach((name) => setIdRoot(el, name));
+ });
+
// packages/alpinejs/src/directives/x-on.js
mapAttributes(startingWith("@", into(prefix("on:"))));
directive("on", skipDuringClone((el, {value, modifiers, expression}, {cleanup: cleanup2}) => {
let evaluate2 = expression ? evaluateLater(el, expression) : () => {
};
+ if (el.tagName.toLowerCase() === "template") {
+ if (!el._x_forwardEvents)
+ el._x_forwardEvents = [];
+ if (!el._x_forwardEvents.includes(value))
+ el._x_forwardEvents.push(value);
+ }
let removeListener = on(el, value, modifiers, (e) => {
evaluate2(() => {
}, {scope: {$event: e}, params: [e]});
diff --git a/alpinejs/packages/alpinejs/dist/cdn.min.js b/alpinejs/packages/alpinejs/dist/cdn.min.js
index 7143450..06be4e5 100644
--- a/alpinejs/packages/alpinejs/dist/cdn.min.js
+++ b/alpinejs/packages/alpinejs/dist/cdn.min.js
@@ -1,5 +1,5 @@
-(()=>{var Ve=!1,Be=!1,ee=[];function Rt(e){Hr(e)}function Hr(e){ee.includes(e)||ee.push(e),qr()}function qr(){!Be&&!Ve&&(Ve=!0,queueMicrotask(Ur))}function Ur(){Ve=!1,Be=!0;for(let e=0;e<ee.length;e++)ee[e]();ee.length=0,Be=!1}var w,j,U,He,qe=!0;function Ct(e){qe=!1,e(),qe=!0}function Mt(e){w=e.reactive,U=e.release,j=t=>e.effect(t,{scheduler:r=>{qe?Rt(r):r()}}),He=e.raw}function Ue(e){j=e}function he(e){let t=()=>{};return[n=>{let i=j(n);e._x_effects||(e._x_effects=new Set,e._x_runEffects=()=>{e._x_effects.forEach(o=>o())}),e._x_effects.add(i),t=()=>{i!==void 0&&(e._x_effects.delete(i),U(i))}},()=>{t()}]}var Nt=[],kt=[],Dt=[];function Pt(e){Dt.push(e)}function It(e){kt.push(e)}function Lt(e){Nt.push(e)}function W(e,t,r){e._x_attributeCleanups||(e._x_attributeCleanups={}),e._x_attributeCleanups[t]||(e._x_attributeCleanups[t]=[]),e._x_attributeCleanups[t].push(r)}function We(e,t){!e._x_attributeCleanups||Object.entries(e._x_attributeCleanups).forEach(([r,n])=>{(t===void 0||t.includes(r))&&(n.forEach(i=>i()),delete e._x_attributeCleanups[r])})}var Ye=new MutationObserver(Ge),Je=!1;function Ze(){Ye.observe(document,{subtree:!0,childList:!0,attributes:!0,attributeOldValue:!0}),Je=!0}function Qe(){Wr(),Ye.disconnect(),Je=!1}var te=[],Xe=!1;function Wr(){te=te.concat(Ye.takeRecords()),te.length&&!Xe&&(Xe=!0,queueMicrotask(()=>{Gr(),Xe=!1}))}function Gr(){Ge(te),te.length=0}function h(e){if(!Je)return e();Qe();let t=e();return Ze(),t}var et=!1,ge=[];function $t(){et=!0}function jt(){et=!1,Ge(ge),ge=[]}function Ge(e){if(et){ge=ge.concat(e);return}let t=[],r=[],n=new Map,i=new Map;for(let o=0;o<e.length;o++)if(!e[o].target._x_ignoreMutationObserver&&(e[o].type==="childList"&&(e[o].addedNodes.forEach(s=>s.nodeType===1&&t.push(s)),e[o].removedNodes.forEach(s=>s.nodeType===1&&r.push(s))),e[o].type==="attributes")){let s=e[o].target,a=e[o].attributeName,c=e[o].oldValue,l=()=>{n.has(s)||n.set(s,[]),n.get(s).push({name:a,value:s.getAttribute(a)})},u=()=>{i.has(s)||i.set(s,[]),i.get(s).push(a)};s.hasAttribute(a)&&c===null?l():s.hasAttribute(a)?(u(),l()):u()}i.forEach((o,s)=>{We(s,o)}),n.forEach((o,s)=>{Nt.forEach(a=>a(s,o))});for(let o of t)r.includes(o)||Dt.forEach(s=>s(o));for(let o of r)t.includes(o)||kt.forEach(s=>s(o));t=null,r=null,n=null,i=null}function G(e,t,r){return e._x_dataStack=[t,...F(r||e)],()=>{e._x_dataStack=e._x_dataStack.filter(n=>n!==t)}}function tt(e,t){let r=e._x_dataStack[0];Object.entries(t).forEach(([n,i])=>{r[n]=i})}function F(e){return e._x_dataStack?e._x_dataStack:typeof ShadowRoot=="function"&&e instanceof ShadowRoot?F(e.host):e.parentNode?F(e.parentNode):[]}function M(e){let t=new Proxy({},{ownKeys:()=>Array.from(new Set(e.flatMap(r=>Object.keys(r)))),has:(r,n)=>e.some(i=>i.hasOwnProperty(n)),get:(r,n)=>(e.find(i=>{if(i.hasOwnProperty(n)){let o=Object.getOwnPropertyDescriptor(i,n);if(o.get&&o.get._x_alreadyBound||o.set&&o.set._x_alreadyBound)return!0;if((o.get||o.set)&&o.enumerable){let s=o.get,a=o.set,c=o;s=s&&s.bind(t),a=a&&a.bind(t),s&&(s._x_alreadyBound=!0),a&&(a._x_alreadyBound=!0),Object.defineProperty(i,n,{...c,get:s,set:a})}return!0}return!1})||{})[n],set:(r,n,i)=>{let o=e.find(s=>s.hasOwnProperty(n));return o?o[n]=i:e[e.length-1][n]=i,!0}});return t}function _e(e){let t=n=>typeof n=="object"&&!Array.isArray(n)&&n!==null,r=(n,i="")=>{Object.entries(Object.getOwnPropertyDescriptors(n)).forEach(([o,{value:s,enumerable:a}])=>{if(a===!1||s===void 0)return;let c=i===""?o:`${i}.${o}`;typeof s=="object"&&s!==null&&s._x_interceptor?n[o]=s.initialize(e,c,o):t(s)&&s!==n&&!(s instanceof Element)&&r(s,c)})};return r(e)}function ye(e,t=()=>{}){let r={initialValue:void 0,_x_interceptor:!0,initialize(n,i,o){return e(this.initialValue,()=>Yr(n,i),s=>rt(n,i,s),i,o)}};return t(r),n=>{if(typeof n=="object"&&n!==null&&n._x_interceptor){let i=r.initialize.bind(r);r.initialize=(o,s,a)=>{let c=n.initialize(o,s,a);return r.initialValue=c,i(o,s,a)}}else r.initialValue=n;return r}}function Yr(e,t){return t.split(".").reduce((r,n)=>r[n],e)}function rt(e,t,r){if(typeof t=="string"&&(t=t.split(".")),t.length===1)e[t[0]]=r;else{if(t.length===0)throw error;return e[t[0]]||(e[t[0]]={}),rt(e[t[0]],t.slice(1),r)}}var Ft={};function b(e,t){Ft[e]=t}function re(e,t){return Object.entries(Ft).forEach(([r,n])=>{Object.defineProperty(e,`$${r}`,{get(){return n(t,{Alpine:S,interceptor:ye})},enumerable:!1})}),{obj:e,cleanup:()=>{t=null}}}function Kt(e,t,r,...n){try{return r(...n)}catch(i){Y(i,e,t)}}function Y(e,t,r=void 0){Object.assign(e,{el:t,expression:r}),console.warn(`Alpine Expression Error: ${e.message}
+(()=>{var Ue=!1,We=!1,F=[];function Dt(e){nn(e)}function nn(e){F.includes(e)||F.push(e),on()}function he(e){let t=F.indexOf(e);t!==-1&&F.splice(t,1)}function on(){!We&&!Ue&&(Ue=!0,queueMicrotask(sn))}function sn(){Ue=!1,We=!0;for(let e=0;e<F.length;e++)F[e]();F.length=0,We=!1}var A,K,Y,Ge,Ye=!0;function $t(e){Ye=!1,e(),Ye=!0}function Lt(e){A=e.reactive,Y=e.release,K=t=>e.effect(t,{scheduler:r=>{Ye?Dt(r):r()}}),Ge=e.raw}function Je(e){K=e}function jt(e){let t=()=>{};return[n=>{let i=K(n);e._x_effects||(e._x_effects=new Set,e._x_runEffects=()=>{e._x_effects.forEach(o=>o())}),e._x_effects.add(i),t=()=>{i!==void 0&&(e._x_effects.delete(i),Y(i))}},()=>{t()}]}var Ft=[],Kt=[],Bt=[];function zt(e){Bt.push(e)}function _e(e,t){typeof t=="function"?(e._x_cleanups||(e._x_cleanups=[]),e._x_cleanups.push(t)):(t=e,Kt.push(t))}function Vt(e){Ft.push(e)}function ge(e,t,r){e._x_attributeCleanups||(e._x_attributeCleanups={}),e._x_attributeCleanups[t]||(e._x_attributeCleanups[t]=[]),e._x_attributeCleanups[t].push(r)}function Ze(e,t){!e._x_attributeCleanups||Object.entries(e._x_attributeCleanups).forEach(([r,n])=>{(t===void 0||t.includes(r))&&(n.forEach(i=>i()),delete e._x_attributeCleanups[r])})}var Xe=new MutationObserver(Qe),et=!1;function tt(){Xe.observe(document,{subtree:!0,childList:!0,attributes:!0,attributeOldValue:!0}),et=!0}function rt(){an(),Xe.disconnect(),et=!1}var te=[],nt=!1;function an(){te=te.concat(Xe.takeRecords()),te.length&&!nt&&(nt=!0,queueMicrotask(()=>{cn(),nt=!1}))}function cn(){Qe(te),te.length=0}function m(e){if(!et)return e();rt();let t=e();return tt(),t}var it=!1,xe=[];function Ht(){it=!0}function qt(){it=!1,Qe(xe),xe=[]}function Qe(e){if(it){xe=xe.concat(e);return}let t=[],r=[],n=new Map,i=new Map;for(let o=0;o<e.length;o++)if(!e[o].target._x_ignoreMutationObserver&&(e[o].type==="childList"&&(e[o].addedNodes.forEach(s=>s.nodeType===1&&t.push(s)),e[o].removedNodes.forEach(s=>s.nodeType===1&&r.push(s))),e[o].type==="attributes")){let s=e[o].target,a=e[o].attributeName,c=e[o].oldValue,l=()=>{n.has(s)||n.set(s,[]),n.get(s).push({name:a,value:s.getAttribute(a)})},u=()=>{i.has(s)||i.set(s,[]),i.get(s).push(a)};s.hasAttribute(a)&&c===null?l():s.hasAttribute(a)?(u(),l()):u()}i.forEach((o,s)=>{Ze(s,o)}),n.forEach((o,s)=>{Ft.forEach(a=>a(s,o))});for(let o of r)if(!t.includes(o)&&(Kt.forEach(s=>s(o)),o._x_cleanups))for(;o._x_cleanups.length;)o._x_cleanups.pop()();t.forEach(o=>{o._x_ignoreSelf=!0,o._x_ignore=!0});for(let o of t)r.includes(o)||!o.isConnected||(delete o._x_ignoreSelf,delete o._x_ignore,Bt.forEach(s=>s(o)),o._x_ignore=!0,o._x_ignoreSelf=!0);t.forEach(o=>{delete o._x_ignoreSelf,delete o._x_ignore}),t=null,r=null,n=null,i=null}function ye(e){return I(k(e))}function T(e,t,r){return e._x_dataStack=[t,...k(r||e)],()=>{e._x_dataStack=e._x_dataStack.filter(n=>n!==t)}}function ot(e,t){let r=e._x_dataStack[0];Object.entries(t).forEach(([n,i])=>{r[n]=i})}function k(e){return e._x_dataStack?e._x_dataStack:typeof ShadowRoot=="function"&&e instanceof ShadowRoot?k(e.host):e.parentNode?k(e.parentNode):[]}function I(e){let t=new Proxy({},{ownKeys:()=>Array.from(new Set(e.flatMap(r=>Object.keys(r)))),has:(r,n)=>e.some(i=>i.hasOwnProperty(n)),get:(r,n)=>(e.find(i=>{if(i.hasOwnProperty(n)){let o=Object.getOwnPropertyDescriptor(i,n);if(o.get&&o.get._x_alreadyBound||o.set&&o.set._x_alreadyBound)return!0;if((o.get||o.set)&&o.enumerable){let s=o.get,a=o.set,c=o;s=s&&s.bind(t),a=a&&a.bind(t),s&&(s._x_alreadyBound=!0),a&&(a._x_alreadyBound=!0),Object.defineProperty(i,n,{...c,get:s,set:a})}return!0}return!1})||{})[n],set:(r,n,i)=>{let o=e.find(s=>s.hasOwnProperty(n));return o?o[n]=i:e[e.length-1][n]=i,!0}});return t}function be(e){let t=n=>typeof n=="object"&&!Array.isArray(n)&&n!==null,r=(n,i="")=>{Object.entries(Object.getOwnPropertyDescriptors(n)).forEach(([o,{value:s,enumerable:a}])=>{if(a===!1||s===void 0)return;let c=i===""?o:`${i}.${o}`;typeof s=="object"&&s!==null&&s._x_interceptor?n[o]=s.initialize(e,c,o):t(s)&&s!==n&&!(s instanceof Element)&&r(s,c)})};return r(e)}function ve(e,t=()=>{}){let r={initialValue:void 0,_x_interceptor:!0,initialize(n,i,o){return e(this.initialValue,()=>ln(n,i),s=>st(n,i,s),i,o)}};return t(r),n=>{if(typeof n=="object"&&n!==null&&n._x_interceptor){let i=r.initialize.bind(r);r.initialize=(o,s,a)=>{let c=n.initialize(o,s,a);return r.initialValue=c,i(o,s,a)}}else r.initialValue=n;return r}}function ln(e,t){return t.split(".").reduce((r,n)=>r[n],e)}function st(e,t,r){if(typeof t=="string"&&(t=t.split(".")),t.length===1)e[t[0]]=r;else{if(t.length===0)throw error;return e[t[0]]||(e[t[0]]={}),st(e[t[0]],t.slice(1),r)}}var Ut={};function y(e,t){Ut[e]=t}function re(e,t){return Object.entries(Ut).forEach(([r,n])=>{Object.defineProperty(e,`$${r}`,{get(){let[i,o]=at(t);return i={interceptor:ve,...i},_e(t,o),n(t,i)},enumerable:!1})}),{obj:e,cleanup:()=>{t=null}}}function Wt(e,t,r,...n){try{return r(...n)}catch(i){J(i,e,t)}}function J(e,t,r=void 0){Object.assign(e,{el:t,expression:r}),console.warn(`Alpine Expression Error: ${e.message}
${r?'Expression: "'+r+`"
-`:""}`,t),setTimeout(()=>{throw e},0)}function v(e,t,r={}){let n;return m(e,t)(i=>n=i,r),n}function m(...e){return zt(...e)}var zt=nt;function Vt(e){zt=e}function nt(e,t){let r={},n=re(r,e).cleanup;W(e,"evaluator",n);let i=[r,...F(e)];if(typeof t=="function")return Jr(i,t);let o=Zr(i,t,e);return Kt.bind(null,e,t,o)}function Jr(e,t){return(r=()=>{},{scope:n={},params:i=[]}={})=>{let o=t.apply(M([n,...e]),i);xe(r,o)}}var it={};function Qr(e,t){if(it[e])return it[e];let r=Object.getPrototypeOf(async function(){}).constructor,n=/^[\n\s]*if.*\(.*\)/.test(e)||/^(let|const)\s/.test(e)?`(() => { ${e} })()`:e,o=(()=>{try{return new r(["__self","scope"],`with (scope) { __self.result = ${n} }; __self.finished = true; return __self.result;`)}catch(s){return Y(s,t,e),Promise.resolve()}})();return it[e]=o,o}function Zr(e,t,r){let n=Qr(t,r);return(i=()=>{},{scope:o={},params:s=[]}={})=>{n.result=void 0,n.finished=!1;let a=M([o,...e]);if(typeof n=="function"){let c=n(n,a).catch(l=>Y(l,r,t));n.finished?xe(i,n.result,a,s,r):c.then(l=>{xe(i,l,a,s,r)}).catch(l=>Y(l,r,t))}}}function xe(e,t,r,n,i){if(typeof t=="function"){let o=t.apply(r,n);o instanceof Promise?o.then(s=>xe(e,s,r,n)).catch(s=>Y(s,i,t)):e(o)}else e(t)}var ot="x-";function A(e=""){return ot+e}function Bt(e){ot=e}var Ht={};function d(e,t){Ht[e]=t}function ne(e,t,r){let n={};return Array.from(t).map(qt((o,s)=>n[o]=s)).filter(Ut).map(en(n,r)).sort(tn).map(o=>Xr(e,o))}function Wt(e){return Array.from(e).map(qt()).filter(t=>!Ut(t))}var st=!1,ie=new Map,Gt=Symbol();function Yt(e){st=!0;let t=Symbol();Gt=t,ie.set(t,[]);let r=()=>{for(;ie.get(t).length;)ie.get(t).shift()();ie.delete(t)},n=()=>{st=!1,r()};e(r),n()}function Xr(e,t){let r=()=>{},n=Ht[t.type]||r,i=[],o=p=>i.push(p),[s,a]=he(e);i.push(a);let c={Alpine:S,effect:s,cleanup:o,evaluateLater:m.bind(m,e),evaluate:v.bind(v,e)},l=()=>i.forEach(p=>p());W(e,t.original,l);let u=()=>{e._x_ignore||e._x_ignoreSelf||(n.inline&&n.inline(e,t,c),n=n.bind(n,e,t,c),st?ie.get(Gt).push(n):n())};return u.runCleanups=l,u}var be=(e,t)=>({name:r,value:n})=>(r.startsWith(e)&&(r=r.replace(e,t)),{name:r,value:n}),ve=e=>e;function qt(e=()=>{}){return({name:t,value:r})=>{let{name:n,value:i}=Jt.reduce((o,s)=>s(o),{name:t,value:r});return n!==t&&e(n,t),{name:n,value:i}}}var Jt=[];function J(e){Jt.push(e)}function Ut({name:e}){return Zt().test(e)}var Zt=()=>new RegExp(`^${ot}([^:^.]+)\\b`);function en(e,t){return({name:r,value:n})=>{let i=r.match(Zt()),o=r.match(/:([a-zA-Z0-9\-:]+)/),s=r.match(/\.[^.\]]+(?=[^\]]*$)/g)||[],a=t||e[r]||r;return{type:i?i[1]:null,value:o?o[1]:null,modifiers:s.map(c=>c.replace(".","")),expression:n,original:a}}}var at="DEFAULT",we=["ignore","ref","data","bind","init","for","model","transition","show","if",at,"element"];function tn(e,t){let r=we.indexOf(e.type)===-1?at:e.type,n=we.indexOf(t.type)===-1?at:t.type;return we.indexOf(r)-we.indexOf(n)}function K(e,t,r={}){e.dispatchEvent(new CustomEvent(t,{detail:r,bubbles:!0,composed:!0,cancelable:!0}))}var ct=[],lt=!1;function Z(e){ct.push(e),queueMicrotask(()=>{lt||setTimeout(()=>{Ee()})})}function Ee(){for(lt=!1;ct.length;)ct.shift()()}function Qt(){lt=!0}function k(e,t){if(typeof ShadowRoot=="function"&&e instanceof ShadowRoot){Array.from(e.children).forEach(i=>k(i,t));return}let r=!1;if(t(e,()=>r=!0),r)return;let n=e.firstElementChild;for(;n;)k(n,t,!1),n=n.nextElementSibling}function Se(e,...t){console.warn(`Alpine Warning: ${e}`,...t)}function er(){document.body||Se("Unable to initialize. Trying to load Alpine before `<body>` is available. Did you forget to add `defer` in Alpine's `<script>` tag?"),K(document,"alpine:init"),K(document,"alpine:initializing"),Ze(),Pt(t=>O(t,k)),It(t=>Z(()=>ut(t))),Lt((t,r)=>{ne(t,r).forEach(n=>n())});let e=t=>!D(t.parentElement,!0);Array.from(document.querySelectorAll(Xt())).filter(e).forEach(t=>{O(t)}),K(document,"alpine:initialized")}var ft=[],tr=[];function rr(){return ft.map(e=>e())}function Xt(){return ft.concat(tr).map(e=>e())}function Ae(e){ft.push(e)}function nr(e){tr.push(e)}function D(e,t=!1){if(!e)return;if((t?Xt():rr()).some(n=>e.matches(n)))return e;if(!!e.parentElement)return D(e.parentElement,t)}function ir(e){return rr().some(t=>e.matches(t))}function O(e,t=k){Yt(()=>{t(e,(r,n)=>{ne(r,r.attributes).forEach(i=>i()),r._x_ignore&&n()})})}function ut(e){k(e,t=>We(t))}function oe(e,t){return Array.isArray(t)?or(e,t.join(" ")):typeof t=="object"&&t!==null?rn(e,t):typeof t=="function"?oe(e,t()):or(e,t)}function or(e,t){let r=o=>o.split(" ").filter(Boolean),n=o=>o.split(" ").filter(s=>!e.classList.contains(s)).filter(Boolean),i=o=>(e.classList.add(...o),()=>{e.classList.remove(...o)});return t=t===!0?t="":t||"",i(n(t))}function rn(e,t){let r=a=>a.split(" ").filter(Boolean),n=Object.entries(t).flatMap(([a,c])=>c?r(a):!1).filter(Boolean),i=Object.entries(t).flatMap(([a,c])=>c?!1:r(a)).filter(Boolean),o=[],s=[];return i.forEach(a=>{e.classList.contains(a)&&(e.classList.remove(a),s.push(a))}),n.forEach(a=>{e.classList.contains(a)||(e.classList.add(a),o.push(a))}),()=>{s.forEach(a=>e.classList.add(a)),o.forEach(a=>e.classList.remove(a))}}function z(e,t){return typeof t=="object"&&t!==null?nn(e,t):on(e,t)}function nn(e,t){let r={};return Object.entries(t).forEach(([n,i])=>{r[n]=e.style[n],e.style.setProperty(sn(n),i)}),setTimeout(()=>{e.style.length===0&&e.removeAttribute("style")}),()=>{z(e,r)}}function on(e,t){let r=e.getAttribute("style",t);return e.setAttribute("style",t),()=>{e.setAttribute("style",r)}}function sn(e){return e.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()}function se(e,t=()=>{}){let r=!1;return function(){r?t.apply(this,arguments):(r=!0,e.apply(this,arguments))}}d("transition",(e,{value:t,modifiers:r,expression:n},{evaluate:i})=>{typeof n=="function"&&(n=i(n)),n?an(e,n,t):cn(e,r,t)});function an(e,t,r){sr(e,oe,""),{enter:i=>{e._x_transition.enter.during=i},"enter-start":i=>{e._x_transition.enter.start=i},"enter-end":i=>{e._x_transition.enter.end=i},leave:i=>{e._x_transition.leave.during=i},"leave-start":i=>{e._x_transition.leave.start=i},"leave-end":i=>{e._x_transition.leave.end=i}}[r](t)}function cn(e,t,r){sr(e,z);let n=!t.includes("in")&&!t.includes("out")&&!r,i=n||t.includes("in")||["enter"].includes(r),o=n||t.includes("out")||["leave"].includes(r);t.includes("in")&&!n&&(t=t.filter((_,x)=>x<t.indexOf("out"))),t.includes("out")&&!n&&(t=t.filter((_,x)=>x>t.indexOf("out")));let s=!t.includes("opacity")&&!t.includes("scale"),a=s||t.includes("opacity"),c=s||t.includes("scale"),l=a?0:1,u=c?ae(t,"scale",95)/100:1,p=ae(t,"delay",0),y=ae(t,"origin","center"),R="opacity, transform",H=ae(t,"duration",150)/1e3,de=ae(t,"duration",75)/1e3,f="cubic-bezier(0.4, 0.0, 0.2, 1)";i&&(e._x_transition.enter.during={transformOrigin:y,transitionDelay:p,transitionProperty:R,transitionDuration:`${H}s`,transitionTimingFunction:f},e._x_transition.enter.start={opacity:l,transform:`scale(${u})`},e._x_transition.enter.end={opacity:1,transform:"scale(1)"}),o&&(e._x_transition.leave.during={transformOrigin:y,transitionDelay:p,transitionProperty:R,transitionDuration:`${de}s`,transitionTimingFunction:f},e._x_transition.leave.start={opacity:1,transform:"scale(1)"},e._x_transition.leave.end={opacity:l,transform:`scale(${u})`})}function sr(e,t,r={}){e._x_transition||(e._x_transition={enter:{during:r,start:r,end:r},leave:{during:r,start:r,end:r},in(n=()=>{},i=()=>{}){Oe(e,t,{during:this.enter.during,start:this.enter.start,end:this.enter.end},n,i)},out(n=()=>{},i=()=>{}){Oe(e,t,{during:this.leave.during,start:this.leave.start,end:this.leave.end},n,i)}})}window.Element.prototype._x_toggleAndCascadeWithTransitions=function(e,t,r,n){let i=()=>{document.visibilityState==="visible"?requestAnimationFrame(r):setTimeout(r)};if(t){e._x_transition&&(e._x_transition.enter||e._x_transition.leave)?e._x_transition.enter&&(Object.entries(e._x_transition.enter.during).length||Object.entries(e._x_transition.enter.start).length||Object.entries(e._x_transition.enter.end).length)?e._x_transition.in(r):i():e._x_transition?e._x_transition.in(r):i();return}e._x_hidePromise=e._x_transition?new Promise((o,s)=>{e._x_transition.out(()=>{},()=>o(n)),e._x_transitioning.beforeCancel(()=>s({isFromCancelledTransition:!0}))}):Promise.resolve(n),queueMicrotask(()=>{let o=ar(e);o?(o._x_hideChildren||(o._x_hideChildren=[]),o._x_hideChildren.push(e)):queueMicrotask(()=>{let s=a=>{let c=Promise.all([a._x_hidePromise,...(a._x_hideChildren||[]).map(s)]).then(([l])=>l());return delete a._x_hidePromise,delete a._x_hideChildren,c};s(e).catch(a=>{if(!a.isFromCancelledTransition)throw a})})})};function ar(e){let t=e.parentNode;if(!!t)return t._x_hidePromise?t:ar(t)}function Oe(e,t,{during:r,start:n,end:i}={},o=()=>{},s=()=>{}){if(e._x_transitioning&&e._x_transitioning.cancel(),Object.keys(r).length===0&&Object.keys(n).length===0&&Object.keys(i).length===0){o(),s();return}let a,c,l;ln(e,{start(){a=t(e,n)},during(){c=t(e,r)},before:o,end(){a(),l=t(e,i)},after:s,cleanup(){c(),l()}})}function ln(e,t){let r,n,i,o=se(()=>{h(()=>{r=!0,n||t.before(),i||(t.end(),Ee()),t.after(),e.isConnected&&t.cleanup(),delete e._x_transitioning})});e._x_transitioning={beforeCancels:[],beforeCancel(s){this.beforeCancels.push(s)},cancel:se(function(){for(;this.beforeCancels.length;)this.beforeCancels.shift()();o()}),finish:o},h(()=>{t.start(),t.during()}),Qt(),requestAnimationFrame(()=>{if(r)return;let s=Number(getComputedStyle(e).transitionDuration.replace(/,.*/,"").replace("s",""))*1e3,a=Number(getComputedStyle(e).transitionDelay.replace(/,.*/,"").replace("s",""))*1e3;s===0&&(s=Number(getComputedStyle(e).animationDuration.replace("s",""))*1e3),h(()=>{t.before()}),n=!0,requestAnimationFrame(()=>{r||(h(()=>{t.end()}),Ee(),setTimeout(e._x_transitioning.finish,s+a),i=!0)})})}function ae(e,t,r){if(e.indexOf(t)===-1)return r;let n=e[e.indexOf(t)+1];if(!n||t==="scale"&&isNaN(n))return r;if(t==="duration"){let i=n.match(/([0-9]+)ms/);if(i)return i[1]}return t==="origin"&&["top","right","left","center","bottom"].includes(e[e.indexOf(t)+2])?[n,e[e.indexOf(t)+2]].join(" "):n}function Te(e,t){var r;return function(){var n=this,i=arguments,o=function(){r=null,e.apply(n,i)};clearTimeout(r),r=setTimeout(o,t)}}function Re(e,t){let r;return function(){let n=this,i=arguments;r||(e.apply(n,i),r=!0,setTimeout(()=>r=!1,t))}}function cr(e){e(S)}var V={},lr=!1;function ur(e,t){if(lr||(V=w(V),lr=!0),t===void 0)return V[e];V[e]=t,typeof t=="object"&&t!==null&&t.hasOwnProperty("init")&&typeof t.init=="function"&&V[e].init(),_e(V[e])}function fr(){return V}var pt=!1;function P(e,t=()=>{}){return(...r)=>pt?t(...r):e(...r)}function pr(e,t){t._x_dataStack=e._x_dataStack,pt=!0,fn(()=>{un(t)}),pt=!1}function un(e){let t=!1;O(e,(n,i)=>{k(n,(o,s)=>{if(t&&ir(o))return s();t=!0,i(o,s)})})}function fn(e){let t=j;Ue((r,n)=>{let i=t(r);return U(i),()=>{}}),e(),Ue(t)}var dr={};function mr(e,t){dr[e]=t}function hr(e,t){return Object.entries(dr).forEach(([r,n])=>{Object.defineProperty(e,r,{get(){return(...i)=>n.bind(t)(...i)},enumerable:!1})}),e}var pn={get reactive(){return w},get release(){return U},get effect(){return j},get raw(){return He},version:"3.5.1",flushAndStopDeferringMutations:jt,disableEffectScheduling:Ct,stopObservingMutations:Qe,setReactivityEngine:Mt,skipDuringClone:P,addRootSelector:Ae,deferMutations:$t,mapAttributes:J,evaluateLater:m,setEvaluator:Vt,mergeProxies:M,destroyTree:ut,closestRoot:D,interceptor:ye,transition:Oe,setStyles:z,mutateDom:h,directive:d,throttle:Re,debounce:Te,evaluate:v,initTree:O,nextTick:Z,prefix:Bt,plugin:cr,magic:b,store:ur,start:er,clone:pr,data:mr},S=pn;function dt(e,t){let r=Object.create(null),n=e.split(",");for(let i=0;i<n.length;i++)r[n[i]]=!0;return t?i=>!!r[i.toLowerCase()]:i=>!!r[i]}var Mo={[1]:"TEXT",[2]:"CLASS",[4]:"STYLE",[8]:"PROPS",[16]:"FULL_PROPS",[32]:"HYDRATE_EVENTS",[64]:"STABLE_FRAGMENT",[128]:"KEYED_FRAGMENT",[256]:"UNKEYED_FRAGMENT",[512]:"NEED_PATCH",[1024]:"DYNAMIC_SLOTS",[2048]:"DEV_ROOT_FRAGMENT",[-1]:"HOISTED",[-2]:"BAIL"},No={[1]:"STABLE",[2]:"DYNAMIC",[3]:"FORWARDED"};var dn="itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly";var ko=dt(dn+",async,autofocus,autoplay,controls,default,defer,disabled,hidden,loop,open,required,reversed,scoped,seamless,checked,muted,multiple,selected");var gr=Object.freeze({}),Do=Object.freeze([]);var mt=Object.assign;var mn=Object.prototype.hasOwnProperty,ce=(e,t)=>mn.call(e,t),I=Array.isArray,Q=e=>_r(e)==="[object Map]";var hn=e=>typeof e=="string",Ce=e=>typeof e=="symbol",le=e=>e!==null&&typeof e=="object";var gn=Object.prototype.toString,_r=e=>gn.call(e),ht=e=>_r(e).slice(8,-1);var Me=e=>hn(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e;var Ne=e=>{let t=Object.create(null);return r=>t[r]||(t[r]=e(r))},_n=/-(\w)/g,Po=Ne(e=>e.replace(_n,(t,r)=>r?r.toUpperCase():"")),yn=/\B([A-Z])/g,Io=Ne(e=>e.replace(yn,"-$1").toLowerCase()),gt=Ne(e=>e.charAt(0).toUpperCase()+e.slice(1)),Lo=Ne(e=>e?`on${gt(e)}`:""),_t=(e,t)=>e!==t&&(e===e||t===t);var yt=new WeakMap,ue=[],T,B=Symbol("iterate"),xt=Symbol("Map key iterate");function xn(e){return e&&e._isEffect===!0}function yr(e,t=gr){xn(e)&&(e=e.raw);let r=bn(e,t);return t.lazy||r(),r}function br(e){e.active&&(xr(e),e.options.onStop&&e.options.onStop(),e.active=!1)}var vn=0;function bn(e,t){let r=function(){if(!r.active)return e();if(!ue.includes(r)){xr(r);try{return wn(),ue.push(r),T=r,e()}finally{ue.pop(),vr(),T=ue[ue.length-1]}}};return r.id=vn++,r.allowRecurse=!!t.allowRecurse,r._isEffect=!0,r.active=!0,r.raw=e,r.deps=[],r.options=t,r}function xr(e){let{deps:t}=e;if(t.length){for(let r=0;r<t.length;r++)t[r].delete(e);t.length=0}}var X=!0,bt=[];function En(){bt.push(X),X=!1}function wn(){bt.push(X),X=!0}function vr(){let e=bt.pop();X=e===void 0?!0:e}function E(e,t,r){if(!X||T===void 0)return;let n=yt.get(e);n||yt.set(e,n=new Map);let i=n.get(r);i||n.set(r,i=new Set),i.has(T)||(i.add(T),T.deps.push(i),T.options.onTrack&&T.options.onTrack({effect:T,target:e,type:t,key:r}))}function L(e,t,r,n,i,o){let s=yt.get(e);if(!s)return;let a=new Set,c=u=>{u&&u.forEach(p=>{(p!==T||p.allowRecurse)&&a.add(p)})};if(t==="clear")s.forEach(c);else if(r==="length"&&I(e))s.forEach((u,p)=>{(p==="length"||p>=n)&&c(u)});else switch(r!==void 0&&c(s.get(r)),t){case"add":I(e)?Me(r)&&c(s.get("length")):(c(s.get(B)),Q(e)&&c(s.get(xt)));break;case"delete":I(e)||(c(s.get(B)),Q(e)&&c(s.get(xt)));break;case"set":Q(e)&&c(s.get(B));break}let l=u=>{u.options.onTrigger&&u.options.onTrigger({effect:u,target:e,key:r,type:t,newValue:n,oldValue:i,oldTarget:o}),u.options.scheduler?u.options.scheduler(u):u()};a.forEach(l)}var Sn=dt("__proto__,__v_isRef,__isVue"),wr=new Set(Object.getOwnPropertyNames(Symbol).map(e=>Symbol[e]).filter(Ce)),An=ke(),On=ke(!1,!0),Tn=ke(!0),Rn=ke(!0,!0),De={};["includes","indexOf","lastIndexOf"].forEach(e=>{let t=Array.prototype[e];De[e]=function(...r){let n=g(this);for(let o=0,s=this.length;o<s;o++)E(n,"get",o+"");let i=t.apply(n,r);return i===-1||i===!1?t.apply(n,r.map(g)):i}});["push","pop","shift","unshift","splice"].forEach(e=>{let t=Array.prototype[e];De[e]=function(...r){En();let n=t.apply(this,r);return vr(),n}});function ke(e=!1,t=!1){return function(n,i,o){if(i==="__v_isReactive")return!e;if(i==="__v_isReadonly")return e;if(i==="__v_raw"&&o===(e?t?Mn:Sr:t?Cn:Er).get(n))return n;let s=I(n);if(!e&&s&&ce(De,i))return Reflect.get(De,i,o);let a=Reflect.get(n,i,o);return(Ce(i)?wr.has(i):Sn(i))||(e||E(n,"get",i),t)?a:vt(a)?!s||!Me(i)?a.value:a:le(a)?e?Ar(a):Pe(a):a}}var Nn=Or(),kn=Or(!0);function Or(e=!1){return function(r,n,i,o){let s=r[n];if(!e&&(i=g(i),s=g(s),!I(r)&&vt(s)&&!vt(i)))return s.value=i,!0;let a=I(r)&&Me(n)?Number(n)<r.length:ce(r,n),c=Reflect.set(r,n,i,o);return r===g(o)&&(a?_t(i,s)&&L(r,"set",n,i,s):L(r,"add",n,i)),c}}function Dn(e,t){let r=ce(e,t),n=e[t],i=Reflect.deleteProperty(e,t);return i&&r&&L(e,"delete",t,void 0,n),i}function Pn(e,t){let r=Reflect.has(e,t);return(!Ce(t)||!wr.has(t))&&E(e,"has",t),r}function In(e){return E(e,"iterate",I(e)?"length":B),Reflect.ownKeys(e)}var Tr={get:An,set:Nn,deleteProperty:Dn,has:Pn,ownKeys:In},Rr={get:Tn,set(e,t){return console.warn(`Set operation on key "${String(t)}" failed: target is readonly.`,e),!0},deleteProperty(e,t){return console.warn(`Delete operation on key "${String(t)}" failed: target is readonly.`,e),!0}},Vo=mt({},Tr,{get:On,set:kn}),Bo=mt({},Rr,{get:Rn}),wt=e=>le(e)?Pe(e):e,Et=e=>le(e)?Ar(e):e,St=e=>e,Ie=e=>Reflect.getPrototypeOf(e);function Le(e,t,r=!1,n=!1){e=e.__v_raw;let i=g(e),o=g(t);t!==o&&!r&&E(i,"get",t),!r&&E(i,"get",o);let{has:s}=Ie(i),a=n?St:r?Et:wt;if(s.call(i,t))return a(e.get(t));if(s.call(i,o))return a(e.get(o));e!==i&&e.get(t)}function $e(e,t=!1){let r=this.__v_raw,n=g(r),i=g(e);return e!==i&&!t&&E(n,"has",e),!t&&E(n,"has",i),e===i?r.has(e):r.has(e)||r.has(i)}function je(e,t=!1){return e=e.__v_raw,!t&&E(g(e),"iterate",B),Reflect.get(e,"size",e)}function Cr(e){e=g(e);let t=g(this);return Ie(t).has.call(t,e)||(t.add(e),L(t,"add",e,e)),this}function Nr(e,t){t=g(t);let r=g(this),{has:n,get:i}=Ie(r),o=n.call(r,e);o?Mr(r,n,e):(e=g(e),o=n.call(r,e));let s=i.call(r,e);return r.set(e,t),o?_t(t,s)&&L(r,"set",e,t,s):L(r,"add",e,t),this}function kr(e){let t=g(this),{has:r,get:n}=Ie(t),i=r.call(t,e);i?Mr(t,r,e):(e=g(e),i=r.call(t,e));let o=n?n.call(t,e):void 0,s=t.delete(e);return i&&L(t,"delete",e,void 0,o),s}function Dr(){let e=g(this),t=e.size!==0,r=Q(e)?new Map(e):new Set(e),n=e.clear();return t&&L(e,"clear",void 0,void 0,r),n}function Fe(e,t){return function(n,i){let o=this,s=o.__v_raw,a=g(s),c=t?St:e?Et:wt;return!e&&E(a,"iterate",B),s.forEach((l,u)=>n.call(i,c(l),c(u),o))}}function Ke(e,t,r){return function(...n){let i=this.__v_raw,o=g(i),s=Q(o),a=e==="entries"||e===Symbol.iterator&&s,c=e==="keys"&&s,l=i[e](...n),u=r?St:t?Et:wt;return!t&&E(o,"iterate",c?xt:B),{next(){let{value:p,done:y}=l.next();return y?{value:p,done:y}:{value:a?[u(p[0]),u(p[1])]:u(p),done:y}},[Symbol.iterator](){return this}}}}function $(e){return function(...t){{let r=t[0]?`on key "${t[0]}" `:"";console.warn(`${gt(e)} operation ${r}failed: target is readonly.`,g(this))}return e==="delete"?!1:this}}var Pr={get(e){return Le(this,e)},get size(){return je(this)},has:$e,add:Cr,set:Nr,delete:kr,clear:Dr,forEach:Fe(!1,!1)},Ir={get(e){return Le(this,e,!1,!0)},get size(){return je(this)},has:$e,add:Cr,set:Nr,delete:kr,clear:Dr,forEach:Fe(!1,!0)},Lr={get(e){return Le(this,e,!0)},get size(){return je(this,!0)},has(e){return $e.call(this,e,!0)},add:$("add"),set:$("set"),delete:$("delete"),clear:$("clear"),forEach:Fe(!0,!1)},$r={get(e){return Le(this,e,!0,!0)},get size(){return je(this,!0)},has(e){return $e.call(this,e,!0)},add:$("add"),set:$("set"),delete:$("delete"),clear:$("clear"),forEach:Fe(!0,!0)},Ln=["keys","values","entries",Symbol.iterator];Ln.forEach(e=>{Pr[e]=Ke(e,!1,!1),Lr[e]=Ke(e,!0,!1),Ir[e]=Ke(e,!1,!0),$r[e]=Ke(e,!0,!0)});function ze(e,t){let r=t?e?$r:Ir:e?Lr:Pr;return(n,i,o)=>i==="__v_isReactive"?!e:i==="__v_isReadonly"?e:i==="__v_raw"?n:Reflect.get(ce(r,i)&&i in n?r:n,i,o)}var $n={get:ze(!1,!1)},Ho={get:ze(!1,!0)},jn={get:ze(!0,!1)},qo={get:ze(!0,!0)};function Mr(e,t,r){let n=g(r);if(n!==r&&t.call(e,n)){let i=ht(e);console.warn(`Reactive ${i} contains both the raw and reactive versions of the same object${i==="Map"?" as keys":""}, which can lead to inconsistencies. Avoid differentiating between the raw and reactive versions of an object and only use the reactive version if possible.`)}}var Er=new WeakMap,Cn=new WeakMap,Sr=new WeakMap,Mn=new WeakMap;function Fn(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function Kn(e){return e.__v_skip||!Object.isExtensible(e)?0:Fn(ht(e))}function Pe(e){return e&&e.__v_isReadonly?e:jr(e,!1,Tr,$n,Er)}function Ar(e){return jr(e,!0,Rr,jn,Sr)}function jr(e,t,r,n,i){if(!le(e))return console.warn(`value cannot be made reactive: ${String(e)}`),e;if(e.__v_raw&&!(t&&e.__v_isReactive))return e;let o=i.get(e);if(o)return o;let s=Kn(e);if(s===0)return e;let a=new Proxy(e,s===2?n:r);return i.set(e,a),a}function g(e){return e&&g(e.__v_raw)||e}function vt(e){return Boolean(e&&e.__v_isRef===!0)}b("nextTick",()=>Z);b("dispatch",e=>K.bind(K,e));b("watch",e=>(t,r)=>{let n=m(e,t),i=!0,o,[s,a]=he(e);W(e,t,a),s(()=>n(c=>{let l=document.createElement("div");l.dataset.throwAway=c,i?o=c:queueMicrotask(()=>{r(c,o),o=c}),i=!1}))});b("store",fr);b("data",e=>M(F(e)));b("root",e=>D(e));b("refs",e=>(e._x_refs_proxy||(e._x_refs_proxy=M(zn(e))),e._x_refs_proxy));function zn(e){let t=[],r=e;for(;r;)r._x_refs&&t.push(r._x_refs),r=r.parentNode;return t}b("el",e=>e);var Fr=()=>{};Fr.inline=(e,{modifiers:t},{cleanup:r})=>{t.includes("self")?e._x_ignoreSelf=!0:e._x_ignore=!0,r(()=>{t.includes("self")?delete e._x_ignoreSelf:delete e._x_ignore})};d("ignore",Fr);d("effect",(e,{expression:t},{effect:r})=>r(m(e,t)));function fe(e,t,r,n=[]){switch(e._x_bindings||(e._x_bindings=w({})),e._x_bindings[t]=r,t=n.includes("camel")?Un(t):t,t){case"value":Vn(e,r);break;case"style":Hn(e,r);break;case"class":Bn(e,r);break;default:qn(e,t,r);break}}function Vn(e,t){if(e.type==="radio")e.attributes.value===void 0&&(e.value=t),window.fromModel&&(e.checked=Kr(e.value,t));else if(e.type==="checkbox")Number.isInteger(t)?e.value=t:!Number.isInteger(t)&&!Array.isArray(t)&&typeof t!="boolean"&&![null,void 0].includes(t)?e.value=String(t):Array.isArray(t)?e.checked=t.some(r=>Kr(r,e.value)):e.checked=!!t;else if(e.tagName==="SELECT")Wn(e,t);else{if(e.value===t)return;e.value=t}}function Bn(e,t){e._x_undoAddedClasses&&e._x_undoAddedClasses(),e._x_undoAddedClasses=oe(e,t)}function Hn(e,t){e._x_undoAddedStyles&&e._x_undoAddedStyles(),e._x_undoAddedStyles=z(e,t)}function qn(e,t,r){[null,void 0,!1].includes(r)&&Jn(t)?e.removeAttribute(t):(Yn(t)&&(r=t),Gn(e,t,r))}function Gn(e,t,r){e.getAttribute(t)!=r&&e.setAttribute(t,r)}function Wn(e,t){let r=[].concat(t).map(n=>n+"");Array.from(e.options).forEach(n=>{n.selected=r.includes(n.value)})}function Un(e){return e.toLowerCase().replace(/-(\w)/g,(t,r)=>r.toUpperCase())}function Kr(e,t){return e==t}function Yn(e){return["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"].includes(e)}function Jn(e){return!["aria-pressed","aria-checked","aria-expanded"].includes(e)}function pe(e,t,r,n){let i=e,o=c=>n(c),s={},a=(c,l)=>u=>l(c,u);if(r.includes("dot")&&(t=Zn(t)),r.includes("camel")&&(t=Qn(t)),r.includes("passive")&&(s.passive=!0),r.includes("capture")&&(s.capture=!0),r.includes("window")&&(i=window),r.includes("document")&&(i=document),r.includes("prevent")&&(o=a(o,(c,l)=>{l.preventDefault(),c(l)})),r.includes("stop")&&(o=a(o,(c,l)=>{l.stopPropagation(),c(l)})),r.includes("self")&&(o=a(o,(c,l)=>{l.target===e&&c(l)})),(r.includes("away")||r.includes("outside"))&&(i=document,o=a(o,(c,l)=>{e.contains(l.target)||e.offsetWidth<1&&e.offsetHeight<1||e._x_isShown!==!1&&c(l)})),o=a(o,(c,l)=>{Xn(t)&&ei(l,r)||c(l)}),r.includes("debounce")){let c=r[r.indexOf("debounce")+1]||"invalid-wait",l=At(c.split("ms")[0])?Number(c.split("ms")[0]):250;o=Te(o,l)}if(r.includes("throttle")){let c=r[r.indexOf("throttle")+1]||"invalid-wait",l=At(c.split("ms")[0])?Number(c.split("ms")[0]):250;o=Re(o,l)}return r.includes("once")&&(o=a(o,(c,l)=>{c(l),i.removeEventListener(t,o,s)})),i.addEventListener(t,o,s),()=>{i.removeEventListener(t,o,s)}}function Zn(e){return e.replace(/-/g,".")}function Qn(e){return e.toLowerCase().replace(/-(\w)/g,(t,r)=>r.toUpperCase())}function At(e){return!Array.isArray(e)&&!isNaN(e)}function ti(e){return e.replace(/([a-z])([A-Z])/g,"$1-$2").replace(/[_\s]/,"-").toLowerCase()}function Xn(e){return["keydown","keyup"].includes(e)}function ei(e,t){let r=t.filter(o=>!["window","document","prevent","stop","once"].includes(o));if(r.includes("debounce")){let o=r.indexOf("debounce");r.splice(o,At((r[o+1]||"invalid-wait").split("ms")[0])?2:1)}if(r.length===0||r.length===1&&zr(e.key).includes(r[0]))return!1;let i=["ctrl","shift","alt","meta","cmd","super"].filter(o=>r.includes(o));return r=r.filter(o=>!i.includes(o)),!(i.length>0&&i.filter(s=>((s==="cmd"||s==="super")&&(s="meta"),e[`${s}Key`])).length===i.length&&zr(e.key).includes(r[0]))}function zr(e){if(!e)return[];e=ti(e);let t={ctrl:"control",slash:"/",space:"-",spacebar:"-",cmd:"meta",esc:"escape",up:"arrow-up",down:"arrow-down",left:"arrow-left",right:"arrow-right",period:".",equal:"="};return t[e]=e,Object.keys(t).map(r=>{if(t[r]===e)return r}).filter(r=>r)}d("model",(e,{modifiers:t,expression:r},{effect:n,cleanup:i})=>{let o=m(e,r),s=`${r} = rightSideOfExpression($event, ${r})`,a=m(e,s);var c=e.tagName.toLowerCase()==="select"||["checkbox","radio"].includes(e.type)||t.includes("lazy")?"change":"input";let l=ri(e,t,r),u=pe(e,c,t,y=>{a(()=>{},{scope:{$event:y,rightSideOfExpression:l}})});i(()=>u());let p=m(e,`${r} = __placeholder`);e._x_model={get(){let y;return o(R=>y=R),y},set(y){p(()=>{},{scope:{__placeholder:y}})}},e._x_forceModelUpdate=()=>{o(y=>{y===void 0&&r.match(/\./)&&(y=""),window.fromModel=!0,h(()=>fe(e,"value",y)),delete window.fromModel})},n(()=>{t.includes("unintrusive")&&document.activeElement.isSameNode(e)||e._x_forceModelUpdate()})});function ri(e,t,r){return e.type==="radio"&&h(()=>{e.hasAttribute("name")||e.setAttribute("name",r)}),(n,i)=>h(()=>{if(n instanceof CustomEvent&&n.detail!==void 0)return n.detail||n.target.value;if(e.type==="checkbox")if(Array.isArray(i)){let o=t.includes("number")?Ot(n.target.value):n.target.value;return n.target.checked?i.concat([o]):i.filter(s=>!ni(s,o))}else return n.target.checked;else{if(e.tagName.toLowerCase()==="select"&&e.multiple)return t.includes("number")?Array.from(n.target.selectedOptions).map(o=>{let s=o.value||o.text;return Ot(s)}):Array.from(n.target.selectedOptions).map(o=>o.value||o.text);{let o=n.target.value;return t.includes("number")?Ot(o):t.includes("trim")?o.trim():o}}})}function Ot(e){let t=e?parseFloat(e):null;return ii(t)?t:e}function ni(e,t){return e==t}function ii(e){return!Array.isArray(e)&&!isNaN(e)}d("cloak",e=>queueMicrotask(()=>h(()=>e.removeAttribute(A("cloak")))));nr(()=>`[${A("init")}]`);d("init",P((e,{expression:t})=>typeof t=="string"?!!t.trim()&&v(e,t,{},!1):v(e,t,{},!1)));d("text",(e,{expression:t},{effect:r,evaluateLater:n})=>{let i=n(t);r(()=>{i(o=>{h(()=>{e.textContent=o})})})});d("html",(e,{expression:t},{effect:r,evaluateLater:n})=>{let i=n(t);r(()=>{i(o=>{e.innerHTML=o})})});J(be(":",ve(A("bind:"))));d("bind",(e,{value:t,modifiers:r,expression:n,original:i},{effect:o})=>{if(!t)return oi(e,n,i,o);if(t==="key")return si(e,n);let s=m(e,n);o(()=>s(a=>{a===void 0&&n.match(/\./)&&(a=""),h(()=>fe(e,t,a,r))}))});function oi(e,t,r,n){let i=m(e,t),o=[];n(()=>{for(;o.length;)o.pop()();i(s=>{let a=Object.entries(s).map(([l,u])=>({name:l,value:u}));a=a.filter(l=>!(typeof l.value=="object"&&!Array.isArray(l.value)&&l.value!==null));let c=Wt(a);a=a.map(l=>c.find(u=>u.name===l.name)?{name:`x-bind:${l.name}`,value:`"${l.value}"`}:l),ne(e,a,r).map(l=>{o.push(l.runCleanups),l()})})})}function si(e,t){e._x_keyExpression=t}Ae(()=>`[${A("data")}]`);d("data",P((e,{expression:t},{cleanup:r})=>{t=t===""?"{}":t;let n={},i=re(n,e).cleanup,o={};hr(o,n);let s=v(e,t,{scope:o});s===void 0&&(s={});let a=re(s,e).cleanup,c=w(s);_e(c);let l=G(e,c);c.init&&v(e,c.init),r(()=>{l(),i(),a(),c.destroy&&v(e,c.destroy)})}));d("show",(e,{modifiers:t,expression:r},{effect:n})=>{let i=m(e,r),o=()=>h(()=>{e.style.display="none",e._x_isShown=!1}),s=()=>h(()=>{e.style.length===1&&e.style.display==="none"?e.removeAttribute("style"):e.style.removeProperty("display"),e._x_isShown=!0}),a=()=>setTimeout(s),c=se(p=>p?s():o(),p=>{typeof e._x_toggleAndCascadeWithTransitions=="function"?e._x_toggleAndCascadeWithTransitions(e,p,s,o):p?a():o()}),l,u=!0;n(()=>i(p=>{!u&&p===l||(t.includes("immediate")&&(p?a():o()),c(p),l=p,u=!1)}))});d("for",(e,{expression:t},{effect:r,cleanup:n})=>{let i=ci(t),o=m(e,i.items),s=m(e,e._x_keyExpression||"index");e._x_prevKeys=[],e._x_lookup={},r(()=>ai(e,i,o,s)),n(()=>{Object.values(e._x_lookup).forEach(a=>a.remove()),delete e._x_prevKeys,delete e._x_lookup})});function ai(e,t,r,n){let i=s=>typeof s=="object"&&!Array.isArray(s),o=e;r(s=>{li(s)&&s>=0&&(s=Array.from(Array(s).keys(),f=>f+1)),s===void 0&&(s=[]);let a=e._x_lookup,c=e._x_prevKeys,l=[],u=[];if(i(s))s=Object.entries(s).map(([f,_])=>{let x=Vr(t,_,f,s);n(C=>u.push(C),{scope:{index:f,...x}}),l.push(x)});else for(let f=0;f<s.length;f++){let _=Vr(t,s[f],f,s);n(x=>u.push(x),{scope:{index:f,..._}}),l.push(_)}let p=[],y=[],R=[],H=[];for(let f=0;f<c.length;f++){let _=c[f];u.indexOf(_)===-1&&R.push(_)}c=c.filter(f=>!R.includes(f));let de="template";for(let f=0;f<u.length;f++){let _=u[f],x=c.indexOf(_);if(x===-1)c.splice(f,0,_),p.push([de,f]);else if(x!==f){let C=c.splice(f,1)[0],N=c.splice(x-1,1)[0];c.splice(f,0,N),c.splice(x,0,C),y.push([C,N])}else H.push(_);de=_}for(let f=0;f<R.length;f++){let _=R[f];a[_].remove(),a[_]=null,delete a[_]}for(let f=0;f<y.length;f++){let[_,x]=y[f],C=a[_],N=a[x],q=document.createElement("div");h(()=>{N.after(q),C.after(N),q.before(C),q.remove()}),tt(N,l[u.indexOf(x)])}for(let f=0;f<p.length;f++){let[_,x]=p[f],C=_==="template"?o:a[_],N=l[x],q=u[x],me=document.importNode(o.content,!0).firstElementChild;G(me,w(N),o),h(()=>{C.after(me),O(me)}),typeof q=="object"&&Se("x-for key cannot be an object, it must be a string or an integer",o),a[q]=me}for(let f=0;f<H.length;f++)tt(a[H[f]],l[u.indexOf(H[f])]);o._x_prevKeys=u})}function ci(e){let t=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,r=/^\s*\(|\)\s*$/g,n=/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/,i=e.match(n);if(!i)return;let o={};o.items=i[2].trim();let s=i[1].replace(r,"").trim(),a=s.match(t);return a?(o.item=s.replace(t,"").trim(),o.index=a[1].trim(),a[2]&&(o.collection=a[2].trim())):o.item=s,o}function Vr(e,t,r,n){let i={};return/^\[.*\]$/.test(e.item)&&Array.isArray(t)?e.item.replace("[","").replace("]","").split(",").map(s=>s.trim()).forEach((s,a)=>{i[s]=t[a]}):/^\{.*\}$/.test(e.item)&&!Array.isArray(t)&&typeof t=="object"?e.item.replace("{","").replace("}","").split(",").map(s=>s.trim()).forEach(s=>{i[s]=t[s]}):i[e.item]=t,e.index&&(i[e.index]=r),e.collection&&(i[e.collection]=n),i}function li(e){return!Array.isArray(e)&&!isNaN(e)}function Br(){}Br.inline=(e,{expression:t},{cleanup:r})=>{let n=D(e);n._x_refs||(n._x_refs={}),n._x_refs[t]=e,r(()=>delete n._x_refs[t])};d("ref",Br);d("if",(e,{expression:t},{effect:r,cleanup:n})=>{let i=m(e,t),o=()=>{if(e._x_currentIfEl)return e._x_currentIfEl;let a=e.content.cloneNode(!0).firstElementChild;return G(a,{},e),h(()=>{e.after(a),O(a)}),e._x_currentIfEl=a,e._x_undoIf=()=>{a.remove(),delete e._x_currentIfEl},a},s=()=>{!e._x_undoIf||(e._x_undoIf(),delete e._x_undoIf)};r(()=>i(a=>{a?o():s()})),n(()=>e._x_undoIf&&e._x_undoIf())});J(be("@",ve(A("on:"))));d("on",P((e,{value:t,modifiers:r,expression:n},{cleanup:i})=>{let o=n?m(e,n):()=>{},s=pe(e,t,r,a=>{o(()=>{},{scope:{$event:a},params:[a]})});i(()=>s())}));S.setEvaluator(nt);S.setReactivityEngine({reactive:Pe,effect:yr,release:br,raw:g});var Tt=S;window.Alpine=Tt;queueMicrotask(()=>{Tt.start()});})();
+`:""}`,t),setTimeout(()=>{throw e},0)}function N(e,t,r={}){let n;return g(e,t)(i=>n=i,r),n}function g(...e){return Gt(...e)}var Gt=ct;function Yt(e){Gt=e}function ct(e,t){let r={},n=re(r,e).cleanup;ge(e,"evaluator",n);let i=[r,...k(e)];if(typeof t=="function")return un(i,t);let o=fn(i,t,e);return Wt.bind(null,e,t,o)}function un(e,t){return(r=()=>{},{scope:n={},params:i=[]}={})=>{let o=t.apply(I([n,...e]),i);we(r,o)}}var lt={};function dn(e,t){if(lt[e])return lt[e];let r=Object.getPrototypeOf(async function(){}).constructor,n=/^[\n\s]*if.*\(.*\)/.test(e)||/^(let|const)\s/.test(e)?`(() => { ${e} })()`:e,o=(()=>{try{return new r(["__self","scope"],`with (scope) { __self.result = ${n} }; __self.finished = true; return __self.result;`)}catch(s){return J(s,t,e),Promise.resolve()}})();return lt[e]=o,o}function fn(e,t,r){let n=dn(t,r);return(i=()=>{},{scope:o={},params:s=[]}={})=>{n.result=void 0,n.finished=!1;let a=I([o,...e]);if(typeof n=="function"){let c=n(n,a).catch(l=>J(l,r,t));n.finished?(we(i,n.result,a,s,r),n.result=void 0):c.then(l=>{we(i,l,a,s,r)}).catch(l=>J(l,r,t)).finally(()=>n.result=void 0)}}}function we(e,t,r,n,i){if(typeof t=="function"){let o=t.apply(r,n);o instanceof Promise?o.then(s=>we(e,s,r,n)).catch(s=>J(s,i,t)):e(o)}else e(t)}var ut="x-";function w(e=""){return ut+e}function Jt(e){ut=e}var Zt={};function p(e,t){Zt[e]=t}function ne(e,t,r){let n={};return Array.from(t).map(Qt((o,s)=>n[o]=s)).filter(Xt).map(mn(n,r)).sort(hn).map(o=>pn(e,o))}function er(e){return Array.from(e).map(Qt()).filter(t=>!Xt(t))}var ft=!1,ie=new Map,tr=Symbol();function rr(e){ft=!0;let t=Symbol();tr=t,ie.set(t,[]);let r=()=>{for(;ie.get(t).length;)ie.get(t).shift()();ie.delete(t)},n=()=>{ft=!1,r()};e(r),n()}function at(e){let t=[],r=a=>t.push(a),[n,i]=jt(e);return t.push(i),[{Alpine:P,effect:n,cleanup:r,evaluateLater:g.bind(g,e),evaluate:N.bind(N,e)},()=>t.forEach(a=>a())]}function pn(e,t){let r=()=>{},n=Zt[t.type]||r,[i,o]=at(e);ge(e,t.original,o);let s=()=>{e._x_ignore||e._x_ignoreSelf||(n.inline&&n.inline(e,t,i),n=n.bind(n,e,t,i),ft?ie.get(tr).push(n):n())};return s.runCleanups=o,s}var Ee=(e,t)=>({name:r,value:n})=>(r.startsWith(e)&&(r=r.replace(e,t)),{name:r,value:n}),Se=e=>e;function Qt(e=()=>{}){return({name:t,value:r})=>{let{name:n,value:i}=nr.reduce((o,s)=>s(o),{name:t,value:r});return n!==t&&e(n,t),{name:n,value:i}}}var nr=[];function Z(e){nr.push(e)}function Xt({name:e}){return ir().test(e)}var ir=()=>new RegExp(`^${ut}([^:^.]+)\\b`);function mn(e,t){return({name:r,value:n})=>{let i=r.match(ir()),o=r.match(/:([a-zA-Z0-9\-:]+)/),s=r.match(/\.[^.\]]+(?=[^\]]*$)/g)||[],a=t||e[r]||r;return{type:i?i[1]:null,value:o?o[1]:null,modifiers:s.map(c=>c.replace(".","")),expression:n,original:a}}}var dt="DEFAULT",Ae=["ignore","ref","data","id","bind","init","for","model","modelable","transition","show","if",dt,"teleport","element"];function hn(e,t){let r=Ae.indexOf(e.type)===-1?dt:e.type,n=Ae.indexOf(t.type)===-1?dt:t.type;return Ae.indexOf(r)-Ae.indexOf(n)}function B(e,t,r={}){e.dispatchEvent(new CustomEvent(t,{detail:r,bubbles:!0,composed:!0,cancelable:!0}))}var pt=[],mt=!1;function Te(e){pt.push(e),queueMicrotask(()=>{mt||setTimeout(()=>{Oe()})})}function Oe(){for(mt=!1;pt.length;)pt.shift()()}function or(){mt=!0}function C(e,t){if(typeof ShadowRoot=="function"&&e instanceof ShadowRoot){Array.from(e.children).forEach(i=>C(i,t));return}let r=!1;if(t(e,()=>r=!0),r)return;let n=e.firstElementChild;for(;n;)C(n,t,!1),n=n.nextElementSibling}function z(e,...t){console.warn(`Alpine Warning: ${e}`,...t)}function ar(){document.body||z("Unable to initialize. Trying to load Alpine before `<body>` is available. Did you forget to add `defer` in Alpine's `<script>` tag?"),B(document,"alpine:init"),B(document,"alpine:initializing"),tt(),zt(t=>E(t,C)),_e(t=>ht(t)),Vt((t,r)=>{ne(t,r).forEach(n=>n())});let e=t=>!V(t.parentElement,!0);Array.from(document.querySelectorAll(sr())).filter(e).forEach(t=>{E(t)}),B(document,"alpine:initialized")}var _t=[],cr=[];function lr(){return _t.map(e=>e())}function sr(){return _t.concat(cr).map(e=>e())}function Ce(e){_t.push(e)}function Re(e){cr.push(e)}function V(e,t=!1){return Q(e,r=>{if((t?sr():lr()).some(i=>r.matches(i)))return!0})}function Q(e,t){if(!!e){if(t(e))return e;if(e._x_teleportBack&&(e=e._x_teleportBack),!!e.parentElement)return Q(e.parentElement,t)}}function ur(e){return lr().some(t=>e.matches(t))}function E(e,t=C){rr(()=>{t(e,(r,n)=>{ne(r,r.attributes).forEach(i=>i()),r._x_ignore&&n()})})}function ht(e){C(e,t=>Ze(t))}function oe(e,t){return Array.isArray(t)?fr(e,t.join(" ")):typeof t=="object"&&t!==null?_n(e,t):typeof t=="function"?oe(e,t()):fr(e,t)}function fr(e,t){let r=o=>o.split(" ").filter(Boolean),n=o=>o.split(" ").filter(s=>!e.classList.contains(s)).filter(Boolean),i=o=>(e.classList.add(...o),()=>{e.classList.remove(...o)});return t=t===!0?t="":t||"",i(n(t))}function _n(e,t){let r=a=>a.split(" ").filter(Boolean),n=Object.entries(t).flatMap(([a,c])=>c?r(a):!1).filter(Boolean),i=Object.entries(t).flatMap(([a,c])=>c?!1:r(a)).filter(Boolean),o=[],s=[];return i.forEach(a=>{e.classList.contains(a)&&(e.classList.remove(a),s.push(a))}),n.forEach(a=>{e.classList.contains(a)||(e.classList.add(a),o.push(a))}),()=>{s.forEach(a=>e.classList.add(a)),o.forEach(a=>e.classList.remove(a))}}function H(e,t){return typeof t=="object"&&t!==null?gn(e,t):xn(e,t)}function gn(e,t){let r={};return Object.entries(t).forEach(([n,i])=>{r[n]=e.style[n],n.startsWith("--")||(n=yn(n)),e.style.setProperty(n,i)}),setTimeout(()=>{e.style.length===0&&e.removeAttribute("style")}),()=>{H(e,r)}}function xn(e,t){let r=e.getAttribute("style",t);return e.setAttribute("style",t),()=>{e.setAttribute("style",r||"")}}function yn(e){return e.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()}function se(e,t=()=>{}){let r=!1;return function(){r?t.apply(this,arguments):(r=!0,e.apply(this,arguments))}}p("transition",(e,{value:t,modifiers:r,expression:n},{evaluate:i})=>{typeof n=="function"&&(n=i(n)),n?bn(e,n,t):vn(e,r,t)});function bn(e,t,r){dr(e,oe,""),{enter:i=>{e._x_transition.enter.during=i},"enter-start":i=>{e._x_transition.enter.start=i},"enter-end":i=>{e._x_transition.enter.end=i},leave:i=>{e._x_transition.leave.during=i},"leave-start":i=>{e._x_transition.leave.start=i},"leave-end":i=>{e._x_transition.leave.end=i}}[r](t)}function vn(e,t,r){dr(e,H);let n=!t.includes("in")&&!t.includes("out")&&!r,i=n||t.includes("in")||["enter"].includes(r),o=n||t.includes("out")||["leave"].includes(r);t.includes("in")&&!n&&(t=t.filter((h,b)=>b<t.indexOf("out"))),t.includes("out")&&!n&&(t=t.filter((h,b)=>b>t.indexOf("out")));let s=!t.includes("opacity")&&!t.includes("scale"),a=s||t.includes("opacity"),c=s||t.includes("scale"),l=a?0:1,u=c?ae(t,"scale",95)/100:1,d=ae(t,"delay",0),x=ae(t,"origin","center"),M="opacity, transform",W=ae(t,"duration",150)/1e3,pe=ae(t,"duration",75)/1e3,f="cubic-bezier(0.4, 0.0, 0.2, 1)";i&&(e._x_transition.enter.during={transformOrigin:x,transitionDelay:d,transitionProperty:M,transitionDuration:`${W}s`,transitionTimingFunction:f},e._x_transition.enter.start={opacity:l,transform:`scale(${u})`},e._x_transition.enter.end={opacity:1,transform:"scale(1)"}),o&&(e._x_transition.leave.during={transformOrigin:x,transitionDelay:d,transitionProperty:M,transitionDuration:`${pe}s`,transitionTimingFunction:f},e._x_transition.leave.start={opacity:1,transform:"scale(1)"},e._x_transition.leave.end={opacity:l,transform:`scale(${u})`})}function dr(e,t,r={}){e._x_transition||(e._x_transition={enter:{during:r,start:r,end:r},leave:{during:r,start:r,end:r},in(n=()=>{},i=()=>{}){Me(e,t,{during:this.enter.during,start:this.enter.start,end:this.enter.end},n,i)},out(n=()=>{},i=()=>{}){Me(e,t,{during:this.leave.during,start:this.leave.start,end:this.leave.end},n,i)}})}window.Element.prototype._x_toggleAndCascadeWithTransitions=function(e,t,r,n){let i=()=>{document.visibilityState==="visible"?requestAnimationFrame(r):setTimeout(r)};if(t){e._x_transition&&(e._x_transition.enter||e._x_transition.leave)?e._x_transition.enter&&(Object.entries(e._x_transition.enter.during).length||Object.entries(e._x_transition.enter.start).length||Object.entries(e._x_transition.enter.end).length)?e._x_transition.in(r):i():e._x_transition?e._x_transition.in(r):i();return}e._x_hidePromise=e._x_transition?new Promise((o,s)=>{e._x_transition.out(()=>{},()=>o(n)),e._x_transitioning.beforeCancel(()=>s({isFromCancelledTransition:!0}))}):Promise.resolve(n),queueMicrotask(()=>{let o=pr(e);o?(o._x_hideChildren||(o._x_hideChildren=[]),o._x_hideChildren.push(e)):queueMicrotask(()=>{let s=a=>{let c=Promise.all([a._x_hidePromise,...(a._x_hideChildren||[]).map(s)]).then(([l])=>l());return delete a._x_hidePromise,delete a._x_hideChildren,c};s(e).catch(a=>{if(!a.isFromCancelledTransition)throw a})})})};function pr(e){let t=e.parentNode;if(!!t)return t._x_hidePromise?t:pr(t)}function Me(e,t,{during:r,start:n,end:i}={},o=()=>{},s=()=>{}){if(e._x_transitioning&&e._x_transitioning.cancel(),Object.keys(r).length===0&&Object.keys(n).length===0&&Object.keys(i).length===0){o(),s();return}let a,c,l;wn(e,{start(){a=t(e,n)},during(){c=t(e,r)},before:o,end(){a(),l=t(e,i)},after:s,cleanup(){c(),l()}})}function wn(e,t){let r,n,i,o=se(()=>{m(()=>{r=!0,n||t.before(),i||(t.end(),Oe()),t.after(),e.isConnected&&t.cleanup(),delete e._x_transitioning})});e._x_transitioning={beforeCancels:[],beforeCancel(s){this.beforeCancels.push(s)},cancel:se(function(){for(;this.beforeCancels.length;)this.beforeCancels.shift()();o()}),finish:o},m(()=>{t.start(),t.during()}),or(),requestAnimationFrame(()=>{if(r)return;let s=Number(getComputedStyle(e).transitionDuration.replace(/,.*/,"").replace("s",""))*1e3,a=Number(getComputedStyle(e).transitionDelay.replace(/,.*/,"").replace("s",""))*1e3;s===0&&(s=Number(getComputedStyle(e).animationDuration.replace("s",""))*1e3),m(()=>{t.before()}),n=!0,requestAnimationFrame(()=>{r||(m(()=>{t.end()}),Oe(),setTimeout(e._x_transitioning.finish,s+a),i=!0)})})}function ae(e,t,r){if(e.indexOf(t)===-1)return r;let n=e[e.indexOf(t)+1];if(!n||t==="scale"&&isNaN(n))return r;if(t==="duration"){let i=n.match(/([0-9]+)ms/);if(i)return i[1]}return t==="origin"&&["top","right","left","center","bottom"].includes(e[e.indexOf(t)+2])?[n,e[e.indexOf(t)+2]].join(" "):n}var gt=!1;function D(e,t=()=>{}){return(...r)=>gt?t(...r):e(...r)}function mr(e,t){t._x_dataStack||(t._x_dataStack=e._x_dataStack),gt=!0,Sn(()=>{En(t)}),gt=!1}function En(e){let t=!1;E(e,(n,i)=>{C(n,(o,s)=>{if(t&&ur(o))return s();t=!0,i(o,s)})})}function Sn(e){let t=K;Je((r,n)=>{let i=t(r);return Y(i),()=>{}}),e(),Je(t)}function ce(e,t,r,n=[]){switch(e._x_bindings||(e._x_bindings=A({})),e._x_bindings[t]=r,t=n.includes("camel")?Rn(t):t,t){case"value":An(e,r);break;case"style":Tn(e,r);break;case"class":On(e,r);break;default:Cn(e,t,r);break}}function An(e,t){if(e.type==="radio")e.attributes.value===void 0&&(e.value=t),window.fromModel&&(e.checked=hr(e.value,t));else if(e.type==="checkbox")Number.isInteger(t)?e.value=t:!Number.isInteger(t)&&!Array.isArray(t)&&typeof t!="boolean"&&![null,void 0].includes(t)?e.value=String(t):Array.isArray(t)?e.checked=t.some(r=>hr(r,e.value)):e.checked=!!t;else if(e.tagName==="SELECT")Mn(e,t);else{if(e.value===t)return;e.value=t}}function On(e,t){e._x_undoAddedClasses&&e._x_undoAddedClasses(),e._x_undoAddedClasses=oe(e,t)}function Tn(e,t){e._x_undoAddedStyles&&e._x_undoAddedStyles(),e._x_undoAddedStyles=H(e,t)}function Cn(e,t,r){[null,void 0,!1].includes(r)&&kn(t)?e.removeAttribute(t):(_r(t)&&(r=t),Nn(e,t,r))}function Nn(e,t,r){e.getAttribute(t)!=r&&e.setAttribute(t,r)}function Mn(e,t){let r=[].concat(t).map(n=>n+"");Array.from(e.options).forEach(n=>{n.selected=r.includes(n.value)})}function Rn(e){return e.toLowerCase().replace(/-(\w)/g,(t,r)=>r.toUpperCase())}function hr(e,t){return e==t}function _r(e){return["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"].includes(e)}function kn(e){return!["aria-pressed","aria-checked","aria-expanded","aria-selected"].includes(e)}function gr(e,t,r){if(e._x_bindings&&e._x_bindings[t]!==void 0)return e._x_bindings[t];let n=e.getAttribute(t);return n===null?typeof r=="function"?r():r:_r(t)?!![t,"true"].includes(n):n===""?!0:n}function Ne(e,t){var r;return function(){var n=this,i=arguments,o=function(){r=null,e.apply(n,i)};clearTimeout(r),r=setTimeout(o,t)}}function ke(e,t){let r;return function(){let n=this,i=arguments;r||(e.apply(n,i),r=!0,setTimeout(()=>r=!1,t))}}function xr(e){e(P)}var q={},yr=!1;function br(e,t){if(yr||(q=A(q),yr=!0),t===void 0)return q[e];q[e]=t,typeof t=="object"&&t!==null&&t.hasOwnProperty("init")&&typeof t.init=="function"&&q[e].init(),be(q[e])}function vr(){return q}var wr={};function Er(e,t){wr[e]=typeof t!="function"?()=>t:t}function Sr(e){return Object.entries(wr).forEach(([t,r])=>{Object.defineProperty(e,t,{get(){return(...n)=>r(...n)}})}),e}var Ar={};function Or(e,t){Ar[e]=t}function Tr(e,t){return Object.entries(Ar).forEach(([r,n])=>{Object.defineProperty(e,r,{get(){return(...i)=>n.bind(t)(...i)},enumerable:!1})}),e}var In={get reactive(){return A},get release(){return Y},get effect(){return K},get raw(){return Ge},version:"3.9.1",flushAndStopDeferringMutations:qt,disableEffectScheduling:$t,stopObservingMutations:rt,destroyTree:ht,setReactivityEngine:Lt,closestDataStack:k,skipDuringClone:D,addRootSelector:Ce,addInitSelector:Re,addScopeToNode:T,deferMutations:Ht,mapAttributes:Z,evaluateLater:g,setEvaluator:Yt,mergeProxies:I,findClosest:Q,closestRoot:V,interceptor:ve,transition:Me,setStyles:H,mutateDom:m,directive:p,throttle:ke,debounce:Ne,evaluate:N,initTree:E,nextTick:Te,prefixed:w,prefix:Jt,plugin:xr,magic:y,store:br,start:ar,clone:mr,bound:gr,$data:ye,data:Or,bind:Er},P=In;function xt(e,t){let r=Object.create(null),n=e.split(",");for(let i=0;i<n.length;i++)r[n[i]]=!0;return t?i=>!!r[i.toLowerCase()]:i=>!!r[i]}var Xo={[1]:"TEXT",[2]:"CLASS",[4]:"STYLE",[8]:"PROPS",[16]:"FULL_PROPS",[32]:"HYDRATE_EVENTS",[64]:"STABLE_FRAGMENT",[128]:"KEYED_FRAGMENT",[256]:"UNKEYED_FRAGMENT",[512]:"NEED_PATCH",[1024]:"DYNAMIC_SLOTS",[2048]:"DEV_ROOT_FRAGMENT",[-1]:"HOISTED",[-2]:"BAIL"},es={[1]:"STABLE",[2]:"DYNAMIC",[3]:"FORWARDED"};var Pn="itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly";var ts=xt(Pn+",async,autofocus,autoplay,controls,default,defer,disabled,hidden,loop,open,required,reversed,scoped,seamless,checked,muted,multiple,selected");var Cr=Object.freeze({}),rs=Object.freeze([]);var yt=Object.assign;var Dn=Object.prototype.hasOwnProperty,le=(e,t)=>Dn.call(e,t),$=Array.isArray,X=e=>Rr(e)==="[object Map]";var $n=e=>typeof e=="string",Ie=e=>typeof e=="symbol",ue=e=>e!==null&&typeof e=="object";var Ln=Object.prototype.toString,Rr=e=>Ln.call(e),bt=e=>Rr(e).slice(8,-1);var Pe=e=>$n(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e;var De=e=>{let t=Object.create(null);return r=>t[r]||(t[r]=e(r))},jn=/-(\w)/g,ns=De(e=>e.replace(jn,(t,r)=>r?r.toUpperCase():"")),Fn=/\B([A-Z])/g,is=De(e=>e.replace(Fn,"-$1").toLowerCase()),vt=De(e=>e.charAt(0).toUpperCase()+e.slice(1)),os=De(e=>e?`on${vt(e)}`:""),wt=(e,t)=>e!==t&&(e===e||t===t);var Et=new WeakMap,fe=[],R,U=Symbol("iterate"),St=Symbol("Map key iterate");function Kn(e){return e&&e._isEffect===!0}function Mr(e,t=Cr){Kn(e)&&(e=e.raw);let r=Bn(e,t);return t.lazy||r(),r}function kr(e){e.active&&(Nr(e),e.options.onStop&&e.options.onStop(),e.active=!1)}var zn=0;function Bn(e,t){let r=function(){if(!r.active)return e();if(!fe.includes(r)){Nr(r);try{return Vn(),fe.push(r),R=r,e()}finally{fe.pop(),Ir(),R=fe[fe.length-1]}}};return r.id=zn++,r.allowRecurse=!!t.allowRecurse,r._isEffect=!0,r.active=!0,r.raw=e,r.deps=[],r.options=t,r}function Nr(e){let{deps:t}=e;if(t.length){for(let r=0;r<t.length;r++)t[r].delete(e);t.length=0}}var ee=!0,At=[];function Hn(){At.push(ee),ee=!1}function Vn(){At.push(ee),ee=!0}function Ir(){let e=At.pop();ee=e===void 0?!0:e}function O(e,t,r){if(!ee||R===void 0)return;let n=Et.get(e);n||Et.set(e,n=new Map);let i=n.get(r);i||n.set(r,i=new Set),i.has(R)||(i.add(R),R.deps.push(i),R.options.onTrack&&R.options.onTrack({effect:R,target:e,type:t,key:r}))}function L(e,t,r,n,i,o){let s=Et.get(e);if(!s)return;let a=new Set,c=u=>{u&&u.forEach(d=>{(d!==R||d.allowRecurse)&&a.add(d)})};if(t==="clear")s.forEach(c);else if(r==="length"&&$(e))s.forEach((u,d)=>{(d==="length"||d>=n)&&c(u)});else switch(r!==void 0&&c(s.get(r)),t){case"add":$(e)?Pe(r)&&c(s.get("length")):(c(s.get(U)),X(e)&&c(s.get(St)));break;case"delete":$(e)||(c(s.get(U)),X(e)&&c(s.get(St)));break;case"set":X(e)&&c(s.get(U));break}let l=u=>{u.options.onTrigger&&u.options.onTrigger({effect:u,target:e,key:r,type:t,newValue:n,oldValue:i,oldTarget:o}),u.options.scheduler?u.options.scheduler(u):u()};a.forEach(l)}var qn=xt("__proto__,__v_isRef,__isVue"),Pr=new Set(Object.getOwnPropertyNames(Symbol).map(e=>Symbol[e]).filter(Ie)),Un=$e(),Wn=$e(!1,!0),Gn=$e(!0),Yn=$e(!0,!0),Le={};["includes","indexOf","lastIndexOf"].forEach(e=>{let t=Array.prototype[e];Le[e]=function(...r){let n=_(this);for(let o=0,s=this.length;o<s;o++)O(n,"get",o+"");let i=t.apply(n,r);return i===-1||i===!1?t.apply(n,r.map(_)):i}});["push","pop","shift","unshift","splice"].forEach(e=>{let t=Array.prototype[e];Le[e]=function(...r){Hn();let n=t.apply(this,r);return Ir(),n}});function $e(e=!1,t=!1){return function(n,i,o){if(i==="__v_isReactive")return!e;if(i==="__v_isReadonly")return e;if(i==="__v_raw"&&o===(e?t?Zn:$r:t?Jn:Dr).get(n))return n;let s=$(n);if(!e&&s&&le(Le,i))return Reflect.get(Le,i,o);let a=Reflect.get(n,i,o);return(Ie(i)?Pr.has(i):qn(i))||(e||O(n,"get",i),t)?a:Ot(a)?!s||!Pe(i)?a.value:a:ue(a)?e?Lr(a):je(a):a}}var Qn=jr(),Xn=jr(!0);function jr(e=!1){return function(r,n,i,o){let s=r[n];if(!e&&(i=_(i),s=_(s),!$(r)&&Ot(s)&&!Ot(i)))return s.value=i,!0;let a=$(r)&&Pe(n)?Number(n)<r.length:le(r,n),c=Reflect.set(r,n,i,o);return r===_(o)&&(a?wt(i,s)&&L(r,"set",n,i,s):L(r,"add",n,i)),c}}function ei(e,t){let r=le(e,t),n=e[t],i=Reflect.deleteProperty(e,t);return i&&r&&L(e,"delete",t,void 0,n),i}function ti(e,t){let r=Reflect.has(e,t);return(!Ie(t)||!Pr.has(t))&&O(e,"has",t),r}function ri(e){return O(e,"iterate",$(e)?"length":U),Reflect.ownKeys(e)}var Fr={get:Un,set:Qn,deleteProperty:ei,has:ti,ownKeys:ri},Kr={get:Gn,set(e,t){return console.warn(`Set operation on key "${String(t)}" failed: target is readonly.`,e),!0},deleteProperty(e,t){return console.warn(`Delete operation on key "${String(t)}" failed: target is readonly.`,e),!0}},fs=yt({},Fr,{get:Wn,set:Xn}),ds=yt({},Kr,{get:Yn}),Tt=e=>ue(e)?je(e):e,Ct=e=>ue(e)?Lr(e):e,Rt=e=>e,Fe=e=>Reflect.getPrototypeOf(e);function Ke(e,t,r=!1,n=!1){e=e.__v_raw;let i=_(e),o=_(t);t!==o&&!r&&O(i,"get",t),!r&&O(i,"get",o);let{has:s}=Fe(i),a=n?Rt:r?Ct:Tt;if(s.call(i,t))return a(e.get(t));if(s.call(i,o))return a(e.get(o));e!==i&&e.get(t)}function Be(e,t=!1){let r=this.__v_raw,n=_(r),i=_(e);return e!==i&&!t&&O(n,"has",e),!t&&O(n,"has",i),e===i?r.has(e):r.has(e)||r.has(i)}function ze(e,t=!1){return e=e.__v_raw,!t&&O(_(e),"iterate",U),Reflect.get(e,"size",e)}function Br(e){e=_(e);let t=_(this);return Fe(t).has.call(t,e)||(t.add(e),L(t,"add",e,e)),this}function Vr(e,t){t=_(t);let r=_(this),{has:n,get:i}=Fe(r),o=n.call(r,e);o?zr(r,n,e):(e=_(e),o=n.call(r,e));let s=i.call(r,e);return r.set(e,t),o?wt(t,s)&&L(r,"set",e,t,s):L(r,"add",e,t),this}function Hr(e){let t=_(this),{has:r,get:n}=Fe(t),i=r.call(t,e);i?zr(t,r,e):(e=_(e),i=r.call(t,e));let o=n?n.call(t,e):void 0,s=t.delete(e);return i&&L(t,"delete",e,void 0,o),s}function qr(){let e=_(this),t=e.size!==0,r=X(e)?new Map(e):new Set(e),n=e.clear();return t&&L(e,"clear",void 0,void 0,r),n}function Ve(e,t){return function(n,i){let o=this,s=o.__v_raw,a=_(s),c=t?Rt:e?Ct:Tt;return!e&&O(a,"iterate",U),s.forEach((l,u)=>n.call(i,c(l),c(u),o))}}function He(e,t,r){return function(...n){let i=this.__v_raw,o=_(i),s=X(o),a=e==="entries"||e===Symbol.iterator&&s,c=e==="keys"&&s,l=i[e](...n),u=r?Rt:t?Ct:Tt;return!t&&O(o,"iterate",c?St:U),{next(){let{value:d,done:x}=l.next();return x?{value:d,done:x}:{value:a?[u(d[0]),u(d[1])]:u(d),done:x}},[Symbol.iterator](){return this}}}}function j(e){return function(...t){{let r=t[0]?`on key "${t[0]}" `:"";console.warn(`${vt(e)} operation ${r}failed: target is readonly.`,_(this))}return e==="delete"?!1:this}}var Ur={get(e){return Ke(this,e)},get size(){return ze(this)},has:Be,add:Br,set:Vr,delete:Hr,clear:qr,forEach:Ve(!1,!1)},Wr={get(e){return Ke(this,e,!1,!0)},get size(){return ze(this)},has:Be,add:Br,set:Vr,delete:Hr,clear:qr,forEach:Ve(!1,!0)},Gr={get(e){return Ke(this,e,!0)},get size(){return ze(this,!0)},has(e){return Be.call(this,e,!0)},add:j("add"),set:j("set"),delete:j("delete"),clear:j("clear"),forEach:Ve(!0,!1)},Yr={get(e){return Ke(this,e,!0,!0)},get size(){return ze(this,!0)},has(e){return Be.call(this,e,!0)},add:j("add"),set:j("set"),delete:j("delete"),clear:j("clear"),forEach:Ve(!0,!0)},ni=["keys","values","entries",Symbol.iterator];ni.forEach(e=>{Ur[e]=He(e,!1,!1),Gr[e]=He(e,!0,!1),Wr[e]=He(e,!1,!0),Yr[e]=He(e,!0,!0)});function qe(e,t){let r=t?e?Yr:Wr:e?Gr:Ur;return(n,i,o)=>i==="__v_isReactive"?!e:i==="__v_isReadonly"?e:i==="__v_raw"?n:Reflect.get(le(r,i)&&i in n?r:n,i,o)}var ii={get:qe(!1,!1)},ps={get:qe(!1,!0)},oi={get:qe(!0,!1)},ms={get:qe(!0,!0)};function zr(e,t,r){let n=_(r);if(n!==r&&t.call(e,n)){let i=bt(e);console.warn(`Reactive ${i} contains both the raw and reactive versions of the same object${i==="Map"?" as keys":""}, which can lead to inconsistencies. Avoid differentiating between the raw and reactive versions of an object and only use the reactive version if possible.`)}}var Dr=new WeakMap,Jn=new WeakMap,$r=new WeakMap,Zn=new WeakMap;function si(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function ai(e){return e.__v_skip||!Object.isExtensible(e)?0:si(bt(e))}function je(e){return e&&e.__v_isReadonly?e:Jr(e,!1,Fr,ii,Dr)}function Lr(e){return Jr(e,!0,Kr,oi,$r)}function Jr(e,t,r,n,i){if(!ue(e))return console.warn(`value cannot be made reactive: ${String(e)}`),e;if(e.__v_raw&&!(t&&e.__v_isReactive))return e;let o=i.get(e);if(o)return o;let s=ai(e);if(s===0)return e;let a=new Proxy(e,s===2?n:r);return i.set(e,a),a}function _(e){return e&&_(e.__v_raw)||e}function Ot(e){return Boolean(e&&e.__v_isRef===!0)}y("nextTick",()=>Te);y("dispatch",e=>B.bind(B,e));y("watch",(e,{evaluateLater:t,effect:r})=>(n,i)=>{let o=t(n),s=!0,a;r(()=>o(c=>{JSON.stringify(c),s?a=c:queueMicrotask(()=>{i(c,a),a=c}),s=!1}))});y("store",vr);y("data",e=>ye(e));y("root",e=>V(e));y("refs",e=>(e._x_refs_proxy||(e._x_refs_proxy=I(ci(e))),e._x_refs_proxy));function ci(e){let t=[],r=e;for(;r;)r._x_refs&&t.push(r._x_refs),r=r.parentNode;return t}var Mt={};function Nt(e){return Mt[e]||(Mt[e]=0),++Mt[e]}function Zr(e,t){return Q(e,r=>{if(r._x_ids&&r._x_ids[t])return!0})}function Qr(e,t){e._x_ids||(e._x_ids={}),e._x_ids[t]||(e._x_ids[t]=Nt(t))}y("id",e=>(t,r=null)=>{let n=Zr(e,t),i=n?n._x_ids[t]:Nt(t);return r?`${t}-${i}-${r}`:`${t}-${i}`});y("el",e=>e);p("modelable",(e,{expression:t},{effect:r,evaluate:n,evaluateLater:i})=>{let o=i(t),s=()=>{let u;return o(d=>u=d),u},a=i(`${t} = __placeholder`),c=u=>a(()=>{},{scope:{__placeholder:u}}),l=s();e._x_modelable_hook&&(l=e._x_modelable_hook(l)),c(l),queueMicrotask(()=>{if(!e._x_model)return;let u=e._x_model.get,d=e._x_model.set;r(()=>c(u())),r(()=>d(s()))})});p("teleport",(e,{expression:t},{cleanup:r})=>{e.tagName.toLowerCase()!=="template"&&z("x-teleport can only be used on a <template> tag",e);let n=document.querySelector(t);n||z(`Cannot find x-teleport element for selector: "${t}"`);let i=e.content.cloneNode(!0).firstElementChild;e._x_teleport=i,i._x_teleportBack=e,e._x_forwardEvents&&e._x_forwardEvents.forEach(o=>{i.addEventListener(o,s=>{s.stopPropagation(),e.dispatchEvent(new s.constructor(s.type,s))})}),T(i,{},e),m(()=>{n.appendChild(i),E(i),i._x_ignore=!0}),r(()=>i.remove())});var Xr=()=>{};Xr.inline=(e,{modifiers:t},{cleanup:r})=>{t.includes("self")?e._x_ignoreSelf=!0:e._x_ignore=!0,r(()=>{t.includes("self")?delete e._x_ignoreSelf:delete e._x_ignore})};p("ignore",Xr);p("effect",(e,{expression:t},{effect:r})=>r(g(e,t)));function de(e,t,r,n){let i=e,o=c=>n(c),s={},a=(c,l)=>u=>l(c,u);if(r.includes("dot")&&(t=li(t)),r.includes("camel")&&(t=ui(t)),r.includes("passive")&&(s.passive=!0),r.includes("capture")&&(s.capture=!0),r.includes("window")&&(i=window),r.includes("document")&&(i=document),r.includes("prevent")&&(o=a(o,(c,l)=>{l.preventDefault(),c(l)})),r.includes("stop")&&(o=a(o,(c,l)=>{l.stopPropagation(),c(l)})),r.includes("self")&&(o=a(o,(c,l)=>{l.target===e&&c(l)})),(r.includes("away")||r.includes("outside"))&&(i=document,o=a(o,(c,l)=>{e.contains(l.target)||e.offsetWidth<1&&e.offsetHeight<1||e._x_isShown!==!1&&c(l)})),o=a(o,(c,l)=>{fi(t)&&di(l,r)||c(l)}),r.includes("debounce")){let c=r[r.indexOf("debounce")+1]||"invalid-wait",l=kt(c.split("ms")[0])?Number(c.split("ms")[0]):250;o=Ne(o,l)}if(r.includes("throttle")){let c=r[r.indexOf("throttle")+1]||"invalid-wait",l=kt(c.split("ms")[0])?Number(c.split("ms")[0]):250;o=ke(o,l)}return r.includes("once")&&(o=a(o,(c,l)=>{c(l),i.removeEventListener(t,o,s)})),i.addEventListener(t,o,s),()=>{i.removeEventListener(t,o,s)}}function li(e){return e.replace(/-/g,".")}function ui(e){return e.toLowerCase().replace(/-(\w)/g,(t,r)=>r.toUpperCase())}function kt(e){return!Array.isArray(e)&&!isNaN(e)}function pi(e){return e.replace(/([a-z])([A-Z])/g,"$1-$2").replace(/[_\s]/,"-").toLowerCase()}function fi(e){return["keydown","keyup"].includes(e)}function di(e,t){let r=t.filter(o=>!["window","document","prevent","stop","once"].includes(o));if(r.includes("debounce")){let o=r.indexOf("debounce");r.splice(o,kt((r[o+1]||"invalid-wait").split("ms")[0])?2:1)}if(r.length===0||r.length===1&&en(e.key).includes(r[0]))return!1;let i=["ctrl","shift","alt","meta","cmd","super"].filter(o=>r.includes(o));return r=r.filter(o=>!i.includes(o)),!(i.length>0&&i.filter(s=>((s==="cmd"||s==="super")&&(s="meta"),e[`${s}Key`])).length===i.length&&en(e.key).includes(r[0]))}function en(e){if(!e)return[];e=pi(e);let t={ctrl:"control",slash:"/",space:"-",spacebar:"-",cmd:"meta",esc:"escape",up:"arrow-up",down:"arrow-down",left:"arrow-left",right:"arrow-right",period:".",equal:"="};return t[e]=e,Object.keys(t).map(r=>{if(t[r]===e)return r}).filter(r=>r)}p("model",(e,{modifiers:t,expression:r},{effect:n,cleanup:i})=>{let o=g(e,r),s=`${r} = rightSideOfExpression($event, ${r})`,a=g(e,s);var c=e.tagName.toLowerCase()==="select"||["checkbox","radio"].includes(e.type)||t.includes("lazy")?"change":"input";let l=mi(e,t,r),u=de(e,c,t,x=>{a(()=>{},{scope:{$event:x,rightSideOfExpression:l}})});i(()=>u());let d=g(e,`${r} = __placeholder`);e._x_model={get(){let x;return o(M=>x=M),x},set(x){d(()=>{},{scope:{__placeholder:x}})}},e._x_forceModelUpdate=()=>{o(x=>{x===void 0&&r.match(/\./)&&(x=""),window.fromModel=!0,m(()=>ce(e,"value",x)),delete window.fromModel})},n(()=>{t.includes("unintrusive")&&document.activeElement.isSameNode(e)||e._x_forceModelUpdate()})});function mi(e,t,r){return e.type==="radio"&&m(()=>{e.hasAttribute("name")||e.setAttribute("name",r)}),(n,i)=>m(()=>{if(n instanceof CustomEvent&&n.detail!==void 0)return n.detail||n.target.value;if(e.type==="checkbox")if(Array.isArray(i)){let o=t.includes("number")?It(n.target.value):n.target.value;return n.target.checked?i.concat([o]):i.filter(s=>!hi(s,o))}else return n.target.checked;else{if(e.tagName.toLowerCase()==="select"&&e.multiple)return t.includes("number")?Array.from(n.target.selectedOptions).map(o=>{let s=o.value||o.text;return It(s)}):Array.from(n.target.selectedOptions).map(o=>o.value||o.text);{let o=n.target.value;return t.includes("number")?It(o):t.includes("trim")?o.trim():o}}})}function It(e){let t=e?parseFloat(e):null;return _i(t)?t:e}function hi(e,t){return e==t}function _i(e){return!Array.isArray(e)&&!isNaN(e)}p("cloak",e=>queueMicrotask(()=>m(()=>e.removeAttribute(w("cloak")))));Re(()=>`[${w("init")}]`);p("init",D((e,{expression:t},{evaluate:r})=>typeof t=="string"?!!t.trim()&&r(t,{},!1):r(t,{},!1)));p("text",(e,{expression:t},{effect:r,evaluateLater:n})=>{let i=n(t);r(()=>{i(o=>{m(()=>{e.textContent=o})})})});p("html",(e,{expression:t},{effect:r,evaluateLater:n})=>{let i=n(t);r(()=>{i(o=>{e.innerHTML=o})})});Z(Ee(":",Se(w("bind:"))));p("bind",(e,{value:t,modifiers:r,expression:n,original:i},{effect:o})=>{if(!t)return gi(e,n,i,o);if(t==="key")return xi(e,n);let s=g(e,n);o(()=>s(a=>{a===void 0&&n.match(/\./)&&(a=""),m(()=>ce(e,t,a,r))}))});function gi(e,t,r,n){let i={};Sr(i);let o=g(e,t),s=[];for(;s.length;)s.pop()();o(a=>{let c=Object.entries(a).map(([u,d])=>({name:u,value:d})),l=er(c);c=c.map(u=>l.find(d=>d.name===u.name)?{name:`x-bind:${u.name}`,value:`"${u.value}"`}:u),ne(e,c,r).map(u=>{s.push(u.runCleanups),u()})},{scope:i})}function xi(e,t){e._x_keyExpression=t}Ce(()=>`[${w("data")}]`);p("data",D((e,{expression:t},{cleanup:r})=>{t=t===""?"{}":t;let n={},i=re(n,e).cleanup,o={};Tr(o,n);let s=N(e,t,{scope:o});s===void 0&&(s={});let a=re(s,e).cleanup,c=A(s);be(c);let l=T(e,c);c.init&&N(e,c.init),r(()=>{l(),i(),a(),c.destroy&&N(e,c.destroy)})}));p("show",(e,{modifiers:t,expression:r},{effect:n})=>{let i=g(e,r),o=()=>m(()=>{e.style.display="none",e._x_isShown=!1}),s=()=>m(()=>{e.style.length===1&&e.style.display==="none"?e.removeAttribute("style"):e.style.removeProperty("display"),e._x_isShown=!0}),a=()=>setTimeout(s),c=se(d=>d?s():o(),d=>{typeof e._x_toggleAndCascadeWithTransitions=="function"?e._x_toggleAndCascadeWithTransitions(e,d,s,o):d?a():o()}),l,u=!0;n(()=>i(d=>{!u&&d===l||(t.includes("immediate")&&(d?a():o()),c(d),l=d,u=!1)}))});p("for",(e,{expression:t},{effect:r,cleanup:n})=>{let i=bi(t),o=g(e,i.items),s=g(e,e._x_keyExpression||"index");e._x_prevKeys=[],e._x_lookup={},r(()=>yi(e,i,o,s)),n(()=>{Object.values(e._x_lookup).forEach(a=>a.remove()),delete e._x_prevKeys,delete e._x_lookup})});function yi(e,t,r,n){let i=s=>typeof s=="object"&&!Array.isArray(s),o=e;r(s=>{vi(s)&&s>=0&&(s=Array.from(Array(s).keys(),f=>f+1)),s===void 0&&(s=[]);let a=e._x_lookup,c=e._x_prevKeys,l=[],u=[];if(i(s))s=Object.entries(s).map(([f,h])=>{let b=tn(t,h,f,s);n(v=>u.push(v),{scope:{index:f,...b}}),l.push(b)});else for(let f=0;f<s.length;f++){let h=tn(t,s[f],f,s);n(b=>u.push(b),{scope:{index:f,...h}}),l.push(h)}let d=[],x=[],M=[],W=[];for(let f=0;f<c.length;f++){let h=c[f];u.indexOf(h)===-1&&M.push(h)}c=c.filter(f=>!M.includes(f));let pe="template";for(let f=0;f<u.length;f++){let h=u[f],b=c.indexOf(h);if(b===-1)c.splice(f,0,h),d.push([pe,f]);else if(b!==f){let v=c.splice(f,1)[0],S=c.splice(b-1,1)[0];c.splice(f,0,S),c.splice(b,0,v),x.push([v,S])}else W.push(h);pe=h}for(let f=0;f<M.length;f++){let h=M[f];a[h]._x_effects&&a[h]._x_effects.forEach(he),a[h].remove(),a[h]=null,delete a[h]}for(let f=0;f<x.length;f++){let[h,b]=x[f],v=a[h],S=a[b],G=document.createElement("div");m(()=>{S.after(G),v.after(S),S._x_currentIfEl&&S.after(S._x_currentIfEl),G.before(v),v._x_currentIfEl&&v.after(v._x_currentIfEl),G.remove()}),ot(S,l[u.indexOf(b)])}for(let f=0;f<d.length;f++){let[h,b]=d[f],v=h==="template"?o:a[h];v._x_currentIfEl&&(v=v._x_currentIfEl);let S=l[b],G=u[b],me=document.importNode(o.content,!0).firstElementChild;T(me,A(S),o),m(()=>{v.after(me),E(me)}),typeof G=="object"&&z("x-for key cannot be an object, it must be a string or an integer",o),a[G]=me}for(let f=0;f<W.length;f++)ot(a[W[f]],l[u.indexOf(W[f])]);o._x_prevKeys=u})}function bi(e){let t=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,r=/^\s*\(|\)\s*$/g,n=/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/,i=e.match(n);if(!i)return;let o={};o.items=i[2].trim();let s=i[1].replace(r,"").trim(),a=s.match(t);return a?(o.item=s.replace(t,"").trim(),o.index=a[1].trim(),a[2]&&(o.collection=a[2].trim())):o.item=s,o}function tn(e,t,r,n){let i={};return/^\[.*\]$/.test(e.item)&&Array.isArray(t)?e.item.replace("[","").replace("]","").split(",").map(s=>s.trim()).forEach((s,a)=>{i[s]=t[a]}):/^\{.*\}$/.test(e.item)&&!Array.isArray(t)&&typeof t=="object"?e.item.replace("{","").replace("}","").split(",").map(s=>s.trim()).forEach(s=>{i[s]=t[s]}):i[e.item]=t,e.index&&(i[e.index]=r),e.collection&&(i[e.collection]=n),i}function vi(e){return!Array.isArray(e)&&!isNaN(e)}function rn(){}rn.inline=(e,{expression:t},{cleanup:r})=>{let n=V(e);n._x_refs||(n._x_refs={}),n._x_refs[t]=e,r(()=>delete n._x_refs[t])};p("ref",rn);p("if",(e,{expression:t},{effect:r,cleanup:n})=>{let i=g(e,t),o=()=>{if(e._x_currentIfEl)return e._x_currentIfEl;let a=e.content.cloneNode(!0).firstElementChild;return T(a,{},e),m(()=>{e.after(a),E(a)}),e._x_currentIfEl=a,e._x_undoIf=()=>{C(a,c=>{c._x_effects&&c._x_effects.forEach(he)}),a.remove(),delete e._x_currentIfEl},a},s=()=>{!e._x_undoIf||(e._x_undoIf(),delete e._x_undoIf)};r(()=>i(a=>{a?o():s()})),n(()=>e._x_undoIf&&e._x_undoIf())});p("id",(e,{expression:t},{evaluate:r})=>{r(t).forEach(i=>Qr(e,i))});Z(Ee("@",Se(w("on:"))));p("on",D((e,{value:t,modifiers:r,expression:n},{cleanup:i})=>{let o=n?g(e,n):()=>{};e.tagName.toLowerCase()==="template"&&(e._x_forwardEvents||(e._x_forwardEvents=[]),e._x_forwardEvents.includes(t)||e._x_forwardEvents.push(t));let s=de(e,t,r,a=>{o(()=>{},{scope:{$event:a},params:[a]})});i(()=>s())}));P.setEvaluator(ct);P.setReactivityEngine({reactive:je,effect:Mr,release:kr,raw:_});var Pt=P;window.Alpine=Pt;queueMicrotask(()=>{Pt.start()});})();
diff --git a/alpinejs/packages/alpinejs/dist/module.cjs.js b/alpinejs/packages/alpinejs/dist/module.cjs.js
index dd47192..fc40a5e 100644
--- a/alpinejs/packages/alpinejs/dist/module.cjs.js
+++ b/alpinejs/packages/alpinejs/dist/module.cjs.js
@@ -1276,6 +1276,11 @@ function queueJob(job) {
queue.push(job);
queueFlush();
}
+function dequeueJob(job) {
+ let index = queue.indexOf(job);
+ if (index !== -1)
+ queue.splice(index, 1);
+}
function queueFlush() {
if (!flushing && !flushPending) {
flushPending = true;
@@ -1349,8 +1354,15 @@ var onElAddeds = [];
function onElAdded(callback) {
onElAddeds.push(callback);
}
-function onElRemoved(callback) {
- onElRemoveds.push(callback);
+function onElRemoved(el, callback) {
+ if (typeof callback === "function") {
+ if (!el._x_cleanups)
+ el._x_cleanups = [];
+ el._x_cleanups.push(callback);
+ } else {
+ callback = el;
+ onElRemoveds.push(callback);
+ }
}
function onAttributesAdded(callback) {
onAttributeAddeds.push(callback);
@@ -1463,16 +1475,34 @@ function onMutate(mutations) {
addedAttributes.forEach((attrs, el) => {
onAttributeAddeds.forEach((i) => i(el, attrs));
});
- for (let node of addedNodes) {
- if (removedNodes.includes(node))
- continue;
- onElAddeds.forEach((i) => i(node));
- }
for (let node of removedNodes) {
if (addedNodes.includes(node))
continue;
onElRemoveds.forEach((i) => i(node));
+ if (node._x_cleanups) {
+ while (node._x_cleanups.length)
+ node._x_cleanups.pop()();
+ }
}
+ addedNodes.forEach((node) => {
+ node._x_ignoreSelf = true;
+ node._x_ignore = true;
+ });
+ for (let node of addedNodes) {
+ if (removedNodes.includes(node))
+ continue;
+ if (!node.isConnected)
+ continue;
+ delete node._x_ignoreSelf;
+ delete node._x_ignore;
+ onElAddeds.forEach((i) => i(node));
+ node._x_ignore = true;
+ node._x_ignoreSelf = true;
+ }
+ addedNodes.forEach((node) => {
+ delete node._x_ignoreSelf;
+ delete node._x_ignore;
+ });
addedNodes = null;
removedNodes = null;
addedAttributes = null;
@@ -1480,15 +1510,18 @@ function onMutate(mutations) {
}
// packages/alpinejs/src/scope.js
+function scope(node) {
+ return mergeProxies(closestDataStack(node));
+}
function addScopeToNode(node, data2, referenceNode) {
node._x_dataStack = [data2, ...closestDataStack(referenceNode || node)];
return () => {
node._x_dataStack = node._x_dataStack.filter((i) => i !== data2);
};
}
-function refreshScope(element, scope) {
+function refreshScope(element, scope2) {
let existingScope = element._x_dataStack[0];
- Object.entries(scope).forEach(([key, value]) => {
+ Object.entries(scope2).forEach(([key, value]) => {
existingScope[key] = value;
});
}
@@ -1624,7 +1657,10 @@ function injectMagics(obj, el) {
Object.entries(magics).forEach(([name, callback]) => {
Object.defineProperty(obj, `$${name}`, {
get() {
- return callback(el, {Alpine: alpine_default, interceptor});
+ let [utilities, cleanup] = getElementBoundUtilities(el);
+ utilities = {interceptor, ...utilities};
+ onElRemoved(el, cleanup);
+ return callback(el, utilities);
},
enumerable: false
});
@@ -1681,8 +1717,8 @@ function normalEvaluator(el, expression) {
}
function generateEvaluatorFromFunction(dataStack, func) {
return (receiver = () => {
- }, {scope = {}, params = []} = {}) => {
- let result = func.apply(mergeProxies([scope, ...dataStack]), params);
+ }, {scope: scope2 = {}, params = []} = {}) => {
+ let result = func.apply(mergeProxies([scope2, ...dataStack]), params);
runIfTypeOfFunction(receiver, result);
};
}
@@ -1709,27 +1745,28 @@ function generateFunctionFromString(expression, el) {
function generateEvaluatorFromString(dataStack, expression, el) {
let func = generateFunctionFromString(expression, el);
return (receiver = () => {
- }, {scope = {}, params = []} = {}) => {
+ }, {scope: scope2 = {}, params = []} = {}) => {
func.result = void 0;
func.finished = false;
- let completeScope = mergeProxies([scope, ...dataStack]);
+ let completeScope = mergeProxies([scope2, ...dataStack]);
if (typeof func === "function") {
let promise = func(func, completeScope).catch((error2) => handleError(error2, el, expression));
if (func.finished) {
runIfTypeOfFunction(receiver, func.result, completeScope, params, el);
+ func.result = void 0;
} else {
promise.then((result) => {
runIfTypeOfFunction(receiver, result, completeScope, params, el);
- }).catch((error2) => handleError(error2, el, expression));
+ }).catch((error2) => handleError(error2, el, expression)).finally(() => func.result = void 0);
}
}
};
}
-function runIfTypeOfFunction(receiver, value, scope, params, el) {
+function runIfTypeOfFunction(receiver, value, scope2, params, el) {
if (typeof value === "function") {
- let result = value.apply(scope, params);
+ let result = value.apply(scope2, params);
if (result instanceof Promise) {
- result.then((i) => runIfTypeOfFunction(receiver, i, scope, params)).catch((error2) => handleError(error2, el, value));
+ result.then((i) => runIfTypeOfFunction(receiver, i, scope2, params)).catch((error2) => handleError(error2, el, value));
} else {
receiver(result);
}
@@ -1780,10 +1817,7 @@ function deferHandlingDirectives(callback) {
callback(flushHandlers);
stopDeferring();
}
-function getDirectiveHandler(el, directive2) {
- let noop = () => {
- };
- let handler3 = directiveHandlers[directive2.type] || noop;
+function getElementBoundUtilities(el) {
let cleanups = [];
let cleanup = (callback) => cleanups.push(callback);
let [effect3, cleanupEffect] = elementBoundEffect(el);
@@ -1796,7 +1830,14 @@ function getDirectiveHandler(el, directive2) {
evaluate: evaluate.bind(evaluate, el)
};
let doCleanup = () => cleanups.forEach((i) => i());
- onAttributeRemoved(el, directive2.original, doCleanup);
+ return [utilities, doCleanup];
+}
+function getDirectiveHandler(el, directive2) {
+ let noop = () => {
+ };
+ let handler3 = directiveHandlers[directive2.type] || noop;
+ let [utilities, cleanup] = getElementBoundUtilities(el);
+ onAttributeRemoved(el, directive2.original, cleanup);
let fullHandler = () => {
if (el._x_ignore || el._x_ignoreSelf)
return;
@@ -1804,7 +1845,7 @@ function getDirectiveHandler(el, directive2) {
handler3 = handler3.bind(handler3, el, directive2, utilities);
isDeferringHandlers ? directiveHandlerStacks.get(currentHandlerStackKey).push(handler3) : handler3();
};
- fullHandler.runCleanups = doCleanup;
+ fullHandler.runCleanups = cleanup;
return fullHandler;
}
var startingWith = (subject, replacement) => ({name, value}) => {
@@ -1852,14 +1893,17 @@ var directiveOrder = [
"ignore",
"ref",
"data",
+ "id",
"bind",
"init",
"for",
"model",
+ "modelable",
"transition",
"show",
"if",
DEFAULT,
+ "teleport",
"element"
];
function byPriority(a, b) {
@@ -1928,7 +1972,7 @@ function start() {
dispatch(document, "alpine:initializing");
startObservingMutations();
onElAdded((el) => initTree(el, walk));
- onElRemoved((el) => nextTick(() => destroyTree(el)));
+ onElRemoved((el) => destroyTree(el));
onAttributesAdded((el, attrs) => {
directives(el, attrs).forEach((handle) => handle());
});
@@ -1953,14 +1997,22 @@ function addInitSelector(selectorCallback) {
initSelectorCallbacks.push(selectorCallback);
}
function closestRoot(el, includeInitSelectors = false) {
+ return findClosest(el, (element) => {
+ const selectors = includeInitSelectors ? allSelectors() : rootSelectors();
+ if (selectors.some((selector) => element.matches(selector)))
+ return true;
+ });
+}
+function findClosest(el, callback) {
if (!el)
return;
- const selectors = includeInitSelectors ? allSelectors() : rootSelectors();
- if (selectors.some((selector) => el.matches(selector)))
+ if (callback(el))
return el;
+ if (el._x_teleportBack)
+ el = el._x_teleportBack;
if (!el.parentElement)
return;
- return closestRoot(el.parentElement, includeInitSelectors);
+ return findClosest(el.parentElement, callback);
}
function isRoot(el) {
return rootSelectors().some((selector) => el.matches(selector));
@@ -2035,7 +2087,10 @@ function setStylesFromObject(el, value) {
let previousStyles = {};
Object.entries(value).forEach(([key, value2]) => {
previousStyles[key] = el.style[key];
- el.style.setProperty(kebabCase(key), value2);
+ if (!key.startsWith("--")) {
+ key = kebabCase(key);
+ }
+ el.style.setProperty(key, value2);
});
setTimeout(() => {
if (el.style.length === 0) {
@@ -2050,7 +2105,7 @@ function setStylesFromString(el, value) {
let cache = el.getAttribute("style", value);
el.setAttribute("style", value);
return () => {
- el.setAttribute("style", cache);
+ el.setAttribute("style", cache || "");
};
}
function kebabCase(subject) {
@@ -2347,6 +2402,179 @@ function modifierValue(modifiers, key, fallback) {
return rawValue;
}
+// packages/alpinejs/src/clone.js
+var isCloning = false;
+function skipDuringClone(callback, fallback = () => {
+}) {
+ return (...args) => isCloning ? fallback(...args) : callback(...args);
+}
+function clone(oldEl, newEl) {
+ if (!newEl._x_dataStack)
+ newEl._x_dataStack = oldEl._x_dataStack;
+ isCloning = true;
+ dontRegisterReactiveSideEffects(() => {
+ cloneTree(newEl);
+ });
+ isCloning = false;
+}
+function cloneTree(el) {
+ let hasRunThroughFirstEl = false;
+ let shallowWalker = (el2, callback) => {
+ walk(el2, (el3, skip) => {
+ if (hasRunThroughFirstEl && isRoot(el3))
+ return skip();
+ hasRunThroughFirstEl = true;
+ callback(el3, skip);
+ });
+ };
+ initTree(el, shallowWalker);
+}
+function dontRegisterReactiveSideEffects(callback) {
+ let cache = effect;
+ overrideEffect((callback2, el) => {
+ let storedEffect = cache(callback2);
+ release(storedEffect);
+ return () => {
+ };
+ });
+ callback();
+ overrideEffect(cache);
+}
+
+// packages/alpinejs/src/utils/bind.js
+function bind(el, name, value, modifiers = []) {
+ if (!el._x_bindings)
+ el._x_bindings = reactive({});
+ el._x_bindings[name] = value;
+ name = modifiers.includes("camel") ? camelCase(name) : name;
+ switch (name) {
+ case "value":
+ bindInputValue(el, value);
+ break;
+ case "style":
+ bindStyles(el, value);
+ break;
+ case "class":
+ bindClasses(el, value);
+ break;
+ default:
+ bindAttribute(el, name, value);
+ break;
+ }
+}
+function bindInputValue(el, value) {
+ if (el.type === "radio") {
+ if (el.attributes.value === void 0) {
+ el.value = value;
+ }
+ if (window.fromModel) {
+ el.checked = checkedAttrLooseCompare(el.value, value);
+ }
+ } else if (el.type === "checkbox") {
+ if (Number.isInteger(value)) {
+ el.value = value;
+ } else if (!Number.isInteger(value) && !Array.isArray(value) && typeof value !== "boolean" && ![null, void 0].includes(value)) {
+ el.value = String(value);
+ } else {
+ if (Array.isArray(value)) {
+ 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;
+ }
+}
+function bindClasses(el, value) {
+ if (el._x_undoAddedClasses)
+ el._x_undoAddedClasses();
+ el._x_undoAddedClasses = setClasses(el, value);
+}
+function bindStyles(el, value) {
+ if (el._x_undoAddedStyles)
+ el._x_undoAddedStyles();
+ el._x_undoAddedStyles = setStyles(el, value);
+}
+function bindAttribute(el, name, value) {
+ if ([null, void 0, false].includes(value) && attributeShouldntBePreservedIfFalsy(name)) {
+ el.removeAttribute(name);
+ } else {
+ if (isBooleanAttr(name))
+ value = name;
+ setIfChanged(el, name, value);
+ }
+}
+function setIfChanged(el, attrName, value) {
+ if (el.getAttribute(attrName) != value) {
+ el.setAttribute(attrName, value);
+ }
+}
+function updateSelect(el, value) {
+ const arrayWrappedValue = [].concat(value).map((value2) => {
+ return value2 + "";
+ });
+ Array.from(el.options).forEach((option) => {
+ option.selected = arrayWrappedValue.includes(option.value);
+ });
+}
+function camelCase(subject) {
+ return subject.toLowerCase().replace(/-(\w)/g, (match, char) => char.toUpperCase());
+}
+function checkedAttrLooseCompare(valueA, valueB) {
+ return valueA == valueB;
+}
+function isBooleanAttr(attrName) {
+ 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 attributeShouldntBePreservedIfFalsy(name) {
+ return !["aria-pressed", "aria-checked", "aria-expanded", "aria-selected"].includes(name);
+}
+function getBinding(el, name, fallback) {
+ if (el._x_bindings && el._x_bindings[name] !== void 0)
+ return el._x_bindings[name];
+ let attr = el.getAttribute(name);
+ if (attr === null)
+ return typeof fallback === "function" ? fallback() : fallback;
+ if (isBooleanAttr(name)) {
+ return !![name, "true"].includes(attr);
+ }
+ if (attr === "")
+ return true;
+ return attr;
+}
+
// packages/alpinejs/src/utils/debounce.js
function debounce(func, wait) {
var timeout;
@@ -2400,42 +2628,22 @@ function getStores() {
return stores;
}
-// packages/alpinejs/src/clone.js
-var isCloning = false;
-function skipDuringClone(callback, fallback = () => {
-}) {
- return (...args) => isCloning ? fallback(...args) : callback(...args);
+// packages/alpinejs/src/binds.js
+var binds = {};
+function bind2(name, object) {
+ binds[name] = typeof object !== "function" ? () => object : object;
}
-function clone(oldEl, newEl) {
- newEl._x_dataStack = oldEl._x_dataStack;
- isCloning = true;
- dontRegisterReactiveSideEffects(() => {
- cloneTree(newEl);
- });
- isCloning = false;
-}
-function cloneTree(el) {
- let hasRunThroughFirstEl = false;
- let shallowWalker = (el2, callback) => {
- walk(el2, (el3, skip) => {
- if (hasRunThroughFirstEl && isRoot(el3))
- return skip();
- hasRunThroughFirstEl = true;
- callback(el3, skip);
+function injectBindingProviders(obj) {
+ Object.entries(binds).forEach(([name, callback]) => {
+ Object.defineProperty(obj, name, {
+ get() {
+ return (...args) => {
+ return callback(...args);
+ };
+ }
});
- };
- initTree(el, shallowWalker);
-}
-function dontRegisterReactiveSideEffects(callback) {
- let cache = effect;
- overrideEffect((callback2, el) => {
- let storedEffect = cache(callback2);
- release(storedEffect);
- return () => {
- };
});
- callback();
- overrideEffect(cache);
+ return obj;
}
// packages/alpinejs/src/datas.js
@@ -2471,19 +2679,23 @@ var Alpine = {
get raw() {
return raw;
},
- version: "3.5.1",
+ version: "3.9.1",
flushAndStopDeferringMutations,
disableEffectScheduling,
stopObservingMutations,
+ destroyTree,
setReactivityEngine,
+ closestDataStack,
skipDuringClone,
addRootSelector,
+ addInitSelector,
+ addScopeToNode,
deferMutations,
mapAttributes,
evaluateLater,
setEvaluator,
mergeProxies,
- destroyTree,
+ findClosest,
closestRoot,
interceptor,
transition,
@@ -2495,18 +2707,22 @@ var Alpine = {
evaluate,
initTree,
nextTick,
+ prefixed: prefix,
prefix: setPrefix,
plugin,
magic,
store,
start,
clone,
- data
+ bound: getBinding,
+ $data: scope,
+ data,
+ bind: bind2
};
var alpine_default = Alpine;
// packages/alpinejs/src/index.js
-var import_reactivity9 = __toModule(require_reactivity());
+var import_reactivity8 = __toModule(require_reactivity());
// packages/alpinejs/src/magics/$nextTick.js
magic("nextTick", () => nextTick);
@@ -2515,15 +2731,12 @@ magic("nextTick", () => nextTick);
magic("dispatch", (el) => dispatch.bind(dispatch, el));
// packages/alpinejs/src/magics/$watch.js
-magic("watch", (el) => (key, callback) => {
- let evaluate2 = evaluateLater(el, key);
+magic("watch", (el, {evaluateLater: evaluateLater2, effect: effect3}) => (key, callback) => {
+ let evaluate2 = evaluateLater2(key);
let firstTime = true;
let oldValue;
- let [effect3, cleanupEffect] = elementBoundEffect(el);
- onAttributeRemoved(el, key, cleanupEffect);
effect3(() => evaluate2((value) => {
- let div = document.createElement("div");
- div.dataset.throwAway = value;
+ JSON.stringify(value);
if (!firstTime) {
queueMicrotask(() => {
callback(value, oldValue);
@@ -2540,9 +2753,7 @@ magic("watch", (el) => (key, callback) => {
magic("store", getStores);
// packages/alpinejs/src/magics/$data.js
-magic("data", (el) => {
- return mergeProxies(closestDataStack(el));
-});
+magic("data", (el) => scope(el));
// packages/alpinejs/src/magics/$root.js
magic("root", (el) => closestRoot(el));
@@ -2565,9 +2776,88 @@ function getArrayOfRefObject(el) {
return refObjects;
}
+// packages/alpinejs/src/ids.js
+var globalIdMemo = {};
+function findAndIncrementId(name) {
+ if (!globalIdMemo[name])
+ globalIdMemo[name] = 0;
+ return ++globalIdMemo[name];
+}
+function closestIdRoot(el, name) {
+ return findClosest(el, (element) => {
+ if (element._x_ids && element._x_ids[name])
+ return true;
+ });
+}
+function setIdRoot(el, name) {
+ if (!el._x_ids)
+ el._x_ids = {};
+ if (!el._x_ids[name])
+ el._x_ids[name] = findAndIncrementId(name);
+}
+
+// packages/alpinejs/src/magics/$id.js
+magic("id", (el) => (name, key = null) => {
+ let root = closestIdRoot(el, name);
+ let id = root ? root._x_ids[name] : findAndIncrementId(name);
+ return key ? `${name}-${id}-${key}` : `${name}-${id}`;
+});
+
// packages/alpinejs/src/magics/$el.js
magic("el", (el) => el);
+// packages/alpinejs/src/directives/x-modelable.js
+directive("modelable", (el, {expression}, {effect: effect3, evaluate: evaluate2, evaluateLater: evaluateLater2}) => {
+ let func = evaluateLater2(expression);
+ let innerGet = () => {
+ let result;
+ func((i) => result = i);
+ return result;
+ };
+ let evaluateInnerSet = evaluateLater2(`${expression} = __placeholder`);
+ let innerSet = (val) => evaluateInnerSet(() => {
+ }, {scope: {__placeholder: val}});
+ let initialValue = innerGet();
+ if (el._x_modelable_hook)
+ initialValue = el._x_modelable_hook(initialValue);
+ innerSet(initialValue);
+ queueMicrotask(() => {
+ if (!el._x_model)
+ return;
+ let outerGet = el._x_model.get;
+ let outerSet = el._x_model.set;
+ effect3(() => innerSet(outerGet()));
+ effect3(() => outerSet(innerGet()));
+ });
+});
+
+// packages/alpinejs/src/directives/x-teleport.js
+directive("teleport", (el, {expression}, {cleanup}) => {
+ if (el.tagName.toLowerCase() !== "template")
+ warn("x-teleport can only be used on a <template> tag", el);
+ let target = document.querySelector(expression);
+ if (!target)
+ warn(`Cannot find x-teleport element for selector: "${expression}"`);
+ let clone2 = el.content.cloneNode(true).firstElementChild;
+ el._x_teleport = clone2;
+ clone2._x_teleportBack = el;
+ if (el._x_forwardEvents) {
+ el._x_forwardEvents.forEach((eventName) => {
+ clone2.addEventListener(eventName, (e) => {
+ e.stopPropagation();
+ el.dispatchEvent(new e.constructor(e.type, e));
+ });
+ });
+ }
+ addScopeToNode(clone2, {}, el);
+ mutateDom(() => {
+ target.appendChild(clone2);
+ initTree(clone2);
+ clone2._x_ignore = true;
+ });
+ cleanup(() => clone2.remove());
+});
+
// packages/alpinejs/src/directives/x-ignore.js
var handler = () => {
};
@@ -2582,127 +2872,6 @@ directive("ignore", handler);
// packages/alpinejs/src/directives/x-effect.js
directive("effect", (el, {expression}, {effect: effect3}) => effect3(evaluateLater(el, expression)));
-// packages/alpinejs/src/utils/bind.js
-function bind(el, name, value, modifiers = []) {
- if (!el._x_bindings)
- el._x_bindings = reactive({});
- el._x_bindings[name] = value;
- name = modifiers.includes("camel") ? camelCase(name) : name;
- switch (name) {
- case "value":
- bindInputValue(el, value);
- break;
- case "style":
- bindStyles(el, value);
- break;
- case "class":
- bindClasses(el, value);
- break;
- default:
- bindAttribute(el, name, value);
- break;
- }
-}
-function bindInputValue(el, value) {
- if (el.type === "radio") {
- if (el.attributes.value === void 0) {
- el.value = value;
- }
- if (window.fromModel) {
- el.checked = checkedAttrLooseCompare(el.value, value);
- }
- } else if (el.type === "checkbox") {
- if (Number.isInteger(value)) {
- el.value = value;
- } else if (!Number.isInteger(value) && !Array.isArray(value) && typeof value !== "boolean" && ![null, void 0].includes(value)) {
- el.value = String(value);
- } else {
- if (Array.isArray(value)) {
- 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;
- }
-}
-function bindClasses(el, value) {
- if (el._x_undoAddedClasses)
- el._x_undoAddedClasses();
- el._x_undoAddedClasses = setClasses(el, value);
-}
-function bindStyles(el, value) {
- if (el._x_undoAddedStyles)
- el._x_undoAddedStyles();
- el._x_undoAddedStyles = setStyles(el, value);
-}
-function bindAttribute(el, name, value) {
- if ([null, void 0, false].includes(value) && attributeShouldntBePreservedIfFalsy(name)) {
- el.removeAttribute(name);
- } else {
- if (isBooleanAttr(name))
- value = name;
- setIfChanged(el, name, value);
- }
-}
-function setIfChanged(el, attrName, value) {
- if (el.getAttribute(attrName) != value) {
- el.setAttribute(attrName, value);
- }
-}
-function updateSelect(el, value) {
- const arrayWrappedValue = [].concat(value).map((value2) => {
- return value2 + "";
- });
- Array.from(el.options).forEach((option) => {
- option.selected = arrayWrappedValue.includes(option.value);
- });
-}
-function camelCase(subject) {
- return subject.toLowerCase().replace(/-(\w)/g, (match, char) => char.toUpperCase());
-}
-function checkedAttrLooseCompare(valueA, valueB) {
- return valueA == valueB;
-}
-function isBooleanAttr(attrName) {
- 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 attributeShouldntBePreservedIfFalsy(name) {
- return !["aria-pressed", "aria-checked", "aria-expanded"].includes(name);
-}
-
// packages/alpinejs/src/utils/on.js
function on(el, event, modifiers, callback) {
let listenerTarget = el;
@@ -2934,11 +3103,11 @@ directive("cloak", (el) => queueMicrotask(() => mutateDom(() => el.removeAttribu
// packages/alpinejs/src/directives/x-init.js
addInitSelector(() => `[${prefix("init")}]`);
-directive("init", skipDuringClone((el, {expression}) => {
+directive("init", skipDuringClone((el, {expression}, {evaluate: evaluate2}) => {
if (typeof expression === "string") {
- return !!expression.trim() && evaluate(el, expression, {}, false);
+ return !!expression.trim() && evaluate2(expression, {}, false);
}
- return evaluate(el, expression, {}, false);
+ return evaluate2(expression, {}, false);
}));
// packages/alpinejs/src/directives/x-text.js
@@ -2966,8 +3135,9 @@ directive("html", (el, {expression}, {effect: effect3, evaluateLater: evaluateLa
// packages/alpinejs/src/directives/x-bind.js
mapAttributes(startingWith(":", into(prefix("bind:"))));
directive("bind", (el, {value, modifiers, expression, original}, {effect: effect3}) => {
- if (!value)
+ if (!value) {
return applyBindingsObject(el, expression, original, effect3);
+ }
if (value === "key")
return storeKeyForXFor(el, expression);
let evaluate2 = evaluateLater(el, expression);
@@ -2978,32 +3148,29 @@ directive("bind", (el, {value, modifiers, expression, original}, {effect: effect
}));
});
function applyBindingsObject(el, expression, original, effect3) {
+ let bindingProviders = {};
+ injectBindingProviders(bindingProviders);
let getBindings = evaluateLater(el, expression);
let cleanupRunners = [];
- effect3(() => {
- while (cleanupRunners.length)
- cleanupRunners.pop()();
- getBindings((bindings) => {
- let attributes = Object.entries(bindings).map(([name, value]) => ({name, value}));
- attributes = attributes.filter((attr) => {
- return !(typeof attr.value === "object" && !Array.isArray(attr.value) && attr.value !== null);
- });
- let staticAttributes = attributesOnly(attributes);
- attributes = attributes.map((attribute) => {
- if (staticAttributes.find((attr) => attr.name === attribute.name)) {
- return {
- name: `x-bind:${attribute.name}`,
- value: `"${attribute.value}"`
- };
- }
- return attribute;
- });
- directives(el, attributes, original).map((handle) => {
- cleanupRunners.push(handle.runCleanups);
- handle();
- });
+ while (cleanupRunners.length)
+ cleanupRunners.pop()();
+ getBindings((bindings) => {
+ let attributes = Object.entries(bindings).map(([name, value]) => ({name, value}));
+ let staticAttributes = attributesOnly(attributes);
+ attributes = attributes.map((attribute) => {
+ if (staticAttributes.find((attr) => attr.name === attribute.name)) {
+ return {
+ name: `x-bind:${attribute.name}`,
+ value: `"${attribute.value}"`
+ };
+ }
+ return attribute;
});
- });
+ directives(el, attributes, original).map((handle) => {
+ cleanupRunners.push(handle.runCleanups);
+ handle();
+ });
+ }, {scope: bindingProviders});
}
function storeKeyForXFor(el, expression) {
el._x_keyExpression = expression;
@@ -3098,15 +3265,15 @@ function loop(el, iteratorNames, evaluateItems, evaluateKey) {
let keys = [];
if (isObject(items)) {
items = Object.entries(items).map(([key, value]) => {
- let scope = getIterationScopeVariables(iteratorNames, value, key, items);
- evaluateKey((value2) => keys.push(value2), {scope: {index: key, ...scope}});
- scopes.push(scope);
+ let scope2 = getIterationScopeVariables(iteratorNames, value, key, items);
+ evaluateKey((value2) => keys.push(value2), {scope: {index: key, ...scope2}});
+ scopes.push(scope2);
});
} else {
for (let i = 0; i < items.length; i++) {
- let scope = getIterationScopeVariables(iteratorNames, items[i], i, items);
- evaluateKey((value) => keys.push(value), {scope: {index: i, ...scope}});
- scopes.push(scope);
+ let scope2 = getIterationScopeVariables(iteratorNames, items[i], i, items);
+ evaluateKey((value) => keys.push(value), {scope: {index: i, ...scope2}});
+ scopes.push(scope2);
}
}
let adds = [];
@@ -3139,6 +3306,9 @@ function loop(el, iteratorNames, evaluateItems, evaluateKey) {
}
for (let i = 0; i < removes.length; i++) {
let key = removes[i];
+ if (!!lookup[key]._x_effects) {
+ lookup[key]._x_effects.forEach(dequeueJob);
+ }
lookup[key].remove();
lookup[key] = null;
delete lookup[key];
@@ -3151,7 +3321,9 @@ function loop(el, iteratorNames, evaluateItems, evaluateKey) {
mutateDom(() => {
elForSpot.after(marker);
elInSpot.after(elForSpot);
+ elForSpot._x_currentIfEl && elForSpot.after(elForSpot._x_currentIfEl);
marker.before(elInSpot);
+ elInSpot._x_currentIfEl && elInSpot.after(elInSpot._x_currentIfEl);
marker.remove();
});
refreshScope(elForSpot, scopes[keys.indexOf(keyForSpot)]);
@@ -3159,10 +3331,12 @@ function loop(el, iteratorNames, evaluateItems, evaluateKey) {
for (let i = 0; i < adds.length; i++) {
let [lastKey2, index] = adds[i];
let lastEl = lastKey2 === "template" ? templateEl : lookup[lastKey2];
- let scope = scopes[index];
+ if (lastEl._x_currentIfEl)
+ lastEl = lastEl._x_currentIfEl;
+ let scope2 = scopes[index];
let key = keys[index];
let clone2 = document.importNode(templateEl.content, true).firstElementChild;
- addScopeToNode(clone2, reactive(scope), templateEl);
+ addScopeToNode(clone2, reactive(scope2), templateEl);
mutateDom(() => {
lastEl.after(clone2);
initTree(clone2);
@@ -3251,6 +3425,11 @@ directive("if", (el, {expression}, {effect: effect3, cleanup}) => {
});
el._x_currentIfEl = clone2;
el._x_undoIf = () => {
+ walk(clone2, (node) => {
+ if (!!node._x_effects) {
+ node._x_effects.forEach(dequeueJob);
+ }
+ });
clone2.remove();
delete el._x_currentIfEl;
};
@@ -3268,11 +3447,23 @@ directive("if", (el, {expression}, {effect: effect3, cleanup}) => {
cleanup(() => el._x_undoIf && el._x_undoIf());
});
+// packages/alpinejs/src/directives/x-id.js
+directive("id", (el, {expression}, {evaluate: evaluate2}) => {
+ let names = evaluate2(expression);
+ names.forEach((name) => setIdRoot(el, name));
+});
+
// packages/alpinejs/src/directives/x-on.js
mapAttributes(startingWith("@", into(prefix("on:"))));
directive("on", skipDuringClone((el, {value, modifiers, expression}, {cleanup}) => {
let evaluate2 = expression ? evaluateLater(el, expression) : () => {
};
+ if (el.tagName.toLowerCase() === "template") {
+ if (!el._x_forwardEvents)
+ el._x_forwardEvents = [];
+ if (!el._x_forwardEvents.includes(value))
+ el._x_forwardEvents.push(value);
+ }
let removeListener = on(el, value, modifiers, (e) => {
evaluate2(() => {
}, {scope: {$event: e}, params: [e]});
@@ -3282,7 +3473,7 @@ directive("on", skipDuringClone((el, {value, modifiers, expression}, {cleanup})
// packages/alpinejs/src/index.js
alpine_default.setEvaluator(normalEvaluator);
-alpine_default.setReactivityEngine({reactive: import_reactivity9.reactive, effect: import_reactivity9.effect, release: import_reactivity9.stop, raw: import_reactivity9.toRaw});
+alpine_default.setReactivityEngine({reactive: import_reactivity8.reactive, effect: import_reactivity8.effect, release: import_reactivity8.stop, raw: import_reactivity8.toRaw});
var src_default = alpine_default;
// packages/alpinejs/builds/module.js
diff --git a/alpinejs/packages/alpinejs/dist/module.esm.js b/alpinejs/packages/alpinejs/dist/module.esm.js
index 7e24133..054b727 100644
--- a/alpinejs/packages/alpinejs/dist/module.esm.js
+++ b/alpinejs/packages/alpinejs/dist/module.esm.js
@@ -1266,6 +1266,11 @@ function queueJob(job) {
queue.push(job);
queueFlush();
}
+function dequeueJob(job) {
+ let index = queue.indexOf(job);
+ if (index !== -1)
+ queue.splice(index, 1);
+}
function queueFlush() {
if (!flushing && !flushPending) {
flushPending = true;
@@ -1339,8 +1344,15 @@ var onElAddeds = [];
function onElAdded(callback) {
onElAddeds.push(callback);
}
-function onElRemoved(callback) {
- onElRemoveds.push(callback);
+function onElRemoved(el, callback) {
+ if (typeof callback === "function") {
+ if (!el._x_cleanups)
+ el._x_cleanups = [];
+ el._x_cleanups.push(callback);
+ } else {
+ callback = el;
+ onElRemoveds.push(callback);
+ }
}
function onAttributesAdded(callback) {
onAttributeAddeds.push(callback);
@@ -1453,16 +1465,34 @@ function onMutate(mutations) {
addedAttributes.forEach((attrs, el) => {
onAttributeAddeds.forEach((i) => i(el, attrs));
});
- for (let node of addedNodes) {
- if (removedNodes.includes(node))
- continue;
- onElAddeds.forEach((i) => i(node));
- }
for (let node of removedNodes) {
if (addedNodes.includes(node))
continue;
onElRemoveds.forEach((i) => i(node));
+ if (node._x_cleanups) {
+ while (node._x_cleanups.length)
+ node._x_cleanups.pop()();
+ }
}
+ addedNodes.forEach((node) => {
+ node._x_ignoreSelf = true;
+ node._x_ignore = true;
+ });
+ for (let node of addedNodes) {
+ if (removedNodes.includes(node))
+ continue;
+ if (!node.isConnected)
+ continue;
+ delete node._x_ignoreSelf;
+ delete node._x_ignore;
+ onElAddeds.forEach((i) => i(node));
+ node._x_ignore = true;
+ node._x_ignoreSelf = true;
+ }
+ addedNodes.forEach((node) => {
+ delete node._x_ignoreSelf;
+ delete node._x_ignore;
+ });
addedNodes = null;
removedNodes = null;
addedAttributes = null;
@@ -1470,15 +1500,18 @@ function onMutate(mutations) {
}
// packages/alpinejs/src/scope.js
+function scope(node) {
+ return mergeProxies(closestDataStack(node));
+}
function addScopeToNode(node, data2, referenceNode) {
node._x_dataStack = [data2, ...closestDataStack(referenceNode || node)];
return () => {
node._x_dataStack = node._x_dataStack.filter((i) => i !== data2);
};
}
-function refreshScope(element, scope) {
+function refreshScope(element, scope2) {
let existingScope = element._x_dataStack[0];
- Object.entries(scope).forEach(([key, value]) => {
+ Object.entries(scope2).forEach(([key, value]) => {
existingScope[key] = value;
});
}
@@ -1614,7 +1647,10 @@ function injectMagics(obj, el) {
Object.entries(magics).forEach(([name, callback]) => {
Object.defineProperty(obj, `$${name}`, {
get() {
- return callback(el, {Alpine: alpine_default, interceptor});
+ let [utilities, cleanup] = getElementBoundUtilities(el);
+ utilities = {interceptor, ...utilities};
+ onElRemoved(el, cleanup);
+ return callback(el, utilities);
},
enumerable: false
});
@@ -1671,8 +1707,8 @@ function normalEvaluator(el, expression) {
}
function generateEvaluatorFromFunction(dataStack, func) {
return (receiver = () => {
- }, {scope = {}, params = []} = {}) => {
- let result = func.apply(mergeProxies([scope, ...dataStack]), params);
+ }, {scope: scope2 = {}, params = []} = {}) => {
+ let result = func.apply(mergeProxies([scope2, ...dataStack]), params);
runIfTypeOfFunction(receiver, result);
};
}
@@ -1699,27 +1735,28 @@ function generateFunctionFromString(expression, el) {
function generateEvaluatorFromString(dataStack, expression, el) {
let func = generateFunctionFromString(expression, el);
return (receiver = () => {
- }, {scope = {}, params = []} = {}) => {
+ }, {scope: scope2 = {}, params = []} = {}) => {
func.result = void 0;
func.finished = false;
- let completeScope = mergeProxies([scope, ...dataStack]);
+ let completeScope = mergeProxies([scope2, ...dataStack]);
if (typeof func === "function") {
let promise = func(func, completeScope).catch((error2) => handleError(error2, el, expression));
if (func.finished) {
runIfTypeOfFunction(receiver, func.result, completeScope, params, el);
+ func.result = void 0;
} else {
promise.then((result) => {
runIfTypeOfFunction(receiver, result, completeScope, params, el);
- }).catch((error2) => handleError(error2, el, expression));
+ }).catch((error2) => handleError(error2, el, expression)).finally(() => func.result = void 0);
}
}
};
}
-function runIfTypeOfFunction(receiver, value, scope, params, el) {
+function runIfTypeOfFunction(receiver, value, scope2, params, el) {
if (typeof value === "function") {
- let result = value.apply(scope, params);
+ let result = value.apply(scope2, params);
if (result instanceof Promise) {
- result.then((i) => runIfTypeOfFunction(receiver, i, scope, params)).catch((error2) => handleError(error2, el, value));
+ result.then((i) => runIfTypeOfFunction(receiver, i, scope2, params)).catch((error2) => handleError(error2, el, value));
} else {
receiver(result);
}
@@ -1770,10 +1807,7 @@ function deferHandlingDirectives(callback) {
callback(flushHandlers);
stopDeferring();
}
-function getDirectiveHandler(el, directive2) {
- let noop = () => {
- };
- let handler3 = directiveHandlers[directive2.type] || noop;
+function getElementBoundUtilities(el) {
let cleanups = [];
let cleanup = (callback) => cleanups.push(callback);
let [effect3, cleanupEffect] = elementBoundEffect(el);
@@ -1786,7 +1820,14 @@ function getDirectiveHandler(el, directive2) {
evaluate: evaluate.bind(evaluate, el)
};
let doCleanup = () => cleanups.forEach((i) => i());
- onAttributeRemoved(el, directive2.original, doCleanup);
+ return [utilities, doCleanup];
+}
+function getDirectiveHandler(el, directive2) {
+ let noop = () => {
+ };
+ let handler3 = directiveHandlers[directive2.type] || noop;
+ let [utilities, cleanup] = getElementBoundUtilities(el);
+ onAttributeRemoved(el, directive2.original, cleanup);
let fullHandler = () => {
if (el._x_ignore || el._x_ignoreSelf)
return;
@@ -1794,7 +1835,7 @@ function getDirectiveHandler(el, directive2) {
handler3 = handler3.bind(handler3, el, directive2, utilities);
isDeferringHandlers ? directiveHandlerStacks.get(currentHandlerStackKey).push(handler3) : handler3();
};
- fullHandler.runCleanups = doCleanup;
+ fullHandler.runCleanups = cleanup;
return fullHandler;
}
var startingWith = (subject, replacement) => ({name, value}) => {
@@ -1842,14 +1883,17 @@ var directiveOrder = [
"ignore",
"ref",
"data",
+ "id",
"bind",
"init",
"for",
"model",
+ "modelable",
"transition",
"show",
"if",
DEFAULT,
+ "teleport",
"element"
];
function byPriority(a, b) {
@@ -1918,7 +1962,7 @@ function start() {
dispatch(document, "alpine:initializing");
startObservingMutations();
onElAdded((el) => initTree(el, walk));
- onElRemoved((el) => nextTick(() => destroyTree(el)));
+ onElRemoved((el) => destroyTree(el));
onAttributesAdded((el, attrs) => {
directives(el, attrs).forEach((handle) => handle());
});
@@ -1943,14 +1987,22 @@ function addInitSelector(selectorCallback) {
initSelectorCallbacks.push(selectorCallback);
}
function closestRoot(el, includeInitSelectors = false) {
+ return findClosest(el, (element) => {
+ const selectors = includeInitSelectors ? allSelectors() : rootSelectors();
+ if (selectors.some((selector) => element.matches(selector)))
+ return true;
+ });
+}
+function findClosest(el, callback) {
if (!el)
return;
- const selectors = includeInitSelectors ? allSelectors() : rootSelectors();
- if (selectors.some((selector) => el.matches(selector)))
+ if (callback(el))
return el;
+ if (el._x_teleportBack)
+ el = el._x_teleportBack;
if (!el.parentElement)
return;
- return closestRoot(el.parentElement, includeInitSelectors);
+ return findClosest(el.parentElement, callback);
}
function isRoot(el) {
return rootSelectors().some((selector) => el.matches(selector));
@@ -2025,7 +2077,10 @@ function setStylesFromObject(el, value) {
let previousStyles = {};
Object.entries(value).forEach(([key, value2]) => {
previousStyles[key] = el.style[key];
- el.style.setProperty(kebabCase(key), value2);
+ if (!key.startsWith("--")) {
+ key = kebabCase(key);
+ }
+ el.style.setProperty(key, value2);
});
setTimeout(() => {
if (el.style.length === 0) {
@@ -2040,7 +2095,7 @@ function setStylesFromString(el, value) {
let cache = el.getAttribute("style", value);
el.setAttribute("style", value);
return () => {
- el.setAttribute("style", cache);
+ el.setAttribute("style", cache || "");
};
}
function kebabCase(subject) {
@@ -2337,6 +2392,179 @@ function modifierValue(modifiers, key, fallback) {
return rawValue;
}
+// packages/alpinejs/src/clone.js
+var isCloning = false;
+function skipDuringClone(callback, fallback = () => {
+}) {
+ return (...args) => isCloning ? fallback(...args) : callback(...args);
+}
+function clone(oldEl, newEl) {
+ if (!newEl._x_dataStack)
+ newEl._x_dataStack = oldEl._x_dataStack;
+ isCloning = true;
+ dontRegisterReactiveSideEffects(() => {
+ cloneTree(newEl);
+ });
+ isCloning = false;
+}
+function cloneTree(el) {
+ let hasRunThroughFirstEl = false;
+ let shallowWalker = (el2, callback) => {
+ walk(el2, (el3, skip) => {
+ if (hasRunThroughFirstEl && isRoot(el3))
+ return skip();
+ hasRunThroughFirstEl = true;
+ callback(el3, skip);
+ });
+ };
+ initTree(el, shallowWalker);
+}
+function dontRegisterReactiveSideEffects(callback) {
+ let cache = effect;
+ overrideEffect((callback2, el) => {
+ let storedEffect = cache(callback2);
+ release(storedEffect);
+ return () => {
+ };
+ });
+ callback();
+ overrideEffect(cache);
+}
+
+// packages/alpinejs/src/utils/bind.js
+function bind(el, name, value, modifiers = []) {
+ if (!el._x_bindings)
+ el._x_bindings = reactive({});
+ el._x_bindings[name] = value;
+ name = modifiers.includes("camel") ? camelCase(name) : name;
+ switch (name) {
+ case "value":
+ bindInputValue(el, value);
+ break;
+ case "style":
+ bindStyles(el, value);
+ break;
+ case "class":
+ bindClasses(el, value);
+ break;
+ default:
+ bindAttribute(el, name, value);
+ break;
+ }
+}
+function bindInputValue(el, value) {
+ if (el.type === "radio") {
+ if (el.attributes.value === void 0) {
+ el.value = value;
+ }
+ if (window.fromModel) {
+ el.checked = checkedAttrLooseCompare(el.value, value);
+ }
+ } else if (el.type === "checkbox") {
+ if (Number.isInteger(value)) {
+ el.value = value;
+ } else if (!Number.isInteger(value) && !Array.isArray(value) && typeof value !== "boolean" && ![null, void 0].includes(value)) {
+ el.value = String(value);
+ } else {
+ if (Array.isArray(value)) {
+ 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;
+ }
+}
+function bindClasses(el, value) {
+ if (el._x_undoAddedClasses)
+ el._x_undoAddedClasses();
+ el._x_undoAddedClasses = setClasses(el, value);
+}
+function bindStyles(el, value) {
+ if (el._x_undoAddedStyles)
+ el._x_undoAddedStyles();
+ el._x_undoAddedStyles = setStyles(el, value);
+}
+function bindAttribute(el, name, value) {
+ if ([null, void 0, false].includes(value) && attributeShouldntBePreservedIfFalsy(name)) {
+ el.removeAttribute(name);
+ } else {
+ if (isBooleanAttr(name))
+ value = name;
+ setIfChanged(el, name, value);
+ }
+}
+function setIfChanged(el, attrName, value) {
+ if (el.getAttribute(attrName) != value) {
+ el.setAttribute(attrName, value);
+ }
+}
+function updateSelect(el, value) {
+ const arrayWrappedValue = [].concat(value).map((value2) => {
+ return value2 + "";
+ });
+ Array.from(el.options).forEach((option) => {
+ option.selected = arrayWrappedValue.includes(option.value);
+ });
+}
+function camelCase(subject) {
+ return subject.toLowerCase().replace(/-(\w)/g, (match, char) => char.toUpperCase());
+}
+function checkedAttrLooseCompare(valueA, valueB) {
+ return valueA == valueB;
+}
+function isBooleanAttr(attrName) {
+ 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 attributeShouldntBePreservedIfFalsy(name) {
+ return !["aria-pressed", "aria-checked", "aria-expanded", "aria-selected"].includes(name);
+}
+function getBinding(el, name, fallback) {
+ if (el._x_bindings && el._x_bindings[name] !== void 0)
+ return el._x_bindings[name];
+ let attr = el.getAttribute(name);
+ if (attr === null)
+ return typeof fallback === "function" ? fallback() : fallback;
+ if (isBooleanAttr(name)) {
+ return !![name, "true"].includes(attr);
+ }
+ if (attr === "")
+ return true;
+ return attr;
+}
+
// packages/alpinejs/src/utils/debounce.js
function debounce(func, wait) {
var timeout;
@@ -2390,42 +2618,22 @@ function getStores() {
return stores;
}
-// packages/alpinejs/src/clone.js
-var isCloning = false;
-function skipDuringClone(callback, fallback = () => {
-}) {
- return (...args) => isCloning ? fallback(...args) : callback(...args);
+// packages/alpinejs/src/binds.js
+var binds = {};
+function bind2(name, object) {
+ binds[name] = typeof object !== "function" ? () => object : object;
}
-function clone(oldEl, newEl) {
- newEl._x_dataStack = oldEl._x_dataStack;
- isCloning = true;
- dontRegisterReactiveSideEffects(() => {
- cloneTree(newEl);
- });
- isCloning = false;
-}
-function cloneTree(el) {
- let hasRunThroughFirstEl = false;
- let shallowWalker = (el2, callback) => {
- walk(el2, (el3, skip) => {
- if (hasRunThroughFirstEl && isRoot(el3))
- return skip();
- hasRunThroughFirstEl = true;
- callback(el3, skip);
+function injectBindingProviders(obj) {
+ Object.entries(binds).forEach(([name, callback]) => {
+ Object.defineProperty(obj, name, {
+ get() {
+ return (...args) => {
+ return callback(...args);
+ };
+ }
});
- };
- initTree(el, shallowWalker);
-}
-function dontRegisterReactiveSideEffects(callback) {
- let cache = effect;
- overrideEffect((callback2, el) => {
- let storedEffect = cache(callback2);
- release(storedEffect);
- return () => {
- };
});
- callback();
- overrideEffect(cache);
+ return obj;
}
// packages/alpinejs/src/datas.js
@@ -2461,19 +2669,23 @@ var Alpine = {
get raw() {
return raw;
},
- version: "3.5.1",
+ version: "3.9.1",
flushAndStopDeferringMutations,
disableEffectScheduling,
stopObservingMutations,
+ destroyTree,
setReactivityEngine,
+ closestDataStack,
skipDuringClone,
addRootSelector,
+ addInitSelector,
+ addScopeToNode,
deferMutations,
mapAttributes,
evaluateLater,
setEvaluator,
mergeProxies,
- destroyTree,
+ findClosest,
closestRoot,
interceptor,
transition,
@@ -2485,18 +2697,22 @@ var Alpine = {
evaluate,
initTree,
nextTick,
+ prefixed: prefix,
prefix: setPrefix,
plugin,
magic,
store,
start,
clone,
- data
+ bound: getBinding,
+ $data: scope,
+ data,
+ bind: bind2
};
var alpine_default = Alpine;
// packages/alpinejs/src/index.js
-var import_reactivity9 = __toModule(require_reactivity());
+var import_reactivity8 = __toModule(require_reactivity());
// packages/alpinejs/src/magics/$nextTick.js
magic("nextTick", () => nextTick);
@@ -2505,15 +2721,12 @@ magic("nextTick", () => nextTick);
magic("dispatch", (el) => dispatch.bind(dispatch, el));
// packages/alpinejs/src/magics/$watch.js
-magic("watch", (el) => (key, callback) => {
- let evaluate2 = evaluateLater(el, key);
+magic("watch", (el, {evaluateLater: evaluateLater2, effect: effect3}) => (key, callback) => {
+ let evaluate2 = evaluateLater2(key);
let firstTime = true;
let oldValue;
- let [effect3, cleanupEffect] = elementBoundEffect(el);
- onAttributeRemoved(el, key, cleanupEffect);
effect3(() => evaluate2((value) => {
- let div = document.createElement("div");
- div.dataset.throwAway = value;
+ JSON.stringify(value);
if (!firstTime) {
queueMicrotask(() => {
callback(value, oldValue);
@@ -2530,9 +2743,7 @@ magic("watch", (el) => (key, callback) => {
magic("store", getStores);
// packages/alpinejs/src/magics/$data.js
-magic("data", (el) => {
- return mergeProxies(closestDataStack(el));
-});
+magic("data", (el) => scope(el));
// packages/alpinejs/src/magics/$root.js
magic("root", (el) => closestRoot(el));
@@ -2555,9 +2766,88 @@ function getArrayOfRefObject(el) {
return refObjects;
}
+// packages/alpinejs/src/ids.js
+var globalIdMemo = {};
+function findAndIncrementId(name) {
+ if (!globalIdMemo[name])
+ globalIdMemo[name] = 0;
+ return ++globalIdMemo[name];
+}
+function closestIdRoot(el, name) {
+ return findClosest(el, (element) => {
+ if (element._x_ids && element._x_ids[name])
+ return true;
+ });
+}
+function setIdRoot(el, name) {
+ if (!el._x_ids)
+ el._x_ids = {};
+ if (!el._x_ids[name])
+ el._x_ids[name] = findAndIncrementId(name);
+}
+
+// packages/alpinejs/src/magics/$id.js
+magic("id", (el) => (name, key = null) => {
+ let root = closestIdRoot(el, name);
+ let id = root ? root._x_ids[name] : findAndIncrementId(name);
+ return key ? `${name}-${id}-${key}` : `${name}-${id}`;
+});
+
// packages/alpinejs/src/magics/$el.js
magic("el", (el) => el);
+// packages/alpinejs/src/directives/x-modelable.js
+directive("modelable", (el, {expression}, {effect: effect3, evaluate: evaluate2, evaluateLater: evaluateLater2}) => {
+ let func = evaluateLater2(expression);
+ let innerGet = () => {
+ let result;
+ func((i) => result = i);
+ return result;
+ };
+ let evaluateInnerSet = evaluateLater2(`${expression} = __placeholder`);
+ let innerSet = (val) => evaluateInnerSet(() => {
+ }, {scope: {__placeholder: val}});
+ let initialValue = innerGet();
+ if (el._x_modelable_hook)
+ initialValue = el._x_modelable_hook(initialValue);
+ innerSet(initialValue);
+ queueMicrotask(() => {
+ if (!el._x_model)
+ return;
+ let outerGet = el._x_model.get;
+ let outerSet = el._x_model.set;
+ effect3(() => innerSet(outerGet()));
+ effect3(() => outerSet(innerGet()));
+ });
+});
+
+// packages/alpinejs/src/directives/x-teleport.js
+directive("teleport", (el, {expression}, {cleanup}) => {
+ if (el.tagName.toLowerCase() !== "template")
+ warn("x-teleport can only be used on a <template> tag", el);
+ let target = document.querySelector(expression);
+ if (!target)
+ warn(`Cannot find x-teleport element for selector: "${expression}"`);
+ let clone2 = el.content.cloneNode(true).firstElementChild;
+ el._x_teleport = clone2;
+ clone2._x_teleportBack = el;
+ if (el._x_forwardEvents) {
+ el._x_forwardEvents.forEach((eventName) => {
+ clone2.addEventListener(eventName, (e) => {
+ e.stopPropagation();
+ el.dispatchEvent(new e.constructor(e.type, e));
+ });
+ });
+ }
+ addScopeToNode(clone2, {}, el);
+ mutateDom(() => {
+ target.appendChild(clone2);
+ initTree(clone2);
+ clone2._x_ignore = true;
+ });
+ cleanup(() => clone2.remove());
+});
+
// packages/alpinejs/src/directives/x-ignore.js
var handler = () => {
};
@@ -2572,127 +2862,6 @@ directive("ignore", handler);
// packages/alpinejs/src/directives/x-effect.js
directive("effect", (el, {expression}, {effect: effect3}) => effect3(evaluateLater(el, expression)));
-// packages/alpinejs/src/utils/bind.js
-function bind(el, name, value, modifiers = []) {
- if (!el._x_bindings)
- el._x_bindings = reactive({});
- el._x_bindings[name] = value;
- name = modifiers.includes("camel") ? camelCase(name) : name;
- switch (name) {
- case "value":
- bindInputValue(el, value);
- break;
- case "style":
- bindStyles(el, value);
- break;
- case "class":
- bindClasses(el, value);
- break;
- default:
- bindAttribute(el, name, value);
- break;
- }
-}
-function bindInputValue(el, value) {
- if (el.type === "radio") {
- if (el.attributes.value === void 0) {
- el.value = value;
- }
- if (window.fromModel) {
- el.checked = checkedAttrLooseCompare(el.value, value);
- }
- } else if (el.type === "checkbox") {
- if (Number.isInteger(value)) {
- el.value = value;
- } else if (!Number.isInteger(value) && !Array.isArray(value) && typeof value !== "boolean" && ![null, void 0].includes(value)) {
- el.value = String(value);
- } else {
- if (Array.isArray(value)) {
- 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;
- }
-}
-function bindClasses(el, value) {
- if (el._x_undoAddedClasses)
- el._x_undoAddedClasses();
- el._x_undoAddedClasses = setClasses(el, value);
-}
-function bindStyles(el, value) {
- if (el._x_undoAddedStyles)
- el._x_undoAddedStyles();
- el._x_undoAddedStyles = setStyles(el, value);
-}
-function bindAttribute(el, name, value) {
- if ([null, void 0, false].includes(value) && attributeShouldntBePreservedIfFalsy(name)) {
- el.removeAttribute(name);
- } else {
- if (isBooleanAttr(name))
- value = name;
- setIfChanged(el, name, value);
- }
-}
-function setIfChanged(el, attrName, value) {
- if (el.getAttribute(attrName) != value) {
- el.setAttribute(attrName, value);
- }
-}
-function updateSelect(el, value) {
- const arrayWrappedValue = [].concat(value).map((value2) => {
- return value2 + "";
- });
- Array.from(el.options).forEach((option) => {
- option.selected = arrayWrappedValue.includes(option.value);
- });
-}
-function camelCase(subject) {
- return subject.toLowerCase().replace(/-(\w)/g, (match, char) => char.toUpperCase());
-}
-function checkedAttrLooseCompare(valueA, valueB) {
- return valueA == valueB;
-}
-function isBooleanAttr(attrName) {
- 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 attributeShouldntBePreservedIfFalsy(name) {
- return !["aria-pressed", "aria-checked", "aria-expanded"].includes(name);
-}
-
// packages/alpinejs/src/utils/on.js
function on(el, event, modifiers, callback) {
let listenerTarget = el;
@@ -2924,11 +3093,11 @@ directive("cloak", (el) => queueMicrotask(() => mutateDom(() => el.removeAttribu
// packages/alpinejs/src/directives/x-init.js
addInitSelector(() => `[${prefix("init")}]`);
-directive("init", skipDuringClone((el, {expression}) => {
+directive("init", skipDuringClone((el, {expression}, {evaluate: evaluate2}) => {
if (typeof expression === "string") {
- return !!expression.trim() && evaluate(el, expression, {}, false);
+ return !!expression.trim() && evaluate2(expression, {}, false);
}
- return evaluate(el, expression, {}, false);
+ return evaluate2(expression, {}, false);
}));
// packages/alpinejs/src/directives/x-text.js
@@ -2956,8 +3125,9 @@ directive("html", (el, {expression}, {effect: effect3, evaluateLater: evaluateLa
// packages/alpinejs/src/directives/x-bind.js
mapAttributes(startingWith(":", into(prefix("bind:"))));
directive("bind", (el, {value, modifiers, expression, original}, {effect: effect3}) => {
- if (!value)
+ if (!value) {
return applyBindingsObject(el, expression, original, effect3);
+ }
if (value === "key")
return storeKeyForXFor(el, expression);
let evaluate2 = evaluateLater(el, expression);
@@ -2968,32 +3138,29 @@ directive("bind", (el, {value, modifiers, expression, original}, {effect: effect
}));
});
function applyBindingsObject(el, expression, original, effect3) {
+ let bindingProviders = {};
+ injectBindingProviders(bindingProviders);
let getBindings = evaluateLater(el, expression);
let cleanupRunners = [];
- effect3(() => {
- while (cleanupRunners.length)
- cleanupRunners.pop()();
- getBindings((bindings) => {
- let attributes = Object.entries(bindings).map(([name, value]) => ({name, value}));
- attributes = attributes.filter((attr) => {
- return !(typeof attr.value === "object" && !Array.isArray(attr.value) && attr.value !== null);
- });
- let staticAttributes = attributesOnly(attributes);
- attributes = attributes.map((attribute) => {
- if (staticAttributes.find((attr) => attr.name === attribute.name)) {
- return {
- name: `x-bind:${attribute.name}`,
- value: `"${attribute.value}"`
- };
- }
- return attribute;
- });
- directives(el, attributes, original).map((handle) => {
- cleanupRunners.push(handle.runCleanups);
- handle();
- });
+ while (cleanupRunners.length)
+ cleanupRunners.pop()();
+ getBindings((bindings) => {
+ let attributes = Object.entries(bindings).map(([name, value]) => ({name, value}));
+ let staticAttributes = attributesOnly(attributes);
+ attributes = attributes.map((attribute) => {
+ if (staticAttributes.find((attr) => attr.name === attribute.name)) {
+ return {
+ name: `x-bind:${attribute.name}`,
+ value: `"${attribute.value}"`
+ };
+ }
+ return attribute;
});
- });
+ directives(el, attributes, original).map((handle) => {
+ cleanupRunners.push(handle.runCleanups);
+ handle();
+ });
+ }, {scope: bindingProviders});
}
function storeKeyForXFor(el, expression) {
el._x_keyExpression = expression;
@@ -3088,15 +3255,15 @@ function loop(el, iteratorNames, evaluateItems, evaluateKey) {
let keys = [];
if (isObject(items)) {
items = Object.entries(items).map(([key, value]) => {
- let scope = getIterationScopeVariables(iteratorNames, value, key, items);
- evaluateKey((value2) => keys.push(value2), {scope: {index: key, ...scope}});
- scopes.push(scope);
+ let scope2 = getIterationScopeVariables(iteratorNames, value, key, items);
+ evaluateKey((value2) => keys.push(value2), {scope: {index: key, ...scope2}});
+ scopes.push(scope2);
});
} else {
for (let i = 0; i < items.length; i++) {
- let scope = getIterationScopeVariables(iteratorNames, items[i], i, items);
- evaluateKey((value) => keys.push(value), {scope: {index: i, ...scope}});
- scopes.push(scope);
+ let scope2 = getIterationScopeVariables(iteratorNames, items[i], i, items);
+ evaluateKey((value) => keys.push(value), {scope: {index: i, ...scope2}});
+ scopes.push(scope2);
}
}
let adds = [];
@@ -3129,6 +3296,9 @@ function loop(el, iteratorNames, evaluateItems, evaluateKey) {
}
for (let i = 0; i < removes.length; i++) {
let key = removes[i];
+ if (!!lookup[key]._x_effects) {
+ lookup[key]._x_effects.forEach(dequeueJob);
+ }
lookup[key].remove();
lookup[key] = null;
delete lookup[key];
@@ -3141,7 +3311,9 @@ function loop(el, iteratorNames, evaluateItems, evaluateKey) {
mutateDom(() => {
elForSpot.after(marker);
elInSpot.after(elForSpot);
+ elForSpot._x_currentIfEl && elForSpot.after(elForSpot._x_currentIfEl);
marker.before(elInSpot);
+ elInSpot._x_currentIfEl && elInSpot.after(elInSpot._x_currentIfEl);
marker.remove();
});
refreshScope(elForSpot, scopes[keys.indexOf(keyForSpot)]);
@@ -3149,10 +3321,12 @@ function loop(el, iteratorNames, evaluateItems, evaluateKey) {
for (let i = 0; i < adds.length; i++) {
let [lastKey2, index] = adds[i];
let lastEl = lastKey2 === "template" ? templateEl : lookup[lastKey2];
- let scope = scopes[index];
+ if (lastEl._x_currentIfEl)
+ lastEl = lastEl._x_currentIfEl;
+ let scope2 = scopes[index];
let key = keys[index];
let clone2 = document.importNode(templateEl.content, true).firstElementChild;
- addScopeToNode(clone2, reactive(scope), templateEl);
+ addScopeToNode(clone2, reactive(scope2), templateEl);
mutateDom(() => {
lastEl.after(clone2);
initTree(clone2);
@@ -3241,6 +3415,11 @@ directive("if", (el, {expression}, {effect: effect3, cleanup}) => {
});
el._x_currentIfEl = clone2;
el._x_undoIf = () => {
+ walk(clone2, (node) => {
+ if (!!node._x_effects) {
+ node._x_effects.forEach(dequeueJob);
+ }
+ });
clone2.remove();
delete el._x_currentIfEl;
};
@@ -3258,11 +3437,23 @@ directive("if", (el, {expression}, {effect: effect3, cleanup}) => {
cleanup(() => el._x_undoIf && el._x_undoIf());
});
+// packages/alpinejs/src/directives/x-id.js
+directive("id", (el, {expression}, {evaluate: evaluate2}) => {
+ let names = evaluate2(expression);
+ names.forEach((name) => setIdRoot(el, name));
+});
+
// packages/alpinejs/src/directives/x-on.js
mapAttributes(startingWith("@", into(prefix("on:"))));
directive("on", skipDuringClone((el, {value, modifiers, expression}, {cleanup}) => {
let evaluate2 = expression ? evaluateLater(el, expression) : () => {
};
+ if (el.tagName.toLowerCase() === "template") {
+ if (!el._x_forwardEvents)
+ el._x_forwardEvents = [];
+ if (!el._x_forwardEvents.includes(value))
+ el._x_forwardEvents.push(value);
+ }
let removeListener = on(el, value, modifiers, (e) => {
evaluate2(() => {
}, {scope: {$event: e}, params: [e]});
@@ -3272,7 +3463,7 @@ directive("on", skipDuringClone((el, {value, modifiers, expression}, {cleanup})
// packages/alpinejs/src/index.js
alpine_default.setEvaluator(normalEvaluator);
-alpine_default.setReactivityEngine({reactive: import_reactivity9.reactive, effect: import_reactivity9.effect, release: import_reactivity9.stop, raw: import_reactivity9.toRaw});
+alpine_default.setReactivityEngine({reactive: import_reactivity8.reactive, effect: import_reactivity8.effect, release: import_reactivity8.stop, raw: import_reactivity8.toRaw});
var src_default = alpine_default;
// packages/alpinejs/builds/module.js
diff --git a/alpinejs/packages/alpinejs/package.json b/alpinejs/packages/alpinejs/package.json
new file mode 100644
index 0000000..3902705
--- /dev/null
+++ b/alpinejs/packages/alpinejs/package.json
@@ -0,0 +1,13 @@
+{
+ "name": "alpinejs",
+ "version": "3.9.1",
+ "description": "The rugged, minimal JavaScript framework",
+ "author": "Caleb Porzio",
+ "license": "MIT",
+ "main": "dist/module.cjs.js",
+ "module": "dist/module.esm.js",
+ "unpkg": "dist/cdn.min.js",
+ "dependencies": {
+ "@vue/reactivity": "~3.1.1"
+ }
+}
diff --git a/alpinejs/packages/alpinejs/src/alpine.js b/alpinejs/packages/alpinejs/src/alpine.js
new file mode 100644
index 0000000..7028bb1
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/alpine.js
@@ -0,0 +1,67 @@
+import { setReactivityEngine, disableEffectScheduling, reactive, effect, release, raw } from './reactivity'
+import { mapAttributes, directive, setPrefix as prefix, prefix as prefixed } from './directives'
+import { start, addRootSelector, addInitSelector, closestRoot, findClosest, initTree, destroyTree } from './lifecycle'
+import { mutateDom, deferMutations, flushAndStopDeferringMutations, stopObservingMutations } from './mutation'
+import { mergeProxies, closestDataStack, addScopeToNode, scope as $data } from './scope'
+import { setEvaluator, evaluate, evaluateLater } from './evaluator'
+import { transition } from './directives/x-transition'
+import { clone, skipDuringClone } from './clone'
+import { interceptor } from './interceptor'
+import { getBinding as bound } from './utils/bind'
+import { debounce } from './utils/debounce'
+import { throttle } from './utils/throttle'
+import { setStyles } from './utils/styles'
+import { nextTick } from './nextTick'
+import { plugin } from './plugin'
+import { magic } from './magics'
+import { store } from './store'
+import { bind } from './binds'
+import { data } from './datas'
+
+let Alpine = {
+ get reactive() { return reactive },
+ get release() { return release },
+ get effect() { return effect },
+ get raw() { return raw },
+ version: ALPINE_VERSION,
+ flushAndStopDeferringMutations,
+ disableEffectScheduling,
+ stopObservingMutations,
+ destroyTree,
+ setReactivityEngine,
+ closestDataStack,
+ skipDuringClone,
+ addRootSelector,
+ addInitSelector,
+ addScopeToNode,
+ deferMutations,
+ mapAttributes,
+ evaluateLater,
+ setEvaluator,
+ mergeProxies,
+ findClosest,
+ closestRoot,
+ interceptor, // INTERNAL: not public API and is subject to change without major release.
+ transition, // INTERNAL
+ setStyles, // INTERNAL
+ mutateDom,
+ directive,
+ throttle,
+ debounce,
+ evaluate,
+ initTree,
+ nextTick,
+ prefixed,
+ prefix,
+ plugin,
+ magic,
+ store,
+ start,
+ clone,
+ bound,
+ $data,
+ data,
+ bind,
+}
+
+export default Alpine
diff --git a/alpinejs/packages/alpinejs/src/binds.js b/alpinejs/packages/alpinejs/src/binds.js
new file mode 100644
index 0000000..b842650
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/binds.js
@@ -0,0 +1,20 @@
+
+let binds = {}
+
+export function bind(name, object) {
+ binds[name] = typeof object !== 'function' ? () => object : object
+}
+
+export function injectBindingProviders(obj) {
+ Object.entries(binds).forEach(([name, callback]) => {
+ Object.defineProperty(obj, name, {
+ get() {
+ return (...args) => {
+ return callback(...args)
+ }
+ }
+ })
+ })
+
+ return obj
+}
diff --git a/alpinejs/packages/alpinejs/src/clone.js b/alpinejs/packages/alpinejs/src/clone.js
new file mode 100644
index 0000000..44f4e97
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/clone.js
@@ -0,0 +1,61 @@
+import { effect, release, overrideEffect } from "./reactivity"
+import { initTree, isRoot } from "./lifecycle"
+import { walk } from "./utils/walk"
+
+let isCloning = false
+
+export function skipDuringClone(callback, fallback = () => {}) {
+ return (...args) => isCloning ? fallback(...args) : callback(...args)
+}
+
+export function onlyDuringClone(callback) {
+ return (...args) => isCloning && callback(...args)
+}
+
+export function interuptCrawl(callback) {
+ return (...args) => isCloning || callback(...args)
+}
+
+export function clone(oldEl, newEl) {
+ if (! newEl._x_dataStack) newEl._x_dataStack = oldEl._x_dataStack
+
+ isCloning = true
+
+ dontRegisterReactiveSideEffects(() => {
+ cloneTree(newEl)
+ })
+
+ isCloning = false
+}
+
+export function cloneTree(el) {
+ let hasRunThroughFirstEl = false
+
+ let shallowWalker = (el, callback) => {
+ walk(el, (el, skip) => {
+ if (hasRunThroughFirstEl && isRoot(el)) return skip()
+
+ hasRunThroughFirstEl = true
+
+ callback(el, skip)
+ })
+ }
+
+ initTree(el, shallowWalker)
+}
+
+function dontRegisterReactiveSideEffects(callback) {
+ let cache = effect
+
+ overrideEffect((callback, el) => {
+ let storedEffect = cache(callback)
+
+ release(storedEffect)
+
+ return () => {}
+ })
+
+ callback()
+
+ overrideEffect(cache)
+}
diff --git a/alpinejs/packages/alpinejs/src/datas.js b/alpinejs/packages/alpinejs/src/datas.js
new file mode 100644
index 0000000..9706581
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/datas.js
@@ -0,0 +1,22 @@
+
+let datas = {}
+
+export function data(name, callback) {
+ datas[name] = callback
+}
+
+export function injectDataProviders(obj, context) {
+ Object.entries(datas).forEach(([name, callback]) => {
+ Object.defineProperty(obj, name, {
+ get() {
+ return (...args) => {
+ return callback.bind(context)(...args)
+ }
+ },
+
+ enumerable: false,
+ })
+ })
+
+ return obj
+}
diff --git a/alpinejs/packages/alpinejs/src/directives.js b/alpinejs/packages/alpinejs/src/directives.js
new file mode 100644
index 0000000..42d1654
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/directives.js
@@ -0,0 +1,188 @@
+import { onAttributeRemoved, onElRemoved } from './mutation'
+import { evaluate, evaluateLater } from './evaluator'
+import { elementBoundEffect } from './reactivity'
+import Alpine from './alpine'
+
+let prefixAsString = 'x-'
+
+export function prefix(subject = '') {
+ return prefixAsString + subject
+}
+
+export function setPrefix(newPrefix) {
+ prefixAsString = newPrefix
+}
+
+let directiveHandlers = {}
+
+export function directive(name, callback) {
+ directiveHandlers[name] = callback
+}
+
+export function directives(el, attributes, originalAttributeOverride) {
+ let transformedAttributeMap = {}
+
+ let directives = Array.from(attributes)
+ .map(toTransformedAttributes((newName, oldName) => transformedAttributeMap[newName] = oldName))
+ .filter(outNonAlpineAttributes)
+ .map(toParsedDirectives(transformedAttributeMap, originalAttributeOverride))
+ .sort(byPriority)
+
+ return directives.map(directive => {
+ return getDirectiveHandler(el, directive)
+ })
+}
+
+export function attributesOnly(attributes) {
+ return Array.from(attributes)
+ .map(toTransformedAttributes())
+ .filter(attr => ! outNonAlpineAttributes(attr))
+}
+
+let isDeferringHandlers = false
+let directiveHandlerStacks = new Map
+let currentHandlerStackKey = Symbol()
+
+export function deferHandlingDirectives(callback) {
+ isDeferringHandlers = true
+
+ let key = Symbol()
+
+ currentHandlerStackKey = key
+
+ directiveHandlerStacks.set(key, [])
+
+ let flushHandlers = () => {
+ while (directiveHandlerStacks.get(key).length) directiveHandlerStacks.get(key).shift()()
+
+ directiveHandlerStacks.delete(key)
+ }
+
+ let stopDeferring = () => { isDeferringHandlers = false; flushHandlers() }
+
+ callback(flushHandlers)
+
+ stopDeferring()
+}
+
+export function getElementBoundUtilities(el) {
+ let cleanups = []
+
+ let cleanup = callback => cleanups.push(callback)
+
+ let [effect, cleanupEffect] = elementBoundEffect(el)
+
+ cleanups.push(cleanupEffect)
+
+ let utilities = {
+ Alpine,
+ effect,
+ cleanup,
+ evaluateLater: evaluateLater.bind(evaluateLater, el),
+ evaluate: evaluate.bind(evaluate, el),
+ }
+
+ let doCleanup = () => cleanups.forEach(i => i())
+
+ return [utilities, doCleanup]
+}
+
+export function getDirectiveHandler(el, directive) {
+ let noop = () => {}
+
+ let handler = directiveHandlers[directive.type] || noop
+
+ let [utilities, cleanup] = getElementBoundUtilities(el)
+
+ onAttributeRemoved(el, directive.original, cleanup)
+
+ let fullHandler = () => {
+ if (el._x_ignore || el._x_ignoreSelf) return
+
+ handler.inline && handler.inline(el, directive, utilities)
+
+ handler = handler.bind(handler, el, directive, utilities)
+
+ isDeferringHandlers ? directiveHandlerStacks.get(currentHandlerStackKey).push(handler) : handler()
+ }
+
+ fullHandler.runCleanups = cleanup
+
+ return fullHandler
+}
+
+export let startingWith = (subject, replacement) => ({ name, value }) => {
+ if (name.startsWith(subject)) name = name.replace(subject, replacement)
+
+ return { name, value }
+}
+
+export let into = i => i
+
+function toTransformedAttributes(callback = () => {}) {
+ return ({ name, value }) => {
+ let { name: newName, value: newValue } = attributeTransformers.reduce((carry, transform) => {
+ return transform(carry)
+ }, { name, value })
+
+ if (newName !== name) callback(newName, name)
+
+ return { name: newName, value: newValue }
+ }
+}
+
+let attributeTransformers = []
+
+export function mapAttributes(callback) {
+ attributeTransformers.push(callback)
+}
+
+function outNonAlpineAttributes({ name }) {
+ return alpineAttributeRegex().test(name)
+}
+
+let alpineAttributeRegex = () => (new RegExp(`^${prefixAsString}([^:^.]+)\\b`))
+
+function toParsedDirectives(transformedAttributeMap, originalAttributeOverride) {
+ return ({ name, value }) => {
+ let typeMatch = name.match(alpineAttributeRegex())
+ let valueMatch = name.match(/:([a-zA-Z0-9\-:]+)/)
+ let modifiers = name.match(/\.[^.\]]+(?=[^\]]*$)/g) || []
+ let original = originalAttributeOverride || transformedAttributeMap[name] || name
+
+ return {
+ type: typeMatch ? typeMatch[1] : null,
+ value: valueMatch ? valueMatch[1] : null,
+ modifiers: modifiers.map(i => i.replace('.', '')),
+ expression: value,
+ original,
+ }
+ }
+}
+
+const DEFAULT = 'DEFAULT'
+
+let directiveOrder = [
+ 'ignore',
+ 'ref',
+ 'data',
+ 'id',
+ 'bind',
+ 'init',
+ 'for',
+ 'model',
+ 'modelable',
+ 'transition',
+ 'show',
+ 'if',
+ DEFAULT,
+ 'teleport',
+ 'element',
+]
+
+function byPriority(a, b) {
+ let typeA = directiveOrder.indexOf(a.type) === -1 ? DEFAULT : a.type
+ let typeB = directiveOrder.indexOf(b.type) === -1 ? DEFAULT : b.type
+
+ return directiveOrder.indexOf(typeA) - directiveOrder.indexOf(typeB)
+}
diff --git a/alpinejs/packages/alpinejs/src/directives/index.js b/alpinejs/packages/alpinejs/src/directives/index.js
new file mode 100644
index 0000000..8da02c5
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/directives/index.js
@@ -0,0 +1,18 @@
+import './x-transition'
+import './x-modelable'
+import './x-teleport'
+import './x-ignore'
+import './x-effect'
+import './x-model'
+import './x-cloak'
+import './x-init'
+import './x-text'
+import './x-html'
+import './x-bind'
+import './x-data'
+import './x-show'
+import './x-for'
+import './x-ref'
+import './x-if'
+import './x-id'
+import './x-on'
diff --git a/alpinejs/packages/alpinejs/src/directives/x-bind.js b/alpinejs/packages/alpinejs/src/directives/x-bind.js
new file mode 100644
index 0000000..39622dc
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/directives/x-bind.js
@@ -0,0 +1,63 @@
+import { attributesOnly, directive, directives, into, mapAttributes, prefix, startingWith } from '../directives'
+import { evaluateLater } from '../evaluator'
+import { mutateDom } from '../mutation'
+import bind from '../utils/bind'
+import { injectBindingProviders } from '../binds'
+
+mapAttributes(startingWith(':', into(prefix('bind:'))))
+
+directive('bind', (el, { value, modifiers, expression, original }, { effect }) => {
+ if (! value) {
+ return applyBindingsObject(el, expression, original, effect)
+ }
+
+ if (value === 'key') return storeKeyForXFor(el, expression)
+
+ let evaluate = evaluateLater(el, expression)
+
+ effect(() => evaluate(result => {
+ // If nested object key is undefined, set the default value to empty string.
+ if (result === undefined && expression.match(/\./)) result = ''
+
+ mutateDom(() => bind(el, value, result, modifiers))
+ }))
+})
+
+function applyBindingsObject(el, expression, original, effect) {
+ let bindingProviders = {}
+ injectBindingProviders(bindingProviders)
+
+ let getBindings = evaluateLater(el, expression)
+
+ let cleanupRunners = []
+
+ while (cleanupRunners.length) cleanupRunners.pop()()
+
+ getBindings(bindings => {
+ let attributes = Object.entries(bindings).map(([name, value]) => ({ name, value }))
+
+ let staticAttributes = attributesOnly(attributes)
+
+ // Handle binding normal HTML attributes (non-Alpine directives).
+ attributes = attributes.map(attribute => {
+ if (staticAttributes.find(attr => attr.name === attribute.name)) {
+ return {
+ name: `x-bind:${attribute.name}`,
+ value: `"${attribute.value}"`,
+ }
+ }
+
+ return attribute
+ })
+
+ directives(el, attributes, original).map(handle => {
+ cleanupRunners.push(handle.runCleanups)
+
+ handle()
+ })
+ }, { scope: bindingProviders } )
+}
+
+function storeKeyForXFor(el, expression) {
+ el._x_keyExpression = expression
+}
diff --git a/alpinejs/packages/alpinejs/src/directives/x-cloak.js b/alpinejs/packages/alpinejs/src/directives/x-cloak.js
new file mode 100644
index 0000000..84639f0
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/directives/x-cloak.js
@@ -0,0 +1,4 @@
+import { directive, prefix } from '../directives'
+import { mutateDom } from '../mutation'
+
+directive('cloak', el => queueMicrotask(() => mutateDom(() => el.removeAttribute(prefix('cloak')))))
diff --git a/alpinejs/packages/alpinejs/src/directives/x-data.js b/alpinejs/packages/alpinejs/src/directives/x-data.js
new file mode 100644
index 0000000..da20b8f
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/directives/x-data.js
@@ -0,0 +1,45 @@
+import { directive, prefix } from '../directives'
+import { initInterceptors } from '../interceptor'
+import { injectDataProviders } from '../datas'
+import { addRootSelector } from '../lifecycle'
+import { skipDuringClone } from '../clone'
+import { addScopeToNode } from '../scope'
+import { injectMagics, magic } from '../magics'
+import { reactive } from '../reactivity'
+import { evaluate } from '../evaluator'
+
+addRootSelector(() => `[${prefix('data')}]`)
+
+directive('data', skipDuringClone((el, { expression }, { cleanup }) => {
+ expression = expression === '' ? '{}' : expression
+
+ let magicContext = {}
+ let cleanup1 = injectMagics(magicContext, el).cleanup
+
+ let dataProviderContext = {}
+ injectDataProviders(dataProviderContext, magicContext)
+
+ let data = evaluate(el, expression, { scope: dataProviderContext })
+
+ if (data === undefined) data = {}
+
+ let cleanup2 = injectMagics(data, el).cleanup
+
+ let reactiveData = reactive(data)
+
+ initInterceptors(reactiveData)
+
+ let undo = addScopeToNode(el, reactiveData)
+
+ reactiveData['init'] && evaluate(el, reactiveData['init'])
+
+ cleanup(() => {
+ undo()
+
+ // MemLeak1: Issue #2140
+ cleanup1()
+ cleanup2()
+
+ reactiveData['destroy'] && evaluate(el, reactiveData['destroy'])
+ })
+}))
diff --git a/alpinejs/packages/alpinejs/src/directives/x-effect.js b/alpinejs/packages/alpinejs/src/directives/x-effect.js
new file mode 100644
index 0000000..c421417
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/directives/x-effect.js
@@ -0,0 +1,4 @@
+import { directive } from '../directives'
+import { evaluateLater } from '../evaluator'
+
+directive('effect', (el, { expression }, { effect }) => effect(evaluateLater(el, expression)))
diff --git a/alpinejs/packages/alpinejs/src/directives/x-for.js b/alpinejs/packages/alpinejs/src/directives/x-for.js
new file mode 100644
index 0000000..306c1e5
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/directives/x-for.js
@@ -0,0 +1,273 @@
+import { addScopeToNode, refreshScope } from '../scope'
+import { evaluateLater } from '../evaluator'
+import { directive } from '../directives'
+import { reactive } from '../reactivity'
+import { initTree } from '../lifecycle'
+import { mutateDom } from '../mutation'
+import { flushJobs } from '../scheduler'
+import { warn } from '../utils/warn'
+import { dequeueJob } from '../scheduler'
+
+directive('for', (el, { expression }, { effect, cleanup }) => {
+ let iteratorNames = parseForExpression(expression)
+
+ let evaluateItems = evaluateLater(el, iteratorNames.items)
+ let evaluateKey = evaluateLater(el,
+ // the x-bind:key expression is stored for our use instead of evaluated.
+ el._x_keyExpression || 'index'
+ )
+
+ el._x_prevKeys = []
+ el._x_lookup = {}
+
+ effect(() => loop(el, iteratorNames, evaluateItems, evaluateKey))
+
+ cleanup(() => {
+ Object.values(el._x_lookup).forEach(el => el.remove())
+
+ delete el._x_prevKeys
+ delete el._x_lookup
+ })
+})
+
+let shouldFastRender = true
+
+function loop(el, iteratorNames, evaluateItems, evaluateKey) {
+ let isObject = i => typeof i === 'object' && ! Array.isArray(i)
+ let templateEl = el
+
+ evaluateItems(items => {
+ // Prepare yourself. There's a lot going on here. Take heart,
+ // every bit of complexity in this function was added for
+ // the purpose of making Alpine fast with large datas.
+
+ // Support number literals. Ex: x-for="i in 100"
+ if (isNumeric(items) && items >= 0) {
+ items = Array.from(Array(items).keys(), i => i + 1)
+ }
+
+ if (items === undefined) items = []
+
+ let lookup = el._x_lookup
+ let prevKeys = el._x_prevKeys
+ let scopes = []
+ let keys = []
+
+ // In order to preserve DOM elements (move instead of replace)
+ // we need to generate all the keys for every iteration up
+ // front. These will be our source of truth for diffing.
+ if (isObject(items)) {
+ items = Object.entries(items).map(([key, value]) => {
+ let scope = getIterationScopeVariables(iteratorNames, value, key, items)
+
+ evaluateKey(value => keys.push(value), { scope: { index: key, ...scope} })
+
+ scopes.push(scope)
+ })
+ } else {
+ for (let i = 0; i < items.length; i++) {
+ let scope = getIterationScopeVariables(iteratorNames, items[i], i, items)
+
+ evaluateKey(value => keys.push(value), { scope: { index: i, ...scope} })
+
+ scopes.push(scope)
+ }
+ }
+
+ // Rather than making DOM manipulations inside one large loop, we'll
+ // instead track which mutations need to be made in the following
+ // arrays. After we're finished, we can batch them at the end.
+ let adds = []
+ let moves = []
+ let removes = []
+ let sames = []
+
+ // First, we track elements that will need to be removed.
+ for (let i = 0; i < prevKeys.length; i++) {
+ let key = prevKeys[i]
+
+ if (keys.indexOf(key) === -1) removes.push(key)
+ }
+
+ // Notice we're mutating prevKeys as we go. This makes it
+ // so that we can efficiently make incremental comparisons.
+ prevKeys = prevKeys.filter(key => ! removes.includes(key))
+
+ let lastKey = 'template'
+
+ // This is the important part of the diffing algo. Identifying
+ // which keys (future DOM elements) are new, which ones have
+ // or haven't moved (noting where they moved to / from).
+ for (let i = 0; i < keys.length; i++) {
+ let key = keys[i]
+
+ let prevIndex = prevKeys.indexOf(key)
+
+ if (prevIndex === -1) {
+ // New key found.
+ prevKeys.splice(i, 0, key)
+
+ adds.push([lastKey, i])
+ } else if (prevIndex !== i) {
+ // A key has moved.
+ let keyInSpot = prevKeys.splice(i, 1)[0]
+ let keyForSpot = prevKeys.splice(prevIndex - 1, 1)[0]
+
+ prevKeys.splice(i, 0, keyForSpot)
+ prevKeys.splice(prevIndex, 0, keyInSpot)
+
+ moves.push([keyInSpot, keyForSpot])
+ } else {
+ // This key hasn't moved, but we'll still keep track
+ // so that we can refresh it later on.
+ sames.push(key)
+ }
+
+ lastKey = key
+ }
+
+ // Now that we've done the diffing work, we can apply the mutations
+ // in batches for both separating types work and optimizing
+ // for browser performance.
+
+ // We'll remove all the nodes that need to be removed,
+ // letting the mutation observer pick them up and
+ // clean up any side effects they had.
+ for (let i = 0; i < removes.length; i++) {
+ let key = removes[i]
+
+ // Remove any queued effects that might run after the DOM node has been removed.
+ if (!! lookup[key]._x_effects) {
+ lookup[key]._x_effects.forEach(dequeueJob)
+ }
+
+ lookup[key].remove()
+
+ lookup[key] = null
+ delete lookup[key]
+ }
+
+ // Here we'll move elements around, skipping
+ // mutation observer triggers by using "mutateDom".
+ for (let i = 0; i < moves.length; i++) {
+ let [keyInSpot, keyForSpot] = moves[i]
+
+ let elInSpot = lookup[keyInSpot]
+ let elForSpot = lookup[keyForSpot]
+
+ let marker = document.createElement('div')
+
+ mutateDom(() => {
+ elForSpot.after(marker)
+ elInSpot.after(elForSpot)
+ elForSpot._x_currentIfEl && elForSpot.after(elForSpot._x_currentIfEl)
+ marker.before(elInSpot)
+ elInSpot._x_currentIfEl && elInSpot.after(elInSpot._x_currentIfEl)
+ marker.remove()
+ })
+
+ refreshScope(elForSpot, scopes[keys.indexOf(keyForSpot)])
+ }
+
+ // We can now create and add new elements.
+ for (let i = 0; i < adds.length; i++) {
+ let [lastKey, index] = adds[i]
+
+ let lastEl = (lastKey === 'template') ? templateEl : lookup[lastKey]
+ // If the element is a x-if template evaluated to true,
+ // point lastEl to the if-generated node
+ if (lastEl._x_currentIfEl) lastEl = lastEl._x_currentIfEl
+
+ let scope = scopes[index]
+ let key = keys[index]
+
+ let clone = document.importNode(templateEl.content, true).firstElementChild
+
+ addScopeToNode(clone, reactive(scope), templateEl)
+
+ mutateDom(() => {
+ lastEl.after(clone)
+
+ initTree(clone)
+ })
+
+ if (typeof key === 'object') {
+ warn('x-for key cannot be an object, it must be a string or an integer', templateEl)
+ }
+
+ lookup[key] = clone
+ }
+
+ // If an element hasn't changed, we still want to "refresh" the
+ // data it depends on in case the data has changed in an
+ // "unobservable" way.
+ for (let i = 0; i < sames.length; i++) {
+ refreshScope(lookup[sames[i]], scopes[keys.indexOf(sames[i])])
+ }
+
+ // Now we'll log the keys (and the order they're in) for comparing
+ // against next time.
+ templateEl._x_prevKeys = keys
+ })
+}
+
+// This was taken from VueJS 2.* core. Thanks Vue!
+function parseForExpression(expression) {
+ let forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/
+ let stripParensRE = /^\s*\(|\)\s*$/g
+ let forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/
+ let inMatch = expression.match(forAliasRE)
+
+ if (! inMatch) return
+
+ let res = {}
+ res.items = inMatch[2].trim()
+ let item = inMatch[1].replace(stripParensRE, '').trim()
+ 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) {
+ // We must create a new object, so each iteration has a new scope
+ let scopeVariables = {}
+
+ // Support array destructuring ([foo, bar]).
+ if (/^\[.*\]$/.test(iteratorNames.item) && Array.isArray(item)) {
+ let names = iteratorNames.item.replace('[', '').replace(']', '').split(',').map(i => i.trim())
+
+ names.forEach((name, i) => {
+ scopeVariables[name] = item[i]
+ })
+ // Support object destructuring ({ foo: 'oof', bar: 'rab' }).
+ } else if (/^\{.*\}$/.test(iteratorNames.item) && ! Array.isArray(item) && typeof item === 'object') {
+ let names = iteratorNames.item.replace('{', '').replace('}', '').split(',').map(i => i.trim())
+
+ names.forEach(name => {
+ scopeVariables[name] = item[name]
+ })
+ } else {
+ scopeVariables[iteratorNames.item] = item
+ }
+
+ if (iteratorNames.index) scopeVariables[iteratorNames.index] = index
+
+ if (iteratorNames.collection) scopeVariables[iteratorNames.collection] = items
+
+ return scopeVariables
+}
+
+function isNumeric(subject){
+ return ! Array.isArray(subject) && ! isNaN(subject)
+}
diff --git a/alpinejs/packages/alpinejs/src/directives/x-html.js b/alpinejs/packages/alpinejs/src/directives/x-html.js
new file mode 100644
index 0000000..b4977d3
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/directives/x-html.js
@@ -0,0 +1,13 @@
+import { evaluateLater } from '../evaluator'
+import { directive } from '../directives'
+import { mutateDom } from '../mutation'
+
+directive('html', (el, { expression }, { effect, evaluateLater }) => {
+ let evaluate = evaluateLater(expression)
+
+ effect(() => {
+ evaluate(value => {
+ el.innerHTML = value
+ })
+ })
+})
diff --git a/alpinejs/packages/alpinejs/src/directives/x-id.js b/alpinejs/packages/alpinejs/src/directives/x-id.js
new file mode 100644
index 0000000..897f279
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/directives/x-id.js
@@ -0,0 +1,8 @@
+import { directive } from "../directives"
+import { setIdRoot } from '../ids'
+
+directive('id', (el, { expression }, { evaluate }) => {
+ let names = evaluate(expression)
+
+ names.forEach(name => setIdRoot(el, name))
+})
diff --git a/alpinejs/packages/alpinejs/src/directives/x-if.js b/alpinejs/packages/alpinejs/src/directives/x-if.js
new file mode 100644
index 0000000..7360fc9
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/directives/x-if.js
@@ -0,0 +1,55 @@
+import { evaluateLater } from '../evaluator'
+import { addScopeToNode } from '../scope'
+import { directive } from '../directives'
+import { initTree } from '../lifecycle'
+import { mutateDom } from '../mutation'
+import { walk } from "../utils/walk"
+import { dequeueJob } from '../scheduler'
+
+directive('if', (el, { expression }, { effect, cleanup }) => {
+ let evaluate = evaluateLater(el, expression)
+
+ let show = () => {
+ if (el._x_currentIfEl) return el._x_currentIfEl
+
+ let clone = el.content.cloneNode(true).firstElementChild
+
+ addScopeToNode(clone, {}, el)
+
+ mutateDom(() => {
+ el.after(clone)
+
+ initTree(clone)
+ })
+
+ el._x_currentIfEl = clone
+
+ el._x_undoIf = () => {
+ walk(clone, (node) => {
+ if (!!node._x_effects) {
+ node._x_effects.forEach(dequeueJob)
+ }
+ })
+
+ clone.remove();
+
+ delete el._x_currentIfEl
+ }
+
+ return clone
+ }
+
+ let hide = () => {
+ if (! el._x_undoIf) return
+
+ el._x_undoIf()
+
+ delete el._x_undoIf
+ }
+
+ effect(() => evaluate(value => {
+ value ? show() : hide()
+ }))
+
+ cleanup(() => el._x_undoIf && el._x_undoIf())
+})
diff --git a/alpinejs/packages/alpinejs/src/directives/x-ignore.js b/alpinejs/packages/alpinejs/src/directives/x-ignore.js
new file mode 100644
index 0000000..2f21de3
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/directives/x-ignore.js
@@ -0,0 +1,17 @@
+import { directive } from "../directives"
+
+let handler = () => {}
+
+handler.inline = (el, { modifiers }, { cleanup }) => {
+ modifiers.includes('self')
+ ? el._x_ignoreSelf = true
+ : el._x_ignore = true
+
+ cleanup(() => {
+ modifiers.includes('self')
+ ? delete el._x_ignoreSelf
+ : delete el._x_ignore
+ })
+}
+
+directive('ignore', handler)
diff --git a/alpinejs/packages/alpinejs/src/directives/x-init.js b/alpinejs/packages/alpinejs/src/directives/x-init.js
new file mode 100644
index 0000000..42d3fb8
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/directives/x-init.js
@@ -0,0 +1,13 @@
+import { directive, prefix } from "../directives";
+import { addInitSelector } from "../lifecycle";
+import { skipDuringClone } from "../clone";
+
+addInitSelector(() => `[${prefix('init')}]`)
+
+directive('init', skipDuringClone((el, { expression }, { evaluate }) => {
+ if (typeof expression === 'string') {
+ return !! expression.trim() && evaluate(expression, {}, false)
+ }
+
+ return evaluate(expression, {}, false)
+}))
diff --git a/alpinejs/packages/alpinejs/src/directives/x-model.js b/alpinejs/packages/alpinejs/src/directives/x-model.js
new file mode 100644
index 0000000..b35e124
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/directives/x-model.js
@@ -0,0 +1,120 @@
+import { evaluateLater } from '../evaluator'
+import { directive } from '../directives'
+import { mutateDom } from '../mutation'
+import bind from '../utils/bind'
+import on from '../utils/on'
+
+directive('model', (el, { modifiers, expression }, { effect, cleanup }) => {
+ let evaluate = evaluateLater(el, expression)
+ let assignmentExpression = `${expression} = rightSideOfExpression($event, ${expression})`
+ let evaluateAssignment = evaluateLater(el, assignmentExpression)
+
+ // 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'
+
+ let assigmentFunction = generateAssignmentFunction(el, modifiers, expression)
+
+ let removeListener = on(el, event, modifiers, (e) => {
+ evaluateAssignment(() => {}, { scope: {
+ '$event': e,
+ rightSideOfExpression: assigmentFunction
+ }})
+ })
+
+ cleanup(() => removeListener())
+
+ // Allow programmatic overiding of x-model.
+ let evaluateSetModel = evaluateLater(el, `${expression} = __placeholder`)
+ el._x_model = {
+ get() {
+ let result
+ evaluate(value => result = value)
+ return result
+ },
+ set(value) {
+ evaluateSetModel(() => {}, { scope: { '__placeholder': value }})
+ },
+ }
+
+ el._x_forceModelUpdate = () => {
+ evaluate(value => {
+ // If nested model key is undefined, set the default value to empty string.
+ if (value === undefined && expression.match(/\./)) value = ''
+
+ // @todo: This is nasty
+ window.fromModel = true
+ mutateDom(() => bind(el, 'value', value))
+ delete window.fromModel
+ })
+ }
+
+ effect(() => {
+ // Don't modify the value of the input if it's focused.
+ if (modifiers.includes('unintrusive') && document.activeElement.isSameNode(el)) return
+
+ el._x_forceModelUpdate()
+ })
+})
+
+function generateAssignmentFunction(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.
+ mutateDom(() => {
+ if (! el.hasAttribute('name')) el.setAttribute('name', expression)
+ })
+ }
+
+ return (event, currentValue) => {
+ return mutateDom(() => {
+ // Check for event.detail due to an issue where IE11 handles other events as a CustomEvent.
+ // Safari autofill triggers event as CustomEvent and assigns value to target
+ // so we return event.target.value instead of event.detail
+ if (event instanceof CustomEvent && event.detail !== undefined) {
+ return event.detail || event.target.value
+ } 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)) {
+ let 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 => {
+ let rawValue = option.value || option.text
+ return safeParseNumber(rawValue)
+ })
+ : Array.from(event.target.selectedOptions).map(option => {
+ return option.value || option.text
+ })
+ } else {
+ let rawValue = event.target.value
+ return modifiers.includes('number')
+ ? safeParseNumber(rawValue)
+ : (modifiers.includes('trim') ? rawValue.trim() : rawValue)
+ }
+ })
+ }
+}
+
+function safeParseNumber(rawValue) {
+ let number = rawValue ? parseFloat(rawValue) : null
+
+ return isNumeric(number) ? number : rawValue
+}
+
+function checkedAttrLooseCompare(valueA, valueB) {
+ return valueA == valueB
+}
+
+function isNumeric(subject){
+ return ! Array.isArray(subject) && ! isNaN(subject)
+}
diff --git a/alpinejs/packages/alpinejs/src/directives/x-modelable.js b/alpinejs/packages/alpinejs/src/directives/x-modelable.js
new file mode 100644
index 0000000..572bf9a
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/directives/x-modelable.js
@@ -0,0 +1,26 @@
+import { evaluateLater } from '../evaluator'
+import { directive } from '../directives'
+
+directive('modelable', (el, { expression }, { effect, evaluate, evaluateLater }) => {
+ let func = evaluateLater(expression)
+ let innerGet = () => { let result; func(i => result = i); return result; }
+ let evaluateInnerSet = evaluateLater(`${expression} = __placeholder`)
+ let innerSet = val => evaluateInnerSet(() => {}, { scope: { '__placeholder': val }})
+
+ let initialValue = innerGet()
+
+ // Allow packages like Livewire to hook into $modelable. Ex: `wire:model.defer`
+ if (el._x_modelable_hook) initialValue = el._x_modelable_hook(initialValue)
+
+ innerSet(initialValue)
+
+ queueMicrotask(() => {
+ if (! el._x_model) return
+
+ let outerGet = el._x_model.get
+ let outerSet = el._x_model.set
+
+ effect(() => innerSet(outerGet()))
+ effect(() => outerSet(innerGet()))
+ })
+})
diff --git a/alpinejs/packages/alpinejs/src/directives/x-on.js b/alpinejs/packages/alpinejs/src/directives/x-on.js
new file mode 100644
index 0000000..cd997a3
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/directives/x-on.js
@@ -0,0 +1,22 @@
+import { directive, into, mapAttributes, prefix, startingWith } from '../directives'
+import { evaluateLater } from '../evaluator'
+import { skipDuringClone } from '../clone'
+import on from '../utils/on'
+
+mapAttributes(startingWith('@', into(prefix('on:'))))
+
+directive('on', skipDuringClone((el, { value, modifiers, expression }, { cleanup }) => {
+ let evaluate = expression ? evaluateLater(el, expression) : () => {}
+
+ // Forward event listeners on portals.
+ if (el.tagName.toLowerCase() === 'template') {
+ if (! el._x_forwardEvents) el._x_forwardEvents = []
+ if (! el._x_forwardEvents.includes(value)) el._x_forwardEvents.push(value)
+ }
+
+ let removeListener = on(el, value, modifiers, e => {
+ evaluate(() => {}, { scope: { '$event': e }, params: [e] })
+ })
+
+ cleanup(() => removeListener())
+}))
diff --git a/alpinejs/packages/alpinejs/src/directives/x-ref.js b/alpinejs/packages/alpinejs/src/directives/x-ref.js
new file mode 100644
index 0000000..9d6bbf6
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/directives/x-ref.js
@@ -0,0 +1,16 @@
+import { closestRoot } from '../lifecycle'
+import { directive } from '../directives'
+
+function handler () {}
+
+handler.inline = (el, { expression }, { cleanup }) => {
+ let root = closestRoot(el)
+
+ if (! root._x_refs) root._x_refs = {}
+
+ root._x_refs[expression] = el
+
+ cleanup(() => delete root._x_refs[expression])
+}
+
+directive('ref', handler)
diff --git a/alpinejs/packages/alpinejs/src/directives/x-show.js b/alpinejs/packages/alpinejs/src/directives/x-show.js
new file mode 100644
index 0000000..b9619b5
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/directives/x-show.js
@@ -0,0 +1,56 @@
+import { evaluateLater } from '../evaluator'
+import { directive } from '../directives'
+import { mutateDom } from '../mutation'
+import { once } from '../utils/once'
+
+directive('show', (el, { modifiers, expression }, { effect }) => {
+ let evaluate = evaluateLater(el, expression)
+
+ let hide = () => mutateDom(() => {
+ el.style.display = 'none'
+
+ el._x_isShown = false
+ })
+
+ let show = () => mutateDom(() => {
+ if (el.style.length === 1 && el.style.display === 'none') {
+ el.removeAttribute('style')
+ } else {
+ el.style.removeProperty('display')
+ }
+
+ el._x_isShown = true
+ })
+
+ // We are wrapping this function in a setTimeout here to prevent
+ // a race condition from happening where elements that have a
+ // @click.away always view themselves as shown on the page.
+ let clickAwayCompatibleShow = () => setTimeout(show)
+
+ let toggle = once(
+ value => value ? show() : hide(),
+ value => {
+ if (typeof el._x_toggleAndCascadeWithTransitions === 'function') {
+ el._x_toggleAndCascadeWithTransitions(el, value, show, hide)
+ } else {
+ value ? clickAwayCompatibleShow() : hide()
+ }
+ }
+ )
+
+ let oldValue
+ let firstTime = true
+
+ effect(() => evaluate(value => {
+ // Let's make sure we only call this effect if the value changed.
+ // This prevents "blip" transitions. (1 tick out, then in)
+ if (! firstTime && value === oldValue) return
+
+ if (modifiers.includes('immediate')) value ? clickAwayCompatibleShow() : hide()
+
+ toggle(value)
+
+ oldValue = value
+ firstTime = false
+ }))
+})
diff --git a/alpinejs/packages/alpinejs/src/directives/x-teleport.js b/alpinejs/packages/alpinejs/src/directives/x-teleport.js
new file mode 100644
index 0000000..624be2c
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/directives/x-teleport.js
@@ -0,0 +1,42 @@
+import { directive } from "../directives"
+import { addInitSelector, initTree } from "../lifecycle"
+import { mutateDom } from "../mutation"
+import { addScopeToNode } from "../scope"
+import { warn } from "../utils/warn"
+
+directive('teleport', (el, { expression }, { cleanup }) => {
+ if (el.tagName.toLowerCase() !== 'template') warn('x-teleport can only be used on a <template> tag', el)
+
+ let target = document.querySelector(expression)
+
+ if (! target) warn(`Cannot find x-teleport element for selector: "${expression}"`)
+
+ let clone = el.content.cloneNode(true).firstElementChild
+
+ // Add reference to element on <template x-teleport, and visa versa.
+ el._x_teleport = clone
+ clone._x_teleportBack = el
+
+ // Forward event listeners:
+ if (el._x_forwardEvents) {
+ el._x_forwardEvents.forEach(eventName => {
+ clone.addEventListener(eventName, e => {
+ e.stopPropagation()
+
+ el.dispatchEvent(new e.constructor(e.type, e))
+ })
+ })
+ }
+
+ addScopeToNode(clone, {}, el)
+
+ mutateDom(() => {
+ target.appendChild(clone)
+
+ initTree(clone)
+
+ clone._x_ignore = true
+ })
+
+ cleanup(() => clone.remove())
+})
diff --git a/alpinejs/packages/alpinejs/src/directives/x-text.js b/alpinejs/packages/alpinejs/src/directives/x-text.js
new file mode 100644
index 0000000..74be109
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/directives/x-text.js
@@ -0,0 +1,14 @@
+import { directive } from '../directives'
+import { mutateDom } from '../mutation'
+
+directive('text', (el, { expression }, { effect, evaluateLater }) => {
+ let evaluate = evaluateLater(expression)
+
+ effect(() => {
+ evaluate(value => {
+ mutateDom(() => {
+ el.textContent = value
+ })
+ })
+ })
+})
diff --git a/alpinejs/packages/alpinejs/src/directives/x-transition.js b/alpinejs/packages/alpinejs/src/directives/x-transition.js
new file mode 100644
index 0000000..47749ad
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/directives/x-transition.js
@@ -0,0 +1,334 @@
+import { releaseNextTicks, holdNextTicks } from '../nextTick'
+import { setClasses } from '../utils/classes'
+import { setStyles } from '../utils/styles'
+import { directive } from '../directives'
+import { mutateDom } from '../mutation'
+import { once } from '../utils/once'
+
+directive('transition', (el, { value, modifiers, expression }, { evaluate }) => {
+ if (typeof expression === 'function') expression = evaluate(expression)
+
+ if (! expression) {
+ registerTransitionsFromHelper(el, modifiers, value)
+ } else {
+ registerTransitionsFromClassString(el, expression, value)
+ }
+})
+
+function registerTransitionsFromClassString(el, classString, stage) {
+ registerTransitionObject(el, setClasses, '')
+
+ let directiveStorageMap = {
+ 'enter': (classes) => { el._x_transition.enter.during = classes },
+ 'enter-start': (classes) => { el._x_transition.enter.start = classes },
+ 'enter-end': (classes) => { el._x_transition.enter.end = classes },
+ 'leave': (classes) => { el._x_transition.leave.during = classes },
+ 'leave-start': (classes) => { el._x_transition.leave.start = classes },
+ 'leave-end': (classes) => { el._x_transition.leave.end = classes },
+ }
+
+ directiveStorageMap[stage](classString)
+}
+
+function registerTransitionsFromHelper(el, modifiers, stage) {
+ registerTransitionObject(el, setStyles)
+
+ let doesntSpecify = (! modifiers.includes('in') && ! modifiers.includes('out')) && ! stage
+ let transitioningIn = doesntSpecify || modifiers.includes('in') || ['enter'].includes(stage)
+ let transitioningOut = doesntSpecify || modifiers.includes('out') || ['leave'].includes(stage)
+
+ if (modifiers.includes('in') && ! doesntSpecify) {
+ modifiers = modifiers.filter((i, index) => index < modifiers.indexOf('out'))
+ }
+
+ if (modifiers.includes('out') && ! doesntSpecify) {
+ modifiers = modifiers.filter((i, index) => index > modifiers.indexOf('out'))
+ }
+
+ let wantsAll = ! modifiers.includes('opacity') && ! modifiers.includes('scale')
+ let wantsOpacity = wantsAll || modifiers.includes('opacity')
+ let wantsScale = wantsAll || modifiers.includes('scale')
+ let opacityValue = wantsOpacity ? 0 : 1
+ let scaleValue = wantsScale ? modifierValue(modifiers, 'scale', 95) / 100 : 1
+ let delay = modifierValue(modifiers, 'delay', 0)
+ let origin = modifierValue(modifiers, 'origin', 'center')
+ let property = 'opacity, transform'
+ let durationIn = modifierValue(modifiers, 'duration', 150) / 1000
+ let durationOut = modifierValue(modifiers, 'duration', 75) / 1000
+ let easing = `cubic-bezier(0.4, 0.0, 0.2, 1)`
+
+ if (transitioningIn) {
+ el._x_transition.enter.during = {
+ transformOrigin: origin,
+ transitionDelay: delay,
+ transitionProperty: property,
+ transitionDuration: `${durationIn}s`,
+ transitionTimingFunction: easing,
+ }
+
+ el._x_transition.enter.start = {
+ opacity: opacityValue,
+ transform: `scale(${scaleValue})`,
+ }
+
+ el._x_transition.enter.end = {
+ opacity: 1,
+ transform: `scale(1)`,
+ }
+ }
+
+ if (transitioningOut) {
+ el._x_transition.leave.during = {
+ transformOrigin: origin,
+ transitionDelay: delay,
+ transitionProperty: property,
+ transitionDuration: `${durationOut}s`,
+ transitionTimingFunction: easing,
+ }
+
+ el._x_transition.leave.start = {
+ opacity: 1,
+ transform: `scale(1)`,
+ }
+
+ el._x_transition.leave.end = {
+ opacity: opacityValue,
+ transform: `scale(${scaleValue})`,
+ }
+ }
+}
+
+function registerTransitionObject(el, setFunction, defaultValue = {}) {
+ if (! el._x_transition) el._x_transition = {
+ enter: { during: defaultValue, start: defaultValue, end: defaultValue },
+
+ leave: { during: defaultValue, start: defaultValue, end: defaultValue },
+
+ in(before = () => {}, after = () => {}) {
+ transition(el, setFunction, {
+ during: this.enter.during,
+ start: this.enter.start,
+ end: this.enter.end,
+ }, before, after)
+ },
+
+ out(before = () => {}, after = () => {}) {
+ transition(el, setFunction, {
+ during: this.leave.during,
+ start: this.leave.start,
+ end: this.leave.end,
+ }, before, after)
+ },
+ }
+}
+
+window.Element.prototype._x_toggleAndCascadeWithTransitions = function (el, value, show, hide) {
+ // We are running this function after one tick to prevent
+ // a race condition from happening where elements that have a
+ // @click.away always view themselves as shown on the page.
+ // If the tab is active, we prioritise requestAnimationFrame which plays
+ // nicely with nested animations otherwise we use setTimeout to make sure
+ // it keeps running in background. setTimeout has a lower priority in the
+ // event loop so it would skip nested transitions but when the tab is
+ // hidden, it's not relevant.
+ let clickAwayCompatibleShow = () => {document.visibilityState === 'visible' ? requestAnimationFrame(show) : setTimeout(show)}
+
+ if (value) {
+ if (el._x_transition && (el._x_transition.enter || el._x_transition.leave)) {
+ // This fixes a bug where if you are only transitioning OUT and you are also using @click.outside
+ // the element when shown immediately starts transitioning out. There is a test in the manual
+ // transition test file for this: /tests/cypress/manual-transition-test.html
+ (el._x_transition.enter && (Object.entries(el._x_transition.enter.during).length || Object.entries(el._x_transition.enter.start).length || Object.entries(el._x_transition.enter.end).length))
+ ? el._x_transition.in(show)
+ : clickAwayCompatibleShow()
+ } else {
+ el._x_transition
+ ? el._x_transition.in(show)
+ : clickAwayCompatibleShow()
+ }
+
+ return
+ }
+
+ // Livewire depends on el._x_hidePromise.
+ el._x_hidePromise = el._x_transition
+ ? new Promise((resolve, reject) => {
+ el._x_transition.out(() => {}, () => resolve(hide))
+
+ el._x_transitioning.beforeCancel(() => reject({ isFromCancelledTransition: true }))
+ })
+ : Promise.resolve(hide)
+
+ queueMicrotask(() => {
+ let closest = closestHide(el)
+
+ if (closest) {
+ if (! closest._x_hideChildren) closest._x_hideChildren = []
+
+ closest._x_hideChildren.push(el)
+ } else {
+ queueMicrotask(() => {
+ let hideAfterChildren = el => {
+ let carry = Promise.all([
+ el._x_hidePromise,
+ ...(el._x_hideChildren || []).map(hideAfterChildren),
+ ]).then(([i]) => i())
+
+ delete el._x_hidePromise
+ delete el._x_hideChildren
+
+ return carry
+ }
+
+ hideAfterChildren(el).catch((e) => {
+ if (! e.isFromCancelledTransition) throw e
+ })
+ })
+ }
+ })
+}
+
+function closestHide(el) {
+ let parent = el.parentNode
+
+ if (! parent) return
+
+ return parent._x_hidePromise ? parent : closestHide(parent)
+}
+
+export function transition(el, setFunction, { during, start, end } = {}, before = () => {}, after = () => {}) {
+ if (el._x_transitioning) el._x_transitioning.cancel()
+
+ if (Object.keys(during).length === 0 && Object.keys(start).length === 0 && Object.keys(end).length === 0) {
+ // Execute right away if there is no transition.
+ before(); after()
+ return
+ }
+
+ let undoStart, undoDuring, undoEnd
+
+ performTransition(el, {
+ start() {
+ undoStart = setFunction(el, start)
+ },
+ during() {
+ undoDuring = setFunction(el, during)
+ },
+ before,
+ end() {
+ undoStart()
+
+ undoEnd = setFunction(el, end)
+ },
+ after,
+ cleanup() {
+ undoDuring()
+ undoEnd()
+ },
+ })
+}
+
+export function performTransition(el, stages) {
+ // All transitions need to be truly "cancellable". Meaning we need to
+ // account for interruptions at ALL stages of the transitions and
+ // immediately run the rest of the transition.
+ let interrupted, reachedBefore, reachedEnd
+
+ let finish = once(() => {
+ mutateDom(() => {
+ interrupted = true
+
+ if (! reachedBefore) stages.before()
+
+ if (! reachedEnd) {
+ stages.end()
+
+ releaseNextTicks()
+ }
+
+ stages.after()
+
+ // Adding an "isConnected" check, in case the callback removed the element from the DOM.
+ if (el.isConnected) stages.cleanup()
+
+ delete el._x_transitioning
+ })
+ })
+
+ el._x_transitioning = {
+ beforeCancels: [],
+ beforeCancel(callback) { this.beforeCancels.push(callback) },
+ cancel: once(function () { while (this.beforeCancels.length) { this.beforeCancels.shift()() }; finish(); }),
+ finish,
+ }
+
+ mutateDom(() => {
+ stages.start()
+ stages.during()
+ })
+
+ holdNextTicks()
+
+ requestAnimationFrame(() => {
+ if (interrupted) return
+
+ // 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
+ let delay = Number(getComputedStyle(el).transitionDelay.replace(/,.*/, '').replace('s', '')) * 1000
+
+ if (duration === 0) duration = Number(getComputedStyle(el).animationDuration.replace('s', '')) * 1000
+
+ mutateDom(() => {
+ stages.before()
+ })
+
+ reachedBefore = true
+
+ requestAnimationFrame(() => {
+ if (interrupted) return
+
+ mutateDom(() => {
+ stages.end()
+ })
+
+ releaseNextTicks()
+
+ setTimeout(el._x_transitioning.finish, duration + delay)
+
+ reachedEnd = true
+ })
+ })
+}
+
+export 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 (isNaN(rawValue)) return fallback
+ }
+
+ if (key === 'duration') {
+ // Support x-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
+}
diff --git a/alpinejs/packages/alpinejs/src/evaluator.js b/alpinejs/packages/alpinejs/src/evaluator.js
new file mode 100644
index 0000000..5f1b0dd
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/evaluator.js
@@ -0,0 +1,132 @@
+import { closestDataStack, mergeProxies } from './scope'
+import { injectMagics } from './magics'
+import { tryCatch, handleError } from './utils/error'
+import { onAttributeRemoved } from './mutation'
+
+export function evaluate(el, expression, extras = {}) {
+ let result
+
+ evaluateLater(el, expression)(value => result = value, extras)
+
+ return result
+}
+
+export function evaluateLater(...args) {
+ return theEvaluatorFunction(...args)
+}
+
+let theEvaluatorFunction = normalEvaluator
+
+export function setEvaluator(newEvaluator) {
+ theEvaluatorFunction = newEvaluator
+}
+
+export function normalEvaluator(el, expression) {
+ let overriddenMagics = {}
+
+ let cleanup = injectMagics(overriddenMagics, el).cleanup
+
+ // MemLeak1: Issue #2140 (note: there are other uses of injectMagics)
+ onAttributeRemoved(el, "evaluator", cleanup)
+
+ let dataStack = [overriddenMagics, ...closestDataStack(el)]
+
+ if (typeof expression === 'function') {
+ return generateEvaluatorFromFunction(dataStack, expression)
+ }
+
+ let evaluator = generateEvaluatorFromString(dataStack, expression, el)
+
+ return tryCatch.bind(null, el, expression, evaluator)
+}
+
+export function generateEvaluatorFromFunction(dataStack, func) {
+ return (receiver = () => {}, { scope = {}, params = [] } = {}) => {
+ let result = func.apply(mergeProxies([scope, ...dataStack]), params)
+
+ runIfTypeOfFunction(receiver, result)
+ }
+}
+
+let evaluatorMemo = {}
+
+function generateFunctionFromString(expression, el) {
+ if (evaluatorMemo[expression]) {
+ return evaluatorMemo[expression]
+ }
+
+ let AsyncFunction = Object.getPrototypeOf(async function(){}).constructor
+
+ // Some expressions that are useful in Alpine are not valid as the right side of an expression.
+ // Here we'll detect if the expression isn't valid for an assignement and wrap it in a self-
+ // calling function so that we don't throw an error AND a "return" statement can b e used.
+ let rightSideSafeExpression = 0
+ // Support expressions starting with "if" statements like: "if (...) doSomething()"
+ || /^[\n\s]*if.*\(.*\)/.test(expression)
+ // Support expressions starting with "let/const" like: "let foo = 'bar'"
+ || /^(let|const)\s/.test(expression)
+ ? `(() => { ${expression} })()`
+ : expression
+
+ const safeAsyncFunction = () => {
+ try {
+ return new AsyncFunction(['__self', 'scope'], `with (scope) { __self.result = ${rightSideSafeExpression} }; __self.finished = true; return __self.result;`)
+ } catch ( error ) {
+ handleError( error, el, expression )
+ return Promise.resolve()
+ }
+ }
+ let func = safeAsyncFunction()
+
+ evaluatorMemo[expression] = func
+
+ return func
+}
+
+function generateEvaluatorFromString(dataStack, expression, el) {
+ let func = generateFunctionFromString(expression, el)
+
+ return (receiver = () => {}, { scope = {}, params = [] } = {}) => {
+ func.result = undefined
+ func.finished = false
+
+ // Run the function.
+
+ let completeScope = mergeProxies([ scope, ...dataStack ])
+
+ if( typeof func === 'function' ) {
+ let promise = func(func, completeScope).catch((error) => handleError(error, el, expression))
+
+ // Check if the function ran synchronously,
+ if (func.finished) {
+ // Return the immediate result.
+ runIfTypeOfFunction(receiver, func.result, completeScope, params, el)
+ // Once the function has run, we clear func.result so we don't create
+ // memory leaks. func is stored in the evaluatorMemo and every time
+ // it runs, it assigns the evaluated expression to result which could
+ // potentially store a reference to the DOM element that will be removed later on.
+ func.result = undefined
+ } else {
+ // If not, return the result when the promise resolves.
+ promise.then(result => {
+ runIfTypeOfFunction(receiver, result, completeScope, params, el)
+ }).catch( error => handleError( error, el, expression ) )
+ .finally( () => func.result = undefined )
+ }
+ }
+ }
+}
+
+export function runIfTypeOfFunction(receiver, value, scope, params, el) {
+ if (typeof value === 'function') {
+ let result = value.apply(scope, params)
+
+ if (result instanceof Promise) {
+ result.then(i => runIfTypeOfFunction(receiver, i, scope, params)).catch( error => handleError( error, el, value ) )
+ } else {
+ receiver(result)
+ }
+ } else {
+ receiver(value)
+ }
+}
diff --git a/alpinejs/packages/alpinejs/src/ids.js b/alpinejs/packages/alpinejs/src/ids.js
new file mode 100644
index 0000000..f2cbd7b
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/ids.js
@@ -0,0 +1,20 @@
+import { findClosest } from './lifecycle'
+
+let globalIdMemo = {}
+
+export function findAndIncrementId(name) {
+ if (! globalIdMemo[name]) globalIdMemo[name] = 0
+
+ return ++globalIdMemo[name]
+}
+
+export function closestIdRoot(el, name) {
+ return findClosest(el, element => {
+ if (element._x_ids && element._x_ids[name]) return true
+ })
+}
+
+export function setIdRoot(el, name) {
+ if (! el._x_ids) el._x_ids = {}
+ if (! el._x_ids[name]) el._x_ids[name] = findAndIncrementId(name)
+}
diff --git a/alpinejs/packages/alpinejs/src/index.js b/alpinejs/packages/alpinejs/src/index.js
new file mode 100644
index 0000000..b0ea550
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/index.js
@@ -0,0 +1,74 @@
+/**
+ * _
+ * /\ | | (_) (_)
+ * / \ | |_ __ _ _ __ ___ _ ___
+ * / /\ \ | | '_ \| | '_ \ / _ \ | / __|
+ * / ____ \| | |_) | | | | | __/_| \__ \
+ * /_/ \_\_| .__/|_|_| |_|\___(_) |___/
+ * | | _/ |
+ * |_| |__/
+ *
+ * Let's build Alpine together. It's easier than you think.
+ * For starters, we'll import Alpine's core. This is the
+ * object that will expose all of Alpine's public API.
+ */
+import Alpine from './alpine'
+
+/**
+ * _______________________________________________________
+ * The Evaluator
+ * -------------------------------------------------------
+ *
+ * Now we're ready to bootstrap Alpine's evaluation system.
+ * It's the function that converts raw JavaScript string
+ * expressions like @click="toggle()", into actual JS.
+ */
+import { normalEvaluator } from './evaluator'
+
+Alpine.setEvaluator(normalEvaluator)
+
+/**
+ * _______________________________________________________
+ * The Reactivity Engine
+ * -------------------------------------------------------
+ *
+ * This is the reactivity core of Alpine. It's the part of
+ * Alpine that triggers an element with x-text="message"
+ * to update its inner text when "message" is changed.
+ */
+import { reactive, effect, stop, toRaw } from '@vue/reactivity'
+
+Alpine.setReactivityEngine({ reactive, effect, release: stop, raw: toRaw })
+
+/**
+ * _______________________________________________________
+ * The Magics
+ * -------------------------------------------------------
+ *
+ * Yeah, we're calling them magics here like they're nouns.
+ * These are the properties that are magically available
+ * to all the Alpine expressions, within your web app.
+ */
+import './magics/index'
+
+/**
+ * _______________________________________________________
+ * The Directives
+ * -------------------------------------------------------
+ *
+ * Now that the core is all set up, we can register Alpine
+ * directives like x-text or x-on that form the basis of
+ * how Alpine adds behavior to an app's static markup.
+ */
+import './directives/index'
+
+/**
+ * _______________________________________________________
+ * The Alpine Global
+ * -------------------------------------------------------
+ *
+ * Now that we have set everything up internally, anything
+ * Alpine-related that will need to be accessed on-going
+ * will be made available through the "Alpine" global.
+ */
+export default Alpine
diff --git a/alpinejs/packages/alpinejs/src/interceptor.js b/alpinejs/packages/alpinejs/src/interceptor.js
new file mode 100644
index 0000000..0f9f557
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/interceptor.js
@@ -0,0 +1,77 @@
+// Warning: The concept of "interceptors" in Alpine is not public API and is subject to change
+// without tagging a major release.
+
+export function initInterceptors(data) {
+ let isObject = val => typeof val === 'object' && !Array.isArray(val) && val !== null
+
+ let recurse = (obj, basePath = '') => {
+ Object.entries(Object.getOwnPropertyDescriptors(obj)).forEach(([key, { value, enumerable }]) => {
+ // Skip getters.
+ if (enumerable === false || value === undefined) return
+
+ let path = basePath === '' ? key : `${basePath}.${key}`
+
+ if (typeof value === 'object' && value !== null && value._x_interceptor) {
+ obj[key] = value.initialize(data, path, key)
+ } else {
+ if (isObject(value) && value !== obj && ! (value instanceof Element)) {
+ recurse(value, path)
+ }
+ }
+ })
+ }
+
+ return recurse(data)
+}
+
+export function interceptor(callback, mutateObj = () => {}) {
+ let obj = {
+ initialValue: undefined,
+
+ _x_interceptor: true,
+
+ initialize(data, path, key) {
+ return callback(this.initialValue, () => get(data, path), (value) => set(data, path, value), path, key)
+ }
+ }
+
+ mutateObj(obj)
+
+ return initialValue => {
+ if (typeof initialValue === 'object' && initialValue !== null && initialValue._x_interceptor) {
+ // Support nesting interceptors.
+ let initialize = obj.initialize.bind(obj)
+
+ obj.initialize = (data, path, key) => {
+ let innerValue = initialValue.initialize(data, path, key)
+
+ obj.initialValue = innerValue
+
+ return initialize(data, path, key)
+ }
+ } else {
+ obj.initialValue = initialValue
+ }
+
+ return obj
+ }
+}
+
+function get(obj, path) {
+ return path.split('.').reduce((carry, segment) => carry[segment], obj)
+}
+
+function set(obj, path, value) {
+ if (typeof path === 'string') path = path.split('.')
+
+ if (path.length === 1) obj[path[0]] = value;
+ else if (path.length === 0) throw error;
+ else {
+ if (obj[path[0]])
+ return set(obj[path[0]], path.slice(1), value);
+ else {
+ obj[path[0]] = {};
+ return set(obj[path[0]], path.slice(1), value);
+ }
+ }
+}
diff --git a/alpinejs/packages/alpinejs/src/lifecycle.js b/alpinejs/packages/alpinejs/src/lifecycle.js
new file mode 100644
index 0000000..75dc6c8
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/lifecycle.js
@@ -0,0 +1,84 @@
+import { startObservingMutations, onAttributesAdded, onElAdded, onElRemoved, cleanupAttributes } from "./mutation"
+import { deferHandlingDirectives, directives } from "./directives"
+import { dispatch } from './utils/dispatch'
+import { nextTick } from "./nextTick"
+import { walk } from "./utils/walk"
+import { warn } from './utils/warn'
+
+export function start() {
+ if (! document.body) warn('Unable to initialize. Trying to load Alpine before `<body>` is available. Did you forget to add `defer` in Alpine\'s `<script>` tag?')
+
+ dispatch(document, 'alpine:init')
+ dispatch(document, 'alpine:initializing')
+
+ startObservingMutations()
+
+ onElAdded(el => initTree(el, walk))
+ onElRemoved(el => destroyTree(el))
+
+ onAttributesAdded((el, attrs) => {
+ directives(el, attrs).forEach(handle => handle())
+ })
+
+ let outNestedComponents = el => ! closestRoot(el.parentElement, true)
+ Array.from(document.querySelectorAll(allSelectors()))
+ .filter(outNestedComponents)
+ .forEach(el => {
+ initTree(el)
+ })
+
+ dispatch(document, 'alpine:initialized')
+}
+
+let rootSelectorCallbacks = []
+let initSelectorCallbacks = []
+
+export function rootSelectors() {
+ return rootSelectorCallbacks.map(fn => fn())
+}
+
+export function allSelectors() {
+ return rootSelectorCallbacks.concat(initSelectorCallbacks).map(fn => fn())
+}
+
+export function addRootSelector(selectorCallback) { rootSelectorCallbacks.push(selectorCallback) }
+export function addInitSelector(selectorCallback) { initSelectorCallbacks.push(selectorCallback) }
+
+export function closestRoot(el, includeInitSelectors = false) {
+ return findClosest(el, element => {
+ const selectors = includeInitSelectors ? allSelectors() : rootSelectors()
+
+ if (selectors.some(selector => element.matches(selector))) return true
+ })
+}
+
+export function findClosest(el, callback) {
+ if (! el) return
+
+ if (callback(el)) return el
+
+ // Support crawling up teleports.
+ if (el._x_teleportBack) el = el._x_teleportBack
+
+ if (! el.parentElement) return
+
+ return findClosest(el.parentElement, callback)
+}
+
+export function isRoot(el) {
+ return rootSelectors().some(selector => el.matches(selector))
+}
+
+export function initTree(el, walker = walk) {
+ deferHandlingDirectives(() => {
+ walker(el, (el, skip) => {
+ directives(el, el.attributes).forEach(handle => handle())
+
+ el._x_ignore && skip()
+ })
+ })
+}
+
+export function destroyTree(root) {
+ walk(root, el => cleanupAttributes(el))
+}
diff --git a/alpinejs/packages/alpinejs/src/magics.js b/alpinejs/packages/alpinejs/src/magics.js
new file mode 100644
index 0000000..5c95bb4
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/magics.js
@@ -0,0 +1,36 @@
+import Alpine from './alpine'
+import { getElementBoundUtilities } from './directives'
+import { interceptor } from './interceptor'
+import { onElRemoved } from './mutation'
+
+let magics = {}
+
+export function magic(name, callback) {
+ magics[name] = callback
+}
+
+export function injectMagics(obj, el) {
+ Object.entries(magics).forEach(([name, callback]) => {
+ Object.defineProperty(obj, `$${name}`, {
+ get() {
+ let [utilities, cleanup] = getElementBoundUtilities(el)
+
+ utilities = {interceptor, ...utilities}
+
+ onElRemoved(el, cleanup)
+
+ return callback(el, utilities)
+ },
+
+ enumerable: false,
+ })
+ })
+
+ return {
+ obj,
+ cleanup: () => {
+ // MemLeak1: Issue #2140
+ el = null;
+ }
+ };
+}
diff --git a/alpinejs/packages/alpinejs/src/magics/$data.js b/alpinejs/packages/alpinejs/src/magics/$data.js
new file mode 100644
index 0000000..b9b0965
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/magics/$data.js
@@ -0,0 +1,4 @@
+import { scope } from '../scope'
+import { magic } from '../magics'
+
+magic('data', el => scope(el))
diff --git a/alpinejs/packages/alpinejs/src/magics/$dispatch.js b/alpinejs/packages/alpinejs/src/magics/$dispatch.js
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/magics/$dispatch.js
@@ -0,0 +1,4 @@
+import { dispatch } from '../utils/dispatch'
+import { magic } from '../magics'
+
+magic('dispatch', el => dispatch.bind(dispatch, el))
diff --git a/alpinejs/packages/alpinejs/src/magics/$el.js b/alpinejs/packages/alpinejs/src/magics/$el.js
new file mode 100644
index 0000000..10b9f49
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/magics/$el.js
@@ -0,0 +1,3 @@
+import { magic } from "../magics";
+
+magic('el', el => el)
diff --git a/alpinejs/packages/alpinejs/src/magics/$id.js b/alpinejs/packages/alpinejs/src/magics/$id.js
new file mode 100644
index 0000000..5a7816f
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/magics/$id.js
@@ -0,0 +1,14 @@
+import { magic } from '../magics'
+import { closestIdRoot, findAndIncrementId } from '../ids'
+
+magic('id', el => (name, key = null) => {
+ let root = closestIdRoot(el, name)
+
+ let id = root
+ ? root._x_ids[name]
+ : findAndIncrementId(name)
+
+ return key
+ ? `${name}-${id}-${key}`
+ : `${name}-${id}`
+})
diff --git a/alpinejs/packages/alpinejs/src/magics/$nextTick.js b/alpinejs/packages/alpinejs/src/magics/$nextTick.js
new file mode 100644
index 0000000..8318cc6
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/magics/$nextTick.js
@@ -0,0 +1,4 @@
+import { nextTick } from '../nextTick'
+import { magic } from '../magics'
+
+magic('nextTick', () => nextTick)
diff --git a/alpinejs/packages/alpinejs/src/magics/$refs.js b/alpinejs/packages/alpinejs/src/magics/$refs.js
new file mode 100644
index 0000000..afd48ed
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/magics/$refs.js
@@ -0,0 +1,25 @@
+import { closestRoot } from '../lifecycle'
+import { mergeProxies } from '../scope'
+import { magic } from '../magics'
+
+magic('refs', el => {
+ if (el._x_refs_proxy) return el._x_refs_proxy
+
+ el._x_refs_proxy = mergeProxies(getArrayOfRefObject(el))
+
+ return el._x_refs_proxy
+})
+
+function getArrayOfRefObject(el) {
+ let refObjects = []
+
+ let currentEl = el
+
+ while (currentEl) {
+ if (currentEl._x_refs) refObjects.push(currentEl._x_refs)
+
+ currentEl = currentEl.parentNode
+ }
+
+ return refObjects
+}
diff --git a/alpinejs/packages/alpinejs/src/magics/$root.js b/alpinejs/packages/alpinejs/src/magics/$root.js
new file mode 100644
index 0000000..140eece
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/magics/$root.js
@@ -0,0 +1,4 @@
+import { closestRoot } from "../lifecycle";
+import { magic } from "../magics";
+
+magic('root', el => closestRoot(el))
diff --git a/alpinejs/packages/alpinejs/src/magics/$store.js b/alpinejs/packages/alpinejs/src/magics/$store.js
new file mode 100644
index 0000000..a14d40d
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/magics/$store.js
@@ -0,0 +1,4 @@
+import { getStores } from '../store'
+import { magic } from '../magics'
+
+magic('store', getStores)
diff --git a/alpinejs/packages/alpinejs/src/magics/$watch.js b/alpinejs/packages/alpinejs/src/magics/$watch.js
new file mode 100644
index 0000000..feb314c
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/magics/$watch.js
@@ -0,0 +1,28 @@
+import { magic } from '../magics'
+
+magic('watch', (el, { evaluateLater, effect }) => (key, callback) => {
+ let evaluate = evaluateLater(key)
+
+ let firstTime = true
+
+ let oldValue
+
+ effect(() => evaluate(value => {
+ // JSON.stringify touches every single property at any level enabling deep watching
+ JSON.stringify(value)
+
+ if (! firstTime) {
+ // We have to queue this watcher as a microtask so that
+ // the watcher doesn't pick up its own dependencies.
+ queueMicrotask(() => {
+ callback(value, oldValue)
+
+ oldValue = value
+ })
+ } else {
+ oldValue = value
+ }
+
+ firstTime = false
+ }))
+})
diff --git a/alpinejs/packages/alpinejs/src/magics/index.js b/alpinejs/packages/alpinejs/src/magics/index.js
new file mode 100644
index 0000000..b3776c6
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/magics/index.js
@@ -0,0 +1,9 @@
+import './$nextTick'
+import './$dispatch'
+import './$watch'
+import './$store'
+import './$data'
+import './$root'
+import './$refs'
+import './$id'
+import './$el'
diff --git a/alpinejs/packages/alpinejs/src/mutation.js b/alpinejs/packages/alpinejs/src/mutation.js
new file mode 100644
index 0000000..15aa750
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/mutation.js
@@ -0,0 +1,217 @@
+let onAttributeAddeds = []
+let onElRemoveds = []
+let onElAddeds = []
+
+export function onElAdded(callback) {
+ onElAddeds.push(callback)
+}
+
+export function onElRemoved(el, callback) {
+ if (typeof callback === 'function') {
+ if (! el._x_cleanups) el._x_cleanups = []
+ el._x_cleanups.push(callback)
+ } else {
+ callback = el
+ onElRemoveds.push(callback)
+ }
+}
+
+export function onAttributesAdded(callback) {
+ onAttributeAddeds.push(callback)
+}
+
+export function onAttributeRemoved(el, name, callback) {
+ if (! el._x_attributeCleanups) el._x_attributeCleanups = {}
+ if (! el._x_attributeCleanups[name]) el._x_attributeCleanups[name] = []
+
+ el._x_attributeCleanups[name].push(callback)
+}
+
+export function cleanupAttributes(el, names) {
+ if (! el._x_attributeCleanups) return
+
+ Object.entries(el._x_attributeCleanups).forEach(([name, value]) => {
+ if (names === undefined || names.includes(name)) {
+ value.forEach(i => i())
+
+ delete el._x_attributeCleanups[name]
+ }
+ })
+}
+
+let observer = new MutationObserver(onMutate)
+
+let currentlyObserving = false
+
+export function startObservingMutations() {
+ observer.observe(document, { subtree: true, childList: true, attributes: true, attributeOldValue: true })
+
+ currentlyObserving = true
+}
+
+export function stopObservingMutations() {
+ flushObserver()
+
+ observer.disconnect()
+
+ currentlyObserving = false
+}
+
+let recordQueue = []
+let willProcessRecordQueue = false
+
+export function flushObserver() {
+ recordQueue = recordQueue.concat(observer.takeRecords())
+
+ if (recordQueue.length && ! willProcessRecordQueue) {
+ willProcessRecordQueue = true
+
+ queueMicrotask(() => {
+ processRecordQueue()
+
+ willProcessRecordQueue = false
+ })
+ }
+}
+
+function processRecordQueue() {
+ onMutate(recordQueue)
+
+ recordQueue.length = 0
+}
+
+export function mutateDom(callback) {
+ if (! currentlyObserving) return callback()
+
+ stopObservingMutations()
+
+ let result = callback()
+
+ startObservingMutations()
+
+ return result
+}
+
+let isCollecting = false
+let deferredMutations = []
+
+export function deferMutations() {
+ isCollecting = true
+}
+
+export function flushAndStopDeferringMutations() {
+ isCollecting = false
+
+ onMutate(deferredMutations)
+
+ deferredMutations = []
+}
+
+function onMutate(mutations) {
+ if (isCollecting) {
+ deferredMutations = deferredMutations.concat(mutations)
+
+ return
+ }
+
+ let addedNodes = []
+ let removedNodes = []
+ let addedAttributes = new Map
+ let removedAttributes = new Map
+
+ for (let i = 0; i < mutations.length; i++) {
+ if (mutations[i].target._x_ignoreMutationObserver) continue
+
+ if (mutations[i].type === 'childList') {
+ mutations[i].addedNodes.forEach(node => node.nodeType === 1 && addedNodes.push(node))
+ mutations[i].removedNodes.forEach(node => node.nodeType === 1 && removedNodes.push(node))
+ }
+
+ if (mutations[i].type === 'attributes') {
+ let el = mutations[i].target
+ let name = mutations[i].attributeName
+ let oldValue = mutations[i].oldValue
+
+ let add = () => {
+ if (! addedAttributes.has(el)) addedAttributes.set(el, [])
+
+ addedAttributes.get(el).push({ name, value: el.getAttribute(name) })
+ }
+
+ let remove = () => {
+ if (! removedAttributes.has(el)) removedAttributes.set(el, [])
+
+ removedAttributes.get(el).push(name)
+ }
+
+ // New attribute.
+ if (el.hasAttribute(name) && oldValue === null) {
+ add()
+ // Changed atttribute.
+ } else if (el.hasAttribute(name)) {
+ remove()
+ add()
+ // Removed atttribute.
+ } else {
+ remove()
+ }
+ }
+ }
+
+ removedAttributes.forEach((attrs, el) => {
+ cleanupAttributes(el, attrs)
+ })
+
+ addedAttributes.forEach((attrs, el) => {
+ onAttributeAddeds.forEach(i => i(el, attrs))
+ })
+
+ for (let node of removedNodes) {
+ // If an element gets moved on a page, it's registered
+ // as both an "add" and "remove", so we want to skip those.
+ if (addedNodes.includes(node)) continue
+
+ onElRemoveds.forEach(i => i(node))
+
+ if (node._x_cleanups) {
+ while (node._x_cleanups.length) node._x_cleanups.pop()()
+ }
+ }
+
+ // Mutations are bundled together by the browser but sometimes
+ // for complex cases, there may be javascript code adding a wrapper
+ // and then an alpine component as a child of that wrapper in the same
+ // function and the mutation observer will receive 2 different mutations.
+ // when it comes time to run them, the dom contains both changes so the child
+ // element would be processed twice as Alpine calls initTree on
+ // both mutations. We mark all nodes as _x_ignored and only remove the flag
+ // when processing the node to avoid those duplicates.
+ addedNodes.forEach((node) => {
+ node._x_ignoreSelf = true
+ node._x_ignore = true
+ })
+ for (let node of addedNodes) {
+ // If an element gets moved on a page, it's registered
+ // as both an "add" and "remove", so we want to skip those.
+ if (removedNodes.includes(node)) continue
+
+ // If the node was eventually removed as part of one of his
+ // parent mutations, skip it
+ if (! node.isConnected) continue
+
+ delete node._x_ignoreSelf
+ delete node._x_ignore
+ onElAddeds.forEach(i => i(node))
+ node._x_ignore = true
+ node._x_ignoreSelf = true
+ }
+ addedNodes.forEach((node) => {
+ delete node._x_ignoreSelf
+ delete node._x_ignore
+ })
+
+ addedNodes = null
+ removedNodes = null
+ addedAttributes = null
+ removedAttributes = null
+}
diff --git a/alpinejs/packages/alpinejs/src/nextTick.js b/alpinejs/packages/alpinejs/src/nextTick.js
new file mode 100644
index 0000000..e5c0d88
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/nextTick.js
@@ -0,0 +1,24 @@
+
+let tickStack = []
+
+let isHolding = false
+
+export function nextTick(callback) {
+ tickStack.push(callback)
+
+ queueMicrotask(() => {
+ isHolding || setTimeout(() => {
+ releaseNextTicks()
+ })
+ })
+}
+
+export function releaseNextTicks() {
+ isHolding = false
+
+ while (tickStack.length) tickStack.shift()()
+}
+
+export function holdNextTicks() {
+ isHolding = true
+}
diff --git a/alpinejs/packages/alpinejs/src/plugin.js b/alpinejs/packages/alpinejs/src/plugin.js
new file mode 100644
index 0000000..98a547b
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/plugin.js
@@ -0,0 +1,5 @@
+import Alpine from './alpine'
+
+export function plugin(callback) {
+ callback(Alpine)
+}
diff --git a/alpinejs/packages/alpinejs/src/reactivity.js b/alpinejs/packages/alpinejs/src/reactivity.js
new file mode 100644
index 0000000..b233d06
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/reactivity.js
@@ -0,0 +1,62 @@
+
+import { scheduler } from './scheduler'
+
+let reactive, effect, release, raw
+
+let shouldSchedule = true
+export function disableEffectScheduling(callback) {
+ shouldSchedule = false
+
+ callback()
+
+ shouldSchedule = true
+}
+
+export function setReactivityEngine(engine) {
+ reactive = engine.reactive
+ release = engine.release
+ effect = (callback) => engine.effect(callback, { scheduler: task => {
+ if (shouldSchedule) {
+ scheduler(task)
+ } else {
+ task()
+ }
+ } })
+ raw = engine.raw
+}
+
+export function overrideEffect(override) { effect = override }
+
+export function elementBoundEffect(el) {
+ let cleanup = () => {}
+
+ let wrappedEffect = (callback) => {
+ let effectReference = effect(callback)
+
+ if (! el._x_effects) {
+ el._x_effects = new Set
+
+ // Livewire depends on el._x_runEffects.
+ el._x_runEffects = () => { el._x_effects.forEach(i => i()) }
+ }
+
+ el._x_effects.add(effectReference)
+
+ cleanup = () => {
+ if (effectReference === undefined) return
+
+ el._x_effects.delete(effectReference)
+
+ release(effectReference)
+ }
+ }
+
+ return [wrappedEffect, () => { cleanup() }]
+}
+
+export {
+ release,
+ reactive,
+ effect,
+ raw,
+}
diff --git a/alpinejs/packages/alpinejs/src/scheduler.js b/alpinejs/packages/alpinejs/src/scheduler.js
new file mode 100644
index 0000000..6c7f10b
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/scheduler.js
@@ -0,0 +1,38 @@
+
+let flushPending = false
+let flushing = false
+let queue = []
+
+export function scheduler (callback) { queueJob(callback) }
+
+function queueJob(job) {
+ if (! queue.includes(job)) queue.push(job)
+
+ queueFlush()
+}
+export function dequeueJob(job) {
+ let index = queue.indexOf(job)
+
+ if (index !== -1) queue.splice(index, 1)
+}
+
+function queueFlush() {
+ if (! flushing && ! flushPending) {
+ flushPending = true
+
+ queueMicrotask(flushJobs)
+ }
+}
+
+export function flushJobs() {
+ flushPending = false
+ flushing = true
+
+ for (let i = 0; i < queue.length; i++) {
+ queue[i]()
+ }
+
+ queue.length = 0
+
+ flushing = false
+}
diff --git a/alpinejs/packages/alpinejs/src/scope.js b/alpinejs/packages/alpinejs/src/scope.js
new file mode 100644
index 0000000..abceae6
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/scope.js
@@ -0,0 +1,105 @@
+
+export function scope(node) {
+ return mergeProxies(closestDataStack(node))
+}
+
+export function addScopeToNode(node, data, referenceNode) {
+ node._x_dataStack = [data, ...closestDataStack(referenceNode || node)]
+
+ return () => {
+ node._x_dataStack = node._x_dataStack.filter(i => i !== data)
+ }
+}
+
+export function hasScope(node) {
+ return !! node._x_dataStack
+}
+
+export function refreshScope(element, scope) {
+ let existingScope = element._x_dataStack[0]
+
+ Object.entries(scope).forEach(([key, value]) => {
+ existingScope[key] = value
+ })
+}
+
+export function closestDataStack(node) {
+ if (node._x_dataStack) return node._x_dataStack
+
+ if (typeof ShadowRoot === 'function' && node instanceof ShadowRoot) {
+ return closestDataStack(node.host)
+ }
+
+ if (! node.parentNode) {
+ return []
+ }
+
+ return closestDataStack(node.parentNode)
+}
+
+export function closestDataProxy(el) {
+ return mergeProxies(closestDataStack(el))
+}
+
+export function mergeProxies(objects) {
+ let thisProxy = new Proxy({}, {
+ ownKeys: () => {
+ return Array.from(new Set(objects.flatMap(i => Object.keys(i))))
+ },
+
+ has: (target, name) => {
+ return objects.some(obj => obj.hasOwnProperty(name))
+ },
+
+ get: (target, name) => {
+ return (objects.find(obj => {
+ if (obj.hasOwnProperty(name)) {
+ let descriptor = Object.getOwnPropertyDescriptor(obj, name)
+
+ // If we already bound this getter, don't rebind.
+ if ((descriptor.get && descriptor.get._x_alreadyBound) || (descriptor.set && descriptor.set._x_alreadyBound)) {
+ return true
+ }
+
+ // Properly bind getters and setters to this wrapper Proxy.
+ if ((descriptor.get || descriptor.set) && descriptor.enumerable) {
+ // Only bind user-defined getters, not our magic properties.
+ let getter = descriptor.get
+ let setter = descriptor.set
+ let property = descriptor
+
+ getter = getter && getter.bind(thisProxy)
+ setter = setter && setter.bind(thisProxy)
+
+ if (getter) getter._x_alreadyBound = true
+ if (setter) setter._x_alreadyBound = true
+
+ Object.defineProperty(obj, name, {
+ ...property,
+ get: getter,
+ set: setter,
+ })
+ }
+
+ return true
+ }
+
+ return false
+ }) || {})[name]
+ },
+
+ set: (target, name, value) => {
+ let closestObjectWithKey = objects.find(obj => obj.hasOwnProperty(name))
+
+ if (closestObjectWithKey) {
+ closestObjectWithKey[name] = value
+ } else {
+ objects[objects.length - 1][name] = value
+ }
+
+ return true
+ },
+ })
+
+ return thisProxy
+}
diff --git a/alpinejs/packages/alpinejs/src/store.js b/alpinejs/packages/alpinejs/src/store.js
new file mode 100644
index 0000000..dc7bf94
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/store.js
@@ -0,0 +1,23 @@
+import { initInterceptors } from "./interceptor";
+import { reactive } from "./reactivity"
+
+let stores = {}
+let isReactive = false
+
+export function store(name, value) {
+ if (! isReactive) { stores = reactive(stores); isReactive = true; }
+
+ if (value === undefined) {
+ return stores[name]
+ }
+
+ stores[name] = value
+
+ if (typeof value === 'object' && value !== null && value.hasOwnProperty('init') && typeof value.init === 'function') {
+ stores[name].init()
+ }
+
+ initInterceptors(stores[name])
+}
+
+export function getStores() { return stores }
diff --git a/alpinejs/packages/alpinejs/src/utils/bind.js b/alpinejs/packages/alpinejs/src/utils/bind.js
new file mode 100644
index 0000000..fc89b20
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/utils/bind.js
@@ -0,0 +1,149 @@
+import { reactive } from '../reactivity'
+import { setClasses } from './classes'
+import { setStyles } from './styles'
+
+export default function bind(el, name, value, modifiers = []) {
+ // Register bound data as pure observable data for other APIs to use.
+ if (! el._x_bindings) el._x_bindings = reactive({})
+
+ el._x_bindings[name] = value
+
+ name = modifiers.includes('camel') ? camelCase(name) : name
+
+ switch (name) {
+ case 'value':
+ bindInputValue(el, value)
+ break;
+
+ case 'style':
+ bindStyles(el, value)
+ break;
+
+ case 'class':
+ bindClasses(el, value)
+ break;
+
+ default:
+ bindAttribute(el, name, value)
+ break;
+ }
+}
+
+function bindInputValue(el, 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) {
+ el.value = value
+ }
+
+ // @todo: yuck
+ if (window.fromModel) {
+ 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/array/number/null/undefined, leave it alone, it will be set to "on"
+ // automatically.
+ if (Number.isInteger(value)) {
+ el.value = value
+ } else if (! Number.isInteger(value) && ! Array.isArray(value) && typeof value !== 'boolean' && ! [null, undefined].includes(value)) {
+ el.value = String(value)
+ } else {
+ if (Array.isArray(value)) {
+ 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
+ }
+}
+
+function bindClasses(el, value) {
+ if (el._x_undoAddedClasses) el._x_undoAddedClasses()
+
+ el._x_undoAddedClasses = setClasses(el, value)
+}
+
+function bindStyles(el, value) {
+ if (el._x_undoAddedStyles) el._x_undoAddedStyles()
+
+ el._x_undoAddedStyles = setStyles(el, value)
+}
+
+function bindAttribute(el, name, value) {
+ if ([null, undefined, false].includes(value) && attributeShouldntBePreservedIfFalsy(name)) {
+ el.removeAttribute(name)
+ } else {
+ if (isBooleanAttr(name)) value = name
+
+ setIfChanged(el, name, 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)
+ })
+}
+
+function camelCase(subject) {
+ return subject.toLowerCase().replace(/-(\w)/g, (match, char) => char.toUpperCase())
+}
+
+function checkedAttrLooseCompare(valueA, valueB) {
+ return valueA == valueB
+}
+
+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 attributeShouldntBePreservedIfFalsy(name) {
+ return ! ['aria-pressed', 'aria-checked', 'aria-expanded', 'aria-selected'].includes(name)
+}
+
+export function getBinding(el, name, fallback) {
+ // First let's get it out of Alpine bound data.
+ if (el._x_bindings && el._x_bindings[name] !== undefined) return el._x_bindings[name]
+
+ // If not, we'll return the literal attribute.
+ let attr = el.getAttribute(name)
+
+ // Nothing bound:
+ if (attr === null) return typeof fallback === 'function' ? fallback() : fallback
+
+ if (isBooleanAttr(name)) {
+ return !! [name, 'true'].includes(attr)
+ }
+
+ // The case of a custom attribute with no value. Ex: <div manual>
+ if (attr === '') return true
+
+ return attr
+}
diff --git a/alpinejs/packages/alpinejs/src/utils/classes.js b/alpinejs/packages/alpinejs/src/utils/classes.js
new file mode 100644
index 0000000..0fd02aa
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/utils/classes.js
@@ -0,0 +1,58 @@
+
+export function setClasses(el, value) {
+ if (Array.isArray(value)) {
+ return setClassesFromString(el, value.join(' '))
+ } else if (typeof value === 'object' && value !== null) {
+ return setClassesFromObject(el, value)
+ } else if (typeof value === 'function') {
+ return setClasses(el, value())
+ }
+
+ return setClassesFromString(el, value)
+}
+
+function setClassesFromString(el, classString) {
+ let split = classString => classString.split(' ').filter(Boolean)
+
+ let missingClasses = classString => classString.split(' ').filter(i => ! el.classList.contains(i)).filter(Boolean)
+
+ let addClassesAndReturnUndo = classes => {
+ el.classList.add(...classes)
+
+ return () => { el.classList.remove(...classes) }
+ }
+
+ // This is to allow short-circuit expressions like: :class="show || 'hidden'" && "show && 'block'"
+ classString = (classString === true) ? classString = '' : (classString || '')
+
+ return addClassesAndReturnUndo(missingClasses(classString))
+}
+
+function setClassesFromObject(el, classObject) {
+ let split = classString => classString.split(' ').filter(Boolean)
+
+ let forAdd = Object.entries(classObject).flatMap(([classString, bool]) => bool ? split(classString) : false).filter(Boolean)
+ let forRemove = Object.entries(classObject).flatMap(([classString, bool]) => ! bool ? split(classString) : false).filter(Boolean)
+
+ let added = []
+ let removed = []
+
+ forRemove.forEach(i => {
+ if (el.classList.contains(i)) {
+ el.classList.remove(i)
+ removed.push(i)
+ }
+ })
+
+ forAdd.forEach(i => {
+ if (! el.classList.contains(i)) {
+ el.classList.add(i)
+ added.push(i)
+ }
+ })
+
+ return () => {
+ removed.forEach(i => el.classList.add(i))
+ added.forEach(i => el.classList.remove(i))
+ }
+}
diff --git a/alpinejs/packages/alpinejs/src/utils/debounce.js b/alpinejs/packages/alpinejs/src/utils/debounce.js
new file mode 100644
index 0000000..850a3b1
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/utils/debounce.js
@@ -0,0 +1,18 @@
+
+export function debounce(func, wait) {
+ var timeout
+
+ return function() {
+ var context = this, args = arguments
+
+ var later = function () {
+ timeout = null
+
+ func.apply(context, args)
+ }
+
+ clearTimeout(timeout)
+
+ timeout = setTimeout(later, wait)
+ }
+}
diff --git a/alpinejs/packages/alpinejs/src/utils/dispatch.js b/alpinejs/packages/alpinejs/src/utils/dispatch.js
new file mode 100644
index 0000000..26f198a
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/utils/dispatch.js
@@ -0,0 +1,12 @@
+
+export function dispatch(el, name, detail = {}) {
+ el.dispatchEvent(
+ new CustomEvent(name, {
+ detail,
+ bubbles: true,
+ // Allows events to pass the shadow DOM barrier.
+ composed: true,
+ cancelable: true,
+ })
+ )
+}
diff --git a/alpinejs/packages/alpinejs/src/utils/error.js b/alpinejs/packages/alpinejs/src/utils/error.js
new file mode 100644
index 0000000..62a2028
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/utils/error.js
@@ -0,0 +1,15 @@
+export function tryCatch(el, expression, callback, ...args) {
+ try {
+ return callback(...args)
+ } catch (e) {
+ handleError( e, el, expression )
+ }
+}
+
+export function handleError(error, el, expression = undefined) {
+ Object.assign( error, { el, expression } )
+
+ console.warn(`Alpine Expression Error: ${error.message}\n\n${ expression ? 'Expression: \"' + expression + '\"\n\n' : '' }`, el)
+
+ setTimeout( () => { throw error }, 0 )
+}
diff --git a/alpinejs/packages/alpinejs/src/utils/on.js b/alpinejs/packages/alpinejs/src/utils/on.js
new file mode 100644
index 0000000..b000cfd
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/utils/on.js
@@ -0,0 +1,167 @@
+import { debounce } from './debounce'
+import { throttle } from './throttle'
+
+export default function on (el, event, modifiers, callback) {
+ let listenerTarget = el
+
+ let handler = e => callback(e)
+
+ let options = {}
+
+ // This little helper allows us to add functionality to the listener's
+ // handler more flexibly in a "middleware" style.
+ let wrapHandler = (callback, wrapper) => (e) => wrapper(callback, e)
+
+ if (modifiers.includes("dot")) event = dotSyntax(event)
+ if (modifiers.includes('camel')) event = camelCase(event)
+ if (modifiers.includes('passive')) options.passive = true
+ if (modifiers.includes('capture')) options.capture = true
+ if (modifiers.includes('window')) listenerTarget = window
+ if (modifiers.includes('document')) listenerTarget = document
+ if (modifiers.includes('prevent')) handler = wrapHandler(handler, (next, e) => { e.preventDefault(); next(e) })
+ if (modifiers.includes('stop')) handler = wrapHandler(handler, (next, e) => { e.stopPropagation(); next(e) })
+ if (modifiers.includes('self')) handler = wrapHandler(handler, (next, e) => { e.target === el && next(e) })
+
+ if (modifiers.includes('away') || modifiers.includes('outside')) {
+ listenerTarget = document
+
+ handler = wrapHandler(handler, (next, e) => {
+ if (el.contains(e.target)) return
+
+ if (el.offsetWidth < 1 && el.offsetHeight < 1) return
+
+ // Additional check for special implementations like x-collapse
+ // where the element doesn't have display: none
+ if (el._x_isShown === false) return
+
+ next(e)
+ })
+ }
+
+ // Handle :keydown and :keyup listeners.
+ handler = wrapHandler(handler, (next, e) => {
+ if (isKeyEvent(event)) {
+ if (isListeningForASpecificKeyThatHasntBeenPressed(e, modifiers)) {
+ return
+ }
+ }
+
+ next(e)
+ })
+
+ 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)
+ }
+
+ if (modifiers.includes('throttle')) {
+ let nextModifier = modifiers[modifiers.indexOf('throttle')+1] || 'invalid-wait'
+ let wait = isNumeric(nextModifier.split('ms')[0]) ? Number(nextModifier.split('ms')[0]) : 250
+
+ handler = throttle(handler, wait)
+ }
+
+ if (modifiers.includes('once')) {
+ handler = wrapHandler(handler, (next, e) => {
+ next(e)
+
+ listenerTarget.removeEventListener(event, handler, options)
+ })
+ }
+
+ listenerTarget.addEventListener(event, handler, options)
+
+ return () => {
+ listenerTarget.removeEventListener(event, handler, options)
+ }
+}
+
+function dotSyntax(subject) {
+ return subject.replace(/-/g, ".")
+}
+
+function camelCase(subject) {
+ return subject.toLowerCase().replace(/-(\w)/g, (match, char) => char.toUpperCase())
+}
+
+function isNumeric(subject){
+ return ! Array.isArray(subject) && ! isNaN(subject)
+}
+
+function kebabCase(subject) {
+ return subject.replace(/([a-z])([A-Z])/g, '$1-$2').replace(/[_\s]/, '-').toLowerCase()
+}
+
+function isKeyEvent(event) {
+ return ['keydown', 'keyup'].includes(event)
+}
+
+function isListeningForASpecificKeyThatHasntBeenPressed(e, modifiers) {
+ let keyModifiers = modifiers.filter(i => {
+ return ! ['window', 'document', 'prevent', 'stop', 'once'].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 && keyToModifiers(e.key).includes(keyModifiers[0])) 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 (keyToModifiers(e.key).includes(keyModifiers[0])) return false
+ }
+ }
+
+ // We'll call it NOT a valid keypress.
+ return true
+}
+
+function keyToModifiers(key) {
+ if (! key) return []
+
+ key = kebabCase(key)
+
+ let modifierToKeyMap = {
+ 'ctrl': 'control',
+ 'slash': '/',
+ 'space': '-',
+ 'spacebar': '-',
+ 'cmd': 'meta',
+ 'esc': 'escape',
+ 'up': 'arrow-up',
+ 'down': 'arrow-down',
+ 'left': 'arrow-left',
+ 'right': 'arrow-right',
+ 'period': '.',
+ 'equal': '=',
+ }
+
+ modifierToKeyMap[key] = key
+
+ return Object.keys(modifierToKeyMap).map(modifier => {
+ if (modifierToKeyMap[modifier] === key) return modifier
+ }).filter(modifier => modifier)
+}
diff --git a/alpinejs/packages/alpinejs/src/utils/once.js b/alpinejs/packages/alpinejs/src/utils/once.js
new file mode 100644
index 0000000..643ee6f
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/utils/once.js
@@ -0,0 +1,14 @@
+
+export function once(callback, fallback = () => {}) {
+ let called = false
+
+ return function () {
+ if (! called) {
+ called = true
+
+ callback.apply(this, arguments)
+ } else {
+ fallback.apply(this, arguments)
+ }
+ }
+}
diff --git a/alpinejs/packages/alpinejs/src/utils/styles.js b/alpinejs/packages/alpinejs/src/utils/styles.js
new file mode 100644
index 0000000..6d521b0
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/utils/styles.js
@@ -0,0 +1,50 @@
+
+export function setStyles(el, value) {
+ if (typeof value === 'object' && value !== null) {
+ return setStylesFromObject(el, value)
+ }
+
+ return setStylesFromString(el, value)
+}
+
+function setStylesFromObject(el, value) {
+ let previousStyles = {}
+
+ Object.entries(value).forEach(([key, value]) => {
+ previousStyles[key] = el.style[key]
+
+ // When we use javascript object, css properties use the camelCase
+ // syntax but when we use setProperty, we need the css format
+ // so we need to convert camelCase to kebab-case.
+ // In case key is a CSS variable, leave it as it is.
+ if (! key.startsWith('--')) {
+ key = kebabCase(key);
+ }
+
+ el.style.setProperty(key, value)
+ })
+
+ setTimeout(() => {
+ if (el.style.length === 0) {
+ el.removeAttribute('style')
+ }
+ })
+
+ return () => {
+ setStyles(el, previousStyles)
+ }
+}
+
+function setStylesFromString(el, value) {
+ let cache = el.getAttribute('style', value)
+
+ el.setAttribute('style', value)
+
+ return () => {
+ el.setAttribute('style', cache || '')
+ }
+}
+
+function kebabCase(subject) {
+ return subject.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase()
+}
diff --git a/alpinejs/packages/alpinejs/src/utils/throttle.js b/alpinejs/packages/alpinejs/src/utils/throttle.js
new file mode 100644
index 0000000..c49108b
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/utils/throttle.js
@@ -0,0 +1,16 @@
+
+export function throttle(func, limit) {
+ let inThrottle
+
+ return function() {
+ let context = this, args = arguments
+
+ if (! inThrottle) {
+ func.apply(context, args)
+
+ inThrottle = true
+
+ setTimeout(() => inThrottle = false, limit)
+ }
+ }
+}
diff --git a/alpinejs/packages/alpinejs/src/utils/walk.js b/alpinejs/packages/alpinejs/src/utils/walk.js
new file mode 100644
index 0000000..909df1a
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/utils/walk.js
@@ -0,0 +1,38 @@
+export function walk(el, callback) {
+ if (typeof ShadowRoot === 'function' && el instanceof ShadowRoot) {
+ Array.from(el.children).forEach(el => walk(el, callback))
+
+ return
+ }
+
+ let skip = false
+
+ callback(el, () => skip = true)
+
+ if (skip) return
+
+ let node = el.firstElementChild
+
+ while (node) {
+ walk(node, callback, false)
+
+ node = node.nextElementSibling
+ }
+}
+// export function walk(el, callback) {
+// if (el instanceof ShadowRoot || el instanceof DocumentFragment) {
+// Array.from(el.children).forEach(el => walk(el, callback))
+
+// return
+// }
+
+// callback(el, () => {
+// let node = el.firstElementChild
+
+// while (node) {
+// walk(node, callback)
+
+// node = node.nextElementSibling
+// }
+// })
+// }
diff --git a/alpinejs/packages/alpinejs/src/utils/warn.js b/alpinejs/packages/alpinejs/src/utils/warn.js
new file mode 100644
index 0000000..b01f80b
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/utils/warn.js
@@ -0,0 +1,4 @@
+
+export function warn(message, ...args) {
+ console.warn(`Alpine Warning: ${message}`, ...args)
+}
diff --git a/alpinejs/packages/collapse/builds/cdn.js b/alpinejs/packages/collapse/builds/cdn.js
new file mode 100644
index 0000000..a7b9ee5
--- /dev/null
+++ b/alpinejs/packages/collapse/builds/cdn.js
@@ -0,0 +1,5 @@
+import collapse from '../src/index.js'
+
+document.addEventListener('alpine:init', () => {
+ window.Alpine.plugin(collapse)
+})
diff --git a/alpinejs/packages/collapse/builds/module.js b/alpinejs/packages/collapse/builds/module.js
new file mode 100644
index 0000000..594d9fa
--- /dev/null
+++ b/alpinejs/packages/collapse/builds/module.js
@@ -0,0 +1,3 @@
+import collapse from '../src/index.js'
+
+export default collapse
diff --git a/alpinejs/packages/collapse/dist/cdn.js b/alpinejs/packages/collapse/dist/cdn.js
index ea1969c..4842723 100644
--- a/alpinejs/packages/collapse/dist/cdn.js
+++ b/alpinejs/packages/collapse/dist/cdn.js
@@ -7,7 +7,7 @@
if (!el._x_isShown)
el.style.height = `${floor}px`;
if (!el._x_isShown)
- el.style.removeProperty("display");
+ el.hidden = true;
if (!el._x_isShown)
el.style.overflow = "hidden";
let setFunction = (el2, styles) => {
@@ -16,7 +16,6 @@
} : revertFunction;
};
let transitionStyles = {
- overflow: "hidden",
transitionProperty: "height",
transitionDuration: `${duration}s`,
transitionTimingFunction: "cubic-bezier(0.4, 0.0, 0.2, 1)"
@@ -25,14 +24,11 @@
in(before = () => {
}, after = () => {
}) {
+ el.hidden = false;
+ el.style.display = null;
let current = el.getBoundingClientRect().height;
- Alpine.setStyles(el, {
- height: "auto"
- });
+ el.style.height = "auto";
let full = el.getBoundingClientRect().height;
- Alpine.setStyles(el, {
- overflow: null
- });
if (current === full) {
current = floor;
}
@@ -41,6 +37,9 @@
start: {height: current + "px"},
end: {height: full + "px"}
}, () => el._x_isShown = true, () => {
+ if (el.style.height == `${full}px`) {
+ el.style.overflow = null;
+ }
});
},
out(before = () => {
@@ -51,13 +50,11 @@
during: transitionStyles,
start: {height: full + "px"},
end: {height: floor + "px"}
- }, () => {
- }, () => {
+ }, () => el.style.overflow = "hidden", () => {
el._x_isShown = false;
if (el.style.height == `${floor}px`) {
- Alpine.nextTick(() => Alpine.setStyles(el, {
- overflow: "hidden"
- }));
+ el.style.display = "none";
+ el.hidden = true;
}
});
}
diff --git a/alpinejs/packages/collapse/dist/cdn.min.js b/alpinejs/packages/collapse/dist/cdn.min.js
index bd12438..5919142 100644
--- a/alpinejs/packages/collapse/dist/cdn.min.js
+++ b/alpinejs/packages/collapse/dist/cdn.min.js
@@ -1 +1 @@
-(()=>{function d(e){e.directive("collapse",(t,{expression:s,modifiers:n},{effect:h,evaluateLater:x})=>{let g=l(n,"duration",250)/1e3,r=0;t._x_isShown||(t.style.height=`${r}px`),t._x_isShown||t.style.removeProperty("display"),t._x_isShown||(t.style.overflow="hidden");let c=(u,o)=>{let i=e.setStyles(u,o);return o.height?()=>{}:i},a={overflow:"hidden",transitionProperty:"height",transitionDuration:`${g}s`,transitionTimingFunction:"cubic-bezier(0.4, 0.0, 0.2, 1)"};t._x_transition={in(u=()=>{},o=()=>{}){let i=t.getBoundingClientRect().height;e.setStyles(t,{height:"auto"});let f=t.getBoundingClientRect().height;e.setStyles(t,{overflow:null}),i===f&&(i=r),e.transition(t,e.setStyles,{during:a,start:{height:i+"px"},end:{height:f+"px"}},()=>t._x_isShown=!0,()=>{})},out(u=()=>{},o=()=>{}){let i=t.getBoundingClientRect().height;e.transition(t,c,{during:a,start:{height:i+"px"},end:{height:r+"px"}},()=>{},()=>{t._x_isShown=!1,t.style.height==`${r}px`&&e.nextTick(()=>e.setStyles(t,{overflow:"hidden"}))})}}})}function l(e,t,s){if(e.indexOf(t)===-1)return s;let n=e[e.indexOf(t)+1];if(!n)return s;if(t==="duration"){let h=n.match(/([0-9]+)ms/);if(h)return h[1]}return n}document.addEventListener("alpine:init",()=>{window.Alpine.plugin(d)});})();
+(()=>{function f(i){i.directive("collapse",(t,{expression:s,modifiers:n},{effect:h,evaluateLater:x})=>{let g=c(n,"duration",250)/1e3,r=0;t._x_isShown||(t.style.height=`${r}px`),t._x_isShown||(t.hidden=!0),t._x_isShown||(t.style.overflow="hidden");let l=(u,o)=>{let e=i.setStyles(u,o);return o.height?()=>{}:e},d={transitionProperty:"height",transitionDuration:`${g}s`,transitionTimingFunction:"cubic-bezier(0.4, 0.0, 0.2, 1)"};t._x_transition={in(u=()=>{},o=()=>{}){t.hidden=!1,t.style.display=null;let e=t.getBoundingClientRect().height;t.style.height="auto";let a=t.getBoundingClientRect().height;e===a&&(e=r),i.transition(t,i.setStyles,{during:d,start:{height:e+"px"},end:{height:a+"px"}},()=>t._x_isShown=!0,()=>{t.style.height==`${a}px`&&(t.style.overflow=null)})},out(u=()=>{},o=()=>{}){let e=t.getBoundingClientRect().height;i.transition(t,l,{during:d,start:{height:e+"px"},end:{height:r+"px"}},()=>t.style.overflow="hidden",()=>{t._x_isShown=!1,t.style.height==`${r}px`&&(t.style.display="none",t.hidden=!0)})}}})}function c(i,t,s){if(i.indexOf(t)===-1)return s;let n=i[i.indexOf(t)+1];if(!n)return s;if(t==="duration"){let h=n.match(/([0-9]+)ms/);if(h)return h[1]}return n}document.addEventListener("alpine:init",()=>{window.Alpine.plugin(f)});})();
diff --git a/alpinejs/packages/collapse/dist/module.cjs.js b/alpinejs/packages/collapse/dist/module.cjs.js
index 419c1c5..63e04a0 100644
--- a/alpinejs/packages/collapse/dist/module.cjs.js
+++ b/alpinejs/packages/collapse/dist/module.cjs.js
@@ -19,7 +19,7 @@ function src_default(Alpine) {
if (!el._x_isShown)
el.style.height = `${floor}px`;
if (!el._x_isShown)
- el.style.removeProperty("display");
+ el.hidden = true;
if (!el._x_isShown)
el.style.overflow = "hidden";
let setFunction = (el2, styles) => {
@@ -28,7 +28,6 @@ function src_default(Alpine) {
} : revertFunction;
};
let transitionStyles = {
- overflow: "hidden",
transitionProperty: "height",
transitionDuration: `${duration}s`,
transitionTimingFunction: "cubic-bezier(0.4, 0.0, 0.2, 1)"
@@ -37,14 +36,11 @@ function src_default(Alpine) {
in(before = () => {
}, after = () => {
}) {
+ el.hidden = false;
+ el.style.display = null;
let current = el.getBoundingClientRect().height;
- Alpine.setStyles(el, {
- height: "auto"
- });
+ el.style.height = "auto";
let full = el.getBoundingClientRect().height;
- Alpine.setStyles(el, {
- overflow: null
- });
if (current === full) {
current = floor;
}
@@ -53,6 +49,9 @@ function src_default(Alpine) {
start: {height: current + "px"},
end: {height: full + "px"}
}, () => el._x_isShown = true, () => {
+ if (el.style.height == `${full}px`) {
+ el.style.overflow = null;
+ }
});
},
out(before = () => {
@@ -63,13 +62,11 @@ function src_default(Alpine) {
during: transitionStyles,
start: {height: full + "px"},
end: {height: floor + "px"}
- }, () => {
- }, () => {
+ }, () => el.style.overflow = "hidden", () => {
el._x_isShown = false;
if (el.style.height == `${floor}px`) {
- Alpine.nextTick(() => Alpine.setStyles(el, {
- overflow: "hidden"
- }));
+ el.style.display = "none";
+ el.hidden = true;
}
});
}
diff --git a/alpinejs/packages/collapse/dist/module.esm.js b/alpinejs/packages/collapse/dist/module.esm.js
index c108a61..82fc363 100644
--- a/alpinejs/packages/collapse/dist/module.esm.js
+++ b/alpinejs/packages/collapse/dist/module.esm.js
@@ -6,7 +6,7 @@ function src_default(Alpine) {
if (!el._x_isShown)
el.style.height = `${floor}px`;
if (!el._x_isShown)
- el.style.removeProperty("display");
+ el.hidden = true;
if (!el._x_isShown)
el.style.overflow = "hidden";
let setFunction = (el2, styles) => {
@@ -15,7 +15,6 @@ function src_default(Alpine) {
} : revertFunction;
};
let transitionStyles = {
- overflow: "hidden",
transitionProperty: "height",
transitionDuration: `${duration}s`,
transitionTimingFunction: "cubic-bezier(0.4, 0.0, 0.2, 1)"
@@ -24,14 +23,11 @@ function src_default(Alpine) {
in(before = () => {
}, after = () => {
}) {
+ el.hidden = false;
+ el.style.display = null;
let current = el.getBoundingClientRect().height;
- Alpine.setStyles(el, {
- height: "auto"
- });
+ el.style.height = "auto";
let full = el.getBoundingClientRect().height;
- Alpine.setStyles(el, {
- overflow: null
- });
if (current === full) {
current = floor;
}
@@ -40,6 +36,9 @@ function src_default(Alpine) {
start: {height: current + "px"},
end: {height: full + "px"}
}, () => el._x_isShown = true, () => {
+ if (el.style.height == `${full}px`) {
+ el.style.overflow = null;
+ }
});
},
out(before = () => {
@@ -50,13 +49,11 @@ function src_default(Alpine) {
during: transitionStyles,
start: {height: full + "px"},
end: {height: floor + "px"}
- }, () => {
- }, () => {
+ }, () => el.style.overflow = "hidden", () => {
el._x_isShown = false;
if (el.style.height == `${floor}px`) {
- Alpine.nextTick(() => Alpine.setStyles(el, {
- overflow: "hidden"
- }));
+ el.style.display = "none";
+ el.hidden = true;
}
});
}
diff --git a/alpinejs/packages/collapse/package.json b/alpinejs/packages/collapse/package.json
new file mode 100644
index 0000000..a14f149
--- /dev/null
+++ b/alpinejs/packages/collapse/package.json
@@ -0,0 +1,11 @@
+{
+ "name": "@alpinejs/collapse",
+ "version": "3.9.1",
+ "description": "Collapse and expand elements with robust animations",
+ "author": "Caleb Porzio",
+ "license": "MIT",
+ "main": "dist/module.cjs.js",
+ "module": "dist/module.esm.js",
+ "unpkg": "dist/cdn.min.js",
+ "dependencies": {}
+}
diff --git a/alpinejs/packages/collapse/src/index.js b/alpinejs/packages/collapse/src/index.js
new file mode 100644
index 0000000..aa2ea94
--- /dev/null
+++ b/alpinejs/packages/collapse/src/index.js
@@ -0,0 +1,90 @@
+export default function (Alpine) {
+ Alpine.directive('collapse', (el, { expression, modifiers }, { effect, evaluateLater }) => {
+ let duration = modifierValue(modifiers, 'duration', 250) / 1000
+ let floor = 0
+
+ if (! el._x_isShown) el.style.height = `${floor}px`
+ // We use the hidden attribute for the benefit of Tailwind
+ // users as the .space utility will ignore [hidden] elements.
+ // We also use display:none as the hidden attribute has very
+ // low CSS specificity and could be accidentally overriden
+ // by a user.
+ if (! el._x_isShown) el.hidden = true
+ if (! el._x_isShown) el.style.overflow = 'hidden'
+
+ // Override the setStyles function with one that won't
+ // revert updates to the height style.
+ let setFunction = (el, styles) => {
+ let revertFunction = Alpine.setStyles(el, styles);
+
+ return styles.height ? () => {} : revertFunction
+ }
+
+ let transitionStyles = {
+ transitionProperty: 'height',
+ transitionDuration: `${duration}s`,
+ transitionTimingFunction: 'cubic-bezier(0.4, 0.0, 0.2, 1)',
+ }
+
+ el._x_transition = {
+ in(before = () => {}, after = () => {}) {
+ el.hidden = false;
+ el.style.display = null
+
+ let current = el.getBoundingClientRect().height
+
+ el.style.height = 'auto'
+
+ let full = el.getBoundingClientRect().height
+
+ if (current === full) { current = floor }
+
+ Alpine.transition(el, Alpine.setStyles, {
+ during: transitionStyles,
+ start: { height: current+'px' },
+ end: { height: full+'px' },
+ }, () => el._x_isShown = true, () => {
+ if (el.style.height == `${full}px`) {
+ el.style.overflow = null
+ }
+ })
+ },
+
+ out(before = () => {}, after = () => {}) {
+ let full = el.getBoundingClientRect().height
+
+ Alpine.transition(el, setFunction, {
+ during: transitionStyles,
+ start: { height: full+'px' },
+ end: { height: floor+'px' },
+ }, () => el.style.overflow = 'hidden', () => {
+ el._x_isShown = false
+
+ // check if element is fully collapsed
+ if (el.style.height == `${floor}px`) {
+ el.style.display = 'none'
+ el.hidden = true
+ }
+ })
+ },
+ }
+ })
+}
+
+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 === 'duration') {
+ // Support x-collapse.duration.500ms && duration.500
+ let match = rawValue.match(/([0-9]+)ms/)
+ if (match) return match[1]
+ }
+
+ return rawValue
+}
diff --git a/alpinejs/packages/csp/builds/cdn.js b/alpinejs/packages/csp/builds/cdn.js
new file mode 100644
index 0000000..a54e7e0
--- /dev/null
+++ b/alpinejs/packages/csp/builds/cdn.js
@@ -0,0 +1,7 @@
+import Alpine from './../src/index'
+
+window.Alpine = Alpine
+
+queueMicrotask(() => {
+ Alpine.start()
+})
diff --git a/alpinejs/packages/csp/builds/module.js b/alpinejs/packages/csp/builds/module.js
new file mode 100644
index 0000000..0382080
--- /dev/null
+++ b/alpinejs/packages/csp/builds/module.js
@@ -0,0 +1,3 @@
+import Alpine from './../src/index'
+
+export default Alpine
diff --git a/alpinejs/packages/csp/dist/cdn.js b/alpinejs/packages/csp/dist/cdn.js
index 8dd1204..1b07e7b 100644
--- a/alpinejs/packages/csp/dist/cdn.js
+++ b/alpinejs/packages/csp/dist/cdn.js
@@ -11,6 +11,11 @@
queue.push(job);
queueFlush();
}
+ function dequeueJob(job) {
+ let index = queue.indexOf(job);
+ if (index !== -1)
+ queue.splice(index, 1);
+ }
function queueFlush() {
if (!flushing && !flushPending) {
flushPending = true;
@@ -84,8 +89,15 @@
function onElAdded(callback) {
onElAddeds.push(callback);
}
- function onElRemoved(callback) {
- onElRemoveds.push(callback);
+ function onElRemoved(el, callback) {
+ if (typeof callback === "function") {
+ if (!el._x_cleanups)
+ el._x_cleanups = [];
+ el._x_cleanups.push(callback);
+ } else {
+ callback = el;
+ onElRemoveds.push(callback);
+ }
}
function onAttributesAdded(callback) {
onAttributeAddeds.push(callback);
@@ -198,16 +210,34 @@
addedAttributes.forEach((attrs, el) => {
onAttributeAddeds.forEach((i) => i(el, attrs));
});
- for (let node of addedNodes) {
- if (removedNodes.includes(node))
- continue;
- onElAddeds.forEach((i) => i(node));
- }
for (let node of removedNodes) {
if (addedNodes.includes(node))
continue;
onElRemoveds.forEach((i) => i(node));
+ if (node._x_cleanups) {
+ while (node._x_cleanups.length)
+ node._x_cleanups.pop()();
+ }
+ }
+ addedNodes.forEach((node) => {
+ node._x_ignoreSelf = true;
+ node._x_ignore = true;
+ });
+ for (let node of addedNodes) {
+ if (removedNodes.includes(node))
+ continue;
+ if (!node.isConnected)
+ continue;
+ delete node._x_ignoreSelf;
+ delete node._x_ignore;
+ onElAddeds.forEach((i) => i(node));
+ node._x_ignore = true;
+ node._x_ignoreSelf = true;
}
+ addedNodes.forEach((node) => {
+ delete node._x_ignoreSelf;
+ delete node._x_ignore;
+ });
addedNodes = null;
removedNodes = null;
addedAttributes = null;
@@ -215,15 +245,18 @@
}
// packages/alpinejs/src/scope.js
+ function scope(node) {
+ return mergeProxies(closestDataStack(node));
+ }
function addScopeToNode(node, data2, referenceNode) {
node._x_dataStack = [data2, ...closestDataStack(referenceNode || node)];
return () => {
node._x_dataStack = node._x_dataStack.filter((i) => i !== data2);
};
}
- function refreshScope(element, scope) {
+ function refreshScope(element, scope2) {
let existingScope = element._x_dataStack[0];
- Object.entries(scope).forEach(([key, value]) => {
+ Object.entries(scope2).forEach(([key, value]) => {
existingScope[key] = value;
});
}
@@ -359,7 +392,10 @@
Object.entries(magics).forEach(([name, callback]) => {
Object.defineProperty(obj, `$${name}`, {
get() {
- return callback(el, {Alpine: alpine_default, interceptor});
+ let [utilities, cleanup2] = getElementBoundUtilities(el);
+ utilities = {interceptor, ...utilities};
+ onElRemoved(el, cleanup2);
+ return callback(el, utilities);
},
enumerable: false
});
@@ -416,8 +452,8 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
}
function generateEvaluatorFromFunction(dataStack, func) {
return (receiver = () => {
- }, {scope = {}, params = []} = {}) => {
- let result = func.apply(mergeProxies([scope, ...dataStack]), params);
+ }, {scope: scope2 = {}, params = []} = {}) => {
+ let result = func.apply(mergeProxies([scope2, ...dataStack]), params);
runIfTypeOfFunction(receiver, result);
};
}
@@ -444,27 +480,28 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
function generateEvaluatorFromString(dataStack, expression, el) {
let func = generateFunctionFromString(expression, el);
return (receiver = () => {
- }, {scope = {}, params = []} = {}) => {
+ }, {scope: scope2 = {}, params = []} = {}) => {
func.result = void 0;
func.finished = false;
- let completeScope = mergeProxies([scope, ...dataStack]);
+ let completeScope = mergeProxies([scope2, ...dataStack]);
if (typeof func === "function") {
let promise = func(func, completeScope).catch((error2) => handleError(error2, el, expression));
if (func.finished) {
runIfTypeOfFunction(receiver, func.result, completeScope, params, el);
+ func.result = void 0;
} else {
promise.then((result) => {
runIfTypeOfFunction(receiver, result, completeScope, params, el);
- }).catch((error2) => handleError(error2, el, expression));
+ }).catch((error2) => handleError(error2, el, expression)).finally(() => func.result = void 0);
}
}
};
}
- function runIfTypeOfFunction(receiver, value, scope, params, el) {
+ function runIfTypeOfFunction(receiver, value, scope2, params, el) {
if (typeof value === "function") {
- let result = value.apply(scope, params);
+ let result = value.apply(scope2, params);
if (result instanceof Promise) {
- result.then((i) => runIfTypeOfFunction(receiver, i, scope, params)).catch((error2) => handleError(error2, el, value));
+ result.then((i) => runIfTypeOfFunction(receiver, i, scope2, params)).catch((error2) => handleError(error2, el, value));
} else {
receiver(result);
}
@@ -515,10 +552,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
callback(flushHandlers);
stopDeferring();
}
- function getDirectiveHandler(el, directive2) {
- let noop = () => {
- };
- let handler3 = directiveHandlers[directive2.type] || noop;
+ function getElementBoundUtilities(el) {
let cleanups = [];
let cleanup2 = (callback) => cleanups.push(callback);
let [effect3, cleanupEffect] = elementBoundEffect(el);
@@ -531,7 +565,14 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
evaluate: evaluate.bind(evaluate, el)
};
let doCleanup = () => cleanups.forEach((i) => i());
- onAttributeRemoved(el, directive2.original, doCleanup);
+ return [utilities, doCleanup];
+ }
+ function getDirectiveHandler(el, directive2) {
+ let noop = () => {
+ };
+ let handler3 = directiveHandlers[directive2.type] || noop;
+ let [utilities, cleanup2] = getElementBoundUtilities(el);
+ onAttributeRemoved(el, directive2.original, cleanup2);
let fullHandler = () => {
if (el._x_ignore || el._x_ignoreSelf)
return;
@@ -539,7 +580,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
handler3 = handler3.bind(handler3, el, directive2, utilities);
isDeferringHandlers ? directiveHandlerStacks.get(currentHandlerStackKey).push(handler3) : handler3();
};
- fullHandler.runCleanups = doCleanup;
+ fullHandler.runCleanups = cleanup2;
return fullHandler;
}
var startingWith = (subject, replacement) => ({name, value}) => {
@@ -587,14 +628,17 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
"ignore",
"ref",
"data",
+ "id",
"bind",
"init",
"for",
"model",
+ "modelable",
"transition",
"show",
"if",
DEFAULT,
+ "teleport",
"element"
];
function byPriority(a, b) {
@@ -663,7 +707,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
dispatch(document, "alpine:initializing");
startObservingMutations();
onElAdded((el) => initTree(el, walk));
- onElRemoved((el) => nextTick(() => destroyTree(el)));
+ onElRemoved((el) => destroyTree(el));
onAttributesAdded((el, attrs) => {
directives(el, attrs).forEach((handle) => handle());
});
@@ -688,14 +732,22 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
initSelectorCallbacks.push(selectorCallback);
}
function closestRoot(el, includeInitSelectors = false) {
+ return findClosest(el, (element) => {
+ const selectors = includeInitSelectors ? allSelectors() : rootSelectors();
+ if (selectors.some((selector) => element.matches(selector)))
+ return true;
+ });
+ }
+ function findClosest(el, callback) {
if (!el)
return;
- const selectors = includeInitSelectors ? allSelectors() : rootSelectors();
- if (selectors.some((selector) => el.matches(selector)))
+ if (callback(el))
return el;
+ if (el._x_teleportBack)
+ el = el._x_teleportBack;
if (!el.parentElement)
return;
- return closestRoot(el.parentElement, includeInitSelectors);
+ return findClosest(el.parentElement, callback);
}
function isRoot(el) {
return rootSelectors().some((selector) => el.matches(selector));
@@ -770,7 +822,10 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
let previousStyles = {};
Object.entries(value).forEach(([key, value2]) => {
previousStyles[key] = el.style[key];
- el.style.setProperty(kebabCase(key), value2);
+ if (!key.startsWith("--")) {
+ key = kebabCase(key);
+ }
+ el.style.setProperty(key, value2);
});
setTimeout(() => {
if (el.style.length === 0) {
@@ -785,7 +840,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
let cache = el.getAttribute("style", value);
el.setAttribute("style", value);
return () => {
- el.setAttribute("style", cache);
+ el.setAttribute("style", cache || "");
};
}
function kebabCase(subject) {
@@ -1082,6 +1137,179 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
return rawValue;
}
+ // packages/alpinejs/src/clone.js
+ var isCloning = false;
+ function skipDuringClone(callback, fallback = () => {
+ }) {
+ return (...args) => isCloning ? fallback(...args) : callback(...args);
+ }
+ function clone(oldEl, newEl) {
+ if (!newEl._x_dataStack)
+ newEl._x_dataStack = oldEl._x_dataStack;
+ isCloning = true;
+ dontRegisterReactiveSideEffects(() => {
+ cloneTree(newEl);
+ });
+ isCloning = false;
+ }
+ function cloneTree(el) {
+ let hasRunThroughFirstEl = false;
+ let shallowWalker = (el2, callback) => {
+ walk(el2, (el3, skip) => {
+ if (hasRunThroughFirstEl && isRoot(el3))
+ return skip();
+ hasRunThroughFirstEl = true;
+ callback(el3, skip);
+ });
+ };
+ initTree(el, shallowWalker);
+ }
+ function dontRegisterReactiveSideEffects(callback) {
+ let cache = effect;
+ overrideEffect((callback2, el) => {
+ let storedEffect = cache(callback2);
+ release(storedEffect);
+ return () => {
+ };
+ });
+ callback();
+ overrideEffect(cache);
+ }
+
+ // packages/alpinejs/src/utils/bind.js
+ function bind(el, name, value, modifiers = []) {
+ if (!el._x_bindings)
+ el._x_bindings = reactive({});
+ el._x_bindings[name] = value;
+ name = modifiers.includes("camel") ? camelCase(name) : name;
+ switch (name) {
+ case "value":
+ bindInputValue(el, value);
+ break;
+ case "style":
+ bindStyles(el, value);
+ break;
+ case "class":
+ bindClasses(el, value);
+ break;
+ default:
+ bindAttribute(el, name, value);
+ break;
+ }
+ }
+ function bindInputValue(el, value) {
+ if (el.type === "radio") {
+ if (el.attributes.value === void 0) {
+ el.value = value;
+ }
+ if (window.fromModel) {
+ el.checked = checkedAttrLooseCompare(el.value, value);
+ }
+ } else if (el.type === "checkbox") {
+ if (Number.isInteger(value)) {
+ el.value = value;
+ } else if (!Number.isInteger(value) && !Array.isArray(value) && typeof value !== "boolean" && ![null, void 0].includes(value)) {
+ el.value = String(value);
+ } else {
+ if (Array.isArray(value)) {
+ 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;
+ }
+ }
+ function bindClasses(el, value) {
+ if (el._x_undoAddedClasses)
+ el._x_undoAddedClasses();
+ el._x_undoAddedClasses = setClasses(el, value);
+ }
+ function bindStyles(el, value) {
+ if (el._x_undoAddedStyles)
+ el._x_undoAddedStyles();
+ el._x_undoAddedStyles = setStyles(el, value);
+ }
+ function bindAttribute(el, name, value) {
+ if ([null, void 0, false].includes(value) && attributeShouldntBePreservedIfFalsy(name)) {
+ el.removeAttribute(name);
+ } else {
+ if (isBooleanAttr(name))
+ value = name;
+ setIfChanged(el, name, value);
+ }
+ }
+ function setIfChanged(el, attrName, value) {
+ if (el.getAttribute(attrName) != value) {
+ el.setAttribute(attrName, value);
+ }
+ }
+ function updateSelect(el, value) {
+ const arrayWrappedValue = [].concat(value).map((value2) => {
+ return value2 + "";
+ });
+ Array.from(el.options).forEach((option) => {
+ option.selected = arrayWrappedValue.includes(option.value);
+ });
+ }
+ function camelCase(subject) {
+ return subject.toLowerCase().replace(/-(\w)/g, (match, char) => char.toUpperCase());
+ }
+ function checkedAttrLooseCompare(valueA, valueB) {
+ return valueA == valueB;
+ }
+ function isBooleanAttr(attrName) {
+ 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 attributeShouldntBePreservedIfFalsy(name) {
+ return !["aria-pressed", "aria-checked", "aria-expanded", "aria-selected"].includes(name);
+ }
+ function getBinding(el, name, fallback) {
+ if (el._x_bindings && el._x_bindings[name] !== void 0)
+ return el._x_bindings[name];
+ let attr = el.getAttribute(name);
+ if (attr === null)
+ return typeof fallback === "function" ? fallback() : fallback;
+ if (isBooleanAttr(name)) {
+ return !![name, "true"].includes(attr);
+ }
+ if (attr === "")
+ return true;
+ return attr;
+ }
+
// packages/alpinejs/src/utils/debounce.js
function debounce(func, wait) {
var timeout;
@@ -1135,42 +1363,22 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
return stores;
}
- // packages/alpinejs/src/clone.js
- var isCloning = false;
- function skipDuringClone(callback, fallback = () => {
- }) {
- return (...args) => isCloning ? fallback(...args) : callback(...args);
+ // packages/alpinejs/src/binds.js
+ var binds = {};
+ function bind2(name, object) {
+ binds[name] = typeof object !== "function" ? () => object : object;
}
- function clone(oldEl, newEl) {
- newEl._x_dataStack = oldEl._x_dataStack;
- isCloning = true;
- dontRegisterReactiveSideEffects(() => {
- cloneTree(newEl);
- });
- isCloning = false;
- }
- function cloneTree(el) {
- let hasRunThroughFirstEl = false;
- let shallowWalker = (el2, callback) => {
- walk(el2, (el3, skip) => {
- if (hasRunThroughFirstEl && isRoot(el3))
- return skip();
- hasRunThroughFirstEl = true;
- callback(el3, skip);
+ function injectBindingProviders(obj) {
+ Object.entries(binds).forEach(([name, callback]) => {
+ Object.defineProperty(obj, name, {
+ get() {
+ return (...args) => {
+ return callback(...args);
+ };
+ }
});
- };
- initTree(el, shallowWalker);
- }
- function dontRegisterReactiveSideEffects(callback) {
- let cache = effect;
- overrideEffect((callback2, el) => {
- let storedEffect = cache(callback2);
- release(storedEffect);
- return () => {
- };
});
- callback();
- overrideEffect(cache);
+ return obj;
}
// packages/alpinejs/src/datas.js
@@ -1206,19 +1414,23 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
get raw() {
return raw;
},
- version: "3.5.1",
+ version: "3.9.1",
flushAndStopDeferringMutations,
disableEffectScheduling,
stopObservingMutations,
+ destroyTree,
setReactivityEngine,
+ closestDataStack,
skipDuringClone,
addRootSelector,
+ addInitSelector,
+ addScopeToNode,
deferMutations,
mapAttributes,
evaluateLater,
setEvaluator,
mergeProxies,
- destroyTree,
+ findClosest,
closestRoot,
interceptor,
transition,
@@ -1230,13 +1442,17 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
evaluate,
initTree,
nextTick,
+ prefixed: prefix,
prefix: setPrefix,
plugin,
magic,
store,
start,
clone,
- data
+ bound: getBinding,
+ $data: scope,
+ data,
+ bind: bind2
};
var alpine_default = Alpine;
@@ -1271,7 +1487,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
[3]: "FORWARDED"
};
var specialBooleanAttrs = `itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly`;
- var isBooleanAttr = /* @__PURE__ */ makeMap(specialBooleanAttrs + `,async,autofocus,autoplay,controls,default,defer,disabled,hidden,loop,open,required,reversed,scoped,seamless,checked,muted,multiple,selected`);
+ var isBooleanAttr2 = /* @__PURE__ */ makeMap(specialBooleanAttrs + `,async,autofocus,autoplay,controls,default,defer,disabled,hidden,loop,open,required,reversed,scoped,seamless,checked,muted,multiple,selected`);
var EMPTY_OBJ = true ? Object.freeze({}) : {};
var EMPTY_ARR = true ? Object.freeze([]) : [];
var extend = Object.assign;
@@ -1926,15 +2142,12 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
magic("dispatch", (el) => dispatch.bind(dispatch, el));
// packages/alpinejs/src/magics/$watch.js
- magic("watch", (el) => (key, callback) => {
- let evaluate2 = evaluateLater(el, key);
+ magic("watch", (el, {evaluateLater: evaluateLater2, effect: effect3}) => (key, callback) => {
+ let evaluate2 = evaluateLater2(key);
let firstTime = true;
let oldValue;
- let [effect3, cleanupEffect] = elementBoundEffect(el);
- onAttributeRemoved(el, key, cleanupEffect);
effect3(() => evaluate2((value) => {
- let div = document.createElement("div");
- div.dataset.throwAway = value;
+ JSON.stringify(value);
if (!firstTime) {
queueMicrotask(() => {
callback(value, oldValue);
@@ -1951,9 +2164,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
magic("store", getStores);
// packages/alpinejs/src/magics/$data.js
- magic("data", (el) => {
- return mergeProxies(closestDataStack(el));
- });
+ magic("data", (el) => scope(el));
// packages/alpinejs/src/magics/$root.js
magic("root", (el) => closestRoot(el));
@@ -1976,9 +2187,88 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
return refObjects;
}
+ // packages/alpinejs/src/ids.js
+ var globalIdMemo = {};
+ function findAndIncrementId(name) {
+ if (!globalIdMemo[name])
+ globalIdMemo[name] = 0;
+ return ++globalIdMemo[name];
+ }
+ function closestIdRoot(el, name) {
+ return findClosest(el, (element) => {
+ if (element._x_ids && element._x_ids[name])
+ return true;
+ });
+ }
+ function setIdRoot(el, name) {
+ if (!el._x_ids)
+ el._x_ids = {};
+ if (!el._x_ids[name])
+ el._x_ids[name] = findAndIncrementId(name);
+ }
+
+ // packages/alpinejs/src/magics/$id.js
+ magic("id", (el) => (name, key = null) => {
+ let root = closestIdRoot(el, name);
+ let id = root ? root._x_ids[name] : findAndIncrementId(name);
+ return key ? `${name}-${id}-${key}` : `${name}-${id}`;
+ });
+
// packages/alpinejs/src/magics/$el.js
magic("el", (el) => el);
+ // packages/alpinejs/src/directives/x-modelable.js
+ directive("modelable", (el, {expression}, {effect: effect3, evaluate: evaluate2, evaluateLater: evaluateLater2}) => {
+ let func = evaluateLater2(expression);
+ let innerGet = () => {
+ let result;
+ func((i) => result = i);
+ return result;
+ };
+ let evaluateInnerSet = evaluateLater2(`${expression} = __placeholder`);
+ let innerSet = (val) => evaluateInnerSet(() => {
+ }, {scope: {__placeholder: val}});
+ let initialValue = innerGet();
+ if (el._x_modelable_hook)
+ initialValue = el._x_modelable_hook(initialValue);
+ innerSet(initialValue);
+ queueMicrotask(() => {
+ if (!el._x_model)
+ return;
+ let outerGet = el._x_model.get;
+ let outerSet = el._x_model.set;
+ effect3(() => innerSet(outerGet()));
+ effect3(() => outerSet(innerGet()));
+ });
+ });
+
+ // packages/alpinejs/src/directives/x-teleport.js
+ directive("teleport", (el, {expression}, {cleanup: cleanup2}) => {
+ if (el.tagName.toLowerCase() !== "template")
+ warn("x-teleport can only be used on a <template> tag", el);
+ let target = document.querySelector(expression);
+ if (!target)
+ warn(`Cannot find x-teleport element for selector: "${expression}"`);
+ let clone2 = el.content.cloneNode(true).firstElementChild;
+ el._x_teleport = clone2;
+ clone2._x_teleportBack = el;
+ if (el._x_forwardEvents) {
+ el._x_forwardEvents.forEach((eventName) => {
+ clone2.addEventListener(eventName, (e) => {
+ e.stopPropagation();
+ el.dispatchEvent(new e.constructor(e.type, e));
+ });
+ });
+ }
+ addScopeToNode(clone2, {}, el);
+ mutateDom(() => {
+ target.appendChild(clone2);
+ initTree(clone2);
+ clone2._x_ignore = true;
+ });
+ cleanup2(() => clone2.remove());
+ });
+
// packages/alpinejs/src/directives/x-ignore.js
var handler = () => {
};
@@ -1993,127 +2283,6 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
// packages/alpinejs/src/directives/x-effect.js
directive("effect", (el, {expression}, {effect: effect3}) => effect3(evaluateLater(el, expression)));
- // packages/alpinejs/src/utils/bind.js
- function bind(el, name, value, modifiers = []) {
- if (!el._x_bindings)
- el._x_bindings = reactive({});
- el._x_bindings[name] = value;
- name = modifiers.includes("camel") ? camelCase(name) : name;
- switch (name) {
- case "value":
- bindInputValue(el, value);
- break;
- case "style":
- bindStyles(el, value);
- break;
- case "class":
- bindClasses(el, value);
- break;
- default:
- bindAttribute(el, name, value);
- break;
- }
- }
- function bindInputValue(el, value) {
- if (el.type === "radio") {
- if (el.attributes.value === void 0) {
- el.value = value;
- }
- if (window.fromModel) {
- el.checked = checkedAttrLooseCompare(el.value, value);
- }
- } else if (el.type === "checkbox") {
- if (Number.isInteger(value)) {
- el.value = value;
- } else if (!Number.isInteger(value) && !Array.isArray(value) && typeof value !== "boolean" && ![null, void 0].includes(value)) {
- el.value = String(value);
- } else {
- if (Array.isArray(value)) {
- 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;
- }
- }
- function bindClasses(el, value) {
- if (el._x_undoAddedClasses)
- el._x_undoAddedClasses();
- el._x_undoAddedClasses = setClasses(el, value);
- }
- function bindStyles(el, value) {
- if (el._x_undoAddedStyles)
- el._x_undoAddedStyles();
- el._x_undoAddedStyles = setStyles(el, value);
- }
- function bindAttribute(el, name, value) {
- if ([null, void 0, false].includes(value) && attributeShouldntBePreservedIfFalsy(name)) {
- el.removeAttribute(name);
- } else {
- if (isBooleanAttr2(name))
- value = name;
- setIfChanged(el, name, value);
- }
- }
- function setIfChanged(el, attrName, value) {
- if (el.getAttribute(attrName) != value) {
- el.setAttribute(attrName, value);
- }
- }
- function updateSelect(el, value) {
- const arrayWrappedValue = [].concat(value).map((value2) => {
- return value2 + "";
- });
- Array.from(el.options).forEach((option) => {
- option.selected = arrayWrappedValue.includes(option.value);
- });
- }
- function camelCase(subject) {
- return subject.toLowerCase().replace(/-(\w)/g, (match, char) => char.toUpperCase());
- }
- function checkedAttrLooseCompare(valueA, valueB) {
- return valueA == valueB;
- }
- function isBooleanAttr2(attrName) {
- 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 attributeShouldntBePreservedIfFalsy(name) {
- return !["aria-pressed", "aria-checked", "aria-expanded"].includes(name);
- }
-
// packages/alpinejs/src/utils/on.js
function on(el, event, modifiers, callback) {
let listenerTarget = el;
@@ -2345,11 +2514,11 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
// packages/alpinejs/src/directives/x-init.js
addInitSelector(() => `[${prefix("init")}]`);
- directive("init", skipDuringClone((el, {expression}) => {
+ directive("init", skipDuringClone((el, {expression}, {evaluate: evaluate2}) => {
if (typeof expression === "string") {
- return !!expression.trim() && evaluate(el, expression, {}, false);
+ return !!expression.trim() && evaluate2(expression, {}, false);
}
- return evaluate(el, expression, {}, false);
+ return evaluate2(expression, {}, false);
}));
// packages/alpinejs/src/directives/x-text.js
@@ -2377,8 +2546,9 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
// packages/alpinejs/src/directives/x-bind.js
mapAttributes(startingWith(":", into(prefix("bind:"))));
directive("bind", (el, {value, modifiers, expression, original}, {effect: effect3}) => {
- if (!value)
+ if (!value) {
return applyBindingsObject(el, expression, original, effect3);
+ }
if (value === "key")
return storeKeyForXFor(el, expression);
let evaluate2 = evaluateLater(el, expression);
@@ -2389,32 +2559,29 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
}));
});
function applyBindingsObject(el, expression, original, effect3) {
+ let bindingProviders = {};
+ injectBindingProviders(bindingProviders);
let getBindings = evaluateLater(el, expression);
let cleanupRunners = [];
- effect3(() => {
- while (cleanupRunners.length)
- cleanupRunners.pop()();
- getBindings((bindings) => {
- let attributes = Object.entries(bindings).map(([name, value]) => ({name, value}));
- attributes = attributes.filter((attr) => {
- return !(typeof attr.value === "object" && !Array.isArray(attr.value) && attr.value !== null);
- });
- let staticAttributes = attributesOnly(attributes);
- attributes = attributes.map((attribute) => {
- if (staticAttributes.find((attr) => attr.name === attribute.name)) {
- return {
- name: `x-bind:${attribute.name}`,
- value: `"${attribute.value}"`
- };
- }
- return attribute;
- });
- directives(el, attributes, original).map((handle) => {
- cleanupRunners.push(handle.runCleanups);
- handle();
- });
+ while (cleanupRunners.length)
+ cleanupRunners.pop()();
+ getBindings((bindings) => {
+ let attributes = Object.entries(bindings).map(([name, value]) => ({name, value}));
+ let staticAttributes = attributesOnly(attributes);
+ attributes = attributes.map((attribute) => {
+ if (staticAttributes.find((attr) => attr.name === attribute.name)) {
+ return {
+ name: `x-bind:${attribute.name}`,
+ value: `"${attribute.value}"`
+ };
+ }
+ return attribute;
});
- });
+ directives(el, attributes, original).map((handle) => {
+ cleanupRunners.push(handle.runCleanups);
+ handle();
+ });
+ }, {scope: bindingProviders});
}
function storeKeyForXFor(el, expression) {
el._x_keyExpression = expression;
@@ -2509,15 +2676,15 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
let keys = [];
if (isObject2(items)) {
items = Object.entries(items).map(([key, value]) => {
- let scope = getIterationScopeVariables(iteratorNames, value, key, items);
- evaluateKey((value2) => keys.push(value2), {scope: {index: key, ...scope}});
- scopes.push(scope);
+ let scope2 = getIterationScopeVariables(iteratorNames, value, key, items);
+ evaluateKey((value2) => keys.push(value2), {scope: {index: key, ...scope2}});
+ scopes.push(scope2);
});
} else {
for (let i = 0; i < items.length; i++) {
- let scope = getIterationScopeVariables(iteratorNames, items[i], i, items);
- evaluateKey((value) => keys.push(value), {scope: {index: i, ...scope}});
- scopes.push(scope);
+ let scope2 = getIterationScopeVariables(iteratorNames, items[i], i, items);
+ evaluateKey((value) => keys.push(value), {scope: {index: i, ...scope2}});
+ scopes.push(scope2);
}
}
let adds = [];
@@ -2550,6 +2717,9 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
}
for (let i = 0; i < removes.length; i++) {
let key = removes[i];
+ if (!!lookup[key]._x_effects) {
+ lookup[key]._x_effects.forEach(dequeueJob);
+ }
lookup[key].remove();
lookup[key] = null;
delete lookup[key];
@@ -2562,7 +2732,9 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
mutateDom(() => {
elForSpot.after(marker);
elInSpot.after(elForSpot);
+ elForSpot._x_currentIfEl && elForSpot.after(elForSpot._x_currentIfEl);
marker.before(elInSpot);
+ elInSpot._x_currentIfEl && elInSpot.after(elInSpot._x_currentIfEl);
marker.remove();
});
refreshScope(elForSpot, scopes[keys.indexOf(keyForSpot)]);
@@ -2570,10 +2742,12 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
for (let i = 0; i < adds.length; i++) {
let [lastKey2, index] = adds[i];
let lastEl = lastKey2 === "template" ? templateEl : lookup[lastKey2];
- let scope = scopes[index];
+ if (lastEl._x_currentIfEl)
+ lastEl = lastEl._x_currentIfEl;
+ let scope2 = scopes[index];
let key = keys[index];
let clone2 = document.importNode(templateEl.content, true).firstElementChild;
- addScopeToNode(clone2, reactive(scope), templateEl);
+ addScopeToNode(clone2, reactive(scope2), templateEl);
mutateDom(() => {
lastEl.after(clone2);
initTree(clone2);
@@ -2662,6 +2836,11 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
});
el._x_currentIfEl = clone2;
el._x_undoIf = () => {
+ walk(clone2, (node) => {
+ if (!!node._x_effects) {
+ node._x_effects.forEach(dequeueJob);
+ }
+ });
clone2.remove();
delete el._x_currentIfEl;
};
@@ -2679,11 +2858,23 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
cleanup2(() => el._x_undoIf && el._x_undoIf());
});
+ // packages/alpinejs/src/directives/x-id.js
+ directive("id", (el, {expression}, {evaluate: evaluate2}) => {
+ let names = evaluate2(expression);
+ names.forEach((name) => setIdRoot(el, name));
+ });
+
// packages/alpinejs/src/directives/x-on.js
mapAttributes(startingWith("@", into(prefix("on:"))));
directive("on", skipDuringClone((el, {value, modifiers, expression}, {cleanup: cleanup2}) => {
let evaluate2 = expression ? evaluateLater(el, expression) : () => {
};
+ if (el.tagName.toLowerCase() === "template") {
+ if (!el._x_forwardEvents)
+ el._x_forwardEvents = [];
+ if (!el._x_forwardEvents.includes(value))
+ el._x_forwardEvents.push(value);
+ }
let removeListener = on(el, value, modifiers, (e) => {
evaluate2(() => {
}, {scope: {$event: e}, params: [e]});
@@ -2702,8 +2893,8 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
return generateEvaluatorFromFunction(dataStack, expression);
}
let evaluator = (receiver = () => {
- }, {scope = {}, params = []} = {}) => {
- let completeScope = mergeProxies([scope, ...dataStack]);
+ }, {scope: scope2 = {}, params = []} = {}) => {
+ let completeScope = mergeProxies([scope2, ...dataStack]);
if (completeScope[expression] !== void 0) {
runIfTypeOfFunction(receiver, completeScope[expression], completeScope, params);
}
diff --git a/alpinejs/packages/csp/dist/cdn.min.js b/alpinejs/packages/csp/dist/cdn.min.js
index ec34965..07a0ea2 100644
--- a/alpinejs/packages/csp/dist/cdn.min.js
+++ b/alpinejs/packages/csp/dist/cdn.min.js
@@ -1,5 +1,5 @@
-(()=>{var Be=!1,He=!1,re=[];function Rt(e){Hr(e)}function Hr(e){re.includes(e)||re.push(e),qr()}function qr(){!He&&!Be&&(Be=!0,queueMicrotask(Ur))}function Ur(){Be=!1,He=!0;for(let e=0;e<re.length;e++)re[e]();re.length=0,He=!1}var w,F,W,qe,Ue=!0;function Mt(e){Ue=!1,e(),Ue=!0}function Nt(e){w=e.reactive,W=e.release,F=t=>e.effect(t,{scheduler:r=>{Ue?Rt(r):r()}}),qe=e.raw}function We(e){F=e}function ge(e){let t=()=>{};return[n=>{let i=F(n);e._x_effects||(e._x_effects=new Set,e._x_runEffects=()=>{e._x_effects.forEach(o=>o())}),e._x_effects.add(i),t=()=>{i!==void 0&&(e._x_effects.delete(i),W(i))}},()=>{t()}]}var kt=[],Dt=[],Pt=[];function It(e){Pt.push(e)}function jt(e){Dt.push(e)}function Lt(e){kt.push(e)}function G(e,t,r){e._x_attributeCleanups||(e._x_attributeCleanups={}),e._x_attributeCleanups[t]||(e._x_attributeCleanups[t]=[]),e._x_attributeCleanups[t].push(r)}function Ge(e,t){!e._x_attributeCleanups||Object.entries(e._x_attributeCleanups).forEach(([r,n])=>{(t===void 0||t.includes(r))&&(n.forEach(i=>i()),delete e._x_attributeCleanups[r])})}var Je=new MutationObserver(Ye),Ze=!1;function Qe(){Je.observe(document,{subtree:!0,childList:!0,attributes:!0,attributeOldValue:!0}),Ze=!0}function Xe(){Wr(),Je.disconnect(),Ze=!1}var ne=[],et=!1;function Wr(){ne=ne.concat(Je.takeRecords()),ne.length&&!et&&(et=!0,queueMicrotask(()=>{Gr(),et=!1}))}function Gr(){Ye(ne),ne.length=0}function h(e){if(!Ze)return e();Xe();let t=e();return Qe(),t}var tt=!1,_e=[];function $t(){tt=!0}function Ft(){tt=!1,Ye(_e),_e=[]}function Ye(e){if(tt){_e=_e.concat(e);return}let t=[],r=[],n=new Map,i=new Map;for(let o=0;o<e.length;o++)if(!e[o].target._x_ignoreMutationObserver&&(e[o].type==="childList"&&(e[o].addedNodes.forEach(s=>s.nodeType===1&&t.push(s)),e[o].removedNodes.forEach(s=>s.nodeType===1&&r.push(s))),e[o].type==="attributes")){let s=e[o].target,a=e[o].attributeName,c=e[o].oldValue,l=()=>{n.has(s)||n.set(s,[]),n.get(s).push({name:a,value:s.getAttribute(a)})},u=()=>{i.has(s)||i.set(s,[]),i.get(s).push(a)};s.hasAttribute(a)&&c===null?l():s.hasAttribute(a)?(u(),l()):u()}i.forEach((o,s)=>{Ge(s,o)}),n.forEach((o,s)=>{kt.forEach(a=>a(s,o))});for(let o of t)r.includes(o)||Pt.forEach(s=>s(o));for(let o of r)t.includes(o)||Dt.forEach(s=>s(o));t=null,r=null,n=null,i=null}function Y(e,t,r){return e._x_dataStack=[t,...N(r||e)],()=>{e._x_dataStack=e._x_dataStack.filter(n=>n!==t)}}function rt(e,t){let r=e._x_dataStack[0];Object.entries(t).forEach(([n,i])=>{r[n]=i})}function N(e){return e._x_dataStack?e._x_dataStack:typeof ShadowRoot=="function"&&e instanceof ShadowRoot?N(e.host):e.parentNode?N(e.parentNode):[]}function E(e){let t=new Proxy({},{ownKeys:()=>Array.from(new Set(e.flatMap(r=>Object.keys(r)))),has:(r,n)=>e.some(i=>i.hasOwnProperty(n)),get:(r,n)=>(e.find(i=>{if(i.hasOwnProperty(n)){let o=Object.getOwnPropertyDescriptor(i,n);if(o.get&&o.get._x_alreadyBound||o.set&&o.set._x_alreadyBound)return!0;if((o.get||o.set)&&o.enumerable){let s=o.get,a=o.set,c=o;s=s&&s.bind(t),a=a&&a.bind(t),s&&(s._x_alreadyBound=!0),a&&(a._x_alreadyBound=!0),Object.defineProperty(i,n,{...c,get:s,set:a})}return!0}return!1})||{})[n],set:(r,n,i)=>{let o=e.find(s=>s.hasOwnProperty(n));return o?o[n]=i:e[e.length-1][n]=i,!0}});return t}function ye(e){let t=n=>typeof n=="object"&&!Array.isArray(n)&&n!==null,r=(n,i="")=>{Object.entries(Object.getOwnPropertyDescriptors(n)).forEach(([o,{value:s,enumerable:a}])=>{if(a===!1||s===void 0)return;let c=i===""?o:`${i}.${o}`;typeof s=="object"&&s!==null&&s._x_interceptor?n[o]=s.initialize(e,c,o):t(s)&&s!==n&&!(s instanceof Element)&&r(s,c)})};return r(e)}function xe(e,t=()=>{}){let r={initialValue:void 0,_x_interceptor:!0,initialize(n,i,o){return e(this.initialValue,()=>Yr(n,i),s=>nt(n,i,s),i,o)}};return t(r),n=>{if(typeof n=="object"&&n!==null&&n._x_interceptor){let i=r.initialize.bind(r);r.initialize=(o,s,a)=>{let c=n.initialize(o,s,a);return r.initialValue=c,i(o,s,a)}}else r.initialValue=n;return r}}function Yr(e,t){return t.split(".").reduce((r,n)=>r[n],e)}function nt(e,t,r){if(typeof t=="string"&&(t=t.split(".")),t.length===1)e[t[0]]=r;else{if(t.length===0)throw error;return e[t[0]]||(e[t[0]]={}),nt(e[t[0]],t.slice(1),r)}}var Kt={};function b(e,t){Kt[e]=t}function K(e,t){return Object.entries(Kt).forEach(([r,n])=>{Object.defineProperty(e,`$${r}`,{get(){return n(t,{Alpine:A,interceptor:xe})},enumerable:!1})}),{obj:e,cleanup:()=>{t=null}}}function be(e,t,r,...n){try{return r(...n)}catch(i){J(i,e,t)}}function J(e,t,r=void 0){Object.assign(e,{el:t,expression:r}),console.warn(`Alpine Expression Error: ${e.message}
+(()=>{var We=!1,Ge=!1,F=[];function $t(e){nn(e)}function nn(e){F.includes(e)||F.push(e),on()}function _e(e){let t=F.indexOf(e);t!==-1&&F.splice(t,1)}function on(){!Ge&&!We&&(We=!0,queueMicrotask(sn))}function sn(){We=!1,Ge=!0;for(let e=0;e<F.length;e++)F[e]();F.length=0,Ge=!1}var A,K,J,Ye,Je=!0;function jt(e){Je=!1,e(),Je=!0}function Lt(e){A=e.reactive,J=e.release,K=t=>e.effect(t,{scheduler:r=>{Je?$t(r):r()}}),Ye=e.raw}function Ze(e){K=e}function Ft(e){let t=()=>{};return[n=>{let i=K(n);e._x_effects||(e._x_effects=new Set,e._x_runEffects=()=>{e._x_effects.forEach(o=>o())}),e._x_effects.add(i),t=()=>{i!==void 0&&(e._x_effects.delete(i),J(i))}},()=>{t()}]}var Kt=[],Bt=[],zt=[];function Vt(e){zt.push(e)}function ge(e,t){typeof t=="function"?(e._x_cleanups||(e._x_cleanups=[]),e._x_cleanups.push(t)):(t=e,Bt.push(t))}function Ht(e){Kt.push(e)}function xe(e,t,r){e._x_attributeCleanups||(e._x_attributeCleanups={}),e._x_attributeCleanups[t]||(e._x_attributeCleanups[t]=[]),e._x_attributeCleanups[t].push(r)}function Qe(e,t){!e._x_attributeCleanups||Object.entries(e._x_attributeCleanups).forEach(([r,n])=>{(t===void 0||t.includes(r))&&(n.forEach(i=>i()),delete e._x_attributeCleanups[r])})}var et=new MutationObserver(Xe),tt=!1;function rt(){et.observe(document,{subtree:!0,childList:!0,attributes:!0,attributeOldValue:!0}),tt=!0}function nt(){an(),et.disconnect(),tt=!1}var ne=[],it=!1;function an(){ne=ne.concat(et.takeRecords()),ne.length&&!it&&(it=!0,queueMicrotask(()=>{cn(),it=!1}))}function cn(){Xe(ne),ne.length=0}function m(e){if(!tt)return e();nt();let t=e();return rt(),t}var ot=!1,ye=[];function qt(){ot=!0}function Ut(){ot=!1,Xe(ye),ye=[]}function Xe(e){if(ot){ye=ye.concat(e);return}let t=[],r=[],n=new Map,i=new Map;for(let o=0;o<e.length;o++)if(!e[o].target._x_ignoreMutationObserver&&(e[o].type==="childList"&&(e[o].addedNodes.forEach(s=>s.nodeType===1&&t.push(s)),e[o].removedNodes.forEach(s=>s.nodeType===1&&r.push(s))),e[o].type==="attributes")){let s=e[o].target,a=e[o].attributeName,c=e[o].oldValue,l=()=>{n.has(s)||n.set(s,[]),n.get(s).push({name:a,value:s.getAttribute(a)})},u=()=>{i.has(s)||i.set(s,[]),i.get(s).push(a)};s.hasAttribute(a)&&c===null?l():s.hasAttribute(a)?(u(),l()):u()}i.forEach((o,s)=>{Qe(s,o)}),n.forEach((o,s)=>{Kt.forEach(a=>a(s,o))});for(let o of r)if(!t.includes(o)&&(Bt.forEach(s=>s(o)),o._x_cleanups))for(;o._x_cleanups.length;)o._x_cleanups.pop()();t.forEach(o=>{o._x_ignoreSelf=!0,o._x_ignore=!0});for(let o of t)r.includes(o)||!o.isConnected||(delete o._x_ignoreSelf,delete o._x_ignore,zt.forEach(s=>s(o)),o._x_ignore=!0,o._x_ignoreSelf=!0);t.forEach(o=>{delete o._x_ignoreSelf,delete o._x_ignore}),t=null,r=null,n=null,i=null}function be(e){return C(T(e))}function R(e,t,r){return e._x_dataStack=[t,...T(r||e)],()=>{e._x_dataStack=e._x_dataStack.filter(n=>n!==t)}}function st(e,t){let r=e._x_dataStack[0];Object.entries(t).forEach(([n,i])=>{r[n]=i})}function T(e){return e._x_dataStack?e._x_dataStack:typeof ShadowRoot=="function"&&e instanceof ShadowRoot?T(e.host):e.parentNode?T(e.parentNode):[]}function C(e){let t=new Proxy({},{ownKeys:()=>Array.from(new Set(e.flatMap(r=>Object.keys(r)))),has:(r,n)=>e.some(i=>i.hasOwnProperty(n)),get:(r,n)=>(e.find(i=>{if(i.hasOwnProperty(n)){let o=Object.getOwnPropertyDescriptor(i,n);if(o.get&&o.get._x_alreadyBound||o.set&&o.set._x_alreadyBound)return!0;if((o.get||o.set)&&o.enumerable){let s=o.get,a=o.set,c=o;s=s&&s.bind(t),a=a&&a.bind(t),s&&(s._x_alreadyBound=!0),a&&(a._x_alreadyBound=!0),Object.defineProperty(i,n,{...c,get:s,set:a})}return!0}return!1})||{})[n],set:(r,n,i)=>{let o=e.find(s=>s.hasOwnProperty(n));return o?o[n]=i:e[e.length-1][n]=i,!0}});return t}function ve(e){let t=n=>typeof n=="object"&&!Array.isArray(n)&&n!==null,r=(n,i="")=>{Object.entries(Object.getOwnPropertyDescriptors(n)).forEach(([o,{value:s,enumerable:a}])=>{if(a===!1||s===void 0)return;let c=i===""?o:`${i}.${o}`;typeof s=="object"&&s!==null&&s._x_interceptor?n[o]=s.initialize(e,c,o):t(s)&&s!==n&&!(s instanceof Element)&&r(s,c)})};return r(e)}function we(e,t=()=>{}){let r={initialValue:void 0,_x_interceptor:!0,initialize(n,i,o){return e(this.initialValue,()=>ln(n,i),s=>at(n,i,s),i,o)}};return t(r),n=>{if(typeof n=="object"&&n!==null&&n._x_interceptor){let i=r.initialize.bind(r);r.initialize=(o,s,a)=>{let c=n.initialize(o,s,a);return r.initialValue=c,i(o,s,a)}}else r.initialValue=n;return r}}function ln(e,t){return t.split(".").reduce((r,n)=>r[n],e)}function at(e,t,r){if(typeof t=="string"&&(t=t.split(".")),t.length===1)e[t[0]]=r;else{if(t.length===0)throw error;return e[t[0]]||(e[t[0]]={}),at(e[t[0]],t.slice(1),r)}}var Wt={};function y(e,t){Wt[e]=t}function B(e,t){return Object.entries(Wt).forEach(([r,n])=>{Object.defineProperty(e,`$${r}`,{get(){let[i,o]=ct(t);return i={interceptor:we,...i},ge(t,o),n(t,i)},enumerable:!1})}),{obj:e,cleanup:()=>{t=null}}}function Ee(e,t,r,...n){try{return r(...n)}catch(i){Z(i,e,t)}}function Z(e,t,r=void 0){Object.assign(e,{el:t,expression:r}),console.warn(`Alpine Expression Error: ${e.message}
${r?'Expression: "'+r+`"
-`:""}`,t),setTimeout(()=>{throw e},0)}function v(e,t,r={}){let n;return m(e,t)(i=>n=i,r),n}function m(...e){return zt(...e)}var zt=Jr;function Vt(e){zt=e}function Jr(e,t){let r={},n=K(r,e).cleanup;G(e,"evaluator",n);let i=[r,...N(e)];if(typeof t=="function")return it(i,t);let o=Zr(i,t,e);return be.bind(null,e,t,o)}function it(e,t){return(r=()=>{},{scope:n={},params:i=[]}={})=>{let o=t.apply(E([n,...e]),i);Z(r,o)}}var ot={};function Qr(e,t){if(ot[e])return ot[e];let r=Object.getPrototypeOf(async function(){}).constructor,n=/^[\n\s]*if.*\(.*\)/.test(e)||/^(let|const)\s/.test(e)?`(() => { ${e} })()`:e,o=(()=>{try{return new r(["__self","scope"],`with (scope) { __self.result = ${n} }; __self.finished = true; return __self.result;`)}catch(s){return J(s,t,e),Promise.resolve()}})();return ot[e]=o,o}function Zr(e,t,r){let n=Qr(t,r);return(i=()=>{},{scope:o={},params:s=[]}={})=>{n.result=void 0,n.finished=!1;let a=E([o,...e]);if(typeof n=="function"){let c=n(n,a).catch(l=>J(l,r,t));n.finished?Z(i,n.result,a,s,r):c.then(l=>{Z(i,l,a,s,r)}).catch(l=>J(l,r,t))}}}function Z(e,t,r,n,i){if(typeof t=="function"){let o=t.apply(r,n);o instanceof Promise?o.then(s=>Z(e,s,r,n)).catch(s=>J(s,i,t)):e(o)}else e(t)}var st="x-";function O(e=""){return st+e}function Bt(e){st=e}var Ht={};function d(e,t){Ht[e]=t}function ie(e,t,r){let n={};return Array.from(t).map(qt((o,s)=>n[o]=s)).filter(Ut).map(en(n,r)).sort(tn).map(o=>Xr(e,o))}function Wt(e){return Array.from(e).map(qt()).filter(t=>!Ut(t))}var at=!1,oe=new Map,Gt=Symbol();function Yt(e){at=!0;let t=Symbol();Gt=t,oe.set(t,[]);let r=()=>{for(;oe.get(t).length;)oe.get(t).shift()();oe.delete(t)},n=()=>{at=!1,r()};e(r),n()}function Xr(e,t){let r=()=>{},n=Ht[t.type]||r,i=[],o=p=>i.push(p),[s,a]=ge(e);i.push(a);let c={Alpine:A,effect:s,cleanup:o,evaluateLater:m.bind(m,e),evaluate:v.bind(v,e)},l=()=>i.forEach(p=>p());G(e,t.original,l);let u=()=>{e._x_ignore||e._x_ignoreSelf||(n.inline&&n.inline(e,t,c),n=n.bind(n,e,t,c),at?oe.get(Gt).push(n):n())};return u.runCleanups=l,u}var ve=(e,t)=>({name:r,value:n})=>(r.startsWith(e)&&(r=r.replace(e,t)),{name:r,value:n}),we=e=>e;function qt(e=()=>{}){return({name:t,value:r})=>{let{name:n,value:i}=Jt.reduce((o,s)=>s(o),{name:t,value:r});return n!==t&&e(n,t),{name:n,value:i}}}var Jt=[];function Q(e){Jt.push(e)}function Ut({name:e}){return Zt().test(e)}var Zt=()=>new RegExp(`^${st}([^:^.]+)\\b`);function en(e,t){return({name:r,value:n})=>{let i=r.match(Zt()),o=r.match(/:([a-zA-Z0-9\-:]+)/),s=r.match(/\.[^.\]]+(?=[^\]]*$)/g)||[],a=t||e[r]||r;return{type:i?i[1]:null,value:o?o[1]:null,modifiers:s.map(c=>c.replace(".","")),expression:n,original:a}}}var ct="DEFAULT",Ee=["ignore","ref","data","bind","init","for","model","transition","show","if",ct,"element"];function tn(e,t){let r=Ee.indexOf(e.type)===-1?ct:e.type,n=Ee.indexOf(t.type)===-1?ct:t.type;return Ee.indexOf(r)-Ee.indexOf(n)}function z(e,t,r={}){e.dispatchEvent(new CustomEvent(t,{detail:r,bubbles:!0,composed:!0,cancelable:!0}))}var lt=[],ut=!1;function X(e){lt.push(e),queueMicrotask(()=>{ut||setTimeout(()=>{Se()})})}function Se(){for(ut=!1;lt.length;)lt.shift()()}function Qt(){ut=!0}function D(e,t){if(typeof ShadowRoot=="function"&&e instanceof ShadowRoot){Array.from(e.children).forEach(i=>D(i,t));return}let r=!1;if(t(e,()=>r=!0),r)return;let n=e.firstElementChild;for(;n;)D(n,t,!1),n=n.nextElementSibling}function Ae(e,...t){console.warn(`Alpine Warning: ${e}`,...t)}function er(){document.body||Ae("Unable to initialize. Trying to load Alpine before `<body>` is available. Did you forget to add `defer` in Alpine's `<script>` tag?"),z(document,"alpine:init"),z(document,"alpine:initializing"),Qe(),It(t=>T(t,D)),jt(t=>X(()=>ft(t))),Lt((t,r)=>{ie(t,r).forEach(n=>n())});let e=t=>!P(t.parentElement,!0);Array.from(document.querySelectorAll(Xt())).filter(e).forEach(t=>{T(t)}),z(document,"alpine:initialized")}var pt=[],tr=[];function rr(){return pt.map(e=>e())}function Xt(){return pt.concat(tr).map(e=>e())}function Oe(e){pt.push(e)}function nr(e){tr.push(e)}function P(e,t=!1){if(!e)return;if((t?Xt():rr()).some(n=>e.matches(n)))return e;if(!!e.parentElement)return P(e.parentElement,t)}function ir(e){return rr().some(t=>e.matches(t))}function T(e,t=D){Yt(()=>{t(e,(r,n)=>{ie(r,r.attributes).forEach(i=>i()),r._x_ignore&&n()})})}function ft(e){D(e,t=>Ge(t))}function se(e,t){return Array.isArray(t)?or(e,t.join(" ")):typeof t=="object"&&t!==null?rn(e,t):typeof t=="function"?se(e,t()):or(e,t)}function or(e,t){let r=o=>o.split(" ").filter(Boolean),n=o=>o.split(" ").filter(s=>!e.classList.contains(s)).filter(Boolean),i=o=>(e.classList.add(...o),()=>{e.classList.remove(...o)});return t=t===!0?t="":t||"",i(n(t))}function rn(e,t){let r=a=>a.split(" ").filter(Boolean),n=Object.entries(t).flatMap(([a,c])=>c?r(a):!1).filter(Boolean),i=Object.entries(t).flatMap(([a,c])=>c?!1:r(a)).filter(Boolean),o=[],s=[];return i.forEach(a=>{e.classList.contains(a)&&(e.classList.remove(a),s.push(a))}),n.forEach(a=>{e.classList.contains(a)||(e.classList.add(a),o.push(a))}),()=>{s.forEach(a=>e.classList.add(a)),o.forEach(a=>e.classList.remove(a))}}function V(e,t){return typeof t=="object"&&t!==null?nn(e,t):on(e,t)}function nn(e,t){let r={};return Object.entries(t).forEach(([n,i])=>{r[n]=e.style[n],e.style.setProperty(sn(n),i)}),setTimeout(()=>{e.style.length===0&&e.removeAttribute("style")}),()=>{V(e,r)}}function on(e,t){let r=e.getAttribute("style",t);return e.setAttribute("style",t),()=>{e.setAttribute("style",r)}}function sn(e){return e.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()}function ae(e,t=()=>{}){let r=!1;return function(){r?t.apply(this,arguments):(r=!0,e.apply(this,arguments))}}d("transition",(e,{value:t,modifiers:r,expression:n},{evaluate:i})=>{typeof n=="function"&&(n=i(n)),n?an(e,n,t):cn(e,r,t)});function an(e,t,r){sr(e,se,""),{enter:i=>{e._x_transition.enter.during=i},"enter-start":i=>{e._x_transition.enter.start=i},"enter-end":i=>{e._x_transition.enter.end=i},leave:i=>{e._x_transition.leave.during=i},"leave-start":i=>{e._x_transition.leave.start=i},"leave-end":i=>{e._x_transition.leave.end=i}}[r](t)}function cn(e,t,r){sr(e,V);let n=!t.includes("in")&&!t.includes("out")&&!r,i=n||t.includes("in")||["enter"].includes(r),o=n||t.includes("out")||["leave"].includes(r);t.includes("in")&&!n&&(t=t.filter((_,x)=>x<t.indexOf("out"))),t.includes("out")&&!n&&(t=t.filter((_,x)=>x>t.indexOf("out")));let s=!t.includes("opacity")&&!t.includes("scale"),a=s||t.includes("opacity"),c=s||t.includes("scale"),l=a?0:1,u=c?ce(t,"scale",95)/100:1,p=ce(t,"delay",0),y=ce(t,"origin","center"),R="opacity, transform",q=ce(t,"duration",150)/1e3,me=ce(t,"duration",75)/1e3,f="cubic-bezier(0.4, 0.0, 0.2, 1)";i&&(e._x_transition.enter.during={transformOrigin:y,transitionDelay:p,transitionProperty:R,transitionDuration:`${q}s`,transitionTimingFunction:f},e._x_transition.enter.start={opacity:l,transform:`scale(${u})`},e._x_transition.enter.end={opacity:1,transform:"scale(1)"}),o&&(e._x_transition.leave.during={transformOrigin:y,transitionDelay:p,transitionProperty:R,transitionDuration:`${me}s`,transitionTimingFunction:f},e._x_transition.leave.start={opacity:1,transform:"scale(1)"},e._x_transition.leave.end={opacity:l,transform:`scale(${u})`})}function sr(e,t,r={}){e._x_transition||(e._x_transition={enter:{during:r,start:r,end:r},leave:{during:r,start:r,end:r},in(n=()=>{},i=()=>{}){Te(e,t,{during:this.enter.during,start:this.enter.start,end:this.enter.end},n,i)},out(n=()=>{},i=()=>{}){Te(e,t,{during:this.leave.during,start:this.leave.start,end:this.leave.end},n,i)}})}window.Element.prototype._x_toggleAndCascadeWithTransitions=function(e,t,r,n){let i=()=>{document.visibilityState==="visible"?requestAnimationFrame(r):setTimeout(r)};if(t){e._x_transition&&(e._x_transition.enter||e._x_transition.leave)?e._x_transition.enter&&(Object.entries(e._x_transition.enter.during).length||Object.entries(e._x_transition.enter.start).length||Object.entries(e._x_transition.enter.end).length)?e._x_transition.in(r):i():e._x_transition?e._x_transition.in(r):i();return}e._x_hidePromise=e._x_transition?new Promise((o,s)=>{e._x_transition.out(()=>{},()=>o(n)),e._x_transitioning.beforeCancel(()=>s({isFromCancelledTransition:!0}))}):Promise.resolve(n),queueMicrotask(()=>{let o=ar(e);o?(o._x_hideChildren||(o._x_hideChildren=[]),o._x_hideChildren.push(e)):queueMicrotask(()=>{let s=a=>{let c=Promise.all([a._x_hidePromise,...(a._x_hideChildren||[]).map(s)]).then(([l])=>l());return delete a._x_hidePromise,delete a._x_hideChildren,c};s(e).catch(a=>{if(!a.isFromCancelledTransition)throw a})})})};function ar(e){let t=e.parentNode;if(!!t)return t._x_hidePromise?t:ar(t)}function Te(e,t,{during:r,start:n,end:i}={},o=()=>{},s=()=>{}){if(e._x_transitioning&&e._x_transitioning.cancel(),Object.keys(r).length===0&&Object.keys(n).length===0&&Object.keys(i).length===0){o(),s();return}let a,c,l;ln(e,{start(){a=t(e,n)},during(){c=t(e,r)},before:o,end(){a(),l=t(e,i)},after:s,cleanup(){c(),l()}})}function ln(e,t){let r,n,i,o=ae(()=>{h(()=>{r=!0,n||t.before(),i||(t.end(),Se()),t.after(),e.isConnected&&t.cleanup(),delete e._x_transitioning})});e._x_transitioning={beforeCancels:[],beforeCancel(s){this.beforeCancels.push(s)},cancel:ae(function(){for(;this.beforeCancels.length;)this.beforeCancels.shift()();o()}),finish:o},h(()=>{t.start(),t.during()}),Qt(),requestAnimationFrame(()=>{if(r)return;let s=Number(getComputedStyle(e).transitionDuration.replace(/,.*/,"").replace("s",""))*1e3,a=Number(getComputedStyle(e).transitionDelay.replace(/,.*/,"").replace("s",""))*1e3;s===0&&(s=Number(getComputedStyle(e).animationDuration.replace("s",""))*1e3),h(()=>{t.before()}),n=!0,requestAnimationFrame(()=>{r||(h(()=>{t.end()}),Se(),setTimeout(e._x_transitioning.finish,s+a),i=!0)})})}function ce(e,t,r){if(e.indexOf(t)===-1)return r;let n=e[e.indexOf(t)+1];if(!n||t==="scale"&&isNaN(n))return r;if(t==="duration"){let i=n.match(/([0-9]+)ms/);if(i)return i[1]}return t==="origin"&&["top","right","left","center","bottom"].includes(e[e.indexOf(t)+2])?[n,e[e.indexOf(t)+2]].join(" "):n}function Ce(e,t){var r;return function(){var n=this,i=arguments,o=function(){r=null,e.apply(n,i)};clearTimeout(r),r=setTimeout(o,t)}}function Re(e,t){let r;return function(){let n=this,i=arguments;r||(e.apply(n,i),r=!0,setTimeout(()=>r=!1,t))}}function cr(e){e(A)}var B={},lr=!1;function ur(e,t){if(lr||(B=w(B),lr=!0),t===void 0)return B[e];B[e]=t,typeof t=="object"&&t!==null&&t.hasOwnProperty("init")&&typeof t.init=="function"&&B[e].init(),ye(B[e])}function fr(){return B}var dt=!1;function I(e,t=()=>{}){return(...r)=>dt?t(...r):e(...r)}function pr(e,t){t._x_dataStack=e._x_dataStack,dt=!0,fn(()=>{un(t)}),dt=!1}function un(e){let t=!1;T(e,(n,i)=>{D(n,(o,s)=>{if(t&&ir(o))return s();t=!0,i(o,s)})})}function fn(e){let t=F;We((r,n)=>{let i=t(r);return W(i),()=>{}}),e(),We(t)}var dr={};function mr(e,t){dr[e]=t}function hr(e,t){return Object.entries(dr).forEach(([r,n])=>{Object.defineProperty(e,r,{get(){return(...i)=>n.bind(t)(...i)},enumerable:!1})}),e}var pn={get reactive(){return w},get release(){return W},get effect(){return F},get raw(){return qe},version:"3.5.1",flushAndStopDeferringMutations:Ft,disableEffectScheduling:Mt,stopObservingMutations:Xe,setReactivityEngine:Nt,skipDuringClone:I,addRootSelector:Oe,deferMutations:$t,mapAttributes:Q,evaluateLater:m,setEvaluator:Vt,mergeProxies:E,destroyTree:ft,closestRoot:P,interceptor:xe,transition:Te,setStyles:V,mutateDom:h,directive:d,throttle:Re,debounce:Ce,evaluate:v,initTree:T,nextTick:X,prefix:Bt,plugin:cr,magic:b,store:ur,start:er,clone:pr,data:mr},A=pn;function mt(e,t){let r=Object.create(null),n=e.split(",");for(let i=0;i<n.length;i++)r[n[i]]=!0;return t?i=>!!r[i.toLowerCase()]:i=>!!r[i]}var No={[1]:"TEXT",[2]:"CLASS",[4]:"STYLE",[8]:"PROPS",[16]:"FULL_PROPS",[32]:"HYDRATE_EVENTS",[64]:"STABLE_FRAGMENT",[128]:"KEYED_FRAGMENT",[256]:"UNKEYED_FRAGMENT",[512]:"NEED_PATCH",[1024]:"DYNAMIC_SLOTS",[2048]:"DEV_ROOT_FRAGMENT",[-1]:"HOISTED",[-2]:"BAIL"},ko={[1]:"STABLE",[2]:"DYNAMIC",[3]:"FORWARDED"};var dn="itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly";var Do=mt(dn+",async,autofocus,autoplay,controls,default,defer,disabled,hidden,loop,open,required,reversed,scoped,seamless,checked,muted,multiple,selected");var gr=Object.freeze({}),Po=Object.freeze([]);var ht=Object.assign;var mn=Object.prototype.hasOwnProperty,le=(e,t)=>mn.call(e,t),j=Array.isArray,ee=e=>_r(e)==="[object Map]";var hn=e=>typeof e=="string",Me=e=>typeof e=="symbol",ue=e=>e!==null&&typeof e=="object";var gn=Object.prototype.toString,_r=e=>gn.call(e),gt=e=>_r(e).slice(8,-1);var Ne=e=>hn(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e;var ke=e=>{let t=Object.create(null);return r=>t[r]||(t[r]=e(r))},_n=/-(\w)/g,Io=ke(e=>e.replace(_n,(t,r)=>r?r.toUpperCase():"")),yn=/\B([A-Z])/g,jo=ke(e=>e.replace(yn,"-$1").toLowerCase()),_t=ke(e=>e.charAt(0).toUpperCase()+e.slice(1)),Lo=ke(e=>e?`on${_t(e)}`:""),yt=(e,t)=>e!==t&&(e===e||t===t);var xt=new WeakMap,fe=[],C,H=Symbol("iterate"),bt=Symbol("Map key iterate");function xn(e){return e&&e._isEffect===!0}function yr(e,t=gr){xn(e)&&(e=e.raw);let r=bn(e,t);return t.lazy||r(),r}function br(e){e.active&&(xr(e),e.options.onStop&&e.options.onStop(),e.active=!1)}var vn=0;function bn(e,t){let r=function(){if(!r.active)return e();if(!fe.includes(r)){xr(r);try{return wn(),fe.push(r),C=r,e()}finally{fe.pop(),vr(),C=fe[fe.length-1]}}};return r.id=vn++,r.allowRecurse=!!t.allowRecurse,r._isEffect=!0,r.active=!0,r.raw=e,r.deps=[],r.options=t,r}function xr(e){let{deps:t}=e;if(t.length){for(let r=0;r<t.length;r++)t[r].delete(e);t.length=0}}var te=!0,vt=[];function En(){vt.push(te),te=!1}function wn(){vt.push(te),te=!0}function vr(){let e=vt.pop();te=e===void 0?!0:e}function S(e,t,r){if(!te||C===void 0)return;let n=xt.get(e);n||xt.set(e,n=new Map);let i=n.get(r);i||n.set(r,i=new Set),i.has(C)||(i.add(C),C.deps.push(i),C.options.onTrack&&C.options.onTrack({effect:C,target:e,type:t,key:r}))}function L(e,t,r,n,i,o){let s=xt.get(e);if(!s)return;let a=new Set,c=u=>{u&&u.forEach(p=>{(p!==C||p.allowRecurse)&&a.add(p)})};if(t==="clear")s.forEach(c);else if(r==="length"&&j(e))s.forEach((u,p)=>{(p==="length"||p>=n)&&c(u)});else switch(r!==void 0&&c(s.get(r)),t){case"add":j(e)?Ne(r)&&c(s.get("length")):(c(s.get(H)),ee(e)&&c(s.get(bt)));break;case"delete":j(e)||(c(s.get(H)),ee(e)&&c(s.get(bt)));break;case"set":ee(e)&&c(s.get(H));break}let l=u=>{u.options.onTrigger&&u.options.onTrigger({effect:u,target:e,key:r,type:t,newValue:n,oldValue:i,oldTarget:o}),u.options.scheduler?u.options.scheduler(u):u()};a.forEach(l)}var Sn=mt("__proto__,__v_isRef,__isVue"),wr=new Set(Object.getOwnPropertyNames(Symbol).map(e=>Symbol[e]).filter(Me)),An=De(),On=De(!1,!0),Tn=De(!0),Cn=De(!0,!0),Pe={};["includes","indexOf","lastIndexOf"].forEach(e=>{let t=Array.prototype[e];Pe[e]=function(...r){let n=g(this);for(let o=0,s=this.length;o<s;o++)S(n,"get",o+"");let i=t.apply(n,r);return i===-1||i===!1?t.apply(n,r.map(g)):i}});["push","pop","shift","unshift","splice"].forEach(e=>{let t=Array.prototype[e];Pe[e]=function(...r){En();let n=t.apply(this,r);return vr(),n}});function De(e=!1,t=!1){return function(n,i,o){if(i==="__v_isReactive")return!e;if(i==="__v_isReadonly")return e;if(i==="__v_raw"&&o===(e?t?Mn:Sr:t?Rn:Er).get(n))return n;let s=j(n);if(!e&&s&&le(Pe,i))return Reflect.get(Pe,i,o);let a=Reflect.get(n,i,o);return(Me(i)?wr.has(i):Sn(i))||(e||S(n,"get",i),t)?a:wt(a)?!s||!Ne(i)?a.value:a:ue(a)?e?Ar(a):Ie(a):a}}var Nn=Or(),kn=Or(!0);function Or(e=!1){return function(r,n,i,o){let s=r[n];if(!e&&(i=g(i),s=g(s),!j(r)&&wt(s)&&!wt(i)))return s.value=i,!0;let a=j(r)&&Ne(n)?Number(n)<r.length:le(r,n),c=Reflect.set(r,n,i,o);return r===g(o)&&(a?yt(i,s)&&L(r,"set",n,i,s):L(r,"add",n,i)),c}}function Dn(e,t){let r=le(e,t),n=e[t],i=Reflect.deleteProperty(e,t);return i&&r&&L(e,"delete",t,void 0,n),i}function Pn(e,t){let r=Reflect.has(e,t);return(!Me(t)||!wr.has(t))&&S(e,"has",t),r}function In(e){return S(e,"iterate",j(e)?"length":H),Reflect.ownKeys(e)}var Tr={get:An,set:Nn,deleteProperty:Dn,has:Pn,ownKeys:In},Cr={get:Tn,set(e,t){return console.warn(`Set operation on key "${String(t)}" failed: target is readonly.`,e),!0},deleteProperty(e,t){return console.warn(`Delete operation on key "${String(t)}" failed: target is readonly.`,e),!0}},Bo=ht({},Tr,{get:On,set:kn}),Ho=ht({},Cr,{get:Cn}),Et=e=>ue(e)?Ie(e):e,St=e=>ue(e)?Ar(e):e,At=e=>e,je=e=>Reflect.getPrototypeOf(e);function Le(e,t,r=!1,n=!1){e=e.__v_raw;let i=g(e),o=g(t);t!==o&&!r&&S(i,"get",t),!r&&S(i,"get",o);let{has:s}=je(i),a=n?At:r?St:Et;if(s.call(i,t))return a(e.get(t));if(s.call(i,o))return a(e.get(o));e!==i&&e.get(t)}function $e(e,t=!1){let r=this.__v_raw,n=g(r),i=g(e);return e!==i&&!t&&S(n,"has",e),!t&&S(n,"has",i),e===i?r.has(e):r.has(e)||r.has(i)}function Fe(e,t=!1){return e=e.__v_raw,!t&&S(g(e),"iterate",H),Reflect.get(e,"size",e)}function Rr(e){e=g(e);let t=g(this);return je(t).has.call(t,e)||(t.add(e),L(t,"add",e,e)),this}function Nr(e,t){t=g(t);let r=g(this),{has:n,get:i}=je(r),o=n.call(r,e);o?Mr(r,n,e):(e=g(e),o=n.call(r,e));let s=i.call(r,e);return r.set(e,t),o?yt(t,s)&&L(r,"set",e,t,s):L(r,"add",e,t),this}function kr(e){let t=g(this),{has:r,get:n}=je(t),i=r.call(t,e);i?Mr(t,r,e):(e=g(e),i=r.call(t,e));let o=n?n.call(t,e):void 0,s=t.delete(e);return i&&L(t,"delete",e,void 0,o),s}function Dr(){let e=g(this),t=e.size!==0,r=ee(e)?new Map(e):new Set(e),n=e.clear();return t&&L(e,"clear",void 0,void 0,r),n}function Ke(e,t){return function(n,i){let o=this,s=o.__v_raw,a=g(s),c=t?At:e?St:Et;return!e&&S(a,"iterate",H),s.forEach((l,u)=>n.call(i,c(l),c(u),o))}}function ze(e,t,r){return function(...n){let i=this.__v_raw,o=g(i),s=ee(o),a=e==="entries"||e===Symbol.iterator&&s,c=e==="keys"&&s,l=i[e](...n),u=r?At:t?St:Et;return!t&&S(o,"iterate",c?bt:H),{next(){let{value:p,done:y}=l.next();return y?{value:p,done:y}:{value:a?[u(p[0]),u(p[1])]:u(p),done:y}},[Symbol.iterator](){return this}}}}function $(e){return function(...t){{let r=t[0]?`on key "${t[0]}" `:"";console.warn(`${_t(e)} operation ${r}failed: target is readonly.`,g(this))}return e==="delete"?!1:this}}var Pr={get(e){return Le(this,e)},get size(){return Fe(this)},has:$e,add:Rr,set:Nr,delete:kr,clear:Dr,forEach:Ke(!1,!1)},Ir={get(e){return Le(this,e,!1,!0)},get size(){return Fe(this)},has:$e,add:Rr,set:Nr,delete:kr,clear:Dr,forEach:Ke(!1,!0)},jr={get(e){return Le(this,e,!0)},get size(){return Fe(this,!0)},has(e){return $e.call(this,e,!0)},add:$("add"),set:$("set"),delete:$("delete"),clear:$("clear"),forEach:Ke(!0,!1)},Lr={get(e){return Le(this,e,!0,!0)},get size(){return Fe(this,!0)},has(e){return $e.call(this,e,!0)},add:$("add"),set:$("set"),delete:$("delete"),clear:$("clear"),forEach:Ke(!0,!0)},jn=["keys","values","entries",Symbol.iterator];jn.forEach(e=>{Pr[e]=ze(e,!1,!1),jr[e]=ze(e,!0,!1),Ir[e]=ze(e,!1,!0),Lr[e]=ze(e,!0,!0)});function Ve(e,t){let r=t?e?Lr:Ir:e?jr:Pr;return(n,i,o)=>i==="__v_isReactive"?!e:i==="__v_isReadonly"?e:i==="__v_raw"?n:Reflect.get(le(r,i)&&i in n?r:n,i,o)}var Ln={get:Ve(!1,!1)},qo={get:Ve(!1,!0)},$n={get:Ve(!0,!1)},Uo={get:Ve(!0,!0)};function Mr(e,t,r){let n=g(r);if(n!==r&&t.call(e,n)){let i=gt(e);console.warn(`Reactive ${i} contains both the raw and reactive versions of the same object${i==="Map"?" as keys":""}, which can lead to inconsistencies. Avoid differentiating between the raw and reactive versions of an object and only use the reactive version if possible.`)}}var Er=new WeakMap,Rn=new WeakMap,Sr=new WeakMap,Mn=new WeakMap;function Fn(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function Kn(e){return e.__v_skip||!Object.isExtensible(e)?0:Fn(gt(e))}function Ie(e){return e&&e.__v_isReadonly?e:$r(e,!1,Tr,Ln,Er)}function Ar(e){return $r(e,!0,Cr,$n,Sr)}function $r(e,t,r,n,i){if(!ue(e))return console.warn(`value cannot be made reactive: ${String(e)}`),e;if(e.__v_raw&&!(t&&e.__v_isReactive))return e;let o=i.get(e);if(o)return o;let s=Kn(e);if(s===0)return e;let a=new Proxy(e,s===2?n:r);return i.set(e,a),a}function g(e){return e&&g(e.__v_raw)||e}function wt(e){return Boolean(e&&e.__v_isRef===!0)}b("nextTick",()=>X);b("dispatch",e=>z.bind(z,e));b("watch",e=>(t,r)=>{let n=m(e,t),i=!0,o,[s,a]=ge(e);G(e,t,a),s(()=>n(c=>{let l=document.createElement("div");l.dataset.throwAway=c,i?o=c:queueMicrotask(()=>{r(c,o),o=c}),i=!1}))});b("store",fr);b("data",e=>E(N(e)));b("root",e=>P(e));b("refs",e=>(e._x_refs_proxy||(e._x_refs_proxy=E(zn(e))),e._x_refs_proxy));function zn(e){let t=[],r=e;for(;r;)r._x_refs&&t.push(r._x_refs),r=r.parentNode;return t}b("el",e=>e);var Fr=()=>{};Fr.inline=(e,{modifiers:t},{cleanup:r})=>{t.includes("self")?e._x_ignoreSelf=!0:e._x_ignore=!0,r(()=>{t.includes("self")?delete e._x_ignoreSelf:delete e._x_ignore})};d("ignore",Fr);d("effect",(e,{expression:t},{effect:r})=>r(m(e,t)));function pe(e,t,r,n=[]){switch(e._x_bindings||(e._x_bindings=w({})),e._x_bindings[t]=r,t=n.includes("camel")?Un(t):t,t){case"value":Vn(e,r);break;case"style":Hn(e,r);break;case"class":Bn(e,r);break;default:qn(e,t,r);break}}function Vn(e,t){if(e.type==="radio")e.attributes.value===void 0&&(e.value=t),window.fromModel&&(e.checked=Kr(e.value,t));else if(e.type==="checkbox")Number.isInteger(t)?e.value=t:!Number.isInteger(t)&&!Array.isArray(t)&&typeof t!="boolean"&&![null,void 0].includes(t)?e.value=String(t):Array.isArray(t)?e.checked=t.some(r=>Kr(r,e.value)):e.checked=!!t;else if(e.tagName==="SELECT")Wn(e,t);else{if(e.value===t)return;e.value=t}}function Bn(e,t){e._x_undoAddedClasses&&e._x_undoAddedClasses(),e._x_undoAddedClasses=se(e,t)}function Hn(e,t){e._x_undoAddedStyles&&e._x_undoAddedStyles(),e._x_undoAddedStyles=V(e,t)}function qn(e,t,r){[null,void 0,!1].includes(r)&&Jn(t)?e.removeAttribute(t):(Yn(t)&&(r=t),Gn(e,t,r))}function Gn(e,t,r){e.getAttribute(t)!=r&&e.setAttribute(t,r)}function Wn(e,t){let r=[].concat(t).map(n=>n+"");Array.from(e.options).forEach(n=>{n.selected=r.includes(n.value)})}function Un(e){return e.toLowerCase().replace(/-(\w)/g,(t,r)=>r.toUpperCase())}function Kr(e,t){return e==t}function Yn(e){return["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"].includes(e)}function Jn(e){return!["aria-pressed","aria-checked","aria-expanded"].includes(e)}function de(e,t,r,n){let i=e,o=c=>n(c),s={},a=(c,l)=>u=>l(c,u);if(r.includes("dot")&&(t=Zn(t)),r.includes("camel")&&(t=Qn(t)),r.includes("passive")&&(s.passive=!0),r.includes("capture")&&(s.capture=!0),r.includes("window")&&(i=window),r.includes("document")&&(i=document),r.includes("prevent")&&(o=a(o,(c,l)=>{l.preventDefault(),c(l)})),r.includes("stop")&&(o=a(o,(c,l)=>{l.stopPropagation(),c(l)})),r.includes("self")&&(o=a(o,(c,l)=>{l.target===e&&c(l)})),(r.includes("away")||r.includes("outside"))&&(i=document,o=a(o,(c,l)=>{e.contains(l.target)||e.offsetWidth<1&&e.offsetHeight<1||e._x_isShown!==!1&&c(l)})),o=a(o,(c,l)=>{Xn(t)&&ei(l,r)||c(l)}),r.includes("debounce")){let c=r[r.indexOf("debounce")+1]||"invalid-wait",l=Ot(c.split("ms")[0])?Number(c.split("ms")[0]):250;o=Ce(o,l)}if(r.includes("throttle")){let c=r[r.indexOf("throttle")+1]||"invalid-wait",l=Ot(c.split("ms")[0])?Number(c.split("ms")[0]):250;o=Re(o,l)}return r.includes("once")&&(o=a(o,(c,l)=>{c(l),i.removeEventListener(t,o,s)})),i.addEventListener(t,o,s),()=>{i.removeEventListener(t,o,s)}}function Zn(e){return e.replace(/-/g,".")}function Qn(e){return e.toLowerCase().replace(/-(\w)/g,(t,r)=>r.toUpperCase())}function Ot(e){return!Array.isArray(e)&&!isNaN(e)}function ti(e){return e.replace(/([a-z])([A-Z])/g,"$1-$2").replace(/[_\s]/,"-").toLowerCase()}function Xn(e){return["keydown","keyup"].includes(e)}function ei(e,t){let r=t.filter(o=>!["window","document","prevent","stop","once"].includes(o));if(r.includes("debounce")){let o=r.indexOf("debounce");r.splice(o,Ot((r[o+1]||"invalid-wait").split("ms")[0])?2:1)}if(r.length===0||r.length===1&&zr(e.key).includes(r[0]))return!1;let i=["ctrl","shift","alt","meta","cmd","super"].filter(o=>r.includes(o));return r=r.filter(o=>!i.includes(o)),!(i.length>0&&i.filter(s=>((s==="cmd"||s==="super")&&(s="meta"),e[`${s}Key`])).length===i.length&&zr(e.key).includes(r[0]))}function zr(e){if(!e)return[];e=ti(e);let t={ctrl:"control",slash:"/",space:"-",spacebar:"-",cmd:"meta",esc:"escape",up:"arrow-up",down:"arrow-down",left:"arrow-left",right:"arrow-right",period:".",equal:"="};return t[e]=e,Object.keys(t).map(r=>{if(t[r]===e)return r}).filter(r=>r)}d("model",(e,{modifiers:t,expression:r},{effect:n,cleanup:i})=>{let o=m(e,r),s=`${r} = rightSideOfExpression($event, ${r})`,a=m(e,s);var c=e.tagName.toLowerCase()==="select"||["checkbox","radio"].includes(e.type)||t.includes("lazy")?"change":"input";let l=ri(e,t,r),u=de(e,c,t,y=>{a(()=>{},{scope:{$event:y,rightSideOfExpression:l}})});i(()=>u());let p=m(e,`${r} = __placeholder`);e._x_model={get(){let y;return o(R=>y=R),y},set(y){p(()=>{},{scope:{__placeholder:y}})}},e._x_forceModelUpdate=()=>{o(y=>{y===void 0&&r.match(/\./)&&(y=""),window.fromModel=!0,h(()=>pe(e,"value",y)),delete window.fromModel})},n(()=>{t.includes("unintrusive")&&document.activeElement.isSameNode(e)||e._x_forceModelUpdate()})});function ri(e,t,r){return e.type==="radio"&&h(()=>{e.hasAttribute("name")||e.setAttribute("name",r)}),(n,i)=>h(()=>{if(n instanceof CustomEvent&&n.detail!==void 0)return n.detail||n.target.value;if(e.type==="checkbox")if(Array.isArray(i)){let o=t.includes("number")?Tt(n.target.value):n.target.value;return n.target.checked?i.concat([o]):i.filter(s=>!ni(s,o))}else return n.target.checked;else{if(e.tagName.toLowerCase()==="select"&&e.multiple)return t.includes("number")?Array.from(n.target.selectedOptions).map(o=>{let s=o.value||o.text;return Tt(s)}):Array.from(n.target.selectedOptions).map(o=>o.value||o.text);{let o=n.target.value;return t.includes("number")?Tt(o):t.includes("trim")?o.trim():o}}})}function Tt(e){let t=e?parseFloat(e):null;return ii(t)?t:e}function ni(e,t){return e==t}function ii(e){return!Array.isArray(e)&&!isNaN(e)}d("cloak",e=>queueMicrotask(()=>h(()=>e.removeAttribute(O("cloak")))));nr(()=>`[${O("init")}]`);d("init",I((e,{expression:t})=>typeof t=="string"?!!t.trim()&&v(e,t,{},!1):v(e,t,{},!1)));d("text",(e,{expression:t},{effect:r,evaluateLater:n})=>{let i=n(t);r(()=>{i(o=>{h(()=>{e.textContent=o})})})});d("html",(e,{expression:t},{effect:r,evaluateLater:n})=>{let i=n(t);r(()=>{i(o=>{e.innerHTML=o})})});Q(ve(":",we(O("bind:"))));d("bind",(e,{value:t,modifiers:r,expression:n,original:i},{effect:o})=>{if(!t)return oi(e,n,i,o);if(t==="key")return si(e,n);let s=m(e,n);o(()=>s(a=>{a===void 0&&n.match(/\./)&&(a=""),h(()=>pe(e,t,a,r))}))});function oi(e,t,r,n){let i=m(e,t),o=[];n(()=>{for(;o.length;)o.pop()();i(s=>{let a=Object.entries(s).map(([l,u])=>({name:l,value:u}));a=a.filter(l=>!(typeof l.value=="object"&&!Array.isArray(l.value)&&l.value!==null));let c=Wt(a);a=a.map(l=>c.find(u=>u.name===l.name)?{name:`x-bind:${l.name}`,value:`"${l.value}"`}:l),ie(e,a,r).map(l=>{o.push(l.runCleanups),l()})})})}function si(e,t){e._x_keyExpression=t}Oe(()=>`[${O("data")}]`);d("data",I((e,{expression:t},{cleanup:r})=>{t=t===""?"{}":t;let n={},i=K(n,e).cleanup,o={};hr(o,n);let s=v(e,t,{scope:o});s===void 0&&(s={});let a=K(s,e).cleanup,c=w(s);ye(c);let l=Y(e,c);c.init&&v(e,c.init),r(()=>{l(),i(),a(),c.destroy&&v(e,c.destroy)})}));d("show",(e,{modifiers:t,expression:r},{effect:n})=>{let i=m(e,r),o=()=>h(()=>{e.style.display="none",e._x_isShown=!1}),s=()=>h(()=>{e.style.length===1&&e.style.display==="none"?e.removeAttribute("style"):e.style.removeProperty("display"),e._x_isShown=!0}),a=()=>setTimeout(s),c=ae(p=>p?s():o(),p=>{typeof e._x_toggleAndCascadeWithTransitions=="function"?e._x_toggleAndCascadeWithTransitions(e,p,s,o):p?a():o()}),l,u=!0;n(()=>i(p=>{!u&&p===l||(t.includes("immediate")&&(p?a():o()),c(p),l=p,u=!1)}))});d("for",(e,{expression:t},{effect:r,cleanup:n})=>{let i=ci(t),o=m(e,i.items),s=m(e,e._x_keyExpression||"index");e._x_prevKeys=[],e._x_lookup={},r(()=>ai(e,i,o,s)),n(()=>{Object.values(e._x_lookup).forEach(a=>a.remove()),delete e._x_prevKeys,delete e._x_lookup})});function ai(e,t,r,n){let i=s=>typeof s=="object"&&!Array.isArray(s),o=e;r(s=>{li(s)&&s>=0&&(s=Array.from(Array(s).keys(),f=>f+1)),s===void 0&&(s=[]);let a=e._x_lookup,c=e._x_prevKeys,l=[],u=[];if(i(s))s=Object.entries(s).map(([f,_])=>{let x=Vr(t,_,f,s);n(M=>u.push(M),{scope:{index:f,...x}}),l.push(x)});else for(let f=0;f<s.length;f++){let _=Vr(t,s[f],f,s);n(x=>u.push(x),{scope:{index:f,..._}}),l.push(_)}let p=[],y=[],R=[],q=[];for(let f=0;f<c.length;f++){let _=c[f];u.indexOf(_)===-1&&R.push(_)}c=c.filter(f=>!R.includes(f));let me="template";for(let f=0;f<u.length;f++){let _=u[f],x=c.indexOf(_);if(x===-1)c.splice(f,0,_),p.push([me,f]);else if(x!==f){let M=c.splice(f,1)[0],k=c.splice(x-1,1)[0];c.splice(f,0,k),c.splice(x,0,M),y.push([M,k])}else q.push(_);me=_}for(let f=0;f<R.length;f++){let _=R[f];a[_].remove(),a[_]=null,delete a[_]}for(let f=0;f<y.length;f++){let[_,x]=y[f],M=a[_],k=a[x],U=document.createElement("div");h(()=>{k.after(U),M.after(k),U.before(M),U.remove()}),rt(k,l[u.indexOf(x)])}for(let f=0;f<p.length;f++){let[_,x]=p[f],M=_==="template"?o:a[_],k=l[x],U=u[x],he=document.importNode(o.content,!0).firstElementChild;Y(he,w(k),o),h(()=>{M.after(he),T(he)}),typeof U=="object"&&Ae("x-for key cannot be an object, it must be a string or an integer",o),a[U]=he}for(let f=0;f<q.length;f++)rt(a[q[f]],l[u.indexOf(q[f])]);o._x_prevKeys=u})}function ci(e){let t=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,r=/^\s*\(|\)\s*$/g,n=/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/,i=e.match(n);if(!i)return;let o={};o.items=i[2].trim();let s=i[1].replace(r,"").trim(),a=s.match(t);return a?(o.item=s.replace(t,"").trim(),o.index=a[1].trim(),a[2]&&(o.collection=a[2].trim())):o.item=s,o}function Vr(e,t,r,n){let i={};return/^\[.*\]$/.test(e.item)&&Array.isArray(t)?e.item.replace("[","").replace("]","").split(",").map(s=>s.trim()).forEach((s,a)=>{i[s]=t[a]}):/^\{.*\}$/.test(e.item)&&!Array.isArray(t)&&typeof t=="object"?e.item.replace("{","").replace("}","").split(",").map(s=>s.trim()).forEach(s=>{i[s]=t[s]}):i[e.item]=t,e.index&&(i[e.index]=r),e.collection&&(i[e.collection]=n),i}function li(e){return!Array.isArray(e)&&!isNaN(e)}function Br(){}Br.inline=(e,{expression:t},{cleanup:r})=>{let n=P(e);n._x_refs||(n._x_refs={}),n._x_refs[t]=e,r(()=>delete n._x_refs[t])};d("ref",Br);d("if",(e,{expression:t},{effect:r,cleanup:n})=>{let i=m(e,t),o=()=>{if(e._x_currentIfEl)return e._x_currentIfEl;let a=e.content.cloneNode(!0).firstElementChild;return Y(a,{},e),h(()=>{e.after(a),T(a)}),e._x_currentIfEl=a,e._x_undoIf=()=>{a.remove(),delete e._x_currentIfEl},a},s=()=>{!e._x_undoIf||(e._x_undoIf(),delete e._x_undoIf)};r(()=>i(a=>{a?o():s()})),n(()=>e._x_undoIf&&e._x_undoIf())});Q(ve("@",we(O("on:"))));d("on",I((e,{value:t,modifiers:r,expression:n},{cleanup:i})=>{let o=n?m(e,n):()=>{},s=de(e,t,r,a=>{o(()=>{},{scope:{$event:a},params:[a]})});i(()=>s())}));A.setEvaluator(ui);A.setReactivityEngine({reactive:Ie,effect:yr,release:br,raw:g});function ui(e,t){let r={};K(r,e);let n=[r,...N(e)];if(typeof t=="function")return it(n,t);let i=(o=()=>{},{scope:s={},params:a=[]}={})=>{let c=E([s,...n]);c[t]!==void 0&&Z(o,c[t],c,a)};return be.bind(null,e,t,i)}var Ct=A;window.Alpine=Ct;queueMicrotask(()=>{Ct.start()});})();
+`:""}`,t),setTimeout(()=>{throw e},0)}function I(e,t,r={}){let n;return g(e,t)(i=>n=i,r),n}function g(...e){return Gt(...e)}var Gt=un;function Yt(e){Gt=e}function un(e,t){let r={},n=B(r,e).cleanup;xe(e,"evaluator",n);let i=[r,...T(e)];if(typeof t=="function")return lt(i,t);let o=fn(i,t,e);return Ee.bind(null,e,t,o)}function lt(e,t){return(r=()=>{},{scope:n={},params:i=[]}={})=>{let o=t.apply(C([n,...e]),i);Q(r,o)}}var ut={};function dn(e,t){if(ut[e])return ut[e];let r=Object.getPrototypeOf(async function(){}).constructor,n=/^[\n\s]*if.*\(.*\)/.test(e)||/^(let|const)\s/.test(e)?`(() => { ${e} })()`:e,o=(()=>{try{return new r(["__self","scope"],`with (scope) { __self.result = ${n} }; __self.finished = true; return __self.result;`)}catch(s){return Z(s,t,e),Promise.resolve()}})();return ut[e]=o,o}function fn(e,t,r){let n=dn(t,r);return(i=()=>{},{scope:o={},params:s=[]}={})=>{n.result=void 0,n.finished=!1;let a=C([o,...e]);if(typeof n=="function"){let c=n(n,a).catch(l=>Z(l,r,t));n.finished?(Q(i,n.result,a,s,r),n.result=void 0):c.then(l=>{Q(i,l,a,s,r)}).catch(l=>Z(l,r,t)).finally(()=>n.result=void 0)}}}function Q(e,t,r,n,i){if(typeof t=="function"){let o=t.apply(r,n);o instanceof Promise?o.then(s=>Q(e,s,r,n)).catch(s=>Z(s,i,t)):e(o)}else e(t)}var ft="x-";function w(e=""){return ft+e}function Jt(e){ft=e}var Zt={};function p(e,t){Zt[e]=t}function ie(e,t,r){let n={};return Array.from(t).map(Qt((o,s)=>n[o]=s)).filter(Xt).map(mn(n,r)).sort(hn).map(o=>pn(e,o))}function er(e){return Array.from(e).map(Qt()).filter(t=>!Xt(t))}var dt=!1,oe=new Map,tr=Symbol();function rr(e){dt=!0;let t=Symbol();tr=t,oe.set(t,[]);let r=()=>{for(;oe.get(t).length;)oe.get(t).shift()();oe.delete(t)},n=()=>{dt=!1,r()};e(r),n()}function ct(e){let t=[],r=a=>t.push(a),[n,i]=Ft(e);return t.push(i),[{Alpine:P,effect:n,cleanup:r,evaluateLater:g.bind(g,e),evaluate:I.bind(I,e)},()=>t.forEach(a=>a())]}function pn(e,t){let r=()=>{},n=Zt[t.type]||r,[i,o]=ct(e);xe(e,t.original,o);let s=()=>{e._x_ignore||e._x_ignoreSelf||(n.inline&&n.inline(e,t,i),n=n.bind(n,e,t,i),dt?oe.get(tr).push(n):n())};return s.runCleanups=o,s}var Se=(e,t)=>({name:r,value:n})=>(r.startsWith(e)&&(r=r.replace(e,t)),{name:r,value:n}),Ae=e=>e;function Qt(e=()=>{}){return({name:t,value:r})=>{let{name:n,value:i}=nr.reduce((o,s)=>s(o),{name:t,value:r});return n!==t&&e(n,t),{name:n,value:i}}}var nr=[];function X(e){nr.push(e)}function Xt({name:e}){return ir().test(e)}var ir=()=>new RegExp(`^${ft}([^:^.]+)\\b`);function mn(e,t){return({name:r,value:n})=>{let i=r.match(ir()),o=r.match(/:([a-zA-Z0-9\-:]+)/),s=r.match(/\.[^.\]]+(?=[^\]]*$)/g)||[],a=t||e[r]||r;return{type:i?i[1]:null,value:o?o[1]:null,modifiers:s.map(c=>c.replace(".","")),expression:n,original:a}}}var pt="DEFAULT",Oe=["ignore","ref","data","id","bind","init","for","model","modelable","transition","show","if",pt,"teleport","element"];function hn(e,t){let r=Oe.indexOf(e.type)===-1?pt:e.type,n=Oe.indexOf(t.type)===-1?pt:t.type;return Oe.indexOf(r)-Oe.indexOf(n)}function z(e,t,r={}){e.dispatchEvent(new CustomEvent(t,{detail:r,bubbles:!0,composed:!0,cancelable:!0}))}var mt=[],ht=!1;function Ce(e){mt.push(e),queueMicrotask(()=>{ht||setTimeout(()=>{Te()})})}function Te(){for(ht=!1;mt.length;)mt.shift()()}function or(){ht=!0}function M(e,t){if(typeof ShadowRoot=="function"&&e instanceof ShadowRoot){Array.from(e.children).forEach(i=>M(i,t));return}let r=!1;if(t(e,()=>r=!0),r)return;let n=e.firstElementChild;for(;n;)M(n,t,!1),n=n.nextElementSibling}function V(e,...t){console.warn(`Alpine Warning: ${e}`,...t)}function ar(){document.body||V("Unable to initialize. Trying to load Alpine before `<body>` is available. Did you forget to add `defer` in Alpine's `<script>` tag?"),z(document,"alpine:init"),z(document,"alpine:initializing"),rt(),Vt(t=>E(t,M)),ge(t=>_t(t)),Ht((t,r)=>{ie(t,r).forEach(n=>n())});let e=t=>!H(t.parentElement,!0);Array.from(document.querySelectorAll(sr())).filter(e).forEach(t=>{E(t)}),z(document,"alpine:initialized")}var gt=[],cr=[];function lr(){return gt.map(e=>e())}function sr(){return gt.concat(cr).map(e=>e())}function Re(e){gt.push(e)}function Me(e){cr.push(e)}function H(e,t=!1){return ee(e,r=>{if((t?sr():lr()).some(i=>r.matches(i)))return!0})}function ee(e,t){if(!!e){if(t(e))return e;if(e._x_teleportBack&&(e=e._x_teleportBack),!!e.parentElement)return ee(e.parentElement,t)}}function ur(e){return lr().some(t=>e.matches(t))}function E(e,t=M){rr(()=>{t(e,(r,n)=>{ie(r,r.attributes).forEach(i=>i()),r._x_ignore&&n()})})}function _t(e){M(e,t=>Qe(t))}function se(e,t){return Array.isArray(t)?fr(e,t.join(" ")):typeof t=="object"&&t!==null?_n(e,t):typeof t=="function"?se(e,t()):fr(e,t)}function fr(e,t){let r=o=>o.split(" ").filter(Boolean),n=o=>o.split(" ").filter(s=>!e.classList.contains(s)).filter(Boolean),i=o=>(e.classList.add(...o),()=>{e.classList.remove(...o)});return t=t===!0?t="":t||"",i(n(t))}function _n(e,t){let r=a=>a.split(" ").filter(Boolean),n=Object.entries(t).flatMap(([a,c])=>c?r(a):!1).filter(Boolean),i=Object.entries(t).flatMap(([a,c])=>c?!1:r(a)).filter(Boolean),o=[],s=[];return i.forEach(a=>{e.classList.contains(a)&&(e.classList.remove(a),s.push(a))}),n.forEach(a=>{e.classList.contains(a)||(e.classList.add(a),o.push(a))}),()=>{s.forEach(a=>e.classList.add(a)),o.forEach(a=>e.classList.remove(a))}}function q(e,t){return typeof t=="object"&&t!==null?gn(e,t):xn(e,t)}function gn(e,t){let r={};return Object.entries(t).forEach(([n,i])=>{r[n]=e.style[n],n.startsWith("--")||(n=yn(n)),e.style.setProperty(n,i)}),setTimeout(()=>{e.style.length===0&&e.removeAttribute("style")}),()=>{q(e,r)}}function xn(e,t){let r=e.getAttribute("style",t);return e.setAttribute("style",t),()=>{e.setAttribute("style",r||"")}}function yn(e){return e.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()}function ae(e,t=()=>{}){let r=!1;return function(){r?t.apply(this,arguments):(r=!0,e.apply(this,arguments))}}p("transition",(e,{value:t,modifiers:r,expression:n},{evaluate:i})=>{typeof n=="function"&&(n=i(n)),n?bn(e,n,t):vn(e,r,t)});function bn(e,t,r){dr(e,se,""),{enter:i=>{e._x_transition.enter.during=i},"enter-start":i=>{e._x_transition.enter.start=i},"enter-end":i=>{e._x_transition.enter.end=i},leave:i=>{e._x_transition.leave.during=i},"leave-start":i=>{e._x_transition.leave.start=i},"leave-end":i=>{e._x_transition.leave.end=i}}[r](t)}function vn(e,t,r){dr(e,q);let n=!t.includes("in")&&!t.includes("out")&&!r,i=n||t.includes("in")||["enter"].includes(r),o=n||t.includes("out")||["leave"].includes(r);t.includes("in")&&!n&&(t=t.filter((h,b)=>b<t.indexOf("out"))),t.includes("out")&&!n&&(t=t.filter((h,b)=>b>t.indexOf("out")));let s=!t.includes("opacity")&&!t.includes("scale"),a=s||t.includes("opacity"),c=s||t.includes("scale"),l=a?0:1,u=c?ce(t,"scale",95)/100:1,d=ce(t,"delay",0),x=ce(t,"origin","center"),k="opacity, transform",G=ce(t,"duration",150)/1e3,me=ce(t,"duration",75)/1e3,f="cubic-bezier(0.4, 0.0, 0.2, 1)";i&&(e._x_transition.enter.during={transformOrigin:x,transitionDelay:d,transitionProperty:k,transitionDuration:`${G}s`,transitionTimingFunction:f},e._x_transition.enter.start={opacity:l,transform:`scale(${u})`},e._x_transition.enter.end={opacity:1,transform:"scale(1)"}),o&&(e._x_transition.leave.during={transformOrigin:x,transitionDelay:d,transitionProperty:k,transitionDuration:`${me}s`,transitionTimingFunction:f},e._x_transition.leave.start={opacity:1,transform:"scale(1)"},e._x_transition.leave.end={opacity:l,transform:`scale(${u})`})}function dr(e,t,r={}){e._x_transition||(e._x_transition={enter:{during:r,start:r,end:r},leave:{during:r,start:r,end:r},in(n=()=>{},i=()=>{}){Ne(e,t,{during:this.enter.during,start:this.enter.start,end:this.enter.end},n,i)},out(n=()=>{},i=()=>{}){Ne(e,t,{during:this.leave.during,start:this.leave.start,end:this.leave.end},n,i)}})}window.Element.prototype._x_toggleAndCascadeWithTransitions=function(e,t,r,n){let i=()=>{document.visibilityState==="visible"?requestAnimationFrame(r):setTimeout(r)};if(t){e._x_transition&&(e._x_transition.enter||e._x_transition.leave)?e._x_transition.enter&&(Object.entries(e._x_transition.enter.during).length||Object.entries(e._x_transition.enter.start).length||Object.entries(e._x_transition.enter.end).length)?e._x_transition.in(r):i():e._x_transition?e._x_transition.in(r):i();return}e._x_hidePromise=e._x_transition?new Promise((o,s)=>{e._x_transition.out(()=>{},()=>o(n)),e._x_transitioning.beforeCancel(()=>s({isFromCancelledTransition:!0}))}):Promise.resolve(n),queueMicrotask(()=>{let o=pr(e);o?(o._x_hideChildren||(o._x_hideChildren=[]),o._x_hideChildren.push(e)):queueMicrotask(()=>{let s=a=>{let c=Promise.all([a._x_hidePromise,...(a._x_hideChildren||[]).map(s)]).then(([l])=>l());return delete a._x_hidePromise,delete a._x_hideChildren,c};s(e).catch(a=>{if(!a.isFromCancelledTransition)throw a})})})};function pr(e){let t=e.parentNode;if(!!t)return t._x_hidePromise?t:pr(t)}function Ne(e,t,{during:r,start:n,end:i}={},o=()=>{},s=()=>{}){if(e._x_transitioning&&e._x_transitioning.cancel(),Object.keys(r).length===0&&Object.keys(n).length===0&&Object.keys(i).length===0){o(),s();return}let a,c,l;wn(e,{start(){a=t(e,n)},during(){c=t(e,r)},before:o,end(){a(),l=t(e,i)},after:s,cleanup(){c(),l()}})}function wn(e,t){let r,n,i,o=ae(()=>{m(()=>{r=!0,n||t.before(),i||(t.end(),Te()),t.after(),e.isConnected&&t.cleanup(),delete e._x_transitioning})});e._x_transitioning={beforeCancels:[],beforeCancel(s){this.beforeCancels.push(s)},cancel:ae(function(){for(;this.beforeCancels.length;)this.beforeCancels.shift()();o()}),finish:o},m(()=>{t.start(),t.during()}),or(),requestAnimationFrame(()=>{if(r)return;let s=Number(getComputedStyle(e).transitionDuration.replace(/,.*/,"").replace("s",""))*1e3,a=Number(getComputedStyle(e).transitionDelay.replace(/,.*/,"").replace("s",""))*1e3;s===0&&(s=Number(getComputedStyle(e).animationDuration.replace("s",""))*1e3),m(()=>{t.before()}),n=!0,requestAnimationFrame(()=>{r||(m(()=>{t.end()}),Te(),setTimeout(e._x_transitioning.finish,s+a),i=!0)})})}function ce(e,t,r){if(e.indexOf(t)===-1)return r;let n=e[e.indexOf(t)+1];if(!n||t==="scale"&&isNaN(n))return r;if(t==="duration"){let i=n.match(/([0-9]+)ms/);if(i)return i[1]}return t==="origin"&&["top","right","left","center","bottom"].includes(e[e.indexOf(t)+2])?[n,e[e.indexOf(t)+2]].join(" "):n}var xt=!1;function D(e,t=()=>{}){return(...r)=>xt?t(...r):e(...r)}function mr(e,t){t._x_dataStack||(t._x_dataStack=e._x_dataStack),xt=!0,Sn(()=>{En(t)}),xt=!1}function En(e){let t=!1;E(e,(n,i)=>{M(n,(o,s)=>{if(t&&ur(o))return s();t=!0,i(o,s)})})}function Sn(e){let t=K;Ze((r,n)=>{let i=t(r);return J(i),()=>{}}),e(),Ze(t)}function le(e,t,r,n=[]){switch(e._x_bindings||(e._x_bindings=A({})),e._x_bindings[t]=r,t=n.includes("camel")?Rn(t):t,t){case"value":An(e,r);break;case"style":Tn(e,r);break;case"class":On(e,r);break;default:Cn(e,t,r);break}}function An(e,t){if(e.type==="radio")e.attributes.value===void 0&&(e.value=t),window.fromModel&&(e.checked=hr(e.value,t));else if(e.type==="checkbox")Number.isInteger(t)?e.value=t:!Number.isInteger(t)&&!Array.isArray(t)&&typeof t!="boolean"&&![null,void 0].includes(t)?e.value=String(t):Array.isArray(t)?e.checked=t.some(r=>hr(r,e.value)):e.checked=!!t;else if(e.tagName==="SELECT")Mn(e,t);else{if(e.value===t)return;e.value=t}}function On(e,t){e._x_undoAddedClasses&&e._x_undoAddedClasses(),e._x_undoAddedClasses=se(e,t)}function Tn(e,t){e._x_undoAddedStyles&&e._x_undoAddedStyles(),e._x_undoAddedStyles=q(e,t)}function Cn(e,t,r){[null,void 0,!1].includes(r)&&kn(t)?e.removeAttribute(t):(_r(t)&&(r=t),Nn(e,t,r))}function Nn(e,t,r){e.getAttribute(t)!=r&&e.setAttribute(t,r)}function Mn(e,t){let r=[].concat(t).map(n=>n+"");Array.from(e.options).forEach(n=>{n.selected=r.includes(n.value)})}function Rn(e){return e.toLowerCase().replace(/-(\w)/g,(t,r)=>r.toUpperCase())}function hr(e,t){return e==t}function _r(e){return["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"].includes(e)}function kn(e){return!["aria-pressed","aria-checked","aria-expanded","aria-selected"].includes(e)}function gr(e,t,r){if(e._x_bindings&&e._x_bindings[t]!==void 0)return e._x_bindings[t];let n=e.getAttribute(t);return n===null?typeof r=="function"?r():r:_r(t)?!![t,"true"].includes(n):n===""?!0:n}function ke(e,t){var r;return function(){var n=this,i=arguments,o=function(){r=null,e.apply(n,i)};clearTimeout(r),r=setTimeout(o,t)}}function Ie(e,t){let r;return function(){let n=this,i=arguments;r||(e.apply(n,i),r=!0,setTimeout(()=>r=!1,t))}}function xr(e){e(P)}var U={},yr=!1;function br(e,t){if(yr||(U=A(U),yr=!0),t===void 0)return U[e];U[e]=t,typeof t=="object"&&t!==null&&t.hasOwnProperty("init")&&typeof t.init=="function"&&U[e].init(),ve(U[e])}function vr(){return U}var wr={};function Er(e,t){wr[e]=typeof t!="function"?()=>t:t}function Sr(e){return Object.entries(wr).forEach(([t,r])=>{Object.defineProperty(e,t,{get(){return(...n)=>r(...n)}})}),e}var Ar={};function Or(e,t){Ar[e]=t}function Tr(e,t){return Object.entries(Ar).forEach(([r,n])=>{Object.defineProperty(e,r,{get(){return(...i)=>n.bind(t)(...i)},enumerable:!1})}),e}var In={get reactive(){return A},get release(){return J},get effect(){return K},get raw(){return Ye},version:"3.9.1",flushAndStopDeferringMutations:Ut,disableEffectScheduling:jt,stopObservingMutations:nt,destroyTree:_t,setReactivityEngine:Lt,closestDataStack:T,skipDuringClone:D,addRootSelector:Re,addInitSelector:Me,addScopeToNode:R,deferMutations:qt,mapAttributes:X,evaluateLater:g,setEvaluator:Yt,mergeProxies:C,findClosest:ee,closestRoot:H,interceptor:we,transition:Ne,setStyles:q,mutateDom:m,directive:p,throttle:Ie,debounce:ke,evaluate:I,initTree:E,nextTick:Ce,prefixed:w,prefix:Jt,plugin:xr,magic:y,store:br,start:ar,clone:mr,bound:gr,$data:be,data:Or,bind:Er},P=In;function yt(e,t){let r=Object.create(null),n=e.split(",");for(let i=0;i<n.length;i++)r[n[i]]=!0;return t?i=>!!r[i.toLowerCase()]:i=>!!r[i]}var es={[1]:"TEXT",[2]:"CLASS",[4]:"STYLE",[8]:"PROPS",[16]:"FULL_PROPS",[32]:"HYDRATE_EVENTS",[64]:"STABLE_FRAGMENT",[128]:"KEYED_FRAGMENT",[256]:"UNKEYED_FRAGMENT",[512]:"NEED_PATCH",[1024]:"DYNAMIC_SLOTS",[2048]:"DEV_ROOT_FRAGMENT",[-1]:"HOISTED",[-2]:"BAIL"},ts={[1]:"STABLE",[2]:"DYNAMIC",[3]:"FORWARDED"};var Pn="itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly";var rs=yt(Pn+",async,autofocus,autoplay,controls,default,defer,disabled,hidden,loop,open,required,reversed,scoped,seamless,checked,muted,multiple,selected");var Cr=Object.freeze({}),ns=Object.freeze([]);var bt=Object.assign;var Dn=Object.prototype.hasOwnProperty,ue=(e,t)=>Dn.call(e,t),$=Array.isArray,te=e=>Rr(e)==="[object Map]";var $n=e=>typeof e=="string",Pe=e=>typeof e=="symbol",fe=e=>e!==null&&typeof e=="object";var jn=Object.prototype.toString,Rr=e=>jn.call(e),vt=e=>Rr(e).slice(8,-1);var De=e=>$n(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e;var $e=e=>{let t=Object.create(null);return r=>t[r]||(t[r]=e(r))},Ln=/-(\w)/g,is=$e(e=>e.replace(Ln,(t,r)=>r?r.toUpperCase():"")),Fn=/\B([A-Z])/g,os=$e(e=>e.replace(Fn,"-$1").toLowerCase()),wt=$e(e=>e.charAt(0).toUpperCase()+e.slice(1)),ss=$e(e=>e?`on${wt(e)}`:""),Et=(e,t)=>e!==t&&(e===e||t===t);var St=new WeakMap,de=[],N,W=Symbol("iterate"),At=Symbol("Map key iterate");function Kn(e){return e&&e._isEffect===!0}function Mr(e,t=Cr){Kn(e)&&(e=e.raw);let r=Bn(e,t);return t.lazy||r(),r}function kr(e){e.active&&(Nr(e),e.options.onStop&&e.options.onStop(),e.active=!1)}var zn=0;function Bn(e,t){let r=function(){if(!r.active)return e();if(!de.includes(r)){Nr(r);try{return Vn(),de.push(r),N=r,e()}finally{de.pop(),Ir(),N=de[de.length-1]}}};return r.id=zn++,r.allowRecurse=!!t.allowRecurse,r._isEffect=!0,r.active=!0,r.raw=e,r.deps=[],r.options=t,r}function Nr(e){let{deps:t}=e;if(t.length){for(let r=0;r<t.length;r++)t[r].delete(e);t.length=0}}var re=!0,Ot=[];function Hn(){Ot.push(re),re=!1}function Vn(){Ot.push(re),re=!0}function Ir(){let e=Ot.pop();re=e===void 0?!0:e}function O(e,t,r){if(!re||N===void 0)return;let n=St.get(e);n||St.set(e,n=new Map);let i=n.get(r);i||n.set(r,i=new Set),i.has(N)||(i.add(N),N.deps.push(i),N.options.onTrack&&N.options.onTrack({effect:N,target:e,type:t,key:r}))}function j(e,t,r,n,i,o){let s=St.get(e);if(!s)return;let a=new Set,c=u=>{u&&u.forEach(d=>{(d!==N||d.allowRecurse)&&a.add(d)})};if(t==="clear")s.forEach(c);else if(r==="length"&&$(e))s.forEach((u,d)=>{(d==="length"||d>=n)&&c(u)});else switch(r!==void 0&&c(s.get(r)),t){case"add":$(e)?De(r)&&c(s.get("length")):(c(s.get(W)),te(e)&&c(s.get(At)));break;case"delete":$(e)||(c(s.get(W)),te(e)&&c(s.get(At)));break;case"set":te(e)&&c(s.get(W));break}let l=u=>{u.options.onTrigger&&u.options.onTrigger({effect:u,target:e,key:r,type:t,newValue:n,oldValue:i,oldTarget:o}),u.options.scheduler?u.options.scheduler(u):u()};a.forEach(l)}var qn=yt("__proto__,__v_isRef,__isVue"),Pr=new Set(Object.getOwnPropertyNames(Symbol).map(e=>Symbol[e]).filter(Pe)),Un=je(),Wn=je(!1,!0),Gn=je(!0),Yn=je(!0,!0),Le={};["includes","indexOf","lastIndexOf"].forEach(e=>{let t=Array.prototype[e];Le[e]=function(...r){let n=_(this);for(let o=0,s=this.length;o<s;o++)O(n,"get",o+"");let i=t.apply(n,r);return i===-1||i===!1?t.apply(n,r.map(_)):i}});["push","pop","shift","unshift","splice"].forEach(e=>{let t=Array.prototype[e];Le[e]=function(...r){Hn();let n=t.apply(this,r);return Ir(),n}});function je(e=!1,t=!1){return function(n,i,o){if(i==="__v_isReactive")return!e;if(i==="__v_isReadonly")return e;if(i==="__v_raw"&&o===(e?t?Zn:$r:t?Jn:Dr).get(n))return n;let s=$(n);if(!e&&s&&ue(Le,i))return Reflect.get(Le,i,o);let a=Reflect.get(n,i,o);return(Pe(i)?Pr.has(i):qn(i))||(e||O(n,"get",i),t)?a:Tt(a)?!s||!De(i)?a.value:a:fe(a)?e?jr(a):Fe(a):a}}var Qn=Lr(),Xn=Lr(!0);function Lr(e=!1){return function(r,n,i,o){let s=r[n];if(!e&&(i=_(i),s=_(s),!$(r)&&Tt(s)&&!Tt(i)))return s.value=i,!0;let a=$(r)&&De(n)?Number(n)<r.length:ue(r,n),c=Reflect.set(r,n,i,o);return r===_(o)&&(a?Et(i,s)&&j(r,"set",n,i,s):j(r,"add",n,i)),c}}function ei(e,t){let r=ue(e,t),n=e[t],i=Reflect.deleteProperty(e,t);return i&&r&&j(e,"delete",t,void 0,n),i}function ti(e,t){let r=Reflect.has(e,t);return(!Pe(t)||!Pr.has(t))&&O(e,"has",t),r}function ri(e){return O(e,"iterate",$(e)?"length":W),Reflect.ownKeys(e)}var Fr={get:Un,set:Qn,deleteProperty:ei,has:ti,ownKeys:ri},Kr={get:Gn,set(e,t){return console.warn(`Set operation on key "${String(t)}" failed: target is readonly.`,e),!0},deleteProperty(e,t){return console.warn(`Delete operation on key "${String(t)}" failed: target is readonly.`,e),!0}},ds=bt({},Fr,{get:Wn,set:Xn}),ps=bt({},Kr,{get:Yn}),Ct=e=>fe(e)?Fe(e):e,Rt=e=>fe(e)?jr(e):e,Mt=e=>e,Ke=e=>Reflect.getPrototypeOf(e);function Be(e,t,r=!1,n=!1){e=e.__v_raw;let i=_(e),o=_(t);t!==o&&!r&&O(i,"get",t),!r&&O(i,"get",o);let{has:s}=Ke(i),a=n?Mt:r?Rt:Ct;if(s.call(i,t))return a(e.get(t));if(s.call(i,o))return a(e.get(o));e!==i&&e.get(t)}function ze(e,t=!1){let r=this.__v_raw,n=_(r),i=_(e);return e!==i&&!t&&O(n,"has",e),!t&&O(n,"has",i),e===i?r.has(e):r.has(e)||r.has(i)}function Ve(e,t=!1){return e=e.__v_raw,!t&&O(_(e),"iterate",W),Reflect.get(e,"size",e)}function Br(e){e=_(e);let t=_(this);return Ke(t).has.call(t,e)||(t.add(e),j(t,"add",e,e)),this}function Vr(e,t){t=_(t);let r=_(this),{has:n,get:i}=Ke(r),o=n.call(r,e);o?zr(r,n,e):(e=_(e),o=n.call(r,e));let s=i.call(r,e);return r.set(e,t),o?Et(t,s)&&j(r,"set",e,t,s):j(r,"add",e,t),this}function Hr(e){let t=_(this),{has:r,get:n}=Ke(t),i=r.call(t,e);i?zr(t,r,e):(e=_(e),i=r.call(t,e));let o=n?n.call(t,e):void 0,s=t.delete(e);return i&&j(t,"delete",e,void 0,o),s}function qr(){let e=_(this),t=e.size!==0,r=te(e)?new Map(e):new Set(e),n=e.clear();return t&&j(e,"clear",void 0,void 0,r),n}function He(e,t){return function(n,i){let o=this,s=o.__v_raw,a=_(s),c=t?Mt:e?Rt:Ct;return!e&&O(a,"iterate",W),s.forEach((l,u)=>n.call(i,c(l),c(u),o))}}function qe(e,t,r){return function(...n){let i=this.__v_raw,o=_(i),s=te(o),a=e==="entries"||e===Symbol.iterator&&s,c=e==="keys"&&s,l=i[e](...n),u=r?Mt:t?Rt:Ct;return!t&&O(o,"iterate",c?At:W),{next(){let{value:d,done:x}=l.next();return x?{value:d,done:x}:{value:a?[u(d[0]),u(d[1])]:u(d),done:x}},[Symbol.iterator](){return this}}}}function L(e){return function(...t){{let r=t[0]?`on key "${t[0]}" `:"";console.warn(`${wt(e)} operation ${r}failed: target is readonly.`,_(this))}return e==="delete"?!1:this}}var Ur={get(e){return Be(this,e)},get size(){return Ve(this)},has:ze,add:Br,set:Vr,delete:Hr,clear:qr,forEach:He(!1,!1)},Wr={get(e){return Be(this,e,!1,!0)},get size(){return Ve(this)},has:ze,add:Br,set:Vr,delete:Hr,clear:qr,forEach:He(!1,!0)},Gr={get(e){return Be(this,e,!0)},get size(){return Ve(this,!0)},has(e){return ze.call(this,e,!0)},add:L("add"),set:L("set"),delete:L("delete"),clear:L("clear"),forEach:He(!0,!1)},Yr={get(e){return Be(this,e,!0,!0)},get size(){return Ve(this,!0)},has(e){return ze.call(this,e,!0)},add:L("add"),set:L("set"),delete:L("delete"),clear:L("clear"),forEach:He(!0,!0)},ni=["keys","values","entries",Symbol.iterator];ni.forEach(e=>{Ur[e]=qe(e,!1,!1),Gr[e]=qe(e,!0,!1),Wr[e]=qe(e,!1,!0),Yr[e]=qe(e,!0,!0)});function Ue(e,t){let r=t?e?Yr:Wr:e?Gr:Ur;return(n,i,o)=>i==="__v_isReactive"?!e:i==="__v_isReadonly"?e:i==="__v_raw"?n:Reflect.get(ue(r,i)&&i in n?r:n,i,o)}var ii={get:Ue(!1,!1)},ms={get:Ue(!1,!0)},oi={get:Ue(!0,!1)},hs={get:Ue(!0,!0)};function zr(e,t,r){let n=_(r);if(n!==r&&t.call(e,n)){let i=vt(e);console.warn(`Reactive ${i} contains both the raw and reactive versions of the same object${i==="Map"?" as keys":""}, which can lead to inconsistencies. Avoid differentiating between the raw and reactive versions of an object and only use the reactive version if possible.`)}}var Dr=new WeakMap,Jn=new WeakMap,$r=new WeakMap,Zn=new WeakMap;function si(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function ai(e){return e.__v_skip||!Object.isExtensible(e)?0:si(vt(e))}function Fe(e){return e&&e.__v_isReadonly?e:Jr(e,!1,Fr,ii,Dr)}function jr(e){return Jr(e,!0,Kr,oi,$r)}function Jr(e,t,r,n,i){if(!fe(e))return console.warn(`value cannot be made reactive: ${String(e)}`),e;if(e.__v_raw&&!(t&&e.__v_isReactive))return e;let o=i.get(e);if(o)return o;let s=ai(e);if(s===0)return e;let a=new Proxy(e,s===2?n:r);return i.set(e,a),a}function _(e){return e&&_(e.__v_raw)||e}function Tt(e){return Boolean(e&&e.__v_isRef===!0)}y("nextTick",()=>Ce);y("dispatch",e=>z.bind(z,e));y("watch",(e,{evaluateLater:t,effect:r})=>(n,i)=>{let o=t(n),s=!0,a;r(()=>o(c=>{JSON.stringify(c),s?a=c:queueMicrotask(()=>{i(c,a),a=c}),s=!1}))});y("store",vr);y("data",e=>be(e));y("root",e=>H(e));y("refs",e=>(e._x_refs_proxy||(e._x_refs_proxy=C(ci(e))),e._x_refs_proxy));function ci(e){let t=[],r=e;for(;r;)r._x_refs&&t.push(r._x_refs),r=r.parentNode;return t}var Nt={};function kt(e){return Nt[e]||(Nt[e]=0),++Nt[e]}function Zr(e,t){return ee(e,r=>{if(r._x_ids&&r._x_ids[t])return!0})}function Qr(e,t){e._x_ids||(e._x_ids={}),e._x_ids[t]||(e._x_ids[t]=kt(t))}y("id",e=>(t,r=null)=>{let n=Zr(e,t),i=n?n._x_ids[t]:kt(t);return r?`${t}-${i}-${r}`:`${t}-${i}`});y("el",e=>e);p("modelable",(e,{expression:t},{effect:r,evaluate:n,evaluateLater:i})=>{let o=i(t),s=()=>{let u;return o(d=>u=d),u},a=i(`${t} = __placeholder`),c=u=>a(()=>{},{scope:{__placeholder:u}}),l=s();e._x_modelable_hook&&(l=e._x_modelable_hook(l)),c(l),queueMicrotask(()=>{if(!e._x_model)return;let u=e._x_model.get,d=e._x_model.set;r(()=>c(u())),r(()=>d(s()))})});p("teleport",(e,{expression:t},{cleanup:r})=>{e.tagName.toLowerCase()!=="template"&&V("x-teleport can only be used on a <template> tag",e);let n=document.querySelector(t);n||V(`Cannot find x-teleport element for selector: "${t}"`);let i=e.content.cloneNode(!0).firstElementChild;e._x_teleport=i,i._x_teleportBack=e,e._x_forwardEvents&&e._x_forwardEvents.forEach(o=>{i.addEventListener(o,s=>{s.stopPropagation(),e.dispatchEvent(new s.constructor(s.type,s))})}),R(i,{},e),m(()=>{n.appendChild(i),E(i),i._x_ignore=!0}),r(()=>i.remove())});var Xr=()=>{};Xr.inline=(e,{modifiers:t},{cleanup:r})=>{t.includes("self")?e._x_ignoreSelf=!0:e._x_ignore=!0,r(()=>{t.includes("self")?delete e._x_ignoreSelf:delete e._x_ignore})};p("ignore",Xr);p("effect",(e,{expression:t},{effect:r})=>r(g(e,t)));function pe(e,t,r,n){let i=e,o=c=>n(c),s={},a=(c,l)=>u=>l(c,u);if(r.includes("dot")&&(t=li(t)),r.includes("camel")&&(t=ui(t)),r.includes("passive")&&(s.passive=!0),r.includes("capture")&&(s.capture=!0),r.includes("window")&&(i=window),r.includes("document")&&(i=document),r.includes("prevent")&&(o=a(o,(c,l)=>{l.preventDefault(),c(l)})),r.includes("stop")&&(o=a(o,(c,l)=>{l.stopPropagation(),c(l)})),r.includes("self")&&(o=a(o,(c,l)=>{l.target===e&&c(l)})),(r.includes("away")||r.includes("outside"))&&(i=document,o=a(o,(c,l)=>{e.contains(l.target)||e.offsetWidth<1&&e.offsetHeight<1||e._x_isShown!==!1&&c(l)})),o=a(o,(c,l)=>{fi(t)&&di(l,r)||c(l)}),r.includes("debounce")){let c=r[r.indexOf("debounce")+1]||"invalid-wait",l=It(c.split("ms")[0])?Number(c.split("ms")[0]):250;o=ke(o,l)}if(r.includes("throttle")){let c=r[r.indexOf("throttle")+1]||"invalid-wait",l=It(c.split("ms")[0])?Number(c.split("ms")[0]):250;o=Ie(o,l)}return r.includes("once")&&(o=a(o,(c,l)=>{c(l),i.removeEventListener(t,o,s)})),i.addEventListener(t,o,s),()=>{i.removeEventListener(t,o,s)}}function li(e){return e.replace(/-/g,".")}function ui(e){return e.toLowerCase().replace(/-(\w)/g,(t,r)=>r.toUpperCase())}function It(e){return!Array.isArray(e)&&!isNaN(e)}function pi(e){return e.replace(/([a-z])([A-Z])/g,"$1-$2").replace(/[_\s]/,"-").toLowerCase()}function fi(e){return["keydown","keyup"].includes(e)}function di(e,t){let r=t.filter(o=>!["window","document","prevent","stop","once"].includes(o));if(r.includes("debounce")){let o=r.indexOf("debounce");r.splice(o,It((r[o+1]||"invalid-wait").split("ms")[0])?2:1)}if(r.length===0||r.length===1&&en(e.key).includes(r[0]))return!1;let i=["ctrl","shift","alt","meta","cmd","super"].filter(o=>r.includes(o));return r=r.filter(o=>!i.includes(o)),!(i.length>0&&i.filter(s=>((s==="cmd"||s==="super")&&(s="meta"),e[`${s}Key`])).length===i.length&&en(e.key).includes(r[0]))}function en(e){if(!e)return[];e=pi(e);let t={ctrl:"control",slash:"/",space:"-",spacebar:"-",cmd:"meta",esc:"escape",up:"arrow-up",down:"arrow-down",left:"arrow-left",right:"arrow-right",period:".",equal:"="};return t[e]=e,Object.keys(t).map(r=>{if(t[r]===e)return r}).filter(r=>r)}p("model",(e,{modifiers:t,expression:r},{effect:n,cleanup:i})=>{let o=g(e,r),s=`${r} = rightSideOfExpression($event, ${r})`,a=g(e,s);var c=e.tagName.toLowerCase()==="select"||["checkbox","radio"].includes(e.type)||t.includes("lazy")?"change":"input";let l=mi(e,t,r),u=pe(e,c,t,x=>{a(()=>{},{scope:{$event:x,rightSideOfExpression:l}})});i(()=>u());let d=g(e,`${r} = __placeholder`);e._x_model={get(){let x;return o(k=>x=k),x},set(x){d(()=>{},{scope:{__placeholder:x}})}},e._x_forceModelUpdate=()=>{o(x=>{x===void 0&&r.match(/\./)&&(x=""),window.fromModel=!0,m(()=>le(e,"value",x)),delete window.fromModel})},n(()=>{t.includes("unintrusive")&&document.activeElement.isSameNode(e)||e._x_forceModelUpdate()})});function mi(e,t,r){return e.type==="radio"&&m(()=>{e.hasAttribute("name")||e.setAttribute("name",r)}),(n,i)=>m(()=>{if(n instanceof CustomEvent&&n.detail!==void 0)return n.detail||n.target.value;if(e.type==="checkbox")if(Array.isArray(i)){let o=t.includes("number")?Pt(n.target.value):n.target.value;return n.target.checked?i.concat([o]):i.filter(s=>!hi(s,o))}else return n.target.checked;else{if(e.tagName.toLowerCase()==="select"&&e.multiple)return t.includes("number")?Array.from(n.target.selectedOptions).map(o=>{let s=o.value||o.text;return Pt(s)}):Array.from(n.target.selectedOptions).map(o=>o.value||o.text);{let o=n.target.value;return t.includes("number")?Pt(o):t.includes("trim")?o.trim():o}}})}function Pt(e){let t=e?parseFloat(e):null;return _i(t)?t:e}function hi(e,t){return e==t}function _i(e){return!Array.isArray(e)&&!isNaN(e)}p("cloak",e=>queueMicrotask(()=>m(()=>e.removeAttribute(w("cloak")))));Me(()=>`[${w("init")}]`);p("init",D((e,{expression:t},{evaluate:r})=>typeof t=="string"?!!t.trim()&&r(t,{},!1):r(t,{},!1)));p("text",(e,{expression:t},{effect:r,evaluateLater:n})=>{let i=n(t);r(()=>{i(o=>{m(()=>{e.textContent=o})})})});p("html",(e,{expression:t},{effect:r,evaluateLater:n})=>{let i=n(t);r(()=>{i(o=>{e.innerHTML=o})})});X(Se(":",Ae(w("bind:"))));p("bind",(e,{value:t,modifiers:r,expression:n,original:i},{effect:o})=>{if(!t)return gi(e,n,i,o);if(t==="key")return xi(e,n);let s=g(e,n);o(()=>s(a=>{a===void 0&&n.match(/\./)&&(a=""),m(()=>le(e,t,a,r))}))});function gi(e,t,r,n){let i={};Sr(i);let o=g(e,t),s=[];for(;s.length;)s.pop()();o(a=>{let c=Object.entries(a).map(([u,d])=>({name:u,value:d})),l=er(c);c=c.map(u=>l.find(d=>d.name===u.name)?{name:`x-bind:${u.name}`,value:`"${u.value}"`}:u),ie(e,c,r).map(u=>{s.push(u.runCleanups),u()})},{scope:i})}function xi(e,t){e._x_keyExpression=t}Re(()=>`[${w("data")}]`);p("data",D((e,{expression:t},{cleanup:r})=>{t=t===""?"{}":t;let n={},i=B(n,e).cleanup,o={};Tr(o,n);let s=I(e,t,{scope:o});s===void 0&&(s={});let a=B(s,e).cleanup,c=A(s);ve(c);let l=R(e,c);c.init&&I(e,c.init),r(()=>{l(),i(),a(),c.destroy&&I(e,c.destroy)})}));p("show",(e,{modifiers:t,expression:r},{effect:n})=>{let i=g(e,r),o=()=>m(()=>{e.style.display="none",e._x_isShown=!1}),s=()=>m(()=>{e.style.length===1&&e.style.display==="none"?e.removeAttribute("style"):e.style.removeProperty("display"),e._x_isShown=!0}),a=()=>setTimeout(s),c=ae(d=>d?s():o(),d=>{typeof e._x_toggleAndCascadeWithTransitions=="function"?e._x_toggleAndCascadeWithTransitions(e,d,s,o):d?a():o()}),l,u=!0;n(()=>i(d=>{!u&&d===l||(t.includes("immediate")&&(d?a():o()),c(d),l=d,u=!1)}))});p("for",(e,{expression:t},{effect:r,cleanup:n})=>{let i=bi(t),o=g(e,i.items),s=g(e,e._x_keyExpression||"index");e._x_prevKeys=[],e._x_lookup={},r(()=>yi(e,i,o,s)),n(()=>{Object.values(e._x_lookup).forEach(a=>a.remove()),delete e._x_prevKeys,delete e._x_lookup})});function yi(e,t,r,n){let i=s=>typeof s=="object"&&!Array.isArray(s),o=e;r(s=>{vi(s)&&s>=0&&(s=Array.from(Array(s).keys(),f=>f+1)),s===void 0&&(s=[]);let a=e._x_lookup,c=e._x_prevKeys,l=[],u=[];if(i(s))s=Object.entries(s).map(([f,h])=>{let b=tn(t,h,f,s);n(v=>u.push(v),{scope:{index:f,...b}}),l.push(b)});else for(let f=0;f<s.length;f++){let h=tn(t,s[f],f,s);n(b=>u.push(b),{scope:{index:f,...h}}),l.push(h)}let d=[],x=[],k=[],G=[];for(let f=0;f<c.length;f++){let h=c[f];u.indexOf(h)===-1&&k.push(h)}c=c.filter(f=>!k.includes(f));let me="template";for(let f=0;f<u.length;f++){let h=u[f],b=c.indexOf(h);if(b===-1)c.splice(f,0,h),d.push([me,f]);else if(b!==f){let v=c.splice(f,1)[0],S=c.splice(b-1,1)[0];c.splice(f,0,S),c.splice(b,0,v),x.push([v,S])}else G.push(h);me=h}for(let f=0;f<k.length;f++){let h=k[f];a[h]._x_effects&&a[h]._x_effects.forEach(_e),a[h].remove(),a[h]=null,delete a[h]}for(let f=0;f<x.length;f++){let[h,b]=x[f],v=a[h],S=a[b],Y=document.createElement("div");m(()=>{S.after(Y),v.after(S),S._x_currentIfEl&&S.after(S._x_currentIfEl),Y.before(v),v._x_currentIfEl&&v.after(v._x_currentIfEl),Y.remove()}),st(S,l[u.indexOf(b)])}for(let f=0;f<d.length;f++){let[h,b]=d[f],v=h==="template"?o:a[h];v._x_currentIfEl&&(v=v._x_currentIfEl);let S=l[b],Y=u[b],he=document.importNode(o.content,!0).firstElementChild;R(he,A(S),o),m(()=>{v.after(he),E(he)}),typeof Y=="object"&&V("x-for key cannot be an object, it must be a string or an integer",o),a[Y]=he}for(let f=0;f<G.length;f++)st(a[G[f]],l[u.indexOf(G[f])]);o._x_prevKeys=u})}function bi(e){let t=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,r=/^\s*\(|\)\s*$/g,n=/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/,i=e.match(n);if(!i)return;let o={};o.items=i[2].trim();let s=i[1].replace(r,"").trim(),a=s.match(t);return a?(o.item=s.replace(t,"").trim(),o.index=a[1].trim(),a[2]&&(o.collection=a[2].trim())):o.item=s,o}function tn(e,t,r,n){let i={};return/^\[.*\]$/.test(e.item)&&Array.isArray(t)?e.item.replace("[","").replace("]","").split(",").map(s=>s.trim()).forEach((s,a)=>{i[s]=t[a]}):/^\{.*\}$/.test(e.item)&&!Array.isArray(t)&&typeof t=="object"?e.item.replace("{","").replace("}","").split(",").map(s=>s.trim()).forEach(s=>{i[s]=t[s]}):i[e.item]=t,e.index&&(i[e.index]=r),e.collection&&(i[e.collection]=n),i}function vi(e){return!Array.isArray(e)&&!isNaN(e)}function rn(){}rn.inline=(e,{expression:t},{cleanup:r})=>{let n=H(e);n._x_refs||(n._x_refs={}),n._x_refs[t]=e,r(()=>delete n._x_refs[t])};p("ref",rn);p("if",(e,{expression:t},{effect:r,cleanup:n})=>{let i=g(e,t),o=()=>{if(e._x_currentIfEl)return e._x_currentIfEl;let a=e.content.cloneNode(!0).firstElementChild;return R(a,{},e),m(()=>{e.after(a),E(a)}),e._x_currentIfEl=a,e._x_undoIf=()=>{M(a,c=>{c._x_effects&&c._x_effects.forEach(_e)}),a.remove(),delete e._x_currentIfEl},a},s=()=>{!e._x_undoIf||(e._x_undoIf(),delete e._x_undoIf)};r(()=>i(a=>{a?o():s()})),n(()=>e._x_undoIf&&e._x_undoIf())});p("id",(e,{expression:t},{evaluate:r})=>{r(t).forEach(i=>Qr(e,i))});X(Se("@",Ae(w("on:"))));p("on",D((e,{value:t,modifiers:r,expression:n},{cleanup:i})=>{let o=n?g(e,n):()=>{};e.tagName.toLowerCase()==="template"&&(e._x_forwardEvents||(e._x_forwardEvents=[]),e._x_forwardEvents.includes(t)||e._x_forwardEvents.push(t));let s=pe(e,t,r,a=>{o(()=>{},{scope:{$event:a},params:[a]})});i(()=>s())}));P.setEvaluator(wi);P.setReactivityEngine({reactive:Fe,effect:Mr,release:kr,raw:_});function wi(e,t){let r={};B(r,e);let n=[r,...T(e)];if(typeof t=="function")return lt(n,t);let i=(o=()=>{},{scope:s={},params:a=[]}={})=>{let c=C([s,...n]);c[t]!==void 0&&Q(o,c[t],c,a)};return Ee.bind(null,e,t,i)}var Dt=P;window.Alpine=Dt;queueMicrotask(()=>{Dt.start()});})();
diff --git a/alpinejs/packages/csp/dist/module.cjs.js b/alpinejs/packages/csp/dist/module.cjs.js
index deb6429..5096393 100644
--- a/alpinejs/packages/csp/dist/module.cjs.js
+++ b/alpinejs/packages/csp/dist/module.cjs.js
@@ -1276,6 +1276,11 @@ function queueJob(job) {
queue.push(job);
queueFlush();
}
+function dequeueJob(job) {
+ let index = queue.indexOf(job);
+ if (index !== -1)
+ queue.splice(index, 1);
+}
function queueFlush() {
if (!flushing && !flushPending) {
flushPending = true;
@@ -1349,8 +1354,15 @@ var onElAddeds = [];
function onElAdded(callback) {
onElAddeds.push(callback);
}
-function onElRemoved(callback) {
- onElRemoveds.push(callback);
+function onElRemoved(el, callback) {
+ if (typeof callback === "function") {
+ if (!el._x_cleanups)
+ el._x_cleanups = [];
+ el._x_cleanups.push(callback);
+ } else {
+ callback = el;
+ onElRemoveds.push(callback);
+ }
}
function onAttributesAdded(callback) {
onAttributeAddeds.push(callback);
@@ -1463,16 +1475,34 @@ function onMutate(mutations) {
addedAttributes.forEach((attrs, el) => {
onAttributeAddeds.forEach((i) => i(el, attrs));
});
- for (let node of addedNodes) {
- if (removedNodes.includes(node))
- continue;
- onElAddeds.forEach((i) => i(node));
- }
for (let node of removedNodes) {
if (addedNodes.includes(node))
continue;
onElRemoveds.forEach((i) => i(node));
+ if (node._x_cleanups) {
+ while (node._x_cleanups.length)
+ node._x_cleanups.pop()();
+ }
}
+ addedNodes.forEach((node) => {
+ node._x_ignoreSelf = true;
+ node._x_ignore = true;
+ });
+ for (let node of addedNodes) {
+ if (removedNodes.includes(node))
+ continue;
+ if (!node.isConnected)
+ continue;
+ delete node._x_ignoreSelf;
+ delete node._x_ignore;
+ onElAddeds.forEach((i) => i(node));
+ node._x_ignore = true;
+ node._x_ignoreSelf = true;
+ }
+ addedNodes.forEach((node) => {
+ delete node._x_ignoreSelf;
+ delete node._x_ignore;
+ });
addedNodes = null;
removedNodes = null;
addedAttributes = null;
@@ -1480,15 +1510,18 @@ function onMutate(mutations) {
}
// packages/alpinejs/src/scope.js
+function scope(node) {
+ return mergeProxies(closestDataStack(node));
+}
function addScopeToNode(node, data2, referenceNode) {
node._x_dataStack = [data2, ...closestDataStack(referenceNode || node)];
return () => {
node._x_dataStack = node._x_dataStack.filter((i) => i !== data2);
};
}
-function refreshScope(element, scope) {
+function refreshScope(element, scope2) {
let existingScope = element._x_dataStack[0];
- Object.entries(scope).forEach(([key, value]) => {
+ Object.entries(scope2).forEach(([key, value]) => {
existingScope[key] = value;
});
}
@@ -1624,7 +1657,10 @@ function injectMagics(obj, el) {
Object.entries(magics).forEach(([name, callback]) => {
Object.defineProperty(obj, `$${name}`, {
get() {
- return callback(el, {Alpine: alpine_default, interceptor});
+ let [utilities, cleanup] = getElementBoundUtilities(el);
+ utilities = {interceptor, ...utilities};
+ onElRemoved(el, cleanup);
+ return callback(el, utilities);
},
enumerable: false
});
@@ -1681,8 +1717,8 @@ function normalEvaluator(el, expression) {
}
function generateEvaluatorFromFunction(dataStack, func) {
return (receiver = () => {
- }, {scope = {}, params = []} = {}) => {
- let result = func.apply(mergeProxies([scope, ...dataStack]), params);
+ }, {scope: scope2 = {}, params = []} = {}) => {
+ let result = func.apply(mergeProxies([scope2, ...dataStack]), params);
runIfTypeOfFunction(receiver, result);
};
}
@@ -1709,27 +1745,28 @@ function generateFunctionFromString(expression, el) {
function generateEvaluatorFromString(dataStack, expression, el) {
let func = generateFunctionFromString(expression, el);
return (receiver = () => {
- }, {scope = {}, params = []} = {}) => {
+ }, {scope: scope2 = {}, params = []} = {}) => {
func.result = void 0;
func.finished = false;
- let completeScope = mergeProxies([scope, ...dataStack]);
+ let completeScope = mergeProxies([scope2, ...dataStack]);
if (typeof func === "function") {
let promise = func(func, completeScope).catch((error2) => handleError(error2, el, expression));
if (func.finished) {
runIfTypeOfFunction(receiver, func.result, completeScope, params, el);
+ func.result = void 0;
} else {
promise.then((result) => {
runIfTypeOfFunction(receiver, result, completeScope, params, el);
- }).catch((error2) => handleError(error2, el, expression));
+ }).catch((error2) => handleError(error2, el, expression)).finally(() => func.result = void 0);
}
}
};
}
-function runIfTypeOfFunction(receiver, value, scope, params, el) {
+function runIfTypeOfFunction(receiver, value, scope2, params, el) {
if (typeof value === "function") {
- let result = value.apply(scope, params);
+ let result = value.apply(scope2, params);
if (result instanceof Promise) {
- result.then((i) => runIfTypeOfFunction(receiver, i, scope, params)).catch((error2) => handleError(error2, el, value));
+ result.then((i) => runIfTypeOfFunction(receiver, i, scope2, params)).catch((error2) => handleError(error2, el, value));
} else {
receiver(result);
}
@@ -1780,10 +1817,7 @@ function deferHandlingDirectives(callback) {
callback(flushHandlers);
stopDeferring();
}
-function getDirectiveHandler(el, directive2) {
- let noop = () => {
- };
- let handler3 = directiveHandlers[directive2.type] || noop;
+function getElementBoundUtilities(el) {
let cleanups = [];
let cleanup = (callback) => cleanups.push(callback);
let [effect3, cleanupEffect] = elementBoundEffect(el);
@@ -1796,7 +1830,14 @@ function getDirectiveHandler(el, directive2) {
evaluate: evaluate.bind(evaluate, el)
};
let doCleanup = () => cleanups.forEach((i) => i());
- onAttributeRemoved(el, directive2.original, doCleanup);
+ return [utilities, doCleanup];
+}
+function getDirectiveHandler(el, directive2) {
+ let noop = () => {
+ };
+ let handler3 = directiveHandlers[directive2.type] || noop;
+ let [utilities, cleanup] = getElementBoundUtilities(el);
+ onAttributeRemoved(el, directive2.original, cleanup);
let fullHandler = () => {
if (el._x_ignore || el._x_ignoreSelf)
return;
@@ -1804,7 +1845,7 @@ function getDirectiveHandler(el, directive2) {
handler3 = handler3.bind(handler3, el, directive2, utilities);
isDeferringHandlers ? directiveHandlerStacks.get(currentHandlerStackKey).push(handler3) : handler3();
};
- fullHandler.runCleanups = doCleanup;
+ fullHandler.runCleanups = cleanup;
return fullHandler;
}
var startingWith = (subject, replacement) => ({name, value}) => {
@@ -1852,14 +1893,17 @@ var directiveOrder = [
"ignore",
"ref",
"data",
+ "id",
"bind",
"init",
"for",
"model",
+ "modelable",
"transition",
"show",
"if",
DEFAULT,
+ "teleport",
"element"
];
function byPriority(a, b) {
@@ -1928,7 +1972,7 @@ function start() {
dispatch(document, "alpine:initializing");
startObservingMutations();
onElAdded((el) => initTree(el, walk));
- onElRemoved((el) => nextTick(() => destroyTree(el)));
+ onElRemoved((el) => destroyTree(el));
onAttributesAdded((el, attrs) => {
directives(el, attrs).forEach((handle) => handle());
});
@@ -1953,14 +1997,22 @@ function addInitSelector(selectorCallback) {
initSelectorCallbacks.push(selectorCallback);
}
function closestRoot(el, includeInitSelectors = false) {
+ return findClosest(el, (element) => {
+ const selectors = includeInitSelectors ? allSelectors() : rootSelectors();
+ if (selectors.some((selector) => element.matches(selector)))
+ return true;
+ });
+}
+function findClosest(el, callback) {
if (!el)
return;
- const selectors = includeInitSelectors ? allSelectors() : rootSelectors();
- if (selectors.some((selector) => el.matches(selector)))
+ if (callback(el))
return el;
+ if (el._x_teleportBack)
+ el = el._x_teleportBack;
if (!el.parentElement)
return;
- return closestRoot(el.parentElement, includeInitSelectors);
+ return findClosest(el.parentElement, callback);
}
function isRoot(el) {
return rootSelectors().some((selector) => el.matches(selector));
@@ -2035,7 +2087,10 @@ function setStylesFromObject(el, value) {
let previousStyles = {};
Object.entries(value).forEach(([key, value2]) => {
previousStyles[key] = el.style[key];
- el.style.setProperty(kebabCase(key), value2);
+ if (!key.startsWith("--")) {
+ key = kebabCase(key);
+ }
+ el.style.setProperty(key, value2);
});
setTimeout(() => {
if (el.style.length === 0) {
@@ -2050,7 +2105,7 @@ function setStylesFromString(el, value) {
let cache = el.getAttribute("style", value);
el.setAttribute("style", value);
return () => {
- el.setAttribute("style", cache);
+ el.setAttribute("style", cache || "");
};
}
function kebabCase(subject) {
@@ -2347,6 +2402,179 @@ function modifierValue(modifiers, key, fallback) {
return rawValue;
}
+// packages/alpinejs/src/clone.js
+var isCloning = false;
+function skipDuringClone(callback, fallback = () => {
+}) {
+ return (...args) => isCloning ? fallback(...args) : callback(...args);
+}
+function clone(oldEl, newEl) {
+ if (!newEl._x_dataStack)
+ newEl._x_dataStack = oldEl._x_dataStack;
+ isCloning = true;
+ dontRegisterReactiveSideEffects(() => {
+ cloneTree(newEl);
+ });
+ isCloning = false;
+}
+function cloneTree(el) {
+ let hasRunThroughFirstEl = false;
+ let shallowWalker = (el2, callback) => {
+ walk(el2, (el3, skip) => {
+ if (hasRunThroughFirstEl && isRoot(el3))
+ return skip();
+ hasRunThroughFirstEl = true;
+ callback(el3, skip);
+ });
+ };
+ initTree(el, shallowWalker);
+}
+function dontRegisterReactiveSideEffects(callback) {
+ let cache = effect;
+ overrideEffect((callback2, el) => {
+ let storedEffect = cache(callback2);
+ release(storedEffect);
+ return () => {
+ };
+ });
+ callback();
+ overrideEffect(cache);
+}
+
+// packages/alpinejs/src/utils/bind.js
+function bind(el, name, value, modifiers = []) {
+ if (!el._x_bindings)
+ el._x_bindings = reactive({});
+ el._x_bindings[name] = value;
+ name = modifiers.includes("camel") ? camelCase(name) : name;
+ switch (name) {
+ case "value":
+ bindInputValue(el, value);
+ break;
+ case "style":
+ bindStyles(el, value);
+ break;
+ case "class":
+ bindClasses(el, value);
+ break;
+ default:
+ bindAttribute(el, name, value);
+ break;
+ }
+}
+function bindInputValue(el, value) {
+ if (el.type === "radio") {
+ if (el.attributes.value === void 0) {
+ el.value = value;
+ }
+ if (window.fromModel) {
+ el.checked = checkedAttrLooseCompare(el.value, value);
+ }
+ } else if (el.type === "checkbox") {
+ if (Number.isInteger(value)) {
+ el.value = value;
+ } else if (!Number.isInteger(value) && !Array.isArray(value) && typeof value !== "boolean" && ![null, void 0].includes(value)) {
+ el.value = String(value);
+ } else {
+ if (Array.isArray(value)) {
+ 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;
+ }
+}
+function bindClasses(el, value) {
+ if (el._x_undoAddedClasses)
+ el._x_undoAddedClasses();
+ el._x_undoAddedClasses = setClasses(el, value);
+}
+function bindStyles(el, value) {
+ if (el._x_undoAddedStyles)
+ el._x_undoAddedStyles();
+ el._x_undoAddedStyles = setStyles(el, value);
+}
+function bindAttribute(el, name, value) {
+ if ([null, void 0, false].includes(value) && attributeShouldntBePreservedIfFalsy(name)) {
+ el.removeAttribute(name);
+ } else {
+ if (isBooleanAttr(name))
+ value = name;
+ setIfChanged(el, name, value);
+ }
+}
+function setIfChanged(el, attrName, value) {
+ if (el.getAttribute(attrName) != value) {
+ el.setAttribute(attrName, value);
+ }
+}
+function updateSelect(el, value) {
+ const arrayWrappedValue = [].concat(value).map((value2) => {
+ return value2 + "";
+ });
+ Array.from(el.options).forEach((option) => {
+ option.selected = arrayWrappedValue.includes(option.value);
+ });
+}
+function camelCase(subject) {
+ return subject.toLowerCase().replace(/-(\w)/g, (match, char) => char.toUpperCase());
+}
+function checkedAttrLooseCompare(valueA, valueB) {
+ return valueA == valueB;
+}
+function isBooleanAttr(attrName) {
+ 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 attributeShouldntBePreservedIfFalsy(name) {
+ return !["aria-pressed", "aria-checked", "aria-expanded", "aria-selected"].includes(name);
+}
+function getBinding(el, name, fallback) {
+ if (el._x_bindings && el._x_bindings[name] !== void 0)
+ return el._x_bindings[name];
+ let attr = el.getAttribute(name);
+ if (attr === null)
+ return typeof fallback === "function" ? fallback() : fallback;
+ if (isBooleanAttr(name)) {
+ return !![name, "true"].includes(attr);
+ }
+ if (attr === "")
+ return true;
+ return attr;
+}
+
// packages/alpinejs/src/utils/debounce.js
function debounce(func, wait) {
var timeout;
@@ -2400,42 +2628,22 @@ function getStores() {
return stores;
}
-// packages/alpinejs/src/clone.js
-var isCloning = false;
-function skipDuringClone(callback, fallback = () => {
-}) {
- return (...args) => isCloning ? fallback(...args) : callback(...args);
+// packages/alpinejs/src/binds.js
+var binds = {};
+function bind2(name, object) {
+ binds[name] = typeof object !== "function" ? () => object : object;
}
-function clone(oldEl, newEl) {
- newEl._x_dataStack = oldEl._x_dataStack;
- isCloning = true;
- dontRegisterReactiveSideEffects(() => {
- cloneTree(newEl);
- });
- isCloning = false;
-}
-function cloneTree(el) {
- let hasRunThroughFirstEl = false;
- let shallowWalker = (el2, callback) => {
- walk(el2, (el3, skip) => {
- if (hasRunThroughFirstEl && isRoot(el3))
- return skip();
- hasRunThroughFirstEl = true;
- callback(el3, skip);
+function injectBindingProviders(obj) {
+ Object.entries(binds).forEach(([name, callback]) => {
+ Object.defineProperty(obj, name, {
+ get() {
+ return (...args) => {
+ return callback(...args);
+ };
+ }
});
- };
- initTree(el, shallowWalker);
-}
-function dontRegisterReactiveSideEffects(callback) {
- let cache = effect;
- overrideEffect((callback2, el) => {
- let storedEffect = cache(callback2);
- release(storedEffect);
- return () => {
- };
});
- callback();
- overrideEffect(cache);
+ return obj;
}
// packages/alpinejs/src/datas.js
@@ -2471,19 +2679,23 @@ var Alpine = {
get raw() {
return raw;
},
- version: "3.5.1",
+ version: "3.9.1",
flushAndStopDeferringMutations,
disableEffectScheduling,
stopObservingMutations,
+ destroyTree,
setReactivityEngine,
+ closestDataStack,
skipDuringClone,
addRootSelector,
+ addInitSelector,
+ addScopeToNode,
deferMutations,
mapAttributes,
evaluateLater,
setEvaluator,
mergeProxies,
- destroyTree,
+ findClosest,
closestRoot,
interceptor,
transition,
@@ -2495,18 +2707,22 @@ var Alpine = {
evaluate,
initTree,
nextTick,
+ prefixed: prefix,
prefix: setPrefix,
plugin,
magic,
store,
start,
clone,
- data
+ bound: getBinding,
+ $data: scope,
+ data,
+ bind: bind2
};
var alpine_default = Alpine;
// packages/csp/src/index.js
-var import_reactivity9 = __toModule(require_reactivity());
+var import_reactivity8 = __toModule(require_reactivity());
// packages/alpinejs/src/magics/$nextTick.js
magic("nextTick", () => nextTick);
@@ -2515,15 +2731,12 @@ magic("nextTick", () => nextTick);
magic("dispatch", (el) => dispatch.bind(dispatch, el));
// packages/alpinejs/src/magics/$watch.js
-magic("watch", (el) => (key, callback) => {
- let evaluate2 = evaluateLater(el, key);
+magic("watch", (el, {evaluateLater: evaluateLater2, effect: effect3}) => (key, callback) => {
+ let evaluate2 = evaluateLater2(key);
let firstTime = true;
let oldValue;
- let [effect3, cleanupEffect] = elementBoundEffect(el);
- onAttributeRemoved(el, key, cleanupEffect);
effect3(() => evaluate2((value) => {
- let div = document.createElement("div");
- div.dataset.throwAway = value;
+ JSON.stringify(value);
if (!firstTime) {
queueMicrotask(() => {
callback(value, oldValue);
@@ -2540,9 +2753,7 @@ magic("watch", (el) => (key, callback) => {
magic("store", getStores);
// packages/alpinejs/src/magics/$data.js
-magic("data", (el) => {
- return mergeProxies(closestDataStack(el));
-});
+magic("data", (el) => scope(el));
// packages/alpinejs/src/magics/$root.js
magic("root", (el) => closestRoot(el));
@@ -2565,9 +2776,88 @@ function getArrayOfRefObject(el) {
return refObjects;
}
+// packages/alpinejs/src/ids.js
+var globalIdMemo = {};
+function findAndIncrementId(name) {
+ if (!globalIdMemo[name])
+ globalIdMemo[name] = 0;
+ return ++globalIdMemo[name];
+}
+function closestIdRoot(el, name) {
+ return findClosest(el, (element) => {
+ if (element._x_ids && element._x_ids[name])
+ return true;
+ });
+}
+function setIdRoot(el, name) {
+ if (!el._x_ids)
+ el._x_ids = {};
+ if (!el._x_ids[name])
+ el._x_ids[name] = findAndIncrementId(name);
+}
+
+// packages/alpinejs/src/magics/$id.js
+magic("id", (el) => (name, key = null) => {
+ let root = closestIdRoot(el, name);
+ let id = root ? root._x_ids[name] : findAndIncrementId(name);
+ return key ? `${name}-${id}-${key}` : `${name}-${id}`;
+});
+
// packages/alpinejs/src/magics/$el.js
magic("el", (el) => el);
+// packages/alpinejs/src/directives/x-modelable.js
+directive("modelable", (el, {expression}, {effect: effect3, evaluate: evaluate2, evaluateLater: evaluateLater2}) => {
+ let func = evaluateLater2(expression);
+ let innerGet = () => {
+ let result;
+ func((i) => result = i);
+ return result;
+ };
+ let evaluateInnerSet = evaluateLater2(`${expression} = __placeholder`);
+ let innerSet = (val) => evaluateInnerSet(() => {
+ }, {scope: {__placeholder: val}});
+ let initialValue = innerGet();
+ if (el._x_modelable_hook)
+ initialValue = el._x_modelable_hook(initialValue);
+ innerSet(initialValue);
+ queueMicrotask(() => {
+ if (!el._x_model)
+ return;
+ let outerGet = el._x_model.get;
+ let outerSet = el._x_model.set;
+ effect3(() => innerSet(outerGet()));
+ effect3(() => outerSet(innerGet()));
+ });
+});
+
+// packages/alpinejs/src/directives/x-teleport.js
+directive("teleport", (el, {expression}, {cleanup}) => {
+ if (el.tagName.toLowerCase() !== "template")
+ warn("x-teleport can only be used on a <template> tag", el);
+ let target = document.querySelector(expression);
+ if (!target)
+ warn(`Cannot find x-teleport element for selector: "${expression}"`);
+ let clone2 = el.content.cloneNode(true).firstElementChild;
+ el._x_teleport = clone2;
+ clone2._x_teleportBack = el;
+ if (el._x_forwardEvents) {
+ el._x_forwardEvents.forEach((eventName) => {
+ clone2.addEventListener(eventName, (e) => {
+ e.stopPropagation();
+ el.dispatchEvent(new e.constructor(e.type, e));
+ });
+ });
+ }
+ addScopeToNode(clone2, {}, el);
+ mutateDom(() => {
+ target.appendChild(clone2);
+ initTree(clone2);
+ clone2._x_ignore = true;
+ });
+ cleanup(() => clone2.remove());
+});
+
// packages/alpinejs/src/directives/x-ignore.js
var handler = () => {
};
@@ -2582,127 +2872,6 @@ directive("ignore", handler);
// packages/alpinejs/src/directives/x-effect.js
directive("effect", (el, {expression}, {effect: effect3}) => effect3(evaluateLater(el, expression)));
-// packages/alpinejs/src/utils/bind.js
-function bind(el, name, value, modifiers = []) {
- if (!el._x_bindings)
- el._x_bindings = reactive({});
- el._x_bindings[name] = value;
- name = modifiers.includes("camel") ? camelCase(name) : name;
- switch (name) {
- case "value":
- bindInputValue(el, value);
- break;
- case "style":
- bindStyles(el, value);
- break;
- case "class":
- bindClasses(el, value);
- break;
- default:
- bindAttribute(el, name, value);
- break;
- }
-}
-function bindInputValue(el, value) {
- if (el.type === "radio") {
- if (el.attributes.value === void 0) {
- el.value = value;
- }
- if (window.fromModel) {
- el.checked = checkedAttrLooseCompare(el.value, value);
- }
- } else if (el.type === "checkbox") {
- if (Number.isInteger(value)) {
- el.value = value;
- } else if (!Number.isInteger(value) && !Array.isArray(value) && typeof value !== "boolean" && ![null, void 0].includes(value)) {
- el.value = String(value);
- } else {
- if (Array.isArray(value)) {
- 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;
- }
-}
-function bindClasses(el, value) {
- if (el._x_undoAddedClasses)
- el._x_undoAddedClasses();
- el._x_undoAddedClasses = setClasses(el, value);
-}
-function bindStyles(el, value) {
- if (el._x_undoAddedStyles)
- el._x_undoAddedStyles();
- el._x_undoAddedStyles = setStyles(el, value);
-}
-function bindAttribute(el, name, value) {
- if ([null, void 0, false].includes(value) && attributeShouldntBePreservedIfFalsy(name)) {
- el.removeAttribute(name);
- } else {
- if (isBooleanAttr(name))
- value = name;
- setIfChanged(el, name, value);
- }
-}
-function setIfChanged(el, attrName, value) {
- if (el.getAttribute(attrName) != value) {
- el.setAttribute(attrName, value);
- }
-}
-function updateSelect(el, value) {
- const arrayWrappedValue = [].concat(value).map((value2) => {
- return value2 + "";
- });
- Array.from(el.options).forEach((option) => {
- option.selected = arrayWrappedValue.includes(option.value);
- });
-}
-function camelCase(subject) {
- return subject.toLowerCase().replace(/-(\w)/g, (match, char) => char.toUpperCase());
-}
-function checkedAttrLooseCompare(valueA, valueB) {
- return valueA == valueB;
-}
-function isBooleanAttr(attrName) {
- 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 attributeShouldntBePreservedIfFalsy(name) {
- return !["aria-pressed", "aria-checked", "aria-expanded"].includes(name);
-}
-
// packages/alpinejs/src/utils/on.js
function on(el, event, modifiers, callback) {
let listenerTarget = el;
@@ -2934,11 +3103,11 @@ directive("cloak", (el) => queueMicrotask(() => mutateDom(() => el.removeAttribu
// packages/alpinejs/src/directives/x-init.js
addInitSelector(() => `[${prefix("init")}]`);
-directive("init", skipDuringClone((el, {expression}) => {
+directive("init", skipDuringClone((el, {expression}, {evaluate: evaluate2}) => {
if (typeof expression === "string") {
- return !!expression.trim() && evaluate(el, expression, {}, false);
+ return !!expression.trim() && evaluate2(expression, {}, false);
}
- return evaluate(el, expression, {}, false);
+ return evaluate2(expression, {}, false);
}));
// packages/alpinejs/src/directives/x-text.js
@@ -2966,8 +3135,9 @@ directive("html", (el, {expression}, {effect: effect3, evaluateLater: evaluateLa
// packages/alpinejs/src/directives/x-bind.js
mapAttributes(startingWith(":", into(prefix("bind:"))));
directive("bind", (el, {value, modifiers, expression, original}, {effect: effect3}) => {
- if (!value)
+ if (!value) {
return applyBindingsObject(el, expression, original, effect3);
+ }
if (value === "key")
return storeKeyForXFor(el, expression);
let evaluate2 = evaluateLater(el, expression);
@@ -2978,32 +3148,29 @@ directive("bind", (el, {value, modifiers, expression, original}, {effect: effect
}));
});
function applyBindingsObject(el, expression, original, effect3) {
+ let bindingProviders = {};
+ injectBindingProviders(bindingProviders);
let getBindings = evaluateLater(el, expression);
let cleanupRunners = [];
- effect3(() => {
- while (cleanupRunners.length)
- cleanupRunners.pop()();
- getBindings((bindings) => {
- let attributes = Object.entries(bindings).map(([name, value]) => ({name, value}));
- attributes = attributes.filter((attr) => {
- return !(typeof attr.value === "object" && !Array.isArray(attr.value) && attr.value !== null);
- });
- let staticAttributes = attributesOnly(attributes);
- attributes = attributes.map((attribute) => {
- if (staticAttributes.find((attr) => attr.name === attribute.name)) {
- return {
- name: `x-bind:${attribute.name}`,
- value: `"${attribute.value}"`
- };
- }
- return attribute;
- });
- directives(el, attributes, original).map((handle) => {
- cleanupRunners.push(handle.runCleanups);
- handle();
- });
+ while (cleanupRunners.length)
+ cleanupRunners.pop()();
+ getBindings((bindings) => {
+ let attributes = Object.entries(bindings).map(([name, value]) => ({name, value}));
+ let staticAttributes = attributesOnly(attributes);
+ attributes = attributes.map((attribute) => {
+ if (staticAttributes.find((attr) => attr.name === attribute.name)) {
+ return {
+ name: `x-bind:${attribute.name}`,
+ value: `"${attribute.value}"`
+ };
+ }
+ return attribute;
});
- });
+ directives(el, attributes, original).map((handle) => {
+ cleanupRunners.push(handle.runCleanups);
+ handle();
+ });
+ }, {scope: bindingProviders});
}
function storeKeyForXFor(el, expression) {
el._x_keyExpression = expression;
@@ -3098,15 +3265,15 @@ function loop(el, iteratorNames, evaluateItems, evaluateKey) {
let keys = [];
if (isObject(items)) {
items = Object.entries(items).map(([key, value]) => {
- let scope = getIterationScopeVariables(iteratorNames, value, key, items);
- evaluateKey((value2) => keys.push(value2), {scope: {index: key, ...scope}});
- scopes.push(scope);
+ let scope2 = getIterationScopeVariables(iteratorNames, value, key, items);
+ evaluateKey((value2) => keys.push(value2), {scope: {index: key, ...scope2}});
+ scopes.push(scope2);
});
} else {
for (let i = 0; i < items.length; i++) {
- let scope = getIterationScopeVariables(iteratorNames, items[i], i, items);
- evaluateKey((value) => keys.push(value), {scope: {index: i, ...scope}});
- scopes.push(scope);
+ let scope2 = getIterationScopeVariables(iteratorNames, items[i], i, items);
+ evaluateKey((value) => keys.push(value), {scope: {index: i, ...scope2}});
+ scopes.push(scope2);
}
}
let adds = [];
@@ -3139,6 +3306,9 @@ function loop(el, iteratorNames, evaluateItems, evaluateKey) {
}
for (let i = 0; i < removes.length; i++) {
let key = removes[i];
+ if (!!lookup[key]._x_effects) {
+ lookup[key]._x_effects.forEach(dequeueJob);
+ }
lookup[key].remove();
lookup[key] = null;
delete lookup[key];
@@ -3151,7 +3321,9 @@ function loop(el, iteratorNames, evaluateItems, evaluateKey) {
mutateDom(() => {
elForSpot.after(marker);
elInSpot.after(elForSpot);
+ elForSpot._x_currentIfEl && elForSpot.after(elForSpot._x_currentIfEl);
marker.before(elInSpot);
+ elInSpot._x_currentIfEl && elInSpot.after(elInSpot._x_currentIfEl);
marker.remove();
});
refreshScope(elForSpot, scopes[keys.indexOf(keyForSpot)]);
@@ -3159,10 +3331,12 @@ function loop(el, iteratorNames, evaluateItems, evaluateKey) {
for (let i = 0; i < adds.length; i++) {
let [lastKey2, index] = adds[i];
let lastEl = lastKey2 === "template" ? templateEl : lookup[lastKey2];
- let scope = scopes[index];
+ if (lastEl._x_currentIfEl)
+ lastEl = lastEl._x_currentIfEl;
+ let scope2 = scopes[index];
let key = keys[index];
let clone2 = document.importNode(templateEl.content, true).firstElementChild;
- addScopeToNode(clone2, reactive(scope), templateEl);
+ addScopeToNode(clone2, reactive(scope2), templateEl);
mutateDom(() => {
lastEl.after(clone2);
initTree(clone2);
@@ -3251,6 +3425,11 @@ directive("if", (el, {expression}, {effect: effect3, cleanup}) => {
});
el._x_currentIfEl = clone2;
el._x_undoIf = () => {
+ walk(clone2, (node) => {
+ if (!!node._x_effects) {
+ node._x_effects.forEach(dequeueJob);
+ }
+ });
clone2.remove();
delete el._x_currentIfEl;
};
@@ -3268,11 +3447,23 @@ directive("if", (el, {expression}, {effect: effect3, cleanup}) => {
cleanup(() => el._x_undoIf && el._x_undoIf());
});
+// packages/alpinejs/src/directives/x-id.js
+directive("id", (el, {expression}, {evaluate: evaluate2}) => {
+ let names = evaluate2(expression);
+ names.forEach((name) => setIdRoot(el, name));
+});
+
// packages/alpinejs/src/directives/x-on.js
mapAttributes(startingWith("@", into(prefix("on:"))));
directive("on", skipDuringClone((el, {value, modifiers, expression}, {cleanup}) => {
let evaluate2 = expression ? evaluateLater(el, expression) : () => {
};
+ if (el.tagName.toLowerCase() === "template") {
+ if (!el._x_forwardEvents)
+ el._x_forwardEvents = [];
+ if (!el._x_forwardEvents.includes(value))
+ el._x_forwardEvents.push(value);
+ }
let removeListener = on(el, value, modifiers, (e) => {
evaluate2(() => {
}, {scope: {$event: e}, params: [e]});
@@ -3282,7 +3473,7 @@ directive("on", skipDuringClone((el, {value, modifiers, expression}, {cleanup})
// packages/csp/src/index.js
alpine_default.setEvaluator(cspCompliantEvaluator);
-alpine_default.setReactivityEngine({reactive: import_reactivity9.reactive, effect: import_reactivity9.effect, release: import_reactivity9.stop, raw: import_reactivity9.toRaw});
+alpine_default.setReactivityEngine({reactive: import_reactivity8.reactive, effect: import_reactivity8.effect, release: import_reactivity8.stop, raw: import_reactivity8.toRaw});
function cspCompliantEvaluator(el, expression) {
let overriddenMagics = {};
injectMagics(overriddenMagics, el);
@@ -3291,8 +3482,8 @@ function cspCompliantEvaluator(el, expression) {
return generateEvaluatorFromFunction(dataStack, expression);
}
let evaluator = (receiver = () => {
- }, {scope = {}, params = []} = {}) => {
- let completeScope = mergeProxies([scope, ...dataStack]);
+ }, {scope: scope2 = {}, params = []} = {}) => {
+ let completeScope = mergeProxies([scope2, ...dataStack]);
if (completeScope[expression] !== void 0) {
runIfTypeOfFunction(receiver, completeScope[expression], completeScope, params);
}
diff --git a/alpinejs/packages/csp/dist/module.esm.js b/alpinejs/packages/csp/dist/module.esm.js
index 28e3c71..5c585f2 100644
--- a/alpinejs/packages/csp/dist/module.esm.js
+++ b/alpinejs/packages/csp/dist/module.esm.js
@@ -1266,6 +1266,11 @@ function queueJob(job) {
queue.push(job);
queueFlush();
}
+function dequeueJob(job) {
+ let index = queue.indexOf(job);
+ if (index !== -1)
+ queue.splice(index, 1);
+}
function queueFlush() {
if (!flushing && !flushPending) {
flushPending = true;
@@ -1339,8 +1344,15 @@ var onElAddeds = [];
function onElAdded(callback) {
onElAddeds.push(callback);
}
-function onElRemoved(callback) {
- onElRemoveds.push(callback);
+function onElRemoved(el, callback) {
+ if (typeof callback === "function") {
+ if (!el._x_cleanups)
+ el._x_cleanups = [];
+ el._x_cleanups.push(callback);
+ } else {
+ callback = el;
+ onElRemoveds.push(callback);
+ }
}
function onAttributesAdded(callback) {
onAttributeAddeds.push(callback);
@@ -1453,16 +1465,34 @@ function onMutate(mutations) {
addedAttributes.forEach((attrs, el) => {
onAttributeAddeds.forEach((i) => i(el, attrs));
});
- for (let node of addedNodes) {
- if (removedNodes.includes(node))
- continue;
- onElAddeds.forEach((i) => i(node));
- }
for (let node of removedNodes) {
if (addedNodes.includes(node))
continue;
onElRemoveds.forEach((i) => i(node));
+ if (node._x_cleanups) {
+ while (node._x_cleanups.length)
+ node._x_cleanups.pop()();
+ }
}
+ addedNodes.forEach((node) => {
+ node._x_ignoreSelf = true;
+ node._x_ignore = true;
+ });
+ for (let node of addedNodes) {
+ if (removedNodes.includes(node))
+ continue;
+ if (!node.isConnected)
+ continue;
+ delete node._x_ignoreSelf;
+ delete node._x_ignore;
+ onElAddeds.forEach((i) => i(node));
+ node._x_ignore = true;
+ node._x_ignoreSelf = true;
+ }
+ addedNodes.forEach((node) => {
+ delete node._x_ignoreSelf;
+ delete node._x_ignore;
+ });
addedNodes = null;
removedNodes = null;
addedAttributes = null;
@@ -1470,15 +1500,18 @@ function onMutate(mutations) {
}
// packages/alpinejs/src/scope.js
+function scope(node) {
+ return mergeProxies(closestDataStack(node));
+}
function addScopeToNode(node, data2, referenceNode) {
node._x_dataStack = [data2, ...closestDataStack(referenceNode || node)];
return () => {
node._x_dataStack = node._x_dataStack.filter((i) => i !== data2);
};
}
-function refreshScope(element, scope) {
+function refreshScope(element, scope2) {
let existingScope = element._x_dataStack[0];
- Object.entries(scope).forEach(([key, value]) => {
+ Object.entries(scope2).forEach(([key, value]) => {
existingScope[key] = value;
});
}
@@ -1614,7 +1647,10 @@ function injectMagics(obj, el) {
Object.entries(magics).forEach(([name, callback]) => {
Object.defineProperty(obj, `$${name}`, {
get() {
- return callback(el, {Alpine: alpine_default, interceptor});
+ let [utilities, cleanup] = getElementBoundUtilities(el);
+ utilities = {interceptor, ...utilities};
+ onElRemoved(el, cleanup);
+ return callback(el, utilities);
},
enumerable: false
});
@@ -1671,8 +1707,8 @@ function normalEvaluator(el, expression) {
}
function generateEvaluatorFromFunction(dataStack, func) {
return (receiver = () => {
- }, {scope = {}, params = []} = {}) => {
- let result = func.apply(mergeProxies([scope, ...dataStack]), params);
+ }, {scope: scope2 = {}, params = []} = {}) => {
+ let result = func.apply(mergeProxies([scope2, ...dataStack]), params);
runIfTypeOfFunction(receiver, result);
};
}
@@ -1699,27 +1735,28 @@ function generateFunctionFromString(expression, el) {
function generateEvaluatorFromString(dataStack, expression, el) {
let func = generateFunctionFromString(expression, el);
return (receiver = () => {
- }, {scope = {}, params = []} = {}) => {
+ }, {scope: scope2 = {}, params = []} = {}) => {
func.result = void 0;
func.finished = false;
- let completeScope = mergeProxies([scope, ...dataStack]);
+ let completeScope = mergeProxies([scope2, ...dataStack]);
if (typeof func === "function") {
let promise = func(func, completeScope).catch((error2) => handleError(error2, el, expression));
if (func.finished) {
runIfTypeOfFunction(receiver, func.result, completeScope, params, el);
+ func.result = void 0;
} else {
promise.then((result) => {
runIfTypeOfFunction(receiver, result, completeScope, params, el);
- }).catch((error2) => handleError(error2, el, expression));
+ }).catch((error2) => handleError(error2, el, expression)).finally(() => func.result = void 0);
}
}
};
}
-function runIfTypeOfFunction(receiver, value, scope, params, el) {
+function runIfTypeOfFunction(receiver, value, scope2, params, el) {
if (typeof value === "function") {
- let result = value.apply(scope, params);
+ let result = value.apply(scope2, params);
if (result instanceof Promise) {
- result.then((i) => runIfTypeOfFunction(receiver, i, scope, params)).catch((error2) => handleError(error2, el, value));
+ result.then((i) => runIfTypeOfFunction(receiver, i, scope2, params)).catch((error2) => handleError(error2, el, value));
} else {
receiver(result);
}
@@ -1770,10 +1807,7 @@ function deferHandlingDirectives(callback) {
callback(flushHandlers);
stopDeferring();
}
-function getDirectiveHandler(el, directive2) {
- let noop = () => {
- };
- let handler3 = directiveHandlers[directive2.type] || noop;
+function getElementBoundUtilities(el) {
let cleanups = [];
let cleanup = (callback) => cleanups.push(callback);
let [effect3, cleanupEffect] = elementBoundEffect(el);
@@ -1786,7 +1820,14 @@ function getDirectiveHandler(el, directive2) {
evaluate: evaluate.bind(evaluate, el)
};
let doCleanup = () => cleanups.forEach((i) => i());
- onAttributeRemoved(el, directive2.original, doCleanup);
+ return [utilities, doCleanup];
+}
+function getDirectiveHandler(el, directive2) {
+ let noop = () => {
+ };
+ let handler3 = directiveHandlers[directive2.type] || noop;
+ let [utilities, cleanup] = getElementBoundUtilities(el);
+ onAttributeRemoved(el, directive2.original, cleanup);
let fullHandler = () => {
if (el._x_ignore || el._x_ignoreSelf)
return;
@@ -1794,7 +1835,7 @@ function getDirectiveHandler(el, directive2) {
handler3 = handler3.bind(handler3, el, directive2, utilities);
isDeferringHandlers ? directiveHandlerStacks.get(currentHandlerStackKey).push(handler3) : handler3();
};
- fullHandler.runCleanups = doCleanup;
+ fullHandler.runCleanups = cleanup;
return fullHandler;
}
var startingWith = (subject, replacement) => ({name, value}) => {
@@ -1842,14 +1883,17 @@ var directiveOrder = [
"ignore",
"ref",
"data",
+ "id",
"bind",
"init",
"for",
"model",
+ "modelable",
"transition",
"show",
"if",
DEFAULT,
+ "teleport",
"element"
];
function byPriority(a, b) {
@@ -1918,7 +1962,7 @@ function start() {
dispatch(document, "alpine:initializing");
startObservingMutations();
onElAdded((el) => initTree(el, walk));
- onElRemoved((el) => nextTick(() => destroyTree(el)));
+ onElRemoved((el) => destroyTree(el));
onAttributesAdded((el, attrs) => {
directives(el, attrs).forEach((handle) => handle());
});
@@ -1943,14 +1987,22 @@ function addInitSelector(selectorCallback) {
initSelectorCallbacks.push(selectorCallback);
}
function closestRoot(el, includeInitSelectors = false) {
+ return findClosest(el, (element) => {
+ const selectors = includeInitSelectors ? allSelectors() : rootSelectors();
+ if (selectors.some((selector) => element.matches(selector)))
+ return true;
+ });
+}
+function findClosest(el, callback) {
if (!el)
return;
- const selectors = includeInitSelectors ? allSelectors() : rootSelectors();
- if (selectors.some((selector) => el.matches(selector)))
+ if (callback(el))
return el;
+ if (el._x_teleportBack)
+ el = el._x_teleportBack;
if (!el.parentElement)
return;
- return closestRoot(el.parentElement, includeInitSelectors);
+ return findClosest(el.parentElement, callback);
}
function isRoot(el) {
return rootSelectors().some((selector) => el.matches(selector));
@@ -2025,7 +2077,10 @@ function setStylesFromObject(el, value) {
let previousStyles = {};
Object.entries(value).forEach(([key, value2]) => {
previousStyles[key] = el.style[key];
- el.style.setProperty(kebabCase(key), value2);
+ if (!key.startsWith("--")) {
+ key = kebabCase(key);
+ }
+ el.style.setProperty(key, value2);
});
setTimeout(() => {
if (el.style.length === 0) {
@@ -2040,7 +2095,7 @@ function setStylesFromString(el, value) {
let cache = el.getAttribute("style", value);
el.setAttribute("style", value);
return () => {
- el.setAttribute("style", cache);
+ el.setAttribute("style", cache || "");
};
}
function kebabCase(subject) {
@@ -2337,6 +2392,179 @@ function modifierValue(modifiers, key, fallback) {
return rawValue;
}
+// packages/alpinejs/src/clone.js
+var isCloning = false;
+function skipDuringClone(callback, fallback = () => {
+}) {
+ return (...args) => isCloning ? fallback(...args) : callback(...args);
+}
+function clone(oldEl, newEl) {
+ if (!newEl._x_dataStack)
+ newEl._x_dataStack = oldEl._x_dataStack;
+ isCloning = true;
+ dontRegisterReactiveSideEffects(() => {
+ cloneTree(newEl);
+ });
+ isCloning = false;
+}
+function cloneTree(el) {
+ let hasRunThroughFirstEl = false;
+ let shallowWalker = (el2, callback) => {
+ walk(el2, (el3, skip) => {
+ if (hasRunThroughFirstEl && isRoot(el3))
+ return skip();
+ hasRunThroughFirstEl = true;
+ callback(el3, skip);
+ });
+ };
+ initTree(el, shallowWalker);
+}
+function dontRegisterReactiveSideEffects(callback) {
+ let cache = effect;
+ overrideEffect((callback2, el) => {
+ let storedEffect = cache(callback2);
+ release(storedEffect);
+ return () => {
+ };
+ });
+ callback();
+ overrideEffect(cache);
+}
+
+// packages/alpinejs/src/utils/bind.js
+function bind(el, name, value, modifiers = []) {
+ if (!el._x_bindings)
+ el._x_bindings = reactive({});
+ el._x_bindings[name] = value;
+ name = modifiers.includes("camel") ? camelCase(name) : name;
+ switch (name) {
+ case "value":
+ bindInputValue(el, value);
+ break;
+ case "style":
+ bindStyles(el, value);
+ break;
+ case "class":
+ bindClasses(el, value);
+ break;
+ default:
+ bindAttribute(el, name, value);
+ break;
+ }
+}
+function bindInputValue(el, value) {
+ if (el.type === "radio") {
+ if (el.attributes.value === void 0) {
+ el.value = value;
+ }
+ if (window.fromModel) {
+ el.checked = checkedAttrLooseCompare(el.value, value);
+ }
+ } else if (el.type === "checkbox") {
+ if (Number.isInteger(value)) {
+ el.value = value;
+ } else if (!Number.isInteger(value) && !Array.isArray(value) && typeof value !== "boolean" && ![null, void 0].includes(value)) {
+ el.value = String(value);
+ } else {
+ if (Array.isArray(value)) {
+ 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;
+ }
+}
+function bindClasses(el, value) {
+ if (el._x_undoAddedClasses)
+ el._x_undoAddedClasses();
+ el._x_undoAddedClasses = setClasses(el, value);
+}
+function bindStyles(el, value) {
+ if (el._x_undoAddedStyles)
+ el._x_undoAddedStyles();
+ el._x_undoAddedStyles = setStyles(el, value);
+}
+function bindAttribute(el, name, value) {
+ if ([null, void 0, false].includes(value) && attributeShouldntBePreservedIfFalsy(name)) {
+ el.removeAttribute(name);
+ } else {
+ if (isBooleanAttr(name))
+ value = name;
+ setIfChanged(el, name, value);
+ }
+}
+function setIfChanged(el, attrName, value) {
+ if (el.getAttribute(attrName) != value) {
+ el.setAttribute(attrName, value);
+ }
+}
+function updateSelect(el, value) {
+ const arrayWrappedValue = [].concat(value).map((value2) => {
+ return value2 + "";
+ });
+ Array.from(el.options).forEach((option) => {
+ option.selected = arrayWrappedValue.includes(option.value);
+ });
+}
+function camelCase(subject) {
+ return subject.toLowerCase().replace(/-(\w)/g, (match, char) => char.toUpperCase());
+}
+function checkedAttrLooseCompare(valueA, valueB) {
+ return valueA == valueB;
+}
+function isBooleanAttr(attrName) {
+ 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 attributeShouldntBePreservedIfFalsy(name) {
+ return !["aria-pressed", "aria-checked", "aria-expanded", "aria-selected"].includes(name);
+}
+function getBinding(el, name, fallback) {
+ if (el._x_bindings && el._x_bindings[name] !== void 0)
+ return el._x_bindings[name];
+ let attr = el.getAttribute(name);
+ if (attr === null)
+ return typeof fallback === "function" ? fallback() : fallback;
+ if (isBooleanAttr(name)) {
+ return !![name, "true"].includes(attr);
+ }
+ if (attr === "")
+ return true;
+ return attr;
+}
+
// packages/alpinejs/src/utils/debounce.js
function debounce(func, wait) {
var timeout;
@@ -2390,42 +2618,22 @@ function getStores() {
return stores;
}
-// packages/alpinejs/src/clone.js
-var isCloning = false;
-function skipDuringClone(callback, fallback = () => {
-}) {
- return (...args) => isCloning ? fallback(...args) : callback(...args);
+// packages/alpinejs/src/binds.js
+var binds = {};
+function bind2(name, object) {
+ binds[name] = typeof object !== "function" ? () => object : object;
}
-function clone(oldEl, newEl) {
- newEl._x_dataStack = oldEl._x_dataStack;
- isCloning = true;
- dontRegisterReactiveSideEffects(() => {
- cloneTree(newEl);
- });
- isCloning = false;
-}
-function cloneTree(el) {
- let hasRunThroughFirstEl = false;
- let shallowWalker = (el2, callback) => {
- walk(el2, (el3, skip) => {
- if (hasRunThroughFirstEl && isRoot(el3))
- return skip();
- hasRunThroughFirstEl = true;
- callback(el3, skip);
+function injectBindingProviders(obj) {
+ Object.entries(binds).forEach(([name, callback]) => {
+ Object.defineProperty(obj, name, {
+ get() {
+ return (...args) => {
+ return callback(...args);
+ };
+ }
});
- };
- initTree(el, shallowWalker);
-}
-function dontRegisterReactiveSideEffects(callback) {
- let cache = effect;
- overrideEffect((callback2, el) => {
- let storedEffect = cache(callback2);
- release(storedEffect);
- return () => {
- };
});
- callback();
- overrideEffect(cache);
+ return obj;
}
// packages/alpinejs/src/datas.js
@@ -2461,19 +2669,23 @@ var Alpine = {
get raw() {
return raw;
},
- version: "3.5.1",
+ version: "3.9.1",
flushAndStopDeferringMutations,
disableEffectScheduling,
stopObservingMutations,
+ destroyTree,
setReactivityEngine,
+ closestDataStack,
skipDuringClone,
addRootSelector,
+ addInitSelector,
+ addScopeToNode,
deferMutations,
mapAttributes,
evaluateLater,
setEvaluator,
mergeProxies,
- destroyTree,
+ findClosest,
closestRoot,
interceptor,
transition,
@@ -2485,18 +2697,22 @@ var Alpine = {
evaluate,
initTree,
nextTick,
+ prefixed: prefix,
prefix: setPrefix,
plugin,
magic,
store,
start,
clone,
- data
+ bound: getBinding,
+ $data: scope,
+ data,
+ bind: bind2
};
var alpine_default = Alpine;
// packages/csp/src/index.js
-var import_reactivity9 = __toModule(require_reactivity());
+var import_reactivity8 = __toModule(require_reactivity());
// packages/alpinejs/src/magics/$nextTick.js
magic("nextTick", () => nextTick);
@@ -2505,15 +2721,12 @@ magic("nextTick", () => nextTick);
magic("dispatch", (el) => dispatch.bind(dispatch, el));
// packages/alpinejs/src/magics/$watch.js
-magic("watch", (el) => (key, callback) => {
- let evaluate2 = evaluateLater(el, key);
+magic("watch", (el, {evaluateLater: evaluateLater2, effect: effect3}) => (key, callback) => {
+ let evaluate2 = evaluateLater2(key);
let firstTime = true;
let oldValue;
- let [effect3, cleanupEffect] = elementBoundEffect(el);
- onAttributeRemoved(el, key, cleanupEffect);
effect3(() => evaluate2((value) => {
- let div = document.createElement("div");
- div.dataset.throwAway = value;
+ JSON.stringify(value);
if (!firstTime) {
queueMicrotask(() => {
callback(value, oldValue);
@@ -2530,9 +2743,7 @@ magic("watch", (el) => (key, callback) => {
magic("store", getStores);
// packages/alpinejs/src/magics/$data.js
-magic("data", (el) => {
- return mergeProxies(closestDataStack(el));
-});
+magic("data", (el) => scope(el));
// packages/alpinejs/src/magics/$root.js
magic("root", (el) => closestRoot(el));
@@ -2555,9 +2766,88 @@ function getArrayOfRefObject(el) {
return refObjects;
}
+// packages/alpinejs/src/ids.js
+var globalIdMemo = {};
+function findAndIncrementId(name) {
+ if (!globalIdMemo[name])
+ globalIdMemo[name] = 0;
+ return ++globalIdMemo[name];
+}
+function closestIdRoot(el, name) {
+ return findClosest(el, (element) => {
+ if (element._x_ids && element._x_ids[name])
+ return true;
+ });
+}
+function setIdRoot(el, name) {
+ if (!el._x_ids)
+ el._x_ids = {};
+ if (!el._x_ids[name])
+ el._x_ids[name] = findAndIncrementId(name);
+}
+
+// packages/alpinejs/src/magics/$id.js
+magic("id", (el) => (name, key = null) => {
+ let root = closestIdRoot(el, name);
+ let id = root ? root._x_ids[name] : findAndIncrementId(name);
+ return key ? `${name}-${id}-${key}` : `${name}-${id}`;
+});
+
// packages/alpinejs/src/magics/$el.js
magic("el", (el) => el);
+// packages/alpinejs/src/directives/x-modelable.js
+directive("modelable", (el, {expression}, {effect: effect3, evaluate: evaluate2, evaluateLater: evaluateLater2}) => {
+ let func = evaluateLater2(expression);
+ let innerGet = () => {
+ let result;
+ func((i) => result = i);
+ return result;
+ };
+ let evaluateInnerSet = evaluateLater2(`${expression} = __placeholder`);
+ let innerSet = (val) => evaluateInnerSet(() => {
+ }, {scope: {__placeholder: val}});
+ let initialValue = innerGet();
+ if (el._x_modelable_hook)
+ initialValue = el._x_modelable_hook(initialValue);
+ innerSet(initialValue);
+ queueMicrotask(() => {
+ if (!el._x_model)
+ return;
+ let outerGet = el._x_model.get;
+ let outerSet = el._x_model.set;
+ effect3(() => innerSet(outerGet()));
+ effect3(() => outerSet(innerGet()));
+ });
+});
+
+// packages/alpinejs/src/directives/x-teleport.js
+directive("teleport", (el, {expression}, {cleanup}) => {
+ if (el.tagName.toLowerCase() !== "template")
+ warn("x-teleport can only be used on a <template> tag", el);
+ let target = document.querySelector(expression);
+ if (!target)
+ warn(`Cannot find x-teleport element for selector: "${expression}"`);
+ let clone2 = el.content.cloneNode(true).firstElementChild;
+ el._x_teleport = clone2;
+ clone2._x_teleportBack = el;
+ if (el._x_forwardEvents) {
+ el._x_forwardEvents.forEach((eventName) => {
+ clone2.addEventListener(eventName, (e) => {
+ e.stopPropagation();
+ el.dispatchEvent(new e.constructor(e.type, e));
+ });
+ });
+ }
+ addScopeToNode(clone2, {}, el);
+ mutateDom(() => {
+ target.appendChild(clone2);
+ initTree(clone2);
+ clone2._x_ignore = true;
+ });
+ cleanup(() => clone2.remove());
+});
+
// packages/alpinejs/src/directives/x-ignore.js
var handler = () => {
};
@@ -2572,127 +2862,6 @@ directive("ignore", handler);
// packages/alpinejs/src/directives/x-effect.js
directive("effect", (el, {expression}, {effect: effect3}) => effect3(evaluateLater(el, expression)));
-// packages/alpinejs/src/utils/bind.js
-function bind(el, name, value, modifiers = []) {
- if (!el._x_bindings)
- el._x_bindings = reactive({});
- el._x_bindings[name] = value;
- name = modifiers.includes("camel") ? camelCase(name) : name;
- switch (name) {
- case "value":
- bindInputValue(el, value);
- break;
- case "style":
- bindStyles(el, value);
- break;
- case "class":
- bindClasses(el, value);
- break;
- default:
- bindAttribute(el, name, value);
- break;
- }
-}
-function bindInputValue(el, value) {
- if (el.type === "radio") {
- if (el.attributes.value === void 0) {
- el.value = value;
- }
- if (window.fromModel) {
- el.checked = checkedAttrLooseCompare(el.value, value);
- }
- } else if (el.type === "checkbox") {
- if (Number.isInteger(value)) {
- el.value = value;
- } else if (!Number.isInteger(value) && !Array.isArray(value) && typeof value !== "boolean" && ![null, void 0].includes(value)) {
- el.value = String(value);
- } else {
- if (Array.isArray(value)) {
- 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;
- }
-}
-function bindClasses(el, value) {
- if (el._x_undoAddedClasses)
- el._x_undoAddedClasses();
- el._x_undoAddedClasses = setClasses(el, value);
-}
-function bindStyles(el, value) {
- if (el._x_undoAddedStyles)
- el._x_undoAddedStyles();
- el._x_undoAddedStyles = setStyles(el, value);
-}
-function bindAttribute(el, name, value) {
- if ([null, void 0, false].includes(value) && attributeShouldntBePreservedIfFalsy(name)) {
- el.removeAttribute(name);
- } else {
- if (isBooleanAttr(name))
- value = name;
- setIfChanged(el, name, value);
- }
-}
-function setIfChanged(el, attrName, value) {
- if (el.getAttribute(attrName) != value) {
- el.setAttribute(attrName, value);
- }
-}
-function updateSelect(el, value) {
- const arrayWrappedValue = [].concat(value).map((value2) => {
- return value2 + "";
- });
- Array.from(el.options).forEach((option) => {
- option.selected = arrayWrappedValue.includes(option.value);
- });
-}
-function camelCase(subject) {
- return subject.toLowerCase().replace(/-(\w)/g, (match, char) => char.toUpperCase());
-}
-function checkedAttrLooseCompare(valueA, valueB) {
- return valueA == valueB;
-}
-function isBooleanAttr(attrName) {
- 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 attributeShouldntBePreservedIfFalsy(name) {
- return !["aria-pressed", "aria-checked", "aria-expanded"].includes(name);
-}
-
// packages/alpinejs/src/utils/on.js
function on(el, event, modifiers, callback) {
let listenerTarget = el;
@@ -2924,11 +3093,11 @@ directive("cloak", (el) => queueMicrotask(() => mutateDom(() => el.removeAttribu
// packages/alpinejs/src/directives/x-init.js
addInitSelector(() => `[${prefix("init")}]`);
-directive("init", skipDuringClone((el, {expression}) => {
+directive("init", skipDuringClone((el, {expression}, {evaluate: evaluate2}) => {
if (typeof expression === "string") {
- return !!expression.trim() && evaluate(el, expression, {}, false);
+ return !!expression.trim() && evaluate2(expression, {}, false);
}
- return evaluate(el, expression, {}, false);
+ return evaluate2(expression, {}, false);
}));
// packages/alpinejs/src/directives/x-text.js
@@ -2956,8 +3125,9 @@ directive("html", (el, {expression}, {effect: effect3, evaluateLater: evaluateLa
// packages/alpinejs/src/directives/x-bind.js
mapAttributes(startingWith(":", into(prefix("bind:"))));
directive("bind", (el, {value, modifiers, expression, original}, {effect: effect3}) => {
- if (!value)
+ if (!value) {
return applyBindingsObject(el, expression, original, effect3);
+ }
if (value === "key")
return storeKeyForXFor(el, expression);
let evaluate2 = evaluateLater(el, expression);
@@ -2968,32 +3138,29 @@ directive("bind", (el, {value, modifiers, expression, original}, {effect: effect
}));
});
function applyBindingsObject(el, expression, original, effect3) {
+ let bindingProviders = {};
+ injectBindingProviders(bindingProviders);
let getBindings = evaluateLater(el, expression);
let cleanupRunners = [];
- effect3(() => {
- while (cleanupRunners.length)
- cleanupRunners.pop()();
- getBindings((bindings) => {
- let attributes = Object.entries(bindings).map(([name, value]) => ({name, value}));
- attributes = attributes.filter((attr) => {
- return !(typeof attr.value === "object" && !Array.isArray(attr.value) && attr.value !== null);
- });
- let staticAttributes = attributesOnly(attributes);
- attributes = attributes.map((attribute) => {
- if (staticAttributes.find((attr) => attr.name === attribute.name)) {
- return {
- name: `x-bind:${attribute.name}`,
- value: `"${attribute.value}"`
- };
- }
- return attribute;
- });
- directives(el, attributes, original).map((handle) => {
- cleanupRunners.push(handle.runCleanups);
- handle();
- });
+ while (cleanupRunners.length)
+ cleanupRunners.pop()();
+ getBindings((bindings) => {
+ let attributes = Object.entries(bindings).map(([name, value]) => ({name, value}));
+ let staticAttributes = attributesOnly(attributes);
+ attributes = attributes.map((attribute) => {
+ if (staticAttributes.find((attr) => attr.name === attribute.name)) {
+ return {
+ name: `x-bind:${attribute.name}`,
+ value: `"${attribute.value}"`
+ };
+ }
+ return attribute;
});
- });
+ directives(el, attributes, original).map((handle) => {
+ cleanupRunners.push(handle.runCleanups);
+ handle();
+ });
+ }, {scope: bindingProviders});
}
function storeKeyForXFor(el, expression) {
el._x_keyExpression = expression;
@@ -3088,15 +3255,15 @@ function loop(el, iteratorNames, evaluateItems, evaluateKey) {
let keys = [];
if (isObject(items)) {
items = Object.entries(items).map(([key, value]) => {
- let scope = getIterationScopeVariables(iteratorNames, value, key, items);
- evaluateKey((value2) => keys.push(value2), {scope: {index: key, ...scope}});
- scopes.push(scope);
+ let scope2 = getIterationScopeVariables(iteratorNames, value, key, items);
+ evaluateKey((value2) => keys.push(value2), {scope: {index: key, ...scope2}});
+ scopes.push(scope2);
});
} else {
for (let i = 0; i < items.length; i++) {
- let scope = getIterationScopeVariables(iteratorNames, items[i], i, items);
- evaluateKey((value) => keys.push(value), {scope: {index: i, ...scope}});
- scopes.push(scope);
+ let scope2 = getIterationScopeVariables(iteratorNames, items[i], i, items);
+ evaluateKey((value) => keys.push(value), {scope: {index: i, ...scope2}});
+ scopes.push(scope2);
}
}
let adds = [];
@@ -3129,6 +3296,9 @@ function loop(el, iteratorNames, evaluateItems, evaluateKey) {
}
for (let i = 0; i < removes.length; i++) {
let key = removes[i];
+ if (!!lookup[key]._x_effects) {
+ lookup[key]._x_effects.forEach(dequeueJob);
+ }
lookup[key].remove();
lookup[key] = null;
delete lookup[key];
@@ -3141,7 +3311,9 @@ function loop(el, iteratorNames, evaluateItems, evaluateKey) {
mutateDom(() => {
elForSpot.after(marker);
elInSpot.after(elForSpot);
+ elForSpot._x_currentIfEl && elForSpot.after(elForSpot._x_currentIfEl);
marker.before(elInSpot);
+ elInSpot._x_currentIfEl && elInSpot.after(elInSpot._x_currentIfEl);
marker.remove();
});
refreshScope(elForSpot, scopes[keys.indexOf(keyForSpot)]);
@@ -3149,10 +3321,12 @@ function loop(el, iteratorNames, evaluateItems, evaluateKey) {
for (let i = 0; i < adds.length; i++) {
let [lastKey2, index] = adds[i];
let lastEl = lastKey2 === "template" ? templateEl : lookup[lastKey2];
- let scope = scopes[index];
+ if (lastEl._x_currentIfEl)
+ lastEl = lastEl._x_currentIfEl;
+ let scope2 = scopes[index];
let key = keys[index];
let clone2 = document.importNode(templateEl.content, true).firstElementChild;
- addScopeToNode(clone2, reactive(scope), templateEl);
+ addScopeToNode(clone2, reactive(scope2), templateEl);
mutateDom(() => {
lastEl.after(clone2);
initTree(clone2);
@@ -3241,6 +3415,11 @@ directive("if", (el, {expression}, {effect: effect3, cleanup}) => {
});
el._x_currentIfEl = clone2;
el._x_undoIf = () => {
+ walk(clone2, (node) => {
+ if (!!node._x_effects) {
+ node._x_effects.forEach(dequeueJob);
+ }
+ });
clone2.remove();
delete el._x_currentIfEl;
};
@@ -3258,11 +3437,23 @@ directive("if", (el, {expression}, {effect: effect3, cleanup}) => {
cleanup(() => el._x_undoIf && el._x_undoIf());
});
+// packages/alpinejs/src/directives/x-id.js
+directive("id", (el, {expression}, {evaluate: evaluate2}) => {
+ let names = evaluate2(expression);
+ names.forEach((name) => setIdRoot(el, name));
+});
+
// packages/alpinejs/src/directives/x-on.js
mapAttributes(startingWith("@", into(prefix("on:"))));
directive("on", skipDuringClone((el, {value, modifiers, expression}, {cleanup}) => {
let evaluate2 = expression ? evaluateLater(el, expression) : () => {
};
+ if (el.tagName.toLowerCase() === "template") {
+ if (!el._x_forwardEvents)
+ el._x_forwardEvents = [];
+ if (!el._x_forwardEvents.includes(value))
+ el._x_forwardEvents.push(value);
+ }
let removeListener = on(el, value, modifiers, (e) => {
evaluate2(() => {
}, {scope: {$event: e}, params: [e]});
@@ -3272,7 +3463,7 @@ directive("on", skipDuringClone((el, {value, modifiers, expression}, {cleanup})
// packages/csp/src/index.js
alpine_default.setEvaluator(cspCompliantEvaluator);
-alpine_default.setReactivityEngine({reactive: import_reactivity9.reactive, effect: import_reactivity9.effect, release: import_reactivity9.stop, raw: import_reactivity9.toRaw});
+alpine_default.setReactivityEngine({reactive: import_reactivity8.reactive, effect: import_reactivity8.effect, release: import_reactivity8.stop, raw: import_reactivity8.toRaw});
function cspCompliantEvaluator(el, expression) {
let overriddenMagics = {};
injectMagics(overriddenMagics, el);
@@ -3281,8 +3472,8 @@ function cspCompliantEvaluator(el, expression) {
return generateEvaluatorFromFunction(dataStack, expression);
}
let evaluator = (receiver = () => {
- }, {scope = {}, params = []} = {}) => {
- let completeScope = mergeProxies([scope, ...dataStack]);
+ }, {scope: scope2 = {}, params = []} = {}) => {
+ let completeScope = mergeProxies([scope2, ...dataStack]);
if (completeScope[expression] !== void 0) {
runIfTypeOfFunction(receiver, completeScope[expression], completeScope, params);
}
diff --git a/alpinejs/packages/csp/package.json b/alpinejs/packages/csp/package.json
new file mode 100644
index 0000000..0a6726b
--- /dev/null
+++ b/alpinejs/packages/csp/package.json
@@ -0,0 +1,12 @@
+{
+ "name": "@alpinejs/csp",
+ "version": "3.0.0-alpha.0",
+ "description": "A CSP compatible build of Alpine",
+ "author": "Caleb Porzio",
+ "license": "MIT",
+ "main": "dist/module.cjs.js",
+ "module": "dist/module.esm.js",
+ "dependencies": {
+ "@vue/reactivity": "^3.0.2"
+ }
+}
diff --git a/alpinejs/packages/csp/src/index.js b/alpinejs/packages/csp/src/index.js
new file mode 100644
index 0000000..9b5b26c
--- /dev/null
+++ b/alpinejs/packages/csp/src/index.js
@@ -0,0 +1,38 @@
+import Alpine from 'alpinejs/src/alpine'
+
+Alpine.setEvaluator(cspCompliantEvaluator)
+
+import { reactive, effect, stop, toRaw } from '@vue/reactivity'
+Alpine.setReactivityEngine({ reactive, effect, release: stop, raw: toRaw })
+
+import 'alpinejs/src/magics/index'
+import 'alpinejs/src/directives/index'
+
+import { closestDataStack, mergeProxies } from 'alpinejs/src/scope'
+import { injectMagics } from 'alpinejs/src/magics'
+import { generateEvaluatorFromFunction, runIfTypeOfFunction } from 'alpinejs/src/evaluator'
+import { tryCatch } from 'alpinejs/src/utils/error'
+
+function cspCompliantEvaluator(el, expression) {
+ let overriddenMagics = {}
+
+ injectMagics(overriddenMagics, el)
+
+ let dataStack = [overriddenMagics, ...closestDataStack(el)]
+
+ if (typeof expression === 'function') {
+ return generateEvaluatorFromFunction(dataStack, expression)
+ }
+
+ let evaluator = (receiver = () => {}, { scope = {}, params = [] } = {}) => {
+ let completeScope = mergeProxies([scope, ...dataStack])
+
+ if (completeScope[expression] !== undefined) {
+ runIfTypeOfFunction(receiver, completeScope[expression], completeScope, params)
+ }
+ }
+
+ return tryCatch.bind(null, el, expression, evaluator)
+}
+
+export default Alpine
diff --git a/alpinejs/packages/docs/package.json b/alpinejs/packages/docs/package.json
new file mode 100644
index 0000000..e888873
--- /dev/null
+++ b/alpinejs/packages/docs/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "@alpinejs/docs",
+ "version": "3.9.1-revision.1",
+ "description": "The documentation for Alpine",
+ "author": "Caleb Porzio",
+ "license": "MIT"
+}
diff --git a/alpinejs/packages/docs/src/en/advanced.md b/alpinejs/packages/docs/src/en/advanced.md
new file mode 100644
index 0000000..e0e2ae2
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/advanced.md
@@ -0,0 +1,5 @@
+---
+order: 8
+title: Advanced
+type: sub-directory
+---
diff --git a/alpinejs/packages/docs/src/en/advanced/async.md b/alpinejs/packages/docs/src/en/advanced/async.md
new file mode 100644
index 0000000..3f76576
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/advanced/async.md
@@ -0,0 +1,40 @@
+---
+order: 4
+title: Async
+---
+
+# Async
+
+Alpine is built to support asynchronous functions in most places it supports standard ones.
+
+For example, let's say you have a simple function called `getLabel()` that you use as the input to an `x-text` directive:
+
+```js
+function getLabel() {
+ return 'Hello World!'
+}
+```
+```alpine
+<span x-text="getLabel()"></span>
+```
+
+Because `getLabel` is synchronous, everything works as expected.
+
+Now let's pretend that `getLabel` makes a network request to retrieve the label and can't return one instantaneously (asynchronous). By making `getLabel` an async function, you can call it from Alpine using JavaScript's `await` syntax.
+
+```js
+async function getLabel() {
+ let response = await fetch('/api/label')
+
+ return await response.text()
+}
+```
+```alpine
+<span x-text="await getLabel()"></span>
+```
+
+Additionally, if you prefer calling methods in Alpine without the trailing parenthesis, you can leave them out and Alpine will detect that the provided function is async and handle it accordingly. For example:
+
+```alpine
+<span x-text="getLabel"></span>
+```
diff --git a/alpinejs/packages/docs/src/en/advanced/csp.md b/alpinejs/packages/docs/src/en/advanced/csp.md
new file mode 100644
index 0000000..a0bda72
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/advanced/csp.md
@@ -0,0 +1,72 @@
+---
+order: 5
+title: CSP
+---
+
+# CSP (Content-Security Policy)
+
+In order for Alpine to be able to execute plain strings from HTML attributes as JavaScript expressions, for example `x-on:click="console.log()"`, it needs to rely on utilities that violate the "unsafe-eval" content security policy.
+
+> Under the hood, Alpine doesn't actually use eval() itself because it's slow and problematic. Instead it uses Function declarations, which are much better, but still violate "unsafe-eval".
+
+In order to accommodate environments where this CSP is necessary, Alpine offers an alternate build that doesn't violate "unsafe-eval", but has a more restrictive syntax.
+
+<a name="installation"></a>
+## Installation
+
+Like all Alpine extensions, you can include this either via `<script>` tag or module import:
+
+<a name="script-tag"></a>
+### Script tag
+
+```alpine
+<html>
+ <script src="alpinejs/alpinejs-csp/cdn.js" defer></script>
+</html>
+```
+
+<a name="module-import"></a>
+### Module import
+
+```js
+import Alpine from '@alpinejs/csp'
+
+window.Alpine = Alpine
+window.Alpine.start()
+```
+
+<a name="restrictions"></a>
+## Restrictions
+
+Since Alpine can no longer interpret strings as plain JavaScript, it has to parse and construct JavaScript functions from them manually.
+
+Due to this limitation, you must use `Alpine.data` to register your `x-data` objects, and must reference properties and methods from it by key only.
+
+For example, an inline component like this will not work.
+
+```alpine
+<!-- Bad -->
+<div x-data="{ count: 1 }">
+ <button @click="count++">Increment</button>
+
+ <span x-text="count"></span>
+</div>
+```
+
+However, breaking out the expressions into external APIs, the following is valid with the CSP build:
+
+```alpine
+<!-- Good -->
+<div x-data="counter">
+ <button @click="increment">Increment</button>
+
+ <span x-text="count"></span>
+</div>
+```
+```js
+Alpine.data('counter', () => ({
+ count: 1,
+
+ increment() { this.count++ }
+}))
+```
diff --git a/alpinejs/packages/docs/src/en/advanced/extending.md b/alpinejs/packages/docs/src/en/advanced/extending.md
new file mode 100644
index 0000000..d75948c
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/advanced/extending.md
@@ -0,0 +1,360 @@
+---
+order: 2
+title: Extending
+---
+
+# Extending
+
+Alpine has a very open codebase that allows for extension in a number of ways. In fact, every available directive and magic in Alpine itself uses these exact APIs. In theory you could rebuild all of Alpine's functionality using them yourself.
+
+<a name="lifecycle-concerns"></a>
+## Lifecycle concerns
+Before we dive into each individual API, let's first talk about where in your codebase you should consume these APIs.
+
+Because these APIs have an impact on how Alpine initializes the page, they must be registered AFTER Alpine is downloaded and available on the page, but BEFORE it has initialized the page itself.
+
+There are two different techniques depending on if you are importing Alpine into a bundle, or including it directly via a `<script>` tag. Let's look at them both:
+
+<a name="via-script-tag"></a>
+### Via a script tag
+
+If you are including Alpine via a script tag, you will need to register any custom extension code inside an `alpine:init` event listener.
+
+Here's an example:
+
+```alpine
+<html>
+ <script src="/js/alpine.js" defer></script>
+
+ <div x-data x-foo></div>
+
+ <script>
+ document.addEventListener('alpine:init', () => {
+ Alpine.directive('foo', ...)
+ })
+ </script>
+</html>
+```
+
+If you want to extract your extension code into an external file, you will need to make sure that file's `<script>` tag is located BEFORE Alpine's like so:
+
+```alpine
+<html>
+ <script src="/js/foo.js" defer></script>
+ <script src="/js/alpine.js" defer></script>
+
+ <div x-data x-foo></div>
+</html>
+```
+
+<a name="via-npm"></a>
+### Via an NPM module
+
+If you imported Alpine into a bundle, you have to make sure you are registering any extension code IN BETWEEN when you import the `Alpine` global object, and when you initialize Alpine by calling `Alpine.start()`. For example:
+
+```js
+import Alpine from 'alpinejs'
+
+Alpine.directive('foo', ...)
+
+window.Alpine = Alpine
+window.Alpine.start()
+```
+
+Now that we know where to use these extension APIs, let's look more closely at how to use each one:
+
+<a name="custom-directives"></a>
+## Custom directives
+
+Alpine allows you to register your own custom directives using the `Alpine.directive()` API.
+
+<a name="method-signature"></a>
+### Method Signature
+
+```js
+Alpine.directive('[name]', (el, { value, modifiers, expression }, { Alpine, effect, cleanup }) => {})
+```
+
+&nbsp; | &nbsp;
+---|---
+name | The name of the directive. The name "foo" for example would be consumed as `x-foo`
+el | The DOM element the directive is added to
+value | If provided, the part of the directive after a colon. Ex: `'bar'` in `x-foo:bar`
+modifiers | An array of dot-separated trailing additions to the directive. Ex: `['baz', 'lob']` from `x-foo.baz.lob`
+expression | The attribute value portion of the directive. Ex: `law` from `x-foo="law"`
+Alpine | The Alpine global object
+effect | A function to create reactive effects that will auto-cleanup after this directive is removed from the DOM
+cleanup | A function you can pass bespoke callbacks to that will run when this directive is removed from the DOM
+
+<a name="simple-example"></a>
+### Simple Example
+
+Here's an example of a simple directive we're going to create called: `x-uppercase`:
+
+```js
+Alpine.directive('uppercase', el => {
+ el.textContent = el.textContent.toUpperCase()
+})
+```
+```alpine
+<div x-data>
+ <span x-uppercase>Hello World!</span>
+</div>
+```
+
+<a name="evaluating-expressions"></a>
+### Evaluating expressions
+
+When registering a custom directive, you may want to evaluate a user-supplied JavaScript expression:
+
+For example, let's say you wanted to create a custom directive as a shortcut to `console.log()`. Something like:
+
+```alpine
+<div x-data="{ message: 'Hello World!' }">
+ <div x-log="message"></div>
+</div>
+```
+
+You need to retrieve the actual value of `message` by evaluating it as a JavaScript expression with the `x-data` scope.
+
+Fortunately, Alpine exposes its system for evaluating JavaScript expressions with an `evaluate()` API. Here's an example:
+
+```js
+Alpine.directive('log', (el, { expression }, { evaluate }) => {
+ // expression === 'message'
+
+ console.log(
+ evaluate(expression)
+ )
+})
+```
+
+Now, when Alpine initializes the `<div x-log...>`, it will retrieve the expression passed into the directive ("message" in this case), and evaluate it in the context of the current element's Alpine component scope.
+
+<a name="introducing-reactivity"></a>
+### Introducing reactivity
+
+Building on the `x-log` example from before, let's say we wanted `x-log` to log the value of `message` and also log it if the value changes.
+
+Given the following template:
+
+```alpine
+<div x-data="{ message: 'Hello World!' }">
+ <div x-log="message"></div>
+
+ <button @click="message = 'yolo'">Change</button>
+</div>
+```
+
+We want "Hello World!" to be logged initially, then we want "yolo" to be logged after pressing the `<button>`.
+
+We can adjust the implementation of `x-log` and introduce two new APIs to achieve this: `evaluateLater()` and `effect()`:
+
+```js
+Alpine.directive('log', (el, { expression }, { evaluateLater, effect }) => {
+ let getThingToLog = evaluateLater(expression)
+
+ effect(() => {
+ getThingToLog(thingToLog => {
+ console.log(thingToLog)
+ })
+ })
+})
+```
+
+Let's walk through the above code, line by line.
+
+```js
+let getThingToLog = evaluateLater(expression)
+```
+
+Here, instead of immediately evaluating `message` and retrieving the result, we will convert the string expression ("message") into an actual JavaScript function that we can run at any time. If you're going to evaluate a JavaScript expression more than once, it is highly recommended to first generate a JavaScript function and use that rather than calling `evaluate()` directly. The reason being that the process to interpret a plain string as a JavaScript function is expensive and should be avoided when unnecessary.
+
+```js
+effect(() => {
+ ...
+})
+```
+
+By passing in a callback to `effect()`, we are telling Alpine to run the callback immediately, then track any dependencies it uses (`x-data` properties like `message` in our case). Now as soon as one of the dependencies changes, this callback will be re-run. This gives us our "reactivity".
+
+You may recognize this functionality from `x-effect`. It is the same mechanism under the hood.
+
+You may also notice that `Alpine.effect()` exists and wonder why we're not using it here. The reason is that the `effect` function provided via the method parameter has special functionality that cleans itself up when the directive is removed from the page for any reason.
+
+For example, if for some reason the element with `x-log` on it got removed from the page, by using `effect()` instead of `Alpine.effect()` when the `message` property is changed, the value will no longer be logged to the console.
+
+[→ Read more about reactivity in Alpine](/advanced/reactivity)
+
+```js
+getThingToLog(thingToLog => {
+ console.log(thingToLog)
+})
+```
+
+Now we will call `getThingToLog`, which if you recall is the actual JavaScript function version of the string expression: "message".
+
+You might expect `getThingToCall()` to return the result right away, but instead Alpine requires you to pass in a callback to receive the result.
+
+The reason for this is to support async expressions like `await getMessage()`. By passing in a "receiver" callback instead of getting the result immediately, you are allowing your directive to work with async expressions as well.
+
+[→ Read more about async in Alpine](/advanced/async)
+
+<a name="cleaning-up"></a>
+### Cleaning Up
+
+Let's say you needed to register an event listener from a custom directive. After that directive is removed from the page for any reason, you would want to remove the event listener as well.
+
+Alpine makes this simple by providing you with a `cleanup` function when registering custom directives.
+
+Here's an example:
+
+```js
+Alpine.directive('...', (el, {}, { cleanup }) => {
+ let handler = () => {}
+
+ window.addEventListener('click', handler)
+
+ cleanup(() => {
+ window.removeEventListener('click', handler)
+ })
+
+})
+```
+
+Now if the directive is removed from this element or the element is removed itself, the event listener will be removed as well.
+
+<a name="custom-magics"></a>
+## Custom magics
+
+Alpine allows you to register custom "magics" (properties or methods) using `Alpine.magic()`. Any magic you register will be available to all your application's Alpine code with the `$` prefix.
+
+<a name="method-signature"></a>
+### Method Signature
+
+```js
+Alpine.magic('[name]', (el, { Alpine }) => {})
+```
+
+&nbsp; | &nbsp;
+---|---
+name | The name of the magic. The name "foo" for example would be consumed as `$foo`
+el | The DOM element the magic was triggered from
+Alpine | The Alpine global object
+
+<a name="magic-properties"></a>
+### Magic Properties
+
+Here's a basic example of a "$now" magic helper to easily get the current time from anywhere in Alpine:
+
+```js
+Alpine.magic('now', () => {
+ return (new Date).toLocaleTimeString()
+})
+```
+```alpine
+<span x-text="$now"></span>
+```
+
+Now the `<span>` tag will contain the current time, resembling something like "12:00:00 PM".
+
+As you can see `$now` behaves like a static property, but under the hood is actually a getter that evaluates every time the property is accessed.
+
+Because of this, you can implement magic "functions" by returning a function from the getter.
+
+<a name="magic-functions"></a>
+### Magic Functions
+
+For example, if we wanted to create a `$clipboard()` magic function that accepts a string to copy to clipboard, we could implement it like so:
+
+```js
+Alpine.magic('clipboard', () => {
+ return subject => navigator.clipboard.writeText(subject)
+})
+```
+```alpine
+<button @click="$clipboard('hello world')">Copy "Hello World"</button>
+```
+
+Now that accessing `$clipboard` returns a function itself, we can immediately call it and pass it an argument like we see in the template with `$clipboard('hello world')`.
+
+You can use the more brief syntax (a double arrow function) for returning a function from a function if you'd prefer:
+
+```js
+Alpine.magic('clipboard', () => subject => {
+ navigator.clipboard.writeText(subject)
+})
+```
+
+<a name="writing-and-sharing-plugins"></a>
+## Writing and sharing plugins
+
+By now you should see how friendly and simple it is to register your own custom directives and magics in your application, but what about sharing that functionality with others via an NPM package or something?
+
+You can get started quickly with Alpine's official "plugin-blueprint" package. It's as simple as cloning the repository and running `npm install && npm run build` to get a plugin authored.
+
+For demonstration purposes, let's create a pretend Alpine plugin from scratch called `Foo` that includes both a directive (`x-foo`) and a magic (`$foo`).
+
+We'll start producing this plugin for consumption as a simple `<script>` tag alongside Alpine, then we'll level it up to a module for importing into a bundle:
+
+<a name="script-include"></a>
+### Script include
+
+Let's start in reverse by looking at how our plugin will be included into a project:
+
+```alpine
+<html>
+ <script src="/js/foo.js" defer></script>
+ <script src="/js/alpine.js" defer></script>
+
+ <div x-data x-init="$foo()">
+ <span x-foo="'hello world'">
+ </div>
+</html>
+```
+
+Notice how our script is included BEFORE Alpine itself. This is important, otherwise, Alpine would have already been initialized by the time our plugin got loaded.
+
+Now let's look inside of `/js/foo.js`'s contents:
+
+```js
+document.addEventListener('alpine:init', () => {
+ window.Alpine.directive('foo', ...)
+
+ window.Alpine.magic('foo', ...)
+})
+```
+
+That's it! Authoring a plugin for inclusion via a script tag is extremely simple with Alpine.
+
+<a name="bundle-module"></a>
+### Bundle module
+
+Now let's say you wanted to author a plugin that someone could install via NPM and include into their bundle.
+
+Like the last example, we'll walk through this in reverse, starting with what it will look like to consume this plugin:
+
+```js
+import Alpine from 'alpinejs'
+
+import foo from 'foo'
+Alpine.plugin(foo)
+
+window.Alpine = Alpine
+window.Alpine.start()
+```
+
+You'll notice a new API here: `Alpine.plugin()`. This is a convenience method Alpine exposes to prevent consumers of your plugin from having to register multiple different directives and magics themselves.
+
+Now let's look at the source of the plugin and what gets exported from `foo`:
+
+```js
+export default function (Alpine) {
+ Alpine.directive('foo', ...)
+ Alpine.magic('foo', ...)
+}
+```
+
+You'll see that `Alpine.plugin` is incredibly simple. It accepts a callback and immediately invokes it while providing the `Alpine` global as a parameter for use inside of it.
+
+Then you can go about extending Alpine as you please.
diff --git a/alpinejs/packages/docs/src/en/advanced/reactivity.md b/alpinejs/packages/docs/src/en/advanced/reactivity.md
new file mode 100644
index 0000000..ddbb601
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/advanced/reactivity.md
@@ -0,0 +1,101 @@
+---
+order: 1
+title: Reactivity
+---
+
+# Reactivity
+
+Alpine is "reactive" in the sense that when you change a piece of data, everything that depends on that data "reacts" automatically to that change.
+
+Every bit of reactivity that takes place in Alpine, happens because of two very important reactive functions in Alpine's core: `Alpine.reactive()`, and `Alpine.effect()`.
+
+> Alpine uses VueJS's reactivity engine under the hood to provide these functions.
+> [→ Read more about @vue/reactivity](https://github.com/vuejs/vue-next/tree/master/packages/reactivity)
+
+Understanding these two functions will give you super powers as an Alpine developer, but also just as a web developer in general.
+
+<a name="alpine-reactive"></a>
+## Alpine.reactive()
+
+Let's first look at `Alpine.reactive()`. This function accepts a JavaScript object as its parameter and returns a "reactive" version of that object. For example:
+
+```js
+let data = { count: 1 }
+
+let reactiveData = Alpine.reactive(data)
+```
+
+Under the hood, when `Alpine.reactive` receives `data`, it wraps it inside a custom JavaScript proxy.
+
+A proxy is a special kind of object in JavaScript that can intercept "get" and "set" calls to a JavaScript object.
+
+[→ Read more about JavaScript proxies](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy)
+
+At face value, `reactiveData` should behave exactly like `data`. For example:
+
+```js
+console.log(data.count) // 1
+console.log(reactiveData.count) // 1
+
+reactiveData.count = 2
+
+console.log(data.count) // 2
+console.log(reactiveData.count) // 2
+```
+
+What you see here is that because `reactiveData` is a thin wrapper around `data`, any attempts to get or set a property will behave exactly as if you had interacted with `data` directly.
+
+The main difference here is that any time you modify or retrieve (get or set) a value from `reactiveData`, Alpine is aware of it and can execute any other logic that depends on this data.
+
+`Alpine.reactive` is only the first half of the story. `Alpine.effect` is the other half, let's dig in.
+
+<a name="alpine-effect"></a><a name="alpine-effect"></a>
+## Alpine.effect()
+
+`Alpine.effect` accepts a single callback function. As soon as `Alpine.effect` is called, it will run the provided function, but actively look for any interactions with reactive data. If it detects an interaction (a get or set from the aforementioned reactive proxy) it will keep track of it and make sure to re-run the callback if any of reactive data changes in the future. For example:
+
+```js
+let data = Alpine.reactive({ count: 1 })
+
+Alpine.effect(() => {
+ console.log(data.count)
+})
+```
+
+When this code is first run, "1" will be logged to the console. Any time `data.count` changes, it's value will be logged to the console again.
+
+This is the mechanism that unlocks all of the reactivity at the core of Alpine.
+
+To connect the dots further, let's look at a simple "counter" component example without using Alpine syntax at all, only using `Alpine.reactive` and `Alpine.effect`:
+
+```alpine
+<button>Increment</button>
+
+Count: <span></span>
+```
+```js
+let button = document.querySelector('button')
+let span = document.querySelector('span')
+
+let data = Alpine.reactive({ count: 1 })
+
+Alpine.effect(() => {
+ span.textContent = data.count
+})
+
+button.addEventListener('click', () => {
+ data.count = data.count + 1
+})
+```
+
+<!-- START_VERBATIM -->
+<div x-data="{ count: 1 }" class="demo">
+ <button @click="count++">Increment</button>
+
+ <div>Count: <span x-text="count"></span></div>
+</div>
+<!-- END_VERBATIM -->
+
+As you can see, you can make any data reactive, and you can also wrap any functionality in `Alpine.effect`.
+
+This combination unlocks an incredibly powerful programming paradigm for web development. Run wild and free.
diff --git a/alpinejs/packages/docs/src/en/directives.md b/alpinejs/packages/docs/src/en/directives.md
new file mode 100644
index 0000000..ef15b7b
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/directives.md
@@ -0,0 +1,7 @@
+---
+order: 4
+title: Directives
+prefix: x-
+font-type: mono
+type: sub-directory
+---
diff --git a/alpinejs/packages/docs/src/en/directives/bind.md b/alpinejs/packages/docs/src/en/directives/bind.md
new file mode 100644
index 0000000..65074eb
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/directives/bind.md
@@ -0,0 +1,197 @@
+---
+order: 4
+title: bind
+---
+
+# x-bind
+
+`x-bind` allows you to set HTML attributes on elements based on the result of JavaScript expressions.
+
+For example, here's a component where we will use `x-bind` to set the placeholder value of an input.
+
+```alpine
+<div x-data="{ placeholder: 'Type here...' }">
+ <input type="text" x-bind:placeholder="placeholder">
+</div>
+```
+
+<a name="shorthand-syntax"></a>
+## Shorthand syntax
+
+If `x-bind:` is too verbose for your liking, you can use the shorthand: `:`. For example, here is the same input element as above, but refactored to use the shorthand syntax.
+
+```alpine
+<input type="text" :placeholder="placeholder">
+```
+
+<a name="binding-classes"></a>
+## Binding classes
+
+`x-bind` is most often useful for setting specific classes on an element based on your Alpine state.
+
+Here's a simple example of a simple dropdown toggle, but instead of using `x-show`, we'll use a "hidden" class to toggle an element.
+
+```alpine
+<div x-data="{ open: false }">
+ <button x-on:click="open = ! open">Toggle Dropdown</button>
+
+ <div :class="open ? '' : 'hidden'">
+ Dropdown Contents...
+ </div>
+</div>
+```
+
+Now, when `open` is `false`, the "hidden" class will be added to the dropdown.
+
+<a name="shorthand-conditionals"></a>
+### Shorthand conditionals
+
+In cases like these, if you prefer a less verbose syntax you can use JavaScript's short-circuit evaluation instead of standard conditionals:
+
+```alpine
+<div :class="show ? '' : 'hidden'">
+<!-- Is equivalent to: -->
+<div :class="show || 'hidden'">
+```
+
+The inverse is also available to you. Suppose instead of `open`, we use a variable with the opposite value: `closed`.
+
+```alpine
+<div :class="closed ? 'hidden' : ''">
+<!-- Is equivalent to: -->
+<div :class="closed && 'hidden'">
+```
+
+<a name="class-object-syntax"></a>
+### Class object syntax
+
+Alpine offers an additional syntax for toggling classes if you prefer. By passing a JavaScript object where the classes are the keys and booleans are the values, Alpine will know which classes to apply and which to remove. For example:
+
+```alpine
+<div :class="{ 'hidden': ! show }">
+```
+
+This technique offers a unique advantage to other methods. When using object-syntax, Alpine will NOT preserve original classes applied to an element's `class` attribute.
+
+For example, if you wanted to apply the "hidden" class to an element before Alpine loads, AND use Alpine to toggle its existence you can only achieve that behavior using object-syntax:
+
+```alpine
+<div class="hidden" :class="{ 'hidden': ! show }">
+```
+
+In case that confused you, let's dig deeper into how Alpine handles `x-bind:class` differently than other attributes.
+
+<a name="special-behavior"></a>
+### Special behavior
+
+`x-bind:class` behaves differently than other attributes under the hood.
+
+Consider the following case.
+
+```alpine
+<div class="opacity-50" :class="hide && 'hidden'">
+```
+
+If "class" were any other attribute, the `:class` binding would overwrite any existing class attribute, causing `opacity-50` to be overwritten by either `hidden` or `''`.
+
+However, Alpine treats `class` bindings differently. It's smart enough to preserve existing classes on an element.
+
+For example, if `hide` is true, the above example will result in the following DOM element:
+
+```alpine
+<div class="opacity-50 hidden">
+```
+
+If `hide` is false, the DOM element will look like:
+
+```alpine
+<div class="opacity-50">
+```
+
+This behavior should be invisible and intuitive to most users, but it is worth mentioning explicitly for the inquiring developer or any special cases that might crop up.
+
+<a name="binding-styles"></a>
+## Binding styles
+
+Similar to the special syntax for binding classes with JavaScript objects, Alpine also offers an object-based syntax for binding `style` attributes.
+
+Just like the class objects, this syntax is entirely optional. Only use it if it affords you some advantage.
+
+```alpine
+<div :style="{ color: 'red', display: 'flex' }">
+
+<!-- Will render: -->
+<div style="color: red; display: flex;" ...>
+```
+
+Conditional inline styling is possible using expressions just like with x-bind:class. Short circuit operators can be used here as well by using a styles object as the second operand.
+```alpine
+<div x-bind:style="true && { color: 'red' }">
+
+<!-- Will render: -->
+<div style="color: red;">
+```
+
+One advantage of this approach is being able to mix it in with existing styles on an element:
+
+```alpine
+<div style="padding: 1rem;" :style="{ color: 'red', display: 'flex' }">
+
+<!-- Will render: -->
+<div style="padding: 1rem; color: red; display: flex;" ...>
+```
+
+And like most expressions in Alpine, you can always use the result of a JavaScript expression as the reference:
+
+```alpine
+<div x-data="{ styles: { color: 'red', display: 'flex' }}">
+ <div :style="styles">
+</div>
+
+<!-- Will render: -->
+<div ...>
+ <div style="color: red; display: flex;" ...>
+</div>
+```
+
+<a name="bind-directives"></a>
+## Binding Alpine Directives Directly
+
+`x-bind` allows you to bind an object of different directives and attributes to an element.
+
+The object keys can be anything you would normally write as an attribute name in Alpine. This includes Alpine directives and modifiers, but also plain HTML attributes. The object values are either plain strings, or in the case of dynamic Alpine directoves, callbacks to be evaluated by Alpine.
+
+```alpine
+<div x-data="dropdown()">
+ <button x-bind="trigger">Open Dropdown</button>
+
+ <span x-bind="dialogue">Dropdown Contents</span>
+</div>
+
+<script>
+ document.addEventListener('alpine:init', () => {
+ Alpine.data('dropdown', () => ({
+ open: false,
+
+ trigger: {
+ ['@click']() {
+ this.open = true
+ },
+ },
+
+ dialogue: {
+ ['x-show']() {
+ return this.open
+ },
+ ['@click.outside']() {
+ this.open = false
+ },
+ },
+ }))
+ })
+</script>
+```
+
+There are a couple of caveats to this usage of `x-bind`:
+
+> When the directive being "bound" or "applied" is `x-for`, you should return a normal expression string from the callback. For example: `['x-for']() { return 'item in items' }`
diff --git a/alpinejs/packages/docs/src/en/directives/cloak.md b/alpinejs/packages/docs/src/en/directives/cloak.md
new file mode 100644
index 0000000..e7616a8
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/directives/cloak.md
@@ -0,0 +1,38 @@
+---
+order: 12
+title: cloak
+---
+
+# x-cloak
+
+Sometimes, when you're using AlpineJS for a part of your template, there is a "blip" where you might see your uninitialized template after the page loads, but before Alpine loads.
+
+`x-cloak` addresses this scenario by hiding the element it's attached to until Alpine is fully loaded on the page.
+
+For `x-cloak` to work however, you must add the following CSS to the page.
+
+```css
+[x-cloak] { display: none !important; }
+```
+
+Now, the following example will hide the `<span>` tag until Alpine has set its text content to the `message` property.
+
+```alpine
+<span x-cloak x-text="message"></span>
+```
+
+When Alpine loads on the page, it removes all `x-cloak` property from the element, which also removes the `display: none;` applied by CSS, therefore showing the element.
+
+If you'd like to achieve this same behavior, but avoid having to include a global style, you can use the following cool, but admittedly odd trick:
+
+```alpine
+<template x-if="true">
+ <span x-text="message"></span>
+</template>
+```
+
+This will achieve the same goal as `x-cloak` by just leveraging the way `x-if` works.
+
+Because `<template>` elements are "hidden" in browsers by default, you won't see the `<span>` until Alpine has had a chance to render the `x-if="true"` and show it.
+
+Again, this solution is not for everyone, but it's worth mentioning for special cases.
diff --git a/alpinejs/packages/docs/src/en/directives/data.md b/alpinejs/packages/docs/src/en/directives/data.md
new file mode 100644
index 0000000..7705370
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/directives/data.md
@@ -0,0 +1,170 @@
+---
+order: 1
+title: data
+---
+
+# x-data
+
+Everything in Alpine starts with the `x-data` directive.
+
+`x-data` defines a chunk of HTML as an Alpine component and provides the reactive data for that component to reference.
+
+Here's an example of a contrived dropdown component:
+
+```alpine
+<div x-data="{ open: false }">
+ <button @click="open = ! open">Toggle Content</button>
+
+ <div x-show="open">
+ Content...
+ </div>
+</div>
+```
+
+Don't worry about the other directives in this example (`@click` and `x-show`), we'll get to those in a bit. For now, let's focus on `x-data`.
+
+<a name="scope"></a>
+## Scope
+
+Properties defined in an `x-data` directive are available to all element children. Even ones inside other, nested `x-data` components.
+
+For example:
+
+```alpine
+<div x-data="{ foo: 'bar' }">
+ <span x-text="foo"><!-- Will output: "bar" --></span>
+
+ <div x-data="{ bar: 'baz' }">
+ <span x-text="foo"><!-- Will output: "bar" --></span>
+
+ <div x-data="{ foo: 'bob' }">
+ <span x-text="foo"><!-- Will output: "bob" --></span>
+ </div>
+ </div>
+</div>
+```
+
+<a name="methods"></a>
+## Methods
+
+Because `x-data` is evaluated as a normal JavaScript object, in addition to state, you can store methods and even getters.
+
+For example, let's extract the "Toggle Content" behavior into a method on `x-data`.
+
+```alpine
+<div x-data="{ open: false, toggle() { this.open = ! this.open } }">
+ <button @click="toggle()">Toggle Content</button>
+
+ <div x-show="open">
+ Content...
+ </div>
+</div>
+```
+
+Notice the added `toggle() { this.open = ! this.open }` method on `x-data`. This method can now be called from anywhere inside the component.
+
+You'll also notice the usage of `this.` to access state on the object itself. This is because Alpine evaluates this data object like any standard JavaScript object with a `this` context.
+
+If you prefer, you can leave the calling parenthesis off of the `toggle` method completely. For example:
+
+```alpine
+<!-- Before -->
+<button @click="toggle()">...</button>
+
+<!-- After -->
+<button @click="toggle">...</button>
+```
+
+<a name="getters"></a>
+## Getters
+
+JavaScript [getters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get) are handy when the sole purpose of a method is to return data based on other state.
+
+Think of them like "computed properties" (although, they are not cached like Vue's computed properties).
+
+Let's refactor our component to use a getter called `isOpen` instead of accessing `open` directly.
+
+```alpine
+<div x-data="{
+ open: false,
+ get isOpen() { return this.open },
+ toggle() { this.open = ! this.open },
+}">
+ <button @click="toggle()">Toggle Content</button>
+
+ <div x-show="isOpen">
+ Content...
+ </div>
+</div>
+```
+
+Notice the "Content" now depends on the `isOpen` getter instead of the `open` property directly.
+
+In this case there is no tangible benefit. But in some cases, getters are helpful for providing a more expressive syntax in your components.
+
+<a name="data-less-components"></a>
+## Data-less components
+
+Occasionally, you want to create an Alpine component, but you don't need any data.
+
+In these cases, you can always pass in an empty object.
+
+```alpine
+<div x-data="{}">
+```
+
+However, if you wish, you can also eliminate the attribute value entirely if it looks better to you.
+
+```alpine
+<div x-data>
+```
+
+<a name="single-element-components"></a>
+## Single-element components
+
+Sometimes you may only have a single element inside your Alpine component, like the following:
+
+```alpine
+<div x-data="{ open: true }">
+ <button @click="open = false" x-show="open">Hide Me</button>
+</div>
+```
+
+In these cases, you can declare `x-data` directly on that single element:
+
+```alpine
+<button x-data="{ open: true }" @click="open = false" x-show="open">
+ Hide Me
+</button>
+```
+
+<a name="re-usable-data"></a>
+## Re-usable Data
+
+If you find yourself duplicating the contents of `x-data`, or you find the inline syntax verbose, you can extract the `x-data` object out to a dedicated component using `Alpine.data`.
+
+Here's a quick example:
+
+```alpine
+<div x-data="dropdown">
+ <button @click="toggle">Toggle Content</button>
+
+ <div x-show="open">
+ Content...
+ </div>
+</div>
+
+<script>
+ document.addEventListener('alpine:init', () => {
+ Alpine.data('dropdown', () => ({
+ open: false,
+
+ toggle() {
+ this.open = ! this.open
+ },
+ }))
+ })
+</script>
+```
+
+[→ Read more about `Alpine.data(...)`](/globals/alpine-data)
diff --git a/alpinejs/packages/docs/src/en/directives/effect.md b/alpinejs/packages/docs/src/en/directives/effect.md
new file mode 100644
index 0000000..d1b5cdf
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/directives/effect.md
@@ -0,0 +1,20 @@
+---
+order: 11
+title: effect
+---
+
+# x-effect
+
+`x-effect` is a useful directive for re-evaluating an expression when one of its dependencies change. You can think of it as a watcher where you don't have to specify what property to watch, it will watch all properties used within it.
+
+If this definition is confusing for you, that's ok. It's better explained through an example:
+
+```alpine
+<div x-data="{ label: 'Hello' }" x-effect="console.log(label)">
+ <button @click="label += ' World!'">Change Message</button>
+</div>
+```
+
+When this component is loaded, the `x-effect` expression will be run and "Hello" will be logged into the console.
+
+Because Alpine knows about any property references contained within `x-effect`, when the button is clicked and `label` is changed, the effect will be re-triggered and "Hello World!" will be logged to the console.
diff --git a/alpinejs/packages/docs/src/en/directives/for.md b/alpinejs/packages/docs/src/en/directives/for.md
new file mode 100644
index 0000000..7526af1
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/directives/for.md
@@ -0,0 +1,87 @@
+---
+order: 8
+title: for
+---
+
+# x-for
+
+Alpine's `x-for` directive allows you to create DOM elements by iterating through a list. Here's a simple example of using it to create a list of colors based on an array.
+
+```alpine
+<ul x-data="{ colors: ['Red', 'Orange', 'Yellow'] }">
+ <template x-for="color in colors">
+ <li x-text="color"></li>
+ </template>
+</ul>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <ul x-data="{ colors: ['Red', 'Orange', 'Yellow'] }">
+ <template x-for="color in colors">
+ <li x-text="color"></li>
+ </template>
+ </ul>
+</div>
+<!-- END_VERBATIM -->
+
+There are two rules worth noting about `x-for`:
+
+* `x-for` MUST be declared on a `<template>` element
+* That `<template>` element MUST have only one root element
+
+<a name="keys"></a>
+## Keys
+
+It is important to specify keys for each `x-for` iteration if you are going to be re-ordering items. Without dynamic keys, Alpine may have a hard time keeping track of what re-orders and will cause odd side-effects.
+
+```alpine
+<ul x-data="{ colors: [
+ { id: 1, label: 'Red' },
+ { id: 2, label: 'Orange' },
+ { id: 3, label: 'Yellow' },
+]}">
+ <template x-for="color in colors" :key="color.id">
+ <li x-text="color.label"></li>
+ </template>
+</ul>
+```
+
+Now if the colors are added, removed, re-ordered, or their "id"s change, Alpine will preserve or destroy the iterated `<li>`elements accordingly.
+
+<a name="accessing-indexes"></a>
+## Accessing indexes
+
+If you need to access the index of each item in the iteration, you can do so using the `([item], [index]) in [items]` syntax like so:
+
+```alpine
+<ul x-data="{ colors: ['Red', 'Orange', 'Yellow'] }">
+ <template x-for="(color, index) in colors">
+ <li>
+ <span x-text="index + ': '"></span>
+ <span x-text="color"></span>
+ </li>
+ </template>
+</ul>
+```
+
+You can also access the index inside a dynamic `:key` expression.
+
+```alpine
+<template x-for="(color, index) in colors" :key="index">
+```
+
+<a name="iterating-over-a-range"></a>
+## Iterating over a range
+
+If you need to simply loop `n` number of times, rather than iterate through an array, Alpine offers a short syntax.
+
+```alpine
+<ul>
+ <template x-for="i in 10">
+ <li x-text="i"></li>
+ </template>
+</ul>
+```
+
+`i` in this case can be named anything you like.
diff --git a/alpinejs/packages/docs/src/en/directives/html.md b/alpinejs/packages/docs/src/en/directives/html.md
new file mode 100644
index 0000000..43a519e
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/directives/html.md
@@ -0,0 +1,29 @@
+---
+order: 7
+title: html
+---
+
+# x-html
+
+`x-html` sets the "innerHTML" property of an element to the result of a given expression.
+
+> ⚠️ Only use on trusted content and never on user-provided content. ⚠️
+> Dynamically rendering HTML from third parties can easily lead to XSS vulnerabilities.
+
+Here's a basic example of using `x-html` to display a user's username.
+
+```alpine
+<div x-data="{ username: '<strong>calebporzio</strong>' }">
+ Username: <span x-html="username"></span>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <div x-data="{ username: '<strong>calebporzio</strong>' }">
+ Username: <span x-html="username"></span>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+Now the `<span>` tag's inner HTML will be set to "<strong>calebporzio</strong>".
diff --git a/alpinejs/packages/docs/src/en/directives/id.md b/alpinejs/packages/docs/src/en/directives/id.md
new file mode 100644
index 0000000..b1faedd
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/directives/id.md
@@ -0,0 +1,33 @@
+---
+order: 17
+title: id
+---
+
+# x-id
+`x-id` allows you to declare a new "scope" for any new IDs generated using `$id()`. It accepts an array of strings (ID names) and adds a suffix to each `$id('...')` generated within it that is unique to other IDs on the page.
+
+`x-id` is meant to be used in conjunction with the `$id(...)` magic.
+
+[Visit the $id documentation](/magics/id) for a better understanding of this feature.
+
+Here's a brief example of this directive in use:
+
+```alpine
+<div x-id="['text-input']">
+ <label :for="$id('text-input')">Username</label>
+ <!-- for="text-input-1" -->
+
+ <input type="text" :id="$id('text-input')">
+ <!-- id="text-input-1" -->
+</div>
+
+<div x-id="['text-input']">
+ <label :for="$id('text-input')">Username</label>
+ <!-- for="text-input-2" -->
+
+ <input type="text" :id="$id('text-input')">
+ <!-- id="text-input-2" -->
+</div>
+```
+
+
diff --git a/alpinejs/packages/docs/src/en/directives/if.md b/alpinejs/packages/docs/src/en/directives/if.md
new file mode 100644
index 0000000..b8300f3
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/directives/if.md
@@ -0,0 +1,20 @@
+---
+order: 16
+title: if
+---
+
+# x-if
+
+`x-if` is used for toggling elements on the page, similarly to `x-show`, however it completely adds and removes the element it's applied to rather than just changing its CSS display property to "none".
+
+Because of this difference in behavior, `x-if` should not be applied directly to the element, but instead to a `<template>` tag that encloses the element. This way, Alpine can keep a record of the element once it's removed from the page.
+
+```alpine
+<template x-if="open">
+ <div>Contents...</div>
+</template>
+```
+
+> Unlike `x-show`, `x-if`, does NOT support transitioning toggles with `x-transition`.
+
+> Remember: `<template>` tags can only contain one root level element.
diff --git a/alpinejs/packages/docs/src/en/directives/ignore.md b/alpinejs/packages/docs/src/en/directives/ignore.md
new file mode 100644
index 0000000..15a18f1
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/directives/ignore.md
@@ -0,0 +1,20 @@
+---
+order: 11
+title: ignore
+---
+
+# x-ignore
+
+By default, Alpine will crawl and initialize the entire DOM tree of an element containing `x-init` or `x-data`.
+
+If for some reason, you don't want Alpine to touch a specific section of your HTML, you can prevent it from doing so using `x-ignore`.
+
+```alpine
+<div x-data="{ label: 'From Alpine' }">
+ <div x-ignore>
+ <span x-text="label"></span>
+ </div>
+</div>
+```
+
+In the above example, the `<span>` tag will not contain "From Alpine" because we told Alpine to ignore the contents of the `div` completely.
diff --git a/alpinejs/packages/docs/src/en/directives/init.md b/alpinejs/packages/docs/src/en/directives/init.md
new file mode 100644
index 0000000..9e4d2eb
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/directives/init.md
@@ -0,0 +1,74 @@
+---
+order: 2
+title: init
+---
+
+# x-init
+
+The `x-init` directive allows you to hook into the initialization phase of any element in Alpine.
+
+```alpine
+<div x-init="console.log('I\'m being initialized!')"></div>
+```
+
+In the above example, "I\'m being initialized!" will be output in the console before it makes further DOM updates.
+
+Consider another example where `x-init` is used to fetch some JSON and store it in `x-data` before the component is processed.
+
+```alpine
+<div
+ x-data="{ posts: [] }"
+ x-init="posts = await (await fetch('/posts')).json()"
+>...</div>
+```
+
+<a name="next-tick"></a>
+## $nextTick
+
+Sometimes, you want to wait until after Alpine has completely finished rendering to execute some code.
+
+This would be something like `useEffect(..., [])` in react, or `mount` in Vue.
+
+By using Alpine's internal `$nextTick` magic, you can make this happen.
+
+```alpine
+<div x-init="$nextTick(() => { ... })"></div>
+```
+
+<a name="standalone-x-init"></a>
+## Standalone `x-init`
+
+You can add `x-init` to any elements inside or outside an `x-data` HTML block. For example:
+
+```alpine
+<div x-data>
+ <span x-init="console.log('I can initialize')"></span>
+</div>
+
+<span x-init="console.log('I can initialize too')"></span>
+```
+
+<a name="auto-evaluate-init-method"></a>
+## Auto-evaluate init() method
+
+If the `x-data` object of a component contains an `init()` method, it will be called automatically. For example:
+
+```alpine
+<div x-data="{
+ init() {
+ console.log('I am called automatically')
+ }
+}">
+ ...
+</div>
+```
+
+This is also the case for components that were registered using the `Alpine.data()` syntax.
+
+```js
+Alpine.data('dropdown', () => ({
+ init() {
+ console.log('I will get evaluated when initializing each "dropdown" component.')
+ },
+}))
+```
diff --git a/alpinejs/packages/docs/src/en/directives/model.md b/alpinejs/packages/docs/src/en/directives/model.md
new file mode 100644
index 0000000..8e9831b
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/directives/model.md
@@ -0,0 +1,374 @@
+---
+order: 7
+title: model
+---
+
+# x-model
+
+`x-model` allows you to bind the value of an input element to Alpine data.
+
+Here's a simple example of using `x-model` to bind the value of a text field to a piece of data in Alpine.
+
+```alpine
+<div x-data="{ message: '' }">
+ <input type="text" x-model="message">
+
+ <span x-text="message">
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <div x-data="{ message: '' }">
+ <input type="text" x-model="message" placeholder="Type message...">
+
+ <div class="pt-4" x-text="message"></div>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+
+Now as the user types into the text field, the `message` will be reflected in the `<span>` tag.
+
+`x-model` is two-way bound, meaning it both "sets" and "gets". In addition to changing data, if the data itself changes, the element will reflect the change.
+
+
+We can use the same example as above but this time, we'll add a button to change the value of the `message` property.
+
+```alpine
+<div x-data="{ message: '' }">
+ <input type="text" x-model="message">
+
+ <button x-on:click="message = 'changed'">Change Message</button>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <div x-data="{ message: '' }">
+ <input type="text" x-model="message" placeholder="Type message...">
+
+ <button x-on:click="message = 'changed'">Change Message</button>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+Now when the `<button>` is clicked, the input element's value will instantly be updated to "changed".
+
+`x-model` works with the following input elements:
+
+* `<input type="text">`
+* `<textarea>`
+* `<input type="checkbox">`
+* `<input type="radio">`
+* `<select>`
+
+<a name="text-inputs"></a>
+## Text inputs
+
+```alpine
+<input type="text" x-model="message">
+
+<span x-text="message"></span>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <div x-data="{ message: '' }">
+ <input type="text" x-model="message" placeholder="Type message">
+
+ <div class="pt-4" x-text="message"></div>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+<a name="textarea-inputs"></a>
+## Textarea inputs
+
+```alpine
+<textarea x-model="message"></textarea>
+
+<span x-text="message"></span>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <div x-data="{ message: '' }">
+ <textarea x-model="message" placeholder="Type message"></textarea>
+
+ <div class="pt-4" x-text="message"></div>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+<a name="checkbox-inputs"></a>
+## Checkbox inputs
+
+<a name="single-checkbox-with-boolean"></a>
+### Single checkbox with boolean
+
+```alpine
+<input type="checkbox" id="checkbox" x-model="show">
+
+<label for="checkbox" x-text="show"></label>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <div x-data="{ open: '' }">
+ <input type="checkbox" id="checkbox" x-model="open">
+
+ <label for="checkbox" x-text="open"></label>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+<a name="multiple-checkboxes-bound-to-array"></a>
+### Multiple checkboxes bound to array
+
+```alpine
+<input type="checkbox" value="red" x-model="colors">
+<input type="checkbox" value="orange" x-model="colors">
+<input type="checkbox" value="yellow" x-model="colors">
+
+Colors: <span x-text="colors"></span>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <div x-data="{ colors: [] }">
+ <input type="checkbox" value="red" x-model="colors">
+ <input type="checkbox" value="orange" x-model="colors">
+ <input type="checkbox" value="yellow" x-model="colors">
+
+ <div class="pt-4">Colors: <span x-text="colors"></span></div>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+<a name="radio-inputs"></a>
+## Radio inputs
+
+```alpine
+<input type="radio" value="yes" x-model="answer">
+<input type="radio" value="no" x-model="answer">
+
+Answer: <span x-text="answer"></span>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <div x-data="{ answer: '' }">
+ <input type="radio" value="yes" x-model="answer">
+ <input type="radio" value="no" x-model="answer">
+
+ <div class="pt-4">Answer: <span x-text="answer"></span></div>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+<a name="select-inputs"></a>
+## Select inputs
+
+
+<a name="single-select"></a>
+### Single select
+
+```alpine
+<select x-model="color">
+ <option>Red</option>
+ <option>Orange</option>
+ <option>Yellow</option>
+</select>
+
+Color: <span x-text="color"></span>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <div x-data="{ color: '' }">
+ <select x-model="color">
+ <option>Red</option>
+ <option>Orange</option>
+ <option>Yellow</option>
+ </select>
+
+ <div class="pt-4">Color: <span x-text="color"></span></div>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+<a name="single-select-with-placeholder"></a>
+### Single select with placeholder
+
+```alpine
+<select x-model="color">
+ <option value="" disabled>Select A Color</option>
+ <option>Red</option>
+ <option>Orange</option>
+ <option>Yellow</option>
+</select>
+
+Color: <span x-text="color"></span>
+```
+
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <div x-data="{ color: '' }">
+ <select x-model="color">
+ <option value="" disabled>Select A Color</option>
+ <option>Red</option>
+ <option>Orange</option>
+ <option>Yellow</option>
+ </select>
+
+ <div class="pt-4">Color: <span x-text="color"></span></div>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+<a name="multiple-select"></a>
+### Multiple select
+
+```alpine
+<select x-model="color" multiple>
+ <option>Red</option>
+ <option>Orange</option>
+ <option>Yellow</option>
+</select>
+
+Colors: <span x-text="color"></span>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <div x-data="{ color: '' }">
+ <select x-model="color" multiple>
+ <option>Red</option>
+ <option>Orange</option>
+ <option>Yellow</option>
+ </select>
+
+ <div class="pt-4">Color: <span x-text="color"></span></div>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+<a name="dynamically-populated-select-options"></a>
+### Dynamically populated Select Options
+
+```alpine
+<select x-model="color">
+ <template x-for="color in ['Red', 'Orange', 'Yellow']">
+ <option x-text="color"></option>
+ </template>
+</select>
+
+Color: <span x-text="color"></span>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <div x-data="{ color: '' }">
+ <select x-model="color">
+ <template x-for="color in ['Red', 'Orange', 'Yellow']">
+ <option x-text="color"></option>
+ </template>
+ </select>
+
+ <div class="pt-4">Color: <span x-text="color"></span></div>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+<a name="modifiers"></a>
+## Modifiers
+
+<a name="lazy"></a>
+### `.lazy`
+
+On text inputs, by default, `x-model` updates the property on every key-stroke. By adding the `.lazy` modifier, you can force an `x-model` input to only update the property when user focuses away from the input element.
+
+This is handy for things like real-time form-validation where you might not want to show an input validation error until the user "tabs" away from a field.
+
+```alpine
+<input type="text" x-model.lazy="username">
+<span x-show="username.length > 20">The username is too long.</span>
+```
+
+<a name="number"></a>
+### `.number`
+
+By default, any data stored in a property via `x-model` is stored as a string. To force Alpine to store the value as a JavaScript number, add the `.number` modifier.
+
+```alpine
+<input type="text" x-model.number="age">
+<span x-text="typeof age"></span>
+```
+
+<a name="debounce"></a>
+### `.debounce`
+
+By adding `.debounce` to `x-model`, you can easily debounce the updating of bound input.
+
+This is useful for things like real-time search inputs that fetch new data from the server every time the search property changes.
+
+```alpine
+<input type="text" x-model.debounce="search">
+```
+
+The default debounce time is 250 milliseconds, you can easily customize this by adding a time modifier like so.
+
+```alpine
+<input type="text" x-model.debounce.500ms="search">
+```
+
+<a name="throttle"></a>
+### `.throttle`
+
+Similar to `.debounce` you can limit the property update triggered by `x-model` to only updating on a specified interval.
+
+<input type="text" x-model.throttle="search">
+
+The default throttle interval is 250 milliseconds, you can easily customize this by adding a time modifier like so.
+
+```alpine
+<input type="text" x-model.throttle.500ms="search">
+```
+
+<a name="programmatic access"></a>
+## Programmatic access
+
+Alpine exposes under-the-hood utilities for getting and setting properties bound with `x-model`. This is useful for complex Alpine utilities that may want to override the default x-model behavior, or instances where you want to allow `x-model` on a non-input element.
+
+You can access these utilities through a property called `_x_model` on the `x-model`ed element. `_x_model` has two methods to get and set the bound property:
+
+* `el._x_model.get()` (returns the value of the bound property)
+* `el._x_model.set()` (sets the value of the bound property)
+
+```alpine
+<div x-data="{ username: 'calebporzio' }">
+ <div x-ref="div" x-model="username"></div>
+
+ <button @click="$refs.div._x_model.set('phantomatrix')">
+ Change username to: 'phantomatrix'
+ </button>
+
+ <span x-text="$refs.div._x_model.get()"></span>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <div x-data="{ username: 'calebporzio' }">
+ <div x-ref="div" x-model="username"></div>
+
+ <button @click="$refs.div._x_model.set('phantomatrix')">
+ Change username to: 'phantomatrix'
+ </button>
+
+ <span x-text="$refs.div._x_model.get()"></span>
+ </div>
+</div>
+<!-- END_VERBATIM -->
diff --git a/alpinejs/packages/docs/src/en/directives/modelable.md b/alpinejs/packages/docs/src/en/directives/modelable.md
new file mode 100644
index 0000000..83eb789
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/directives/modelable.md
@@ -0,0 +1,37 @@
+---
+order: 7
+title: modelable
+---
+
+# x-modelable
+
+`x-modelable` allows you to expose any value by name as the target of the `x-model` directive.
+
+Typically this feature would be used in conjunction with a backend templating framework like Laravel Blade. It's useful for abstracting away Alpine components into backend templates and exposing state to the outside through `x-model` as if it were a native input.
+
+Here's a simple example of using `x-modelable` to expose a variable for binding with `x-model`.
+
+```alpine
+<div x-data="{ number: 5 }">
+ <div x-data="{ count: 0 }" x-modelable="count" x-model="number">
+ <button @click="count++">Increment</button>
+ </div>
+
+ Some Number: <span x-text="number"></span>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <div x-data="{ number: 5 }">
+ <div x-data="{ count: 0 }" x-modelable="count" x-model="number">
+ <button @click="count++">Increment</button>
+ </div>
+
+ Number: <span x-text="number"></span>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+As you can see the outer scope property "number" is now bound to the inner scope property "count".
+
diff --git a/alpinejs/packages/docs/src/en/directives/on.md b/alpinejs/packages/docs/src/en/directives/on.md
new file mode 100644
index 0000000..271c874
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/directives/on.md
@@ -0,0 +1,299 @@
+---
+order: 5
+title: on
+---
+
+# x-on
+
+`x-on` allows you to easily run code on dispatched DOM events.
+
+Here's an example of simple button that shows an alert when clicked.
+
+```alpine
+<button x-on:click="alert('Hello World!')">Say Hi</button>
+```
+
+> `x-on` can only listen for events with lower case names, as HTML attribtes are case-insensitive. Writing `x-on:CLICK` will listen for an event named `click`. If you need to listen for a custom event with a camelCase name, you can use the [`.camel` helper](#camel) to work around this limitation. Alternatively, you can use [`x-bind`](/directives/bind.md#bind-directives) to attach an `x-on` directive to an element in javascript code (where case will be preserved).
+
+<a name="shorthand-syntax"></a>
+## Shorthand syntax
+
+If `x-on:` is too verbose for your tastes, you can use the shorthand syntax: `@`.
+
+Here's the same component as above, but using the shorthand syntax instead:
+
+```alpine
+<button @click="alert('Hello World!')">Say Hi</button>
+```
+
+<a name="the-event-object"></a>
+## The event object
+
+If you wish to access the native JavaScript event object from your expression, you can use Alpine's magic `$event` property.
+
+```alpine
+<button @click="alert($event.target.getAttribute('message'))" message="Hello World">Say Hi</button>
+```
+
+In addition, Alpine also passes the event object to any methods referenced without trailing parenthesis. For example:
+
+```alpine
+<button @click="handleClick">...</button>
+
+<script>
+ function handleClick(e) {
+ // Now you can access the event object (e) directly
+ }
+</script>
+```
+
+<a name="keyboard-events"></a>
+## Keyboard events
+
+Alpine makes it easy to listen for `keydown` and `keyup` events on specific keys.
+
+Here's an example of listening for the `Enter` key inside an input element.
+
+```alpine
+<input type="text" @keyup.enter="alert('Submitted!')">
+```
+
+You can also chain these key modifiers to achieve more complex listeners.
+
+Here's a listener that runs when the `Shift` key is held and `Enter` is pressed, but not when `Enter` is pressed alone.
+
+```alpine
+<input type="text" @keyup.shift.enter="alert('Submitted!')">
+```
+
+You can directly use any valid key names exposed via [`KeyboardEvent.key`](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values) as modifiers by converting them to kebab-case.
+
+```alpine
+<input type="text" @keyup.page-down="alert('Submitted!')">
+```
+
+For easy reference, here is a list of common keys you may want to listen for.
+
+| Modifier | Keyboard Key |
+| -------------------------- | --------------------------- |
+| `.shift` | Shift |
+| `.enter` | Enter |
+| `.space` | Space |
+| `.ctrl` | Ctrl |
+| `.cmd` | Cmd |
+| `.meta` | Cmd on Mac, Ctrl on Windows |
+| `.alt` | Alt |
+| `.up` `.down` `.left` `.right` | Up/Down/Left/Right arrows |
+| `.escape` | Escape |
+| `.tab` | Tab |
+| `.caps-lock` | Caps Lock |
+| `.equal` | Equal, `=` |
+| `.period` | Period, `.` |
+
+<a name="custom-events"></a>
+## Custom events
+
+Alpine event listeners are a wrapper for native DOM event listeners. Therefore, they can listen for ANY DOM event, including custom events.
+
+Here's an example of a component that dispatches a custom DOM event and listens for it as well.
+
+```alpine
+<div x-data @foo="alert('Button Was Clicked!')">
+ <button @click="$event.target.dispatchEvent(new CustomEvent('foo', { bubbles: true }))">...</button>
+</div>
+```
+
+When the button is clicked, the `@foo` listener will be called.
+
+Because the `.dispatchEvent` API is verbose, Alpine offers a `$dispatch` helper to simplify things.
+
+Here's the same component re-written with the `$dispatch` magic property.
+
+```alpine
+<div x-data @foo="alert('Button Was Clicked!')">
+ <button @click="$dispatch('foo')">...</button>
+</div>
+```
+
+[→ Read more about `$dispatch`](/magics/dispatch)
+
+<a name="modifiers"></a>
+## Modifiers
+
+Alpine offers a number of directive modifiers to customize the behavior of your event listeners.
+
+<a name="prevent"></a>
+### .prevent
+
+`.prevent` is the equivalent of calling `.preventDefault()` inside a listener on the browser event object.
+
+```alpine
+<form @submit.prevent="console.log('submitted')" action="/foo">
+ <button>Submit</button>
+</form>
+```
+
+In the above example, with the `.prevent`, clicking the button will NOT submit the form to the `/foo` endpoint. Instead, Alpine's listener will handle it and "prevent" the event from being handled any further.
+
+<a name="stop"></a>
+### .stop
+
+Similar to `.prevent`, `.stop` is the equivalent of calling `.stopPropagation()` inside a listener on the browser event object.
+
+```alpine
+<div @click="console.log('I will not get logged')">
+ <button @click.stop>Click Me</button>
+</div>
+```
+
+In the above example, clicking the button WON'T log the message. This is because we are stopping the propagation of the event immediately and not allowing it to "bubble" up to the `<div>` with the `@click` listener on it.
+
+<a name="outside"></a>
+### .outside
+
+`.outside` is a convenience helper for listening for a click outside of the element it is attached to. Here's a simple dropdown component example to demonstrate:
+
+```alpine
+<div x-data="{ open: false }">
+ <button @click="open = ! open">Toggle</button>
+
+ <div x-show="open" @click.outside="open = false">
+ Contents...
+ </div>
+</div>
+```
+
+In the above example, after showing the dropdown contents by clicking the "Toggle" button, you can close the dropdown by clicking anywhere on the page outside the content.
+
+This is because `.outside` is listening for clicks that DONT originate from the element it's registered on.
+
+> It's worth noting that the `.outside` expression will only be evaluated when the element it's registered on is visible on the page. Otherwise, there would be nasty race conditions where clicking the "Toggle" button would also fire the `@click.outside` handler when it is not visible.
+
+<a name="window"></a>
+### .window
+
+When the `.window` modifier is present, Alpine will register the event listener on the root `window` object on the page instead of the element itself.
+
+```alpine
+<div @keyup.escape.window="...">...</div>
+```
+
+The above snippet will listen for the "escape" key to be pressed ANYWHERE on the page.
+
+Adding `.window` to listeners is extremely useful for these sorts of cases where a small part of your markup is concerned with events that take place on the entire page.
+
+<a name="document"></a>
+### .document
+
+`.document` works similarly to `.window` only it registers listeners on the `document` global, instead of the `window` global.
+
+<a name="once"></a>
+### .once
+
+By adding `.once` to a listener, you are ensuring that the handler is only called ONCE.
+
+```alpine
+<button @click.once="console.log('I will only log once')">...</button>
+```
+
+<a name="debounce"></a>
+### .debounce
+
+Sometimes it is useful to "debounce" an event handler so that it only is called after a certain period of inactivity (250 milliseconds by default).
+
+For example if you have a search field that fires network requests as the user types into it, adding a debounce will prevent the network requests from firing on every single keystroke.
+
+```alpine
+<input @input.debounce="fetchResults">
+```
+
+Now, instead of calling `fetchResults` after every keystroke, `fetchResults` will only be called after 250 milliseconds of no keystrokes.
+
+If you wish to lengthen or shorten the debounce time, you can do so by trailing a duration after the `.debounce` modifier like so:
+
+```alpine
+<input @input.debounce.500ms="fetchResults">
+```
+
+Now, `fetchResults` will only be called after 500 milliseconds of inactivity.
+
+<a name="throttle"></a>
+### .throttle
+
+`.throttle` is similar to `.debounce` except it will release a handler call every 250 milliseconds instead of deferring it indefinitely.
+
+This is useful for cases where there may be repeated and prolonged event firing and using `.debounce` won't work because you want to still handle the event every so often.
+
+For example:
+
+```alpine
+<div @scroll.window.throttle="handleScroll">...</div>
+```
+
+The above example is a great use case of throttling. Without `.throttle`, the `handleScroll` method would be fired hundreds of times as the user scrolls down a page. This can really slow down a site. By adding `.throttle`, we are ensuring that `handleScroll` only gets called every 250 milliseconds.
+
+> Fun Fact: This exact strategy is used on this very documentation site to update the currently highlighted section in the right sidebar.
+
+Just like with `.debounce`, you can add a custom duration to your throttled event:
+
+```alpine
+<div @scroll.window.throttle.750ms="handleScroll">...</div>
+```
+
+Now, `handleScroll` will only be called every 750 milliseconds.
+
+<a name="self"></a>
+### .self
+
+By adding `.self` to an event listener, you are ensuring that the event originated on the element it is declared on, and not from a child element.
+
+```alpine
+<button @click.self="handleClick">
+ Click Me
+
+ <img src="...">
+</button>
+```
+
+In the above example, we have an `<img>` tag inside the `<button>` tag. Normally, any click originating within the `<button>` element (like on `<img>` for example), would be picked up by a `@click` listener on the button.
+
+However, in this case, because we've added a `.self`, only clicking the button itself will call `handleClick`. Only clicks originating on the `<img>` element will not be handled.
+
+<a name="camel"></a>
+### .camel
+
+```alpine
+<div @custom-event.camel="handleCustomEvent">
+ ...
+</div>
+```
+
+Sometimes you may want to listen for camelCased events such as `customEvent` in our example. Because camelCasing inside HTML attributes is not supported, adding the `.camel` modifier is necessary for Alpine to camelCase the event name internally.
+
+By adding `.camel` in the above example, Alpine is now listening for `customEvent` instead of `custom-event`.
+
+<a name="dot"></a>
+### .dot
+
+```alpine
+<div @custom-event.dot="handleCustomEvent">
+ ...
+</div>
+```
+
+Similar to the `.camelCase` modifier there may be situations where you want to listen for events that have dots in their name (like `custom.event`). Since dots within the event name are reserved by Alpine you need to write them with dashes and add the `.dot` modifier.
+
+In the code example above `custom-event.dot` will correspond to the event name `custom.event`.
+
+<a name="passive"></a>
+### .passive
+
+Browsers optimize scrolling on pages to be fast and smooth even when JavaScript is being executed on the page. However, improperly implemented touch and wheel listeners can block this optimization and cause poor site performance.
+
+If you are listening for touch events, it's important to add `.passive` to your listeners to not block scroll performance.
+
+```alpine
+<div @touchstart.passive="...">...</div>
+```
+
+[→ Read more about passive listeners](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#improving_scrolling_performance_with_passive_listeners)
diff --git a/alpinejs/packages/docs/src/en/directives/ref.md b/alpinejs/packages/docs/src/en/directives/ref.md
new file mode 100644
index 0000000..0753076
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/directives/ref.md
@@ -0,0 +1,24 @@
+---
+order: 11
+title: ref
+---
+
+# x-ref
+
+`x-ref` in combination with `$refs` is a useful utility for easily accessing DOM elements directly. It's most useful as a replacement for APIs like `getElementById` and `querySelector`.
+
+```alpine
+<button @click="$refs.text.remove()">Remove Text</button>
+
+<span x-ref="text">Hello 👋</span>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <div x-data>
+ <button @click="$refs.text.remove()">Remove Text</button>
+
+ <div class="pt-4" x-ref="text">Hello 👋</div>
+ </div>
+</div>
+<!-- END_VERBATIM -->
diff --git a/alpinejs/packages/docs/src/en/directives/show.md b/alpinejs/packages/docs/src/en/directives/show.md
new file mode 100644
index 0000000..988a16f
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/directives/show.md
@@ -0,0 +1,39 @@
+---
+order: 3
+title: show
+---
+
+# x-show
+
+`x-show` is one of the most useful and powerful directives in Alpine. It provides an expressive way to show and hide DOM elements.
+
+Here's an example of a simple dropdown component using `x-show`.
+
+```alpine
+<div x-data="{ open: false }">
+ <button x-on:click="open = ! open">Toggle Dropdown</button>
+
+ <div x-show="open">
+ Dropdown Contents...
+ </div>
+</div>
+```
+
+When the "Toggle Dropdown" button is clicked, the dropdown will show and hide accordingly.
+
+> If the "default" state of an `x-show` on page load is "false", you may want to use `x-cloak` on the page to avoid "page flicker" (The effect that happens when the browser renders your content before Alpine is finished initializing and hiding it.) You can learn more about `x-cloak` in its documentation.
+
+<a name="with-transitions"></a>
+## With transitions
+
+If you want to apply smooth transitions to the `x-show` behavior, you can use it in conjunction with `x-transition`. You can learn more about that directive [here](/directives/transition), but here's a quick example of the same component as above, just with transitions applied.
+
+```alpine
+<div x-data="{ open: false }">
+ <button x-on:click="open = ! open">Toggle Dropdown</button>
+
+ <div x-show="open" x-transition>
+ Dropdown Contents...
+ </div>
+</div>
+```
diff --git a/alpinejs/packages/docs/src/en/directives/teleport.md b/alpinejs/packages/docs/src/en/directives/teleport.md
new file mode 100644
index 0000000..8b782ef
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/directives/teleport.md
@@ -0,0 +1,159 @@
+---
+order: 12
+title: teleport
+description: Send Alpine templates to other parts of the DOM
+graph_image: https://alpinejs.dev/social_teleport.jpg
+---
+
+# x-teleport
+
+The `x-teleport` directive allows you to transport part of your Alpine template to another part of the DOM on the page entirely.
+
+This is useful for things like modals (especially nesting them), where it's helpful to break out of the z-index of the current Alpine component.
+
+> Warning: if you are a [Livewire](https://laravel-livewire.com) user, this functionality does not currently work inside Livewire components. Support for this is on the roadmap.
+
+<a name="x-teleport"></a>
+## x-teleport
+
+By attaching `x-teleport` to a `<template>` element, you are telling Alpine to "append" that element to the provided selector.
+
+> The `x-teleport` selector can be any string you would normally pass into something like `document.querySelector`. It will find the first element that matches, be it a tag name (`body`), class name (`.my-class`), ID (`#my-id`), or any other valid CSS selector.
+
+[→ Read more about `document.querySelector`](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector)
+
+Here's a contrived modal example:
+
+```alpine
+<body>
+ <div x-data="{ open: false }">
+ <button @click="open = ! open">Toggle Modal</button>
+
+ <template x-teleport="body">
+ <div x-show="open">
+ Modal contents...
+ </div>
+ </template>
+ </div>
+
+ <div>Some other content placed AFTER the modal markup.</div>
+
+ ...
+
+</body>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo" x-ref="root" id="modal2">
+ <div x-data="{ open: false }">
+ <button @click="open = ! open">Toggle Modal</button>
+
+ <template x-teleport="#modal2">
+ <div x-show="open">
+ Modal contents...
+ </div>
+ </template>
+
+ </div>
+
+ <div class="py-4">Some other content placed AFTER the modal markup.</div>
+</div>
+<!-- END_VERBATIM -->
+
+Notice how when toggling the modal, the actual modal contents show up AFTER the "Some other content..." element? This is because when Alpine is initializing, it sees `x-teleport="body"` and appends and initializes that element to the provided element selector.
+
+<a name="forwarding-events"></a>
+## Forwarding events
+
+Alpine tries its best to make the experience of teleporting seamless. Anything you would normally do in a template, you should be able to do inside an `x-teleport` template. Teleported content can access the normal Alpine scope of the component as well as other features like `$refs`, `$root`, etc...
+
+However, native DOM events have no concept of teleportation, so if, for example, you trigger a "click" event from inside a teleported element, that event will bubble up the DOM tree as it normally would.
+
+To make this experience more seamless, you can "forward" events by simply registering event listeners on the `<template x-teleport...>` element itself like so:
+
+```alpine
+<div x-data="{ open: false }">
+ <button @click="open = ! open">Toggle Modal</button>
+
+ <template x-teleport="body" @click="open = false">
+ <div x-show="open">
+ Modal contents...
+ (click to close)
+ </div>
+ </template>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo" x-ref="root" id="modal3">
+ <div x-data="{ open: false }">
+ <button @click="open = ! open">Toggle Modal</button>
+
+ <template x-teleport="#modal3" @click="open = false">
+ <div x-show="open">
+ Modal contents...
+ <div>(click to close)</div>
+ </div>
+ </template>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+Notice how we are now able to listen for events dispatched from within the teleported element from outside the `<template>` element itself?
+
+Alpine does this by looking for event listeners registered on `<template x-teleport...>` and stops those events from propogating past the live, teleported, DOM element. Then, it creates a copy of that event and re-dispatches it from `<template x-teleport...>`.
+
+<a name="nesting"></a>
+## Nesting
+
+Teleporting is especially helpful if you are trying to nest one modal within another. Alpine makes it simple to do so:
+
+```alpine
+<div x-data="{ open: false }">
+ <button @click="open = ! open">Toggle Modal</button>
+
+ <template x-teleport="body">
+ <div x-show="open">
+ Modal contents...
+
+ <div x-data="{ open: false }">
+ <button @click="open = ! open">Toggle Nested Modal</button>
+
+ <template x-teleport="body">
+ <div x-show="open">
+ Nested modal contents...
+ </div>
+ </template>
+ </div>
+ </div>
+ </template>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo" x-ref="root" id="modal4">
+ <div x-data="{ open: false }">
+ <button @click="open = ! open">Toggle Modal</button>
+
+ <template x-teleport="#modal4">
+ <div x-show="open">
+ <div class="py-4">Modal contents...</div>
+
+ <div x-data="{ open: false }">
+ <button @click="open = ! open">Toggle Nested Modal</button>
+
+ <template x-teleport="#modal4">
+ <div class="pt-4" x-show="open">
+ Nested modal contents...
+ </div>
+ </template>
+ </div>
+ </div>
+ </template>
+ </div>
+
+ <template x-teleport-target="modals3"></template>
+</div>
+<!-- END_VERBATIM -->
+
+After toggling "on" both modals, they are authored as children, but will be rendered as sibling elements on the page, not within one another.
diff --git a/alpinejs/packages/docs/src/en/directives/text.md b/alpinejs/packages/docs/src/en/directives/text.md
new file mode 100644
index 0000000..13abe1d
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/directives/text.md
@@ -0,0 +1,26 @@
+---
+order: 6
+title: text
+---
+
+# x-text
+
+`x-text` sets the text content of an element to the result of a given expression.
+
+Here's a basic example of using `x-text` to display a user's username.
+
+```alpine
+<div x-data="{ username: 'calebporzio' }">
+ Username: <strong x-text="username"></strong>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <div x-data="{ username: 'calebporzio' }">
+ Username: <strong x-text="username"></strong>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+Now the `<strong>` tag's inner text content will be set to "calebporzio".
diff --git a/alpinejs/packages/docs/src/en/directives/transition.md b/alpinejs/packages/docs/src/en/directives/transition.md
new file mode 100644
index 0000000..1cbceb6
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/directives/transition.md
@@ -0,0 +1,175 @@
+---
+order: 10
+title: transition
+---
+
+# x-transition
+
+Alpine provides a robust transitions utility out of the box. With a few `x-transition` directives, you can create smooth transitions between when an element is shown or hidden.
+
+There are two primary ways to handle transitions in Alpine:
+
+* [The Transition Helper](#the-transition-helper)
+* [Applying CSS Classes](#applying-css-classes)
+
+<a name="the-transition-helper"></a>
+## The transition helper
+
+The simplest way to achieve a transition using Alpine is by adding `x-transition` to an element with `x-show` on it. For example:
+
+```alpine
+<div x-data="{ open: false }">
+ <button @click="open = ! open">Toggle</button>
+
+ <span x-show="open" x-transition>
+ Hello 👋
+ </span>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <div x-data="{ open: false }">
+ <button @click="open = ! open">Toggle</button>
+
+ <span x-show="open" x-transition>
+ Hello 👋
+ </span>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+As you can see, by default, `x-transition` applies pleasant transition defaults to fade and scale the revealing element.
+
+You can override these defaults with modifiers attached to `x-transition`. Let's take a look at those.
+
+<a name="customizing-duration"></a>
+### Customizing duration
+
+You can configure the duration you want for a transition with the `.duration` modifier:
+
+```alpine
+<div ... x-transition.duration.500ms>
+```
+
+The above `<div>` will transition for 500 milliseconds when entering, and 250 milliseconds when leaving.
+
+This difference in duration generally desirable default. If you wish to customize the durations specifically for entering and leaving, you can do that like so:
+
+```alpine
+<div ...
+ x-transition:enter.duration.500ms
+ x-transition:leave.duration.400ms
+>
+```
+
+<a name="customizing-delay"></a>
+### Customizing delay
+
+You can delay a transition using the `.delay` modifier like so:
+
+```alpine
+<div ... x-transition.delay.50ms>
+```
+
+The above example will delay the transition and in and out of the element by 50 milliseconds.
+
+<a name="customizing-opacity"></a>
+### Customizing opacity
+
+By default, Alpine's `x-transition` applies both a scale and opacity transition to achieve a "fade" effect.
+
+If you wish to only apply the opacity transition (no scale), you can accomplish that like so:
+
+```alpine
+<div ... x-transition.opacity>
+```
+
+<a name="customizing-scale"></a>
+### Customizing scale
+
+Similar to the `.opacity` modifier, you can configure `x-transition` to ONLY scale (and not transition opacity as well) like so:
+
+```alpine
+<div ... x-transition.scale>
+```
+
+The `.scale` modifier also offers the ability to configure its scale values AND its origin values:
+
+```alpine
+<div ... x-transition.scale.80>
+```
+
+The above snippet will scale the element up and down by 80%.
+
+Again, you may customize these values separately for enter and leaving transitions like so:
+
+```alpine
+<div ...
+ x-transition:enter.scale.80
+ x-transition:leave.scale.90
+>
+```
+
+To customize the origin of the scale transition, you can use the `.origin` modifier:
+
+```alpine
+<div ... x-transition.scale.origin.top>
+```
+
+Now the scale will be applied using the top of the element as the origin, instead of the center by default.
+
+Like you may have guessed, the possible values for this customization are: `top`, `bottom`, `left`, and `right`.
+
+If you wish, you can also combine two origin values. For example, if you want the origin of the scale to be "top right", you can use: `.origin.top.right` as the modifier.
+
+
+<a name="applying-css-classes"></a>
+## Applying CSS classes
+
+For direct control over exactly what goes into your transitions, you can apply CSS classes at different stages of the transition.
+
+> The following examples use [TailwindCSS](https://tailwindcss.com/docs/transition-property) utility classes.
+
+```alpine
+<div x-data="{ open: false }">
+ <button @click="open = ! open">Toggle</button>
+
+ <div
+ x-show="open"
+ x-transition:enter="transition ease-out duration-300"
+ x-transition:enter-start="opacity-0 scale-90"
+ x-transition:enter-end="opacity-100 scale-100"
+ x-transition:leave="transition ease-in duration-300"
+ x-transition:leave-start="opacity-100 scale-100"
+ x-transition:leave-end="opacity-0 scale-90"
+ >Hello 👋</div>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <div x-data="{ open: false }">
+ <button @click="open = ! open">Toggle</button>
+
+ <div
+ x-show="open"
+ x-transition:enter="transition ease-out duration-300"
+ x-transition:enter-start="opacity-0 transform scale-90"
+ x-transition:enter-end="opacity-100 transform scale-100"
+ x-transition:leave="transition ease-in duration-300"
+ x-transition:leave-start="opacity-100 transform scale-100"
+ x-transition:leave-end="opacity-0 transform scale-90"
+ >Hello 👋</div>
+</div>
+</div>
+<!-- END_VERBATIM -->
+
+| Directive | Description |
+| --- | --- |
+| `:enter` | Applied during the entire entering phase. |
+| `:enter-start` | Added before element is inserted, removed one frame after element is inserted. |
+| `:enter-end` | Added one frame after element is inserted (at the same time `enter-start` is removed), removed when transition/animation finishes.
+| `:leave` | Applied during the entire leaving phase. |
+| `:leave-start` | Added immediately when a leaving transition is triggered, removed after one frame. |
+| `:leave-end` | Added one frame after a leaving transition is triggered (at the same time `leave-start` is removed), removed when the transition/animation finishes.
diff --git a/alpinejs/packages/docs/src/en/essentials.md b/alpinejs/packages/docs/src/en/essentials.md
new file mode 100644
index 0000000..017c4d4
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/essentials.md
@@ -0,0 +1,5 @@
+---
+order: 3
+title: Essentials
+type: sub-directory
+---
diff --git a/alpinejs/packages/docs/src/en/essentials/events.md b/alpinejs/packages/docs/src/en/essentials/events.md
new file mode 100644
index 0000000..10b15a1
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/essentials/events.md
@@ -0,0 +1,101 @@
+---
+order: 4
+title: Events
+---
+
+# Events
+
+Alpine makes it simple to listen for browser events and react to them.
+
+<a name="listening-for-simple-events"></a>
+## Listening for simple events
+
+By using `x-on`, you can listen for browser events that are dispatched on or within an element.
+
+Here's a basic example of listening for a click on a button:
+
+```alpine
+<button x-on:click="console.log('clicked')">...</button>
+```
+
+As an alternative, you can use the event shorthand syntax if you prefer: `@`. Here's the same example as before, but using the shorthand syntax (which we'll be using from now on):
+
+```alpine
+<button @click="...">...</button>
+```
+
+In addition to `click`, you can listen for any browser event by name. For example: `@mouseenter`, `@keyup`, etc... are all valid syntax.
+
+<a name="listening-for-specific-keys"></a>
+## Listening for specific keys
+
+Let's say you wanted to listen for the `enter` key to be pressed inside an `<input>` element. Alpine makes this easy by adding the `.enter` like so:
+
+```alpine
+<input @keyup.enter="...">
+```
+
+You can even combine key modifiers to listen for key combinations like pressing `enter` while holding `shift`:
+
+```alpine
+<input @keyup.shift.enter="...">
+```
+
+<a name="preventing-default"></a>
+## Preventing default
+
+When reacting to browser events, it is often necessary to "prevent default" (prevent the default behavior of the browser event).
+
+For example, if you want to listen for a form submission but prevent the browser from submitting a form request, you can use `.prevent`:
+
+```alpine
+<form @submit.prevent="...">...</form>
+```
+
+You can also apply `.stop` to achieve the equivalent of `event.stopPropagation()`.
+
+<a name="accessing-the-event-object"></a>
+## Accessing the event object
+
+Sometimes you may want to access the native browser event object inside your own code. To make this easy, Alpine automatically injects an `$event` magic variable:
+
+```alpine
+<button @click="$event.target.remove()">Remove Me</button>
+```
+
+<a name="dispatching-custom-events"></a>
+## Dispatching custom events
+
+In addition to listening for browser events, you can dispatch them as well. This is extremely useful for communicating with other Alpine components or triggering events in tools outside of Alpine itself.
+
+Alpine exposes a magic helper called `$dispatch` for this:
+
+```alpine
+<div @foo="console.log('foo was dispatched')">
+ <button @click="$dispatch('foo')"></button>
+</div>
+```
+
+As you can see, when the button is clicked, Alpine will dispatch a browser event called "foo", and our `@foo` listener on the `<div>` will pick it up and react to it.
+
+<a name="listening-for-events-on-window"></a>
+## Listening for events on window
+
+Because of the nature of events in the browser, it is sometimes useful to listen to events on the top-level window object.
+
+This allows you to communicate across components completely like the following example:
+
+
+```alpine
+<div x-data>
+ <button @click="$dispatch('foo')"></button>
+</div>
+
+<div x-data @foo.window="console.log('foo was dispatched')">...</div>
+```
+
+In the above example, if we click the button in the first component, Alpine will dispatch the "foo" event. Because of the way events work in the browser, they "bubble" up through parent elements all the way to the top-level "window".
+
+Now, because in our second component we are listening for "foo" on the window (with `.window`), when the button is clicked, this listener will pick it up and log the "foo was dispatched" message.
+
+[→ Read more about x-on](/directives/on)
diff --git a/alpinejs/packages/docs/src/en/essentials/installation.md b/alpinejs/packages/docs/src/en/essentials/installation.md
new file mode 100644
index 0000000..0b4ea49
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/essentials/installation.md
@@ -0,0 +1,68 @@
+---
+order: 1
+title: Installation
+---
+
+# Installation
+
+There are 2 ways to include Alpine into your project:
+
+* Including it from a `<script>` tag
+* Importing it as a module
+
+Either is perfectly valid. It all depends on the project's needs and the developer's taste.
+
+<a name="from-a-script-tag"></a>
+## From a script tag
+
+This is by far the simplest way to get started with Alpine. Include the following `<script>` tag in the head of your HTML page.
+
+```alpine
+<html>
+ <head>
+ ...
+
+ <script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>
+ </head>
+ ...
+</html>
+```
+
+> Don't forget the "defer" attribute in the `<script>` tag.
+
+Notice the `@3.x.x` in the provided CDN link. This will pull the latest version of Alpine version 3. For stability in production, it's recommended that you hardcode the latest version in the CDN link.
+
+```alpine
+<script defer src="https://unpkg.com/alpinejs@3.9.1/dist/cdn.min.js"></script>
+```
+
+That's it! Alpine is now available for use inside your page.
+
+<a name="as-a-module"></a>
+## As a module
+
+If you prefer the more robust approach, you can install Alpine via NPM and import it into a bundle.
+
+Run the following command to install it.
+
+```shell
+npm install alpinejs
+```
+
+Now import Alpine into your bundle and initialize it like so:
+
+```js
+import Alpine from 'alpinejs'
+
+window.Alpine = Alpine
+
+Alpine.start()
+```
+
+> The `window.Alpine = Alpine` bit is optional, but is nice to have for freedom and flexibility. Like when tinkering with Alpine from the devtools for example.
+
+
+> If you imported Alpine into a bundle, you have to make sure you are registering any extension code IN BETWEEN when you import the `Alpine` global object, and when you initialize Alpine by calling `Alpine.start()`.
+
+
+[→ Read more about extending Alpine](/advanced/extending)
diff --git a/alpinejs/packages/docs/src/en/essentials/lifecycle.md b/alpinejs/packages/docs/src/en/essentials/lifecycle.md
new file mode 100644
index 0000000..7a6d321
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/essentials/lifecycle.md
@@ -0,0 +1,96 @@
+---
+order: 5
+title: Lifecycle
+---
+
+# Lifecycle
+
+Alpine has a handful of different techniques for hooking into different parts of its lifecycle. Let's go through the most useful ones to familiarize yourself with:
+
+<a name="element-initialization"></a>
+## Element initialization
+
+Another extremely useful lifecycle hook in Alpine is the `x-init` directive.
+
+`x-init` can be added to any element on a page and will execute any JavaScript you call inside it when Alpine begins initializing that element.
+
+```alpine
+<button x-init="console.log('Im initing')">
+```
+
+In addition to the directive, Alpine will automatically call any `init()` methods stored on a data object. For example:
+
+```js
+Alpine.data('dropdown', () => ({
+ init() {
+ // I get called before the element using this data initializes.
+ }
+}))
+```
+
+<a name="after-a-state-change"></a>
+## After a state change
+
+Alpine allows you to execute code when a piece of data (state) changes. It offers two different APIs for such a task: `$watch` and `x-effect`.
+
+<a name="watch"></a>
+### `$watch`
+
+```alpine
+<div x-data="{ open: false }" x-init="$watch('open', value => console.log(value))">
+```
+
+As you can see above, `$watch` allows you to hook into data changes using a dot-notation key. When that piece of data changes, Alpine will call the passed callback and pass it the new value. along with the old value before the change.
+
+[→ Read more about $watch](/magics/watch)
+
+<a name="x-effect"></a>
+### `x-effect`
+
+`x-effect` uses the same mechanism under the hood as `$watch` but has very different usage.
+
+Instead of specifying which data key you wish to watch, `x-effect` will call the provided code and intelligently look for any Alpine data used within it. Now when one of those pieces of data changes, the `x-effect` expression will be re-run.
+
+Here's the same bit of code from the `$watch` example rewritten using `x-effect`:
+
+```alpine
+<div x-data="{ open: false }" x-effect="console.log(open)">
+```
+
+Now, this expression will be called right away, and re-called every time `open` is updated.
+
+The two main behavioral differences with this approach are:
+
+1. The provided code will be run right away AND when data changes (`$watch` is "lazy" -- won't run until the first data change)
+2. No knowledge of the previous value. (The callback provided to `$watch` receives both the new value AND the old one)
+
+[→ Read more about x-effect](/directives/effect)
+
+<a name="alpine-initialization"></a>
+## Alpine initialization
+
+<a name="alpine-initializing"></a>
+### `alpine:init`
+
+Ensuring a bit of code executes after Alpine is loaded, but BEFORE it initializes itself on the page is a necessary task.
+
+This hook allows you to register custom data, directives, magics, etc. before Alpine does its thing on a page.
+
+You can hook into this point in the lifecycle by listening for an event that Alpine dispatches called: `alpine:init`
+
+```js
+document.addEventListener('alpine:init', () => {
+ Alpine.data(...)
+})
+```
+
+<a name="alpine-initialized"></a>
+### `alpine:initialized`
+
+Alpine also offers a hook that you can use to execute code After it's done initializing called `alpine:initialized`:
+
+```js
+document.addEventListener('alpine:initialized', () => {
+ //
+})
+```
diff --git a/alpinejs/packages/docs/src/en/essentials/state.md b/alpinejs/packages/docs/src/en/essentials/state.md
new file mode 100644
index 0000000..fd1f39b
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/essentials/state.md
@@ -0,0 +1,133 @@
+---
+order: 2
+title: State
+---
+
+# State
+
+State (JavaScript data that Alpine watches for changes) is at the core of everything you do in Alpine. You can provide local data to a chunk of HTML, or make it globally available for use anywhere on a page using `x-data` or `Alpine.store()` respectively.
+
+<a name="local-state-x-data"></a>
+## Local state
+
+Alpine allows you to declare an HTML block's state in a single `x-data` attribute without ever leaving your markup.
+
+Here's a basic example:
+
+```alpine
+<div x-data="{ open: false }">
+ ...
+</div>
+```
+
+Now any other Alpine syntax on or within this element will be able to access `open`. And like you'd guess, when `open` changes for any reason, everything that depends on it will react automatically.
+
+[→ Read more about `x-data`](/directives/data)
+
+<a name="nesting-data"></a>
+### Nesting data
+
+Data is nestable in Alpine. For example, if you have two elements with Alpine data attached (one inside the other), you can access the parent's data from inside the child element.
+
+```alpine
+<div x-data="{ open: false }">
+ <div x-data="{ label: 'Content:' }">
+ <span x-text="label"></span>
+ <span x-show="open"></span>
+ </div>
+</div>
+```
+
+This is similar to scoping in JavaScript itself (code within a function can access variables declared outside that function.)
+
+Like you may have guessed, if the child has a data property matching the name of a parent's property, the child property will take precedence.
+
+<a name="single-element-data"></a>
+### Single-element data
+
+Although this may seem obvious to some, it's worth mentioning that Alpine data can be used within the same element. For example:
+
+```alpine
+<button x-data="{ label: 'Click Here' }" x-text="label"></button>
+```
+
+<a name="data-less-alpine"></a>
+### Data-less Alpine
+
+Sometimes you may want to use Alpine functionality, but don't need any reactive data. In these cases, you can opt-out of passing an expression to `x-data` entirely. For example:
+
+```alpine
+<button x-data @click="alert('I\'ve been clicked!')">Click Me</button>
+```
+
+<a name="re-usable-data"></a>
+### Re-usable data
+
+When using Alpine, you may find the need to re-use a chunk of data and/or its corresponding template.
+
+If you are using a backend framework like Rails or Laravel, Alpine first recommends that you extract the entire block of HTML into a template partial or include.
+
+If for some reason that isn't ideal for you or you're not in a back-end templating environment, Alpine allows you to globally register and re-use the data portion of a component using `Alpine.data(...)`.
+
+```js
+Alpine.data('dropdown', () => ({
+ open: false,
+
+ toggle() {
+ this.open = ! this.open
+ }
+}))
+```
+
+Now that you've registered the "dropdown" data, you can use it inside your markup in as many places as you like:
+
+```alpine
+<div x-data="dropdown">
+ <button @click="toggle">Expand</button>
+
+ <span x-show="open">Content...</span>
+</div>
+
+<div x-data="dropdown">
+ <button @click="toggle">Expand</button>
+
+ <span x-show="open">Some Other Content...</span>
+</div>
+```
+
+[→ Read more about using `Alpine.data()`](/globals/alpine-data)
+
+<a name="global-state"></a>
+## Global state
+
+If you wish to make some data available to every component on the page, you can do so using Alpine's "global store" feature.
+
+You can register a store using `Alpine.store(...)`, and reference one with the magic `$store()` method.
+
+Let's look at a simple example. First we'll register the store globally:
+
+```js
+Alpine.store('tabs', {
+ current: 'first',
+
+ items: ['first', 'second', 'third'],
+})
+```
+
+Now we can access or modify its data from anywhere on our page:
+
+```alpine
+<div x-data>
+ <template x-for="tab in $store.tabs.items">
+ ...
+ </template>
+</div>
+
+<div x-data>
+ <button @click="$store.tabs.current = 'first'">First Tab</button>
+ <button @click="$store.tabs.current = 'second'">Second Tab</button>
+ <button @click="$store.tabs.current = 'third'">Third Tab</button>
+</div>
+```
+
+[→ Read more about `Alpine.store()`](/globals/alpine-store)
diff --git a/alpinejs/packages/docs/src/en/essentials/templating.md b/alpinejs/packages/docs/src/en/essentials/templating.md
new file mode 100644
index 0000000..697f172
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/essentials/templating.md
@@ -0,0 +1,368 @@
+---
+order: 3
+title: Templating
+---
+
+# Templating
+
+Alpine offers a handful of useful directives for manipulating the DOM on a web page.
+
+Let's cover a few of the basic templating directives here, but be sure to look through the available directives in the sidebar for an exhaustive list.
+
+<a name="text-content"></a>
+## Text content
+
+Alpine makes it easy to control the text content of an element with the `x-text` directive.
+
+```alpine
+<div x-data="{ title: 'Start Here' }">
+ <h1 x-text="title"></h1>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div x-data="{ title: 'Start Here' }" class="demo">
+ <strong x-text="title"></strong>
+</div>
+<!-- END_VERBATIM -->
+
+Now, Alpine will set the text content of the `<h1>` with the value of `title` ("Start Here"). When `title` changes, so will the contents of `<h1>`.
+
+Like all directives in Alpine, you can use any JavaScript expression you like. For example:
+
+```alpine
+<span x-text="1 + 2"></span>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo" x-data>
+ <span x-text="1 + 2"></span>
+</div>
+<!-- END_VERBATIM -->
+
+The `<span>` will now contain the sum of "1" and "2".
+
+[→ Read more about `x-text`](/directives/text)
+
+<a name="toggling-elements"></a>
+## Toggling elements
+
+Toggling elements is a common need in web pages and applications. Dropdowns, modals, dialogues, "show-more"s, etc... are all good examples.
+
+Alpine offers the `x-show` and `x-if` directives for toggling elements on a page.
+
+<a name="x-show"></a>
+### `x-show`
+
+Here's a simple toggle component using `x-show`.
+
+```alpine
+<div x-data="{ open: false }">
+ <button @click="open = ! open">Expand</button>
+
+ <div x-show="open">
+ Content...
+ </div>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div x-data="{ open: false }" class="demo">
+ <button @click="open = ! open" :aria-pressed="open">Expand</button>
+
+ <div x-show="open">
+ Content...
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+Now the entire `<div>` containing the contents will be shown and hidden based on the value of `open`.
+
+Under the hood, Alpine adds the CSS property `display: none;` to the element when it should be hidden.
+
+[→ Read more about `x-show`](/directives/show)
+
+This works well for most cases, but sometimes you may want to completely add and remove the element from the DOM entirely. This is what `x-if` is for.
+
+<a name="x-if"></a>
+### `x-if`
+
+Here is the same toggle from before, but this time using `x-if` instead of `x-show`.
+
+```alpine
+<div x-data="{ open: false }">
+ <button @click="open = ! open">Expand</button>
+
+ <template x-if="open">
+ <div>
+ Content...
+ </div>
+ </template>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div x-data="{ open: false }" class="demo">
+ <button @click="open = ! open" :aria-pressed="open">Expand</button>
+
+ <template x-if="open">
+ <div>
+ Content...
+ </div>
+ </template>
+</div>
+<!-- END_VERBATIM -->
+
+Notice that `x-if` must be declared on a `<template>` tag. This is so that Alpine can leverage the existing browser behavior of the `<template>` element and use it as the source of the target `<div>` to be added and removed from the page.
+
+When `open` is true, Alpine will append the `<div>` to the `<template>` tag, and remove it when `open` is false.
+
+[→ Read more about `x-if`](/directives/if)
+
+<a name="toggling-with-transitions"></a>
+## Toggling with transitions
+
+Alpine makes it simple to smoothly transition between "shown" and "hidden" states using the `x-transition` directive.
+
+> `x-transition` only works with `x-show`, not with `x-if`.
+
+Here is, again, the simple toggle example, but this time with transitions applied:
+
+```alpine
+<div x-data="{ open: false }">
+ <button @click="open = ! open">Expands</button>
+
+ <div x-show="open" x-transition>
+ Content...
+ </div>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div x-data="{ open: false }" class="demo">
+ <button @click="open = ! open">Expands</button>
+
+ <div class="flex">
+ <div x-show="open" x-transition style="will-change: transform;">
+ Content...
+ </div>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+Let's zoom in on the portion of the template dealing with transitions:
+
+```alpine
+<div x-show="open" x-transition>
+```
+
+`x-transition` by itself will apply sensible default transitions (fade and scale) to the toggle.
+
+There are two ways to customize these transitions:
+
+* Transition helpers
+* Transition CSS classes.
+
+Let's take a look at each of these approaches:
+
+<a name="transition-helpers"></a>
+### Transition helpers
+
+Let's say you wanted to make the duration of the transition longer, you can manually specify that using the `.duration` modifier like so:
+
+```alpine
+<div x-show="open" x-transition.duration.500ms>
+```
+
+<!-- START_VERBATIM -->
+<div x-data="{ open: false }" class="demo">
+ <button @click="open = ! open">Expands</button>
+
+ <div class="flex">
+ <div x-show="open" x-transition.duration.500ms style="will-change: transform;">
+ Content...
+ </div>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+Now the transition will last 500 milliseconds.
+
+If you want to specify different values for in and out transitions, you can use `x-transition:enter` and `x-transition:leave`:
+
+```alpine
+<div
+ x-show="open"
+ x-transition:enter.duration.500ms
+ x-transition:leave.duration.1000ms
+>
+```
+
+<!-- START_VERBATIM -->
+<div x-data="{ open: false }" class="demo">
+ <button @click="open = ! open">Expands</button>
+
+ <div class="flex">
+ <div x-show="open" x-transition:enter.duration.500ms x-transition:leave.duration.1000ms style="will-change: transform;">
+ Content...
+ </div>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+Additionally, you can add either `.opacity` or `.scale` to only transition that property. For example:
+
+```alpine
+<div x-show="open" x-transition.opacity>
+```
+
+<!-- START_VERBATIM -->
+<div x-data="{ open: false }" class="demo">
+ <button @click="open = ! open">Expands</button>
+
+ <div class="flex">
+ <div x-show="open" x-transition:enter.opacity.duration.500 x-transition:leave.opacity.duration.250>
+ Content...
+ </div>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+[→ Read more about transition helpers](/directives/transition#the-transition-helper)
+
+<a name="transition-classes"></a>
+### Transition classes
+
+If you need more fine-grained control over the transitions in your application, you can apply specific CSS classes at specific phases of the transition using the following syntax (this example uses [Tailwind CSS](https://tailwindcss.com/)):
+
+```alpine
+<div
+ x-show="open"
+ x-transition:enter="transition ease-out duration-300"
+ x-transition:enter-start="opacity-0 transform scale-90"
+ x-transition:enter-end="opacity-100 transform scale-100"
+ x-transition:leave="transition ease-in duration-300"
+ x-transition:leave-start="opacity-100 transform scale-100"
+ x-transition:leave-end="opacity-0 transform scale-90"
+>...</div>
+```
+
+<!-- START_VERBATIM -->
+<div x-data="{ open: false }" class="demo">
+ <button @click="open = ! open">Expands</button>
+
+ <div class="flex">
+ <div
+ x-show="open"
+ x-transition:enter="transition ease-out duration-300"
+ x-transition:enter-start="opacity-0 transform scale-90"
+ x-transition:enter-end="opacity-100 transform scale-100"
+ x-transition:leave="transition ease-in duration-300"
+ x-transition:leave-start="opacity-100 transform scale-100"
+ x-transition:leave-end="opacity-0 transform scale-90"
+ style="will-change: transform"
+ >
+ Content...
+ </div>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+[→ Read more about transition classes](/directives/transition#applying-css-classes)
+
+<a name="binding-attributes"></a>
+## Binding attributes
+
+You can add HTML attributes like `class`, `style`, `disabled`, etc... to elements in Alpine using the `x-bind` directive.
+
+Here is an example of a dynamically bound `class` attribute:
+
+```alpine
+<button
+ x-data="{ red: false }"
+ x-bind:class="red ? 'bg-red' : ''"
+ @click="red = ! red"
+>
+ Toggle Red
+</button>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <button
+ x-data="{ red: false }"
+ x-bind:style="red && 'background: red'"
+ @click="red = ! red"
+ >
+ Toggle Red
+ </button>
+</div>
+<!-- END_VERBATIM -->
+
+
+As a shortcut, you can leave out the `x-bind` and use the shorthand `:` syntax directly:
+
+```alpine
+<button ... :class="red ? 'bg-red' : ''">
+```
+
+Toggling classes on and off based on data inside Alpine is a common need. Here's an example of toggling a class using Alpine's `class` binding object syntax: (Note: this syntax is only available for `class` attributes)
+
+```alpine
+<div x-data="{ open: true }">
+ <span :class="{ 'hidden': ! open }">...</span>
+</div>
+```
+
+Now the `hidden` class will be added to the element if `open` is false, and removed if `open` is true.
+
+<a name="looping-elements"></a>
+## Looping elements
+
+Alpine allows for iterating parts of your template based on JavaScript data using the `x-for` directive. Here is a simple example:
+
+```alpine
+<div x-data="{ statuses: ['open', 'closed', 'archived'] }">
+ <template x-for="status in statuses">
+ <div x-text="status"></div>
+ </template>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div x-data="{ statuses: ['open', 'closed', 'archived'] }" class="demo">
+ <template x-for="status in statuses">
+ <div x-text="status"></div>
+ </template>
+</div>
+<!-- END_VERBATIM -->
+
+Similar to `x-if`, `x-for` must be applied to a `<template>` tag. Internally, Alpine will append the contents of `<template>` tag for every iteration in the loop.
+
+As you can see the new `status` variable is available in the scope of the iterated templates.
+
+[→ Read more about `x-for`](/directives/for)
+
+<a name="inner-html"></a>
+## Inner HTML
+
+Alpine makes it easy to control the HTML content of an element with the `x-html` directive.
+
+```alpine
+<div x-data="{ title: '<h1>Start Here</h1>' }">
+ <div x-html="title"></div>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div x-data="{ title: '<h1>Start Here</h1>' }" class="demo">
+ <div x-html="title"></div>
+</div>
+<!-- END_VERBATIM -->
+
+Now, Alpine will set the text content of the `<div>` with the element `<h1>Start Here</h1>`. When `title` changes, so will the contents of `<h1>`.
+
+> ⚠️ Only use on trusted content and never on user-provided content. ⚠️
+> Dynamically rendering HTML from third parties can easily lead to XSS vulnerabilities.
+
+[→ Read more about `x-html`](/directives/html)
diff --git a/alpinejs/packages/docs/src/en/globals.md b/alpinejs/packages/docs/src/en/globals.md
new file mode 100644
index 0000000..f96ce88
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/globals.md
@@ -0,0 +1,7 @@
+---
+order: 6
+title: Globals
+font-type: mono
+prefix: Alpine.
+type: sub-directory
+---
diff --git a/alpinejs/packages/docs/src/en/globals/alpine-bind.md b/alpinejs/packages/docs/src/en/globals/alpine-bind.md
new file mode 100644
index 0000000..7ea0873
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/globals/alpine-bind.md
@@ -0,0 +1,36 @@
+---
+order: 3
+title: bind()
+---
+
+# Alpine.bind
+
+`Alpine.bind(...)` provides a way to re-use [`x-bind`](/directives/bind#bind-directives) objects within your application.
+
+Here's a simple example. Rather than binding attributes manually with Alpine:
+
+```alpine
+<button type="button" @click="doSomething()" :disabled="shouldDisable"></button>
+```
+
+You can bundle these attributes up into a reusable object and use `x-bind` to bind to that:
+
+```alpine
+<button x-bind="SomeButton"></button>
+
+<script>
+ document.addEventListener('alpine:init', () => {
+ Alpine.bind('SomeButton', () => ({
+ type: 'button',
+
+ '@click'() {
+ this.doSomething()
+ },
+
+ ':disabled'() {
+ return this.shouldDisable
+ },
+ }))
+ })
+</script>
+```
diff --git a/alpinejs/packages/docs/src/en/globals/alpine-data.md b/alpinejs/packages/docs/src/en/globals/alpine-data.md
new file mode 100644
index 0000000..51e40a6
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/globals/alpine-data.md
@@ -0,0 +1,136 @@
+---
+order: 1
+title: data()
+---
+
+# Alpine.data
+
+`Alpine.data(...)` provides a way to re-use `x-data` contexts within your application.
+
+Here's a contrived `dropdown` component for example:
+
+```alpine
+<div x-data="dropdown">
+ <button @click="toggle">...</button>
+
+ <div x-show="open">...</div>
+</div>
+
+<script>
+ document.addEventListener('alpine:init', () => {
+ Alpine.data('dropdown', () => ({
+ open: false,
+
+ toggle() {
+ this.open = ! this.open
+ }
+ }))
+ })
+</script>
+```
+
+As you can see we've extracted the properties and methods we would usually define directly inside `x-data` into a separate Alpine component object.
+
+<a name="registering-from-a-bundle"></a>
+## Registering from a bundle
+
+If you've chosen to use a build step for your Alpine code, you should register your components in the following way:
+
+```js
+import Alpine from `alpinejs`
+import dropdown from './dropdown.js'
+
+Alpine.data('dropdown', dropdown)
+
+Alpine.start()
+```
+
+This assumes you have a file called `dropdown.js` with the following contents:
+
+```js
+export default () => ({
+ open: false,
+
+ toggle() {
+ this.open = ! this.open
+ }
+})
+```
+
+<a name="initial-parameters"></a>
+## Initial parameters
+
+In addition to referencing `Alpine.data` providers by their name plainly (like `x-data="dropdown"`), you can also reference them as functions (`x-data="dropdown()"`). By calling them as functions directly, you can pass in additional parameters to be used when creating the initial data object like so:
+
+```alpine
+<div x-data="dropdown(true)">
+```
+```js
+Alpine.data('dropdown', (initialOpenState = false) => ({
+ open: initialOpenState
+}))
+```
+
+Now, you can re-use the `dropdown` object, but provide it with different parameters as you need to.
+
+<a name="init-functions"></a>
+## Init functions
+
+If your component contains an `init()` method, Alpine will automatically execute it before it renders the component. For example:
+
+```js
+Alpine.data('dropdown', () => ({
+ init() {
+ // This code will be executed before Alpine
+ // initializes the rest of the component.
+ }
+}))
+```
+
+<a name="using-magic-properties"></a>
+## Using magic properties
+
+If you want to access magic methods or properties from a component object, you can do so using the `this` context:
+
+```js
+Alpine.data('dropdown', () => ({
+ open: false,
+
+ init() {
+ this.$watch('open', () => {...})
+ }
+}))
+```
+
+<a name="encapsulating-directives-with-x-bind"></a>
+## Encapsulating directives with `x-bind`
+
+If you wish to re-use more than just the data object of a component, you can encapsulate entire Alpine template directives using `x-bind`.
+
+The following is an example of extracting the templating details of our previous dropdown component using `x-bind`:
+
+```alpine
+<div x-data="dropdown">
+ <button x-bind="trigger"></button>
+
+ <div x-bind="dialogue"></div>
+</div>
+```
+
+```js
+Alpine.data('dropdown', () => ({
+ open: false,
+
+ trigger: {
+ ['@click']() {
+ this.open = ! this.open
+ },
+ },
+
+ dialogue: {
+ ['x-show']() {
+ return this.open
+ },
+ },
+}))
+```
diff --git a/alpinejs/packages/docs/src/en/globals/alpine-store.md b/alpinejs/packages/docs/src/en/globals/alpine-store.md
new file mode 100644
index 0000000..c5714bc
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/globals/alpine-store.md
@@ -0,0 +1,115 @@
+---
+order: 2
+title: store()
+---
+
+# Alpine.store
+
+Alpine offers global state management through the `Alpine.store()` API.
+
+<a name="registering-a-store"></a>
+## Registering A Store
+
+You can either define an Alpine store inside of an `alpine:init` listener (in the case of including Alpine via a `<script>` tag), OR you can define it before manually calling `Alpine.start()` (in the case of importing Alpine into a build):
+
+**From a script tag:**
+```alpine
+<script>
+ document.addEventListener('alpine:init', () => {
+ Alpine.store('darkMode', {
+ on: false,
+
+ toggle() {
+ this.on = ! this.on
+ }
+ })
+ })
+</script>
+```
+
+**From a bundle:**
+```js
+import Alpine from 'alpinejs'
+
+Alpine.store('darkMode', {
+ on: false,
+
+ toggle() {
+ this.on = ! this.on
+ }
+})
+
+Alpine.start()
+```
+
+<a name="accessing stores"></a>
+## Accessing stores
+
+You can access data from any store within Alpine expressions using the `$store` magic property:
+
+```alpine
+<div x-data :class="$store.darkMode.on && 'bg-black'">...</div>
+```
+
+You can also modify properties within the store and everything that depends on those properties will automatically react. For example:
+
+```alpine
+<button x-data @click="$store.darkMode.toggle()">Toggle Dark Mode</button>
+```
+
+Additionally, you can access a store externally using `Alpine.store()` by omitting the second parameter like so:
+
+```alpine
+<script>
+ Alpine.store('darkMode').toggle()
+</script>
+```
+
+<a name="initializing-stores"></a>
+## Initializing stores
+
+If you provide `init()` method in an Alpine store, it will be executed right after the store is registered. This is useful for initializing any state inside the store with sensible starting values.
+
+```alpine
+<script>
+ document.addEventListener('alpine:init', () => {
+ Alpine.store('darkMode', {
+ init() {
+ this.on = window.matchMedia('(prefers-color-scheme: dark)').matches
+ },
+
+ on: false,
+
+ toggle() {
+ this.on = ! this.on
+ }
+ })
+ })
+</script>
+```
+
+Notice the newly added `init()` method in the example above. With this addition, the `on` store variable will be set to the browser's color scheme preference before Alpine renders anything on the page.
+
+<a name="single-value-stores"></a>
+## Single-value stores
+
+If you don't need an entire object for a store, you can set and use any kind of data as a store.
+
+Here's the example from above but using it more simply as a boolean value:
+
+```alpine
+<button x-data @click="$store.darkMode = ! $store.darkMode">Toggle Dark Mode</button>
+
+...
+
+<div x-data :class="$store.darkMode && 'bg-black'">
+ ...
+</div>
+
+
+<script>
+ document.addEventListener('alpine:init', () => {
+ Alpine.store('darkMode', false)
+ })
+</script>
+```
diff --git a/alpinejs/packages/docs/src/en/magics.md b/alpinejs/packages/docs/src/en/magics.md
new file mode 100644
index 0000000..dcef517
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/magics.md
@@ -0,0 +1,7 @@
+---
+order: 5
+title: Magics
+prefix: $
+font-type: mono
+type: sub-directory
+---
diff --git a/alpinejs/packages/docs/src/en/magics/data.md b/alpinejs/packages/docs/src/en/magics/data.md
new file mode 100644
index 0000000..c3b9236
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/magics/data.md
@@ -0,0 +1,45 @@
+---
+order: 8
+prefix: $
+title: data
+---
+
+# $data
+
+`$data` is a magic property that gives you access to the current Alpine data scope (generally provided by `x-data`).
+
+Most of the time, you can just access Alpine data within expressions directly. for example `x-data="{ message: 'Hello Caleb!' }"` will allow you to do things like `x-text="message"`.
+
+However, sometimes it is helpful to have an actual object that encapsulates all scope that you can pass around to other functions:
+
+```alpine
+<div x-data="{ greeting: 'Hello' }">
+ <div x-data="{ name: 'Caleb' }">
+ <button @click="sayHello($data)">Say Hello</button>
+ </div>
+</div>
+
+<script>
+ function sayHello({ greeting, name }) {
+ alert(greeting + ' ' + name + '!')
+ }
+</script>
+```
+
+<!-- START_VERBATIM -->
+<div x-data="{ greeting: 'Hello' }" class="demo">
+ <div x-data="{ name: 'Caleb' }">
+ <button @click="sayHello($data)">Say Hello</button>
+ </div>
+</div>
+
+<script>
+ function sayHello({ greeting, name }) {
+ alert(greeting + ' ' + name + '!')
+ }
+</script>
+<!-- END_VERBATIM -->
+
+Now when the button is pressed, the browser will alert `Hello Caleb!` because it was passed a data object that contained all the Alpine scope of the expression that called it (`@click="..."`).
+
+Most applications won't need this magic property, but it can be very helpful for deeper, more complicated Alpine utilities.
diff --git a/alpinejs/packages/docs/src/en/magics/dispatch.md b/alpinejs/packages/docs/src/en/magics/dispatch.md
new file mode 100644
index 0000000..376b70f
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/magics/dispatch.md
@@ -0,0 +1,106 @@
+---
+order: 5
+title: dispatch
+---
+
+# $dispatch
+
+`$dispatch` is a helpful shortcut for dispatching browser events.
+
+```alpine
+<div @notify="alert('Hello World!')">
+ <button @click="$dispatch('notify')">
+ Notify
+ </button>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <div x-data @notify="alert('Hello World!')">
+ <button @click="$dispatch('notify')">
+ Notify
+ </button>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+You can also pass data along with the dispatched event if you wish. This data will be accessible as the `.detail` property of the event:
+
+```alpine
+<div @notify="alert($event.detail.message)">
+ <button @click="$dispatch('notify', { message: 'Hello World!' })">
+ Notify
+ </button>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <div x-data @notify="alert($event.detail.message)">
+ <button @click="$dispatch('notify', { message: 'Hello World!' })">Notify</button>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+
+Under the hood, `$dispatch` is a wrapper for the more verbose API: `element.dispatchEvent(new CustomEvent(...))`
+
+**Note on event propagation**
+
+Notice that, because of [event bubbling](https://en.wikipedia.org/wiki/Event_bubbling), when you need to capture events dispatched from nodes that are under the same nesting hierarchy, you'll need to use the [`.window`](https://github.com/alpinejs/alpine#x-on) modifier:
+
+**Example:**
+
+```alpine
+<!-- 🚫 Won't work -->
+<div x-data>
+ <span @notify="..."></span>
+ <button @click="$dispatch('notify')">Notify</button>
+</div>
+
+<!-- ✅ Will work (because of .window) -->
+<div x-data>
+ <span @notify.window="..."></span>
+ <button @click="$dispatch('notify')">Notify</button>
+</div>
+```
+
+> The first example won't work because when `custom-event` is dispatched, it'll propagate to its common ancestor, the `div`, not its sibling, the `<span>`. The second example will work because the sibling is listening for `notify` at the `window` level, which the custom event will eventually bubble up to.
+
+<a name="dispatching-to-components"></a>
+## Dispatching to other components
+
+You can also take advantage of the previous technique to make your components talk to each other:
+
+**Example:**
+
+```alpine
+<div
+ x-data="{ title: 'Hello' }"
+ @set-title.window="title = $event.detail"
+>
+ <h1 x-text="title"></h1>
+</div>
+
+<div x-data>
+ <button @click="$dispatch('set-title', 'Hello World!')">Click me</button>
+</div>
+<!-- When clicked, the content of the h1 will set to "Hello World!". -->
+```
+
+<a name="dispatching-to-x-model"></a>
+## Dispatching to x-model
+
+You can also use `$dispatch()` to trigger data updates for `x-model` data bindings. For example:
+
+```alpine
+<div x-data="{ title: 'Hello' }">
+ <span x-model="title">
+ <button @click="$dispatch('input', 'Hello World!')">Click me</button>
+ <!-- After the button is pressed, `x-model` will catch the bubbling "input" event, and update title. -->
+ </span>
+</div>
+```
+
+This opens up the door for making custom input components whose value can be set via `x-model`.
diff --git a/alpinejs/packages/docs/src/en/magics/el.md b/alpinejs/packages/docs/src/en/magics/el.md
new file mode 100644
index 0000000..2a6d732
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/magics/el.md
@@ -0,0 +1,21 @@
+---
+order: 1
+prefix: $
+title: el
+---
+
+# $el
+
+`$el` is a magic property that can be used to retrieve the current DOM node.
+
+```alpine
+<button @click="$el.innerHTML = 'Hello World!'">Replace me with "Hello World!"</button>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <div x-data>
+ <button @click="$el.textContent = 'Hello World!'">Replace me with "Hello World!"</button>
+ </div>
+</div>
+<!-- END_VERBATIM -->
diff --git a/alpinejs/packages/docs/src/en/magics/id.md b/alpinejs/packages/docs/src/en/magics/id.md
new file mode 100644
index 0000000..d0e2b8d
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/magics/id.md
@@ -0,0 +1,106 @@
+---
+order: 9
+prefix: $
+title: id
+---
+
+# $id
+
+`$id` is a magic property that can be used to generate an element's ID and ensure that it won't conflict with other IDs of the same name on the same page.
+
+This utility is extremely helpful when building re-usable components (presumably in a back-end template) that might occur multiple times on a page, and make use of ID attributes.
+
+Things like input components, modals, listboxes, etc. will all benefit from this utility.
+
+<a name="basic-usage"></a>
+## Basic usage
+
+Suppose you have two input elements on a page, and you want them to have a unique ID from each other, you can do the following:
+
+```alpine
+<input type="text" :id="$id('text-input')">
+<!-- id="text-input-1" -->
+
+<input type="text" :id="$id('text-input')">
+<!-- id="text-input-2" -->
+```
+
+As you can see, `$id` takes in a string and spits out an appended suffix that is unique on the page.
+
+<a name="groups-with-x-id"></a>
+## Grouping with x-id
+
+Now let's say you want to have those same two input elements, but this time you want `<label>` elements for each of them.
+
+This presents a problem, you now need to be able to reference the same ID twice. One for the `<label>`'s `for` attribute, and the other for the `id` on the input.
+
+Here's is a way that you might think to accomplish this and is totally valid:
+
+```alpine
+<div x-data="{ id: $id('text-input') }">
+ <label :for="id"> <!-- "text-input-1" -->
+ <input type="text" :id="id"> <!-- "text-input-1" -->
+</div>
+
+<div x-data="{ id: $id('text-input') }">
+ <label :for="id"> <!-- "text-input-2" -->
+ <input type="text" :id="id"> <!-- "text-input-2" -->
+</div>
+```
+
+This approach is fine, however, having to name and store the ID in your component scope feels cumbersome.
+
+To accomplish this same task in a more flexible way, you can use Alpine's `x-id` directive to declare an "id scope" for a set of IDs:
+
+```alpine
+<div x-id="['text-input']">
+ <label :for="$id('text-input')"> <!-- "text-input-1" -->
+ <input type="text" :id="$id('text-input')"> <!-- "text-input-1" -->
+</div>
+
+<div x-id="['text-input']">
+ <label :for="$id('text-input')"> <!-- "text-input-2" -->
+ <input type="text" :id="$id('text-input')"> <!-- "text-input-2" -->
+</div>
+```
+
+As you can see, `x-id` accepts an array of ID names. Now any usages of `$id()` within that scope, will all use the same ID. Think of them as "id groups".
+
+<a name="nesting"></a>
+## Nesting
+
+As you might have intuited, you can freely nest these `x-id` groups, like so:
+
+```alpine
+<div x-id="['text-input']">
+ <label :for="$id('text-input')"> <!-- "text-input-1" -->
+ <input type="text" :id="$id('text-input')"> <!-- "text-input-1" -->
+
+ <div x-id="['text-input']">
+ <label :for="$id('text-input')"> <!-- "text-input-2" -->
+ <input type="text" :id="$id('text-input')"> <!-- "text-input-2" -->
+ </div>
+</div>
+```
+
+<a name="keyed-ids"></a>
+## Keyed IDs (For Looping)
+
+Sometimes, it is helpful to specify an additional suffix on the end of an ID for the purpose of identifying it within a loop.
+
+For this, `$id()` accepts an optional second parameter that will be added as a suffix on the end of the generated ID.
+
+A common example of this need is something like a listbox component that uses the `aria-activedescendant` attribute to tell assistive technologies which element is "active" in the list:
+
+```alpine
+<ul
+ x-id="['list-item']"
+ :aria-activedescendant="$id('list-item', activeItem.id)"
+>
+ <template x-for="item in items" :key="item.id">
+ <li :id="$id('list-item', item.id)">...</li>
+ </template>
+</ul>
+```
+
+This is an incomplete example of a listbox, but it should still be helpful to demonstrate a scenario where you might need each ID in a group to still be unique to the page, but also be keyed within a loop so that you can reference individual IDs within that group.
diff --git a/alpinejs/packages/docs/src/en/magics/nextTick.md b/alpinejs/packages/docs/src/en/magics/nextTick.md
new file mode 100644
index 0000000..8b119f9
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/magics/nextTick.md
@@ -0,0 +1,23 @@
+---
+order: 6
+prefix: $
+title: nextTick
+---
+
+# $nextTick
+
+`$nextTick` is a magic property that allows you to only execute a given expression AFTER Alpine has made its reactive DOM updates. This is useful for times you want to interact with the DOM state AFTER it's reflected any data updates you've made.
+
+```alpine
+<div x-data="{ title: 'Hello' }">
+ <button
+ @click="
+ title = 'Hello World!';
+ $nextTick(() => { console.log($el.innerText) });
+ "
+ x-text="title"
+ ></button>
+</div>
+```
+
+In the above example, rather than logging "Hello" to the console, "Hello World!" will be logged because `$nextTick` was used to wait until Alpine was finished updating the DOM.
diff --git a/alpinejs/packages/docs/src/en/magics/refs.md b/alpinejs/packages/docs/src/en/magics/refs.md
new file mode 100644
index 0000000..6c42f5e
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/magics/refs.md
@@ -0,0 +1,27 @@
+---
+order: 2
+prefix: $
+title: refs
+---
+
+# $refs
+
+`$refs` is a magic property that can be used to retrieve DOM elements marked with `x-ref` inside the component. This is useful when you need to manually manipulate DOM elements. It's often used as a more succinct, scoped, alternative to `document.querySelector`.
+
+```alpine
+<button @click="$refs.text.remove()">Remove Text</button>
+
+<span x-ref="text">Hello 👋</span>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <div x-data>
+ <button @click="$refs.text.remove()">Remove Text</button>
+
+ <div class="pt-4" x-ref="text">Hello 👋</div>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+Now, when the `<button>` is pressed, the `<span>` will be removed.
diff --git a/alpinejs/packages/docs/src/en/magics/root.md b/alpinejs/packages/docs/src/en/magics/root.md
new file mode 100644
index 0000000..e182804
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/magics/root.md
@@ -0,0 +1,21 @@
+---
+order: 7
+prefix: $
+title: root
+---
+
+# $root
+
+`$root` is a magic property that can be used to retrieve the root element of any Alpine component. In other words the closest element up the DOM tree that contains `x-data`.
+
+```alpine
+<div x-data data-message="Hello World!">
+ <button @click="alert($root.dataset.message)">Say Hi</button>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div x-data data-message="Hello World!" class="demo">
+ <button @click="alert($root.dataset.message)">Say Hi</button>
+</div>
+<!-- END_VERBATIM -->
diff --git a/alpinejs/packages/docs/src/en/magics/store.md b/alpinejs/packages/docs/src/en/magics/store.md
new file mode 100644
index 0000000..e18eb60
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/magics/store.md
@@ -0,0 +1,60 @@
+---
+order: 3
+prefix: $
+title: store
+---
+
+# $store
+
+You can use `$store` to conveniently access global Alpine stores registered using [`Alpine.store(...)`](#). For example:
+
+```alpine
+<button x-data @click="$store.darkMode.toggle()">Toggle Dark Mode</button>
+
+...
+
+<div x-data :class="$store.darkMode.on && 'bg-black'">
+ ...
+</div>
+
+
+<script>
+ document.addEventListener('alpine:init', () => {
+ Alpine.store('darkMode', {
+ on: false,
+
+ toggle() {
+ this.on = ! this.on
+ }
+ })
+ })
+</script>
+```
+
+Given that we've registered the `darkMode` store and set `on` to "false", when the `<button>` is pressed, `on` will be "true" and the background color of the page will change to black.
+
+<a name="single-value-stores"></a>
+## Single-value stores
+
+If you don't need an entire object for a store, you can set and use any kind of data as a store.
+
+Here's the example from above but using it more simply as a boolean value:
+
+```alpine
+<button x-data @click="$store.darkMode = ! $store.darkMode">Toggle Dark Mode</button>
+
+...
+
+<div x-data :class="$store.darkMode && 'bg-black'">
+ ...
+</div>
+
+
+<script>
+ document.addEventListener('alpine:init', () => {
+ Alpine.store('darkMode', false)
+ })
+</script>
+```
+
+[→ Read more about Alpine stores](/globals/alpine-store)
diff --git a/alpinejs/packages/docs/src/en/magics/watch.md b/alpinejs/packages/docs/src/en/magics/watch.md
new file mode 100644
index 0000000..e70886e
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/magics/watch.md
@@ -0,0 +1,59 @@
+---
+order: 4
+title: watch
+---
+
+# $watch
+
+You can "watch" a component property using the `$watch` magic method. For example:
+
+```alpine
+<div x-data="{ open: false }" x-init="$watch('open', value => console.log(value))">
+ <button @click="open = ! open">Toggle Open</button>
+</div>
+```
+
+In the above example, when the button is pressed and `open` is changed, the provided callback will fire and `console.log` the new value:
+
+You can watch deeply nested properties using "dot" notation
+
+```alpine
+<div x-data="{ foo: { bar: 'baz' }}" x-init="$watch('foo.bar', value => console.log(value))">
+ <button @click="foo.bar = 'bob'">Toggle Open</button>
+</div>
+```
+
+When the `<button>` is pressed, `foo.bar` will be set to "bob", and "bob" will be logged to the console.
+
+<a name="getting-the-old-value"></a>
+### Getting the "old" value
+
+`$watch` keeps track of the previous value of the property being watched, You can access it using the optional second argument to the callback like so:
+
+```alpine
+<div x-data="{ open: false }" x-init="$watch('open', (value, oldValue) => console.log(value, oldValue))">
+ <button @click="open = ! open">Toggle Open</button>
+</div>
+```
+
+<a name="deep-watching"></a>
+### Deep watching
+
+`$watch` will automatically watches from changes at any level but you should keep in mind that, when a change is detected, the watcher will return the value of the observed property, not the value of the subproperty that has changed.
+
+```alpine
+<div x-data="{ foo: { bar: 'baz' }}" x-init="$watch('foo', (value, oldValue) => console.log(value, oldValue))">
+ <button @click="foo.bar = 'bob'">Update</button>
+</div>
+```
+
+When the `<button>` is pressed, `foo.bar` will be set to "bob", and "{bar: 'bob'} {bar: 'baz'}" will be logged to the console (new and old value).
+
+> ⚠️ Changing a property of a "watched" object as a side effect of the `$watch` callback will generate an infinite loop and eventually error.
+
+```alpine
+<!-- 🚫 Infinite loop -->
+<div x-data="{ foo: { bar: 'baz', bob: 'lob' }}" x-init="$watch('foo', value => foo.bob = foo.bar)">
+ <button @click="foo.bar = 'bob'">Update</button>
+</div>
+```
diff --git a/alpinejs/packages/docs/src/en/plugins.md b/alpinejs/packages/docs/src/en/plugins.md
new file mode 100644
index 0000000..75b8b2f
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/plugins.md
@@ -0,0 +1,6 @@
+---
+order: 7
+title: Plugins
+font-type: mono
+type: sub-directory
+---
diff --git a/alpinejs/packages/docs/src/en/plugins/collapse.md b/alpinejs/packages/docs/src/en/plugins/collapse.md
new file mode 100644
index 0000000..183f12f
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/plugins/collapse.md
@@ -0,0 +1,109 @@
+---
+order: 4
+title: Collapse
+description: Collapse and expand elements with robust animations
+graph_image: https://alpinejs.dev/social_collapse.jpg
+---
+
+# Collapse Plugin
+
+Alpine's Collapse plugin allows you to expand and collapse elements using smooth animations.
+
+Because this behavior and implementation differs from Alpine's standard transition system, this functionality was made into a dedicated plugin.
+
+<a name="installation"></a>
+## Installation
+
+You can use this plugin by either including it from a `<script>` tag or installing it via NPM:
+
+### Via CDN
+
+You can include the CDN build of this plugin as a `<script>` tag, just make sure to include it BEFORE Alpine's core JS file.
+
+```alpine
+<!-- Alpine Plugins -->
+<script defer src="https://unpkg.com/@alpinejs/collapse@3.x.x/dist/cdn.min.js"></script>
+
+<!-- Alpine Core -->
+<script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>
+```
+
+### Via NPM
+
+You can install Collapse from NPM for use inside your bundle like so:
+
+```shell
+npm install @alpinejs/collapse
+```
+
+Then initialize it from your bundle:
+
+```js
+import Alpine from 'alpinejs'
+import collapse from '@alpinejs/collapse'
+
+Alpine.plugin(collapse)
+
+...
+```
+
+<a name="x-collapse"></a>
+## x-collapse
+
+The primary API for using this plugin is the `x-collapse` directive.
+
+`x-collapse` can only exist on an element that already has an `x-show` directive. When added to an `x-show` element, `x-collapse` will smoothly "collapse" and "expand" the element when it's visibility is toggled by animating its height property.
+
+For example:
+
+```alpine
+<div x-data="{ expanded: false }">
+ <button @click="expanded = ! expanded">Toggle Content</button>
+
+ <p x-show="expanded" x-collapse>
+ ...
+ </p>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div x-data="{ expanded: false }" class="demo">
+ <button @click="expanded = ! expanded">Toggle Content</button>
+
+ <div x-show="expanded" x-collapse>
+ <div class="pt-4">
+ Reprehenderit eu excepteur ullamco esse cillum reprehenderit exercitation labore non. Dolore dolore ea dolore veniam sint in sint ex Lorem ipsum. Sint laborum deserunt deserunt amet voluptate cillum deserunt. Amet nisi pariatur sit ut id. Ipsum est minim est commodo id dolor sint id quis sint Lorem.
+ </div>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+<a name="modifiers"></a>
+## Modifiers
+
+<a name="dot-duration"></a>
+### .duration
+
+You can customize the duration of the collapse/expand transition by appending the `.duration` modifier like so:
+
+```alpine
+<div x-data="{ expanded: false }">
+ <button @click="expanded = ! expanded">Toggle Content</button>
+
+ <p x-show="expanded" x-collapse.duration.1000ms>
+ ...
+ </p>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div x-data="{ expanded: false }" class="demo">
+ <button @click="expanded = ! expanded">Toggle Content</button>
+
+ <div x-show="expanded" x-collapse.duration.1000ms>
+ <div class="pt-4">
+ Reprehenderit eu excepteur ullamco esse cillum reprehenderit exercitation labore non. Dolore dolore ea dolore veniam sint in sint ex Lorem ipsum. Sint laborum deserunt deserunt amet voluptate cillum deserunt. Amet nisi pariatur sit ut id. Ipsum est minim est commodo id dolor sint id quis sint Lorem.
+ </div>
+ </div>
+</div>
+<!-- END_VERBATIM -->
diff --git a/alpinejs/packages/docs/src/en/plugins/focus.md b/alpinejs/packages/docs/src/en/plugins/focus.md
new file mode 100644
index 0000000..1ae3522
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/plugins/focus.md
@@ -0,0 +1,420 @@
+---
+order: 3
+title: Focus
+description: Easily manage focus within the page
+graph_image: https://alpinejs.dev/social_focus.jpg
+---
+
+> Notice: This Plugin was previously called "Trap". Trap's functionality has been absorbed into this plugin along with additional functionality. You can swap Trap for Focus without any breaking changes.
+
+# Focus Plugin
+
+Alpine's Focus plugin allows you to manage focus on a page.
+
+> This plugin internally makes heavy use of the open source tool: [Tabbable](https://github.com/focus-trap/tabbable). Big thanks to that team for providing a much needed solution to this problem.
+
+<a name="installation"></a>
+## Installation
+
+You can use this plugin by either including it from a `<script>` tag or installing it via NPM:
+
+### Via CDN
+
+You can include the CDN build of this plugin as a `<script>` tag, just make sure to include it BEFORE Alpine's core JS file.
+
+```alpine
+<!-- Alpine Plugins -->
+<script defer src="https://unpkg.com/@alpinejs/focus@3.x.x/dist/cdn.min.js"></script>
+
+<!-- Alpine Core -->
+<script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>
+```
+
+### Via NPM
+
+You can install Focus from NPM for use inside your bundle like so:
+
+```shell
+npm install @alpinejs/focus
+```
+
+Then initialize it from your bundle:
+
+```js
+import Alpine from 'alpinejs'
+import focus from '@alpinejs/focus'
+
+Alpine.plugin(focus)
+
+...
+```
+
+<a name="x-trap"></a>
+## x-trap
+
+Focus offers a dedicated API for trapping focus within an element: the `x-trap` directive.
+
+`x-trap` accepts a JS expression. If the result of that expression is true, then the focus will be trapped inside that element until the expression becomes false, then at that point, focus will be returned to where it was previously.
+
+For example:
+
+```alpine
+<div x-data="{ open: false }">
+ <button @click="open = true">Open Dialog</button>
+
+ <span x-show="open" x-trap="open">
+ <p>...</p>
+
+ <input type="text" placeholder="Some input...">
+
+ <input type="text" placeholder="Some other input...">
+
+ <button @click="open = false">Close Dialog</button>
+ </span>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div x-data="{ open: false }" class="demo">
+ <div :class="open && 'opacity-50'">
+ <button x-on:click="open = true">Open Dialog</button>
+ </div>
+
+ <div x-show="open" x-trap="open" class="mt-4 space-y-4 p-4 border bg-yellow-100" @keyup.escape.window="open = false">
+ <strong>
+ <div>Focus is now "trapped" inside this dialog, meaning you can only click/focus elements within this yellow dialog. If you press tab repeatedly, the focus will stay within this dialog.</div>
+ </strong>
+
+ <div>
+ <input type="text" placeholder="Some input...">
+ </div>
+
+ <div>
+ <input type="text" placeholder="Some other input...">
+ </div>
+
+ <div>
+ <button @click="open = false">Close Dialog</button>
+ </div>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+<a name="nesting"></a>
+### Nesting dialogs
+
+Sometimes you may want to nest one dialog inside another. `x-trap` makes this trivial and handles it automatically.
+
+`x-trap` keeps track of newly "trapped" elements and stores the last actively focused element. Once the element is "untrapped" then the focus will be returned to where it was originally.
+
+This mechanism is recursive, so you can trap focus within an already trapped element infinite times, then "untrap" each element successively.
+
+Here is nesting in action:
+
+```alpine
+<div x-data="{ open: false }">
+ <button @click="open = true">Open Dialog</button>
+
+ <span x-show="open" x-trap="open">
+
+ ...
+
+ <div x-data="{ open: false }">
+ <button @click="open = true">Open Nested Dialog</button>
+
+ <span x-show="open" x-trap="open">
+
+ ...
+
+ <button @click="open = false">Close Nested Dialog</button>
+ </span>
+ </div>
+
+ <button @click="open = false">Close Dialog</button>
+ </span>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div x-data="{ open: false }" class="demo">
+ <div :class="open && 'opacity-50'">
+ <button x-on:click="open = true">Open Dialog</button>
+ </div>
+
+ <div x-show="open" x-trap="open" class="mt-4 space-y-4 p-4 border bg-yellow-100" @keyup.escape.window="open = false">
+ <div>
+ <input type="text" placeholder="Some input...">
+ </div>
+
+ <div>
+ <input type="text" placeholder="Some other input...">
+ </div>
+
+ <div x-data="{ open: false }">
+ <div :class="open && 'opacity-50'">
+ <button x-on:click="open = true">Open Nested Dialog</button>
+ </div>
+
+ <div x-show="open" x-trap="open" class="mt-4 space-y-4 p-4 border border-gray-500 bg-yellow-200" @keyup.escape.window="open = false">
+ <strong>
+ <div>Focus is now "trapped" inside this nested dialog. You cannot focus anything inside the outer dialog while this is open. If you close this dialog, focus will be returned to the last known active element.</div>
+ </strong>
+
+ <div>
+ <input type="text" placeholder="Some input...">
+ </div>
+
+ <div>
+ <input type="text" placeholder="Some other input...">
+ </div>
+
+ <div>
+ <button @click="open = false">Close Nested Dialog</button>
+ </div>
+ </div>
+ </div>
+
+ <div>
+ <button @click="open = false">Close Dialog</button>
+ </div>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+<a name="modifiers"></a>
+### Modifiers
+
+<a name="inert"></a>
+#### .inert
+
+When building things like dialogs/modals, it's recommended to hide all the other elements on the page from screenreaders when trapping focus.
+
+By adding `.inert` to `x-trap`, when focus is trapped, all other elements on the page will receive `aria-hidden="true"` attributes, and when focus trapping is disabled, those attributes will also be removed.
+
+```alpine
+<!-- When `open` is `false`: -->
+<body x-data="{ open: false }">
+ <div x-trap.inert="open" ...>
+ ...
+ </div>
+
+ <div>
+ ...
+ </div>
+</body>
+
+<!-- When `open` is `true`: -->
+<body x-data="{ open: true }">
+ <div x-trap.inert="open" ...>
+ ...
+ </div>
+
+ <div aria-hidden="true">
+ ...
+ </div>
+</body>
+```
+
+<a name="noscroll"></a>
+#### .noscroll
+
+When building dialogs/modals with Alpine, it's recommended that you disable scrollling for the surrounding content when the dialog is open.
+
+`x-trap` allows you to do this automatically with the `.noscroll` modifiers.
+
+By adding `.noscroll`, Alpine will remove the scrollbar from the page and block users from scrolling down the page while a dialog is open.
+
+For example:
+
+```alpine
+<div x-data="{ open: false }">
+ <button>Open Dialog</button>
+
+ <div x-show="open" x-trap.noscroll="open">
+ Dialog Contents
+
+ <button @click="open = false">Close Dialog</button>
+ </div>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <div x-data="{ open: false }">
+ <button @click="open = true">Open Dialog</button>
+
+ <div x-show="open" x-trap.noscroll="open" class="border mt-4 p-4">
+ <div class="mb-4 text-bold">Dialog Contents</div>
+
+ <p class="mb-4 text-gray-600 text-sm">Notice how you can no longer scroll on this page while this dialog is open.</p>
+
+ <button class="mt-4" @click="open = false">Close Dialog</button>
+ </div>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+<a name="noreturn"></a>
+#### .noreturn
+
+Sometimes you may not want focus to be returned to where it was previously. Consider a dropdown that's triggered upon focusing an input, returning focus to the input on close will just trigger the dropdown to open again.
+
+`x-trap` allows you to disable this behavior with the `.noreturn` modifier.
+
+By adding `.noreturn`, Alpine will not return focus upon x-trap evaluating to false.
+
+For example:
+
+```alpine
+<div x-data="{ open: false }" x-trap.noreturn="open">
+ <input type="search" placeholder="search for something" />
+
+ <div x-show="open">
+ Search results
+
+ <button @click="open = false">Close</button>
+ </div>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <div
+ x-data="{ open: false }"
+ x-trap.noreturn="open"
+ @click.outside="open = false"
+ @keyup.escape.prevent.stop="open = false"
+ >
+ <input type="search" placeholder="search for something"
+ @focus="open = true"
+ @keyup.escape.prevent="$el.blur()"
+ />
+
+ <div x-show="open">
+ <div class="mb-4 text-bold">Search results</div>
+
+ <p class="mb-4 text-gray-600 text-sm">Notice when closing this dropdown, focus is not returned to the input.</p>
+
+ <button class="mt-4" @click="open = false">Close Dialog</button>
+ </div>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+<a name="focus-magic"></a>
+## $focus
+
+This plugin offers many smaller utilities for managing focus within a page. These utilities are exposed via the `$focus` magic.
+
+| Property | Description |
+| --- | --- |
+| `focus(el)` | Focus the passed element (handling annoyances internally: using nextTick, etc.) |
+| `focusable(el)` | Detect weather or not an element is focusable |
+| `focusables()` | Get all "focusable" elements within the current element |
+| `focused()` | Get the currently focused element on the page |
+| `lastFocused()` | Get the last focused element on the page |
+| `within(el)` | Specify an element to scope the `$focus` magic to (the current element by default) |
+| `first()` | Focus the first focusable element |
+| `last()` | Focus the last focusable element |
+| `next()` | Focus the next focusable element |
+| `previous()` | Focus the previous focusable element |
+| `noscroll()` | Prevent scrolling to the element about to be focused |
+| `wrap()` | When retrieving "next" or "previous" use "wrap around" (ex. returning the first element if getting the "next" element of the last element) |
+| `getFirst()` | Retrieve the first focusable element |
+| `getLast()` | Retrieve the last focusable element |
+| `getNext()` | Retrieve the next focusable element |
+| `getPrevious()` | Retrieve the previous focusable element |
+
+Let's walk through a few examples of these utilities in use. The example below allows the user to control focus within the group of buttons using the arrow keys. You can test this by clicking on a button, then using the arrow keys to move focus around:
+
+```alpine
+<div
+ @keydown.right="$focus.next()"
+ @keydown.left="$focus.previous()"
+>
+ <button>First</button>
+ <button>Second</button>
+ <button>Third</button>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+<div
+ x-data
+ @keydown.right="$focus.next()"
+ @keydown.left="$focus.previous()"
+>
+ <button class="focus:outline-none focus:ring-2 focus:ring-aqua-400">First</button>
+ <button class="focus:outline-none focus:ring-2 focus:ring-aqua-400">Second</button>
+ <button class="focus:outline-none focus:ring-2 focus:ring-aqua-400">Third</button>
+</div>
+(Click a button, then use the arrow keys to move left and right)
+</div>
+<!-- END_VERBATIM -->
+
+Notice how if the last button is focused, pressing "right arrow" won't do anything. Let's add the `.wrap()` method so that focus "wraps around":
+
+```alpine
+<div
+ @keydown.right="$focus.wrap().next()"
+ @keydown.left="$focus.wrap().previous()"
+>
+ <button>First</button>
+ <button>Second</button>
+ <button>Third</button>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+<div
+ x-data
+ @keydown.right="$focus.wrap().next()"
+ @keydown.left="$focus.wrap().previous()"
+>
+ <button class="focus:outline-none focus:ring-2 focus:ring-aqua-400">First</button>
+ <button class="focus:outline-none focus:ring-2 focus:ring-aqua-400">Second</button>
+ <button class="focus:outline-none focus:ring-2 focus:ring-aqua-400">Third</button>
+</div>
+(Click a button, then use the arrow keys to move left and right)
+</div>
+<!-- END_VERBATIM -->
+
+Now, let's add two buttons, one to focus the first element in the button group, and another focus the last element:
+
+```alpine
+<button @click="$focus.within($refs.buttons).first()">Focus "First"</button>
+<button @click="$focus.within($refs.buttons).last()">Focus "Last"</button>
+
+<div
+ x-ref="buttons"
+ @keydown.right="$focus.wrap().next()"
+ @keydown.left="$focus.wrap().previous()"
+>
+ <button>First</button>
+ <button>Second</button>
+ <button>Third</button>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo" x-data>
+<button @click="$focus.within($refs.buttons).first()">Focus "First"</button>
+<button @click="$focus.within($refs.buttons).last()">Focus "Last"</button>
+
+<hr class="mt-2 mb-2"/>
+
+<div
+ x-ref="buttons"
+ @keydown.right="$focus.wrap().next()"
+ @keydown.left="$focus.wrap().previous()"
+>
+ <button class="focus:outline-none focus:ring-2 focus:ring-aqua-400">First</button>
+ <button class="focus:outline-none focus:ring-2 focus:ring-aqua-400">Second</button>
+ <button class="focus:outline-none focus:ring-2 focus:ring-aqua-400">Third</button>
+</div>
+</div>
+<!-- END_VERBATIM -->
+
+Notice that we needed to add a `.within()` method for each button so that `$focus` knows to scope itself to a different element (the `div` wrapping the buttons).
diff --git a/alpinejs/packages/docs/src/en/plugins/intersect.md b/alpinejs/packages/docs/src/en/plugins/intersect.md
new file mode 100644
index 0000000..1e82cb7
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/plugins/intersect.md
@@ -0,0 +1,152 @@
+---
+order: 1
+title: Intersect
+description: An Alpine convenience wrapper for Intersection Observer that allows you to easily react when an element enters the viewport.
+graph_image: https://alpinejs.dev/social_intersect.jpg
+---
+
+# Intersect Plugin
+
+Alpine's Intersect plugin is a convenience wrapper for [Intersection Observer](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) that allows you to easily react when an element enters the viewport.
+
+This is useful for: lazy loading images and other content, triggering animations, infinite scrolling, logging "views" of content, etc.
+
+<a name="installation"></a>
+## Installation
+
+You can use this plugin by either including it from a `<script>` tag or installing it via NPM:
+
+### Via CDN
+
+You can include the CDN build of this plugin as a `<script>` tag, just make sure to include it BEFORE Alpine's core JS file.
+
+```alpine
+<!-- Alpine Plugins -->
+<script defer src="https://unpkg.com/@alpinejs/intersect@3.x.x/dist/cdn.min.js"></script>
+
+<!-- Alpine Core -->
+<script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>
+```
+
+### Via NPM
+
+You can install Intersect from NPM for use inside your bundle like so:
+
+```shell
+npm install @alpinejs/intersect
+```
+
+Then initialize it from your bundle:
+
+```js
+import Alpine from 'alpinejs'
+import intersect from '@alpinejs/intersect'
+
+Alpine.plugin(intersect)
+
+...
+```
+
+<a name="x-intersect"></a>
+## x-intersect
+
+The primary API for using this plugin is `x-intersect`. You can add `x-intersect` to any element within an Alpine component, and when that component enters the viewport (is scrolled into view), the provided expression will execute.
+
+For example, in the following snippet, `shown` will remain `false` until the element is scrolled into view. At that point, the expression will execute and `shown` will become `true`:
+
+```alpine
+<div x-data="{ shown: false }" x-intersect="shown = true">
+ <div x-show="shown" x-transition>
+ I'm in the viewport!
+ </div>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo" style="height: 60px; overflow-y: scroll;" x-data x-ref="root">
+ <a href="#" @click.prevent="$refs.root.scrollTo({ top: $refs.root.scrollHeight, behavior: 'smooth' })">Scroll Down 👇</a>
+ <div style="height: 50vh"></div>
+ <div x-data="{ shown: false }" x-intersect="shown = true" id="yoyo">
+ <div x-show="shown" x-transition.duration.1000ms>
+ I'm in the viewport!
+ </div>
+ <div x-show="! shown">&nbsp;</div>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+<a name="x-intersect-enter"></a>
+### x-intersect:enter
+
+The `:enter` suffix is an alias of `x-intersect`, and works the same way:
+
+```alpine
+<div x-intersect:enter="shown = true">...</div>
+```
+
+You may choose to use this for clarity when also using the `:leave` suffix.
+
+<a name="x-intersect-leave"></a>
+### x-intersect:leave
+
+Appending `:leave` runs your expression when the element leaves the viewport:
+
+```alpine
+<div x-intersect:leave="shown = true">...</div>
+```
+
+<a name="modifiers"></a>
+## Modifiers
+
+<a name="once"></a>
+### .once
+
+Sometimes it's useful to evaluate an expression only the first time an element enters the viewport and not subsequent times. For example when triggering "enter" animations. In these cases, you can add the `.once` modifier to `x-intersect` to achieve this.
+
+```alpine
+<div x-intersect.once="shown = true">...</div>
+```
+
+<a name="half"></a>
+### .half
+
+Evaluates the expression once the intersection threshold exceeds `0.5`.
+
+Useful for elements where it's important to show at least part of the element.
+
+```alpine
+<div x-intersect.half="shown = true">...</div> // when `0.5` of the element is in the viewport
+```
+
+<a name="full"></a>
+### .full
+
+Evaluates the expression once the intersection threshold exceeds `0.99`.
+
+Useful for elements where it's important to show the whole element.
+
+```alpine
+<div x-intersect.full="shown = true">...</div> // when `0.99` of the element is in the viewport
+```
+
+<a name="margin"></a>
+### .margin
+
+Allows you to control the `rootMargin` property of the underlying `IntersectionObserver`.
+This effectively tweaks the size of the viewport boundary. Positive values
+expand the boundary beyond the viewport, and negative values shrink it inward. The values
+work like CSS margin: one value for all sides, two values for top/bottom, left/right, or
+four values for top, right, bottom, left. You can use `px` and `%` values, or use a bare number to
+get a pixel value.
+
+```alpine
+<div x-intersect.margin.200px="loaded = true">...</div> // Load when the element is within 200px of the viewport
+```
+
+```alpine
+<div x-intersect:leave.margin.10%.25px.25.25px="loaded = false">...</div> // Unload when the element gets within 10% of the top of the viewport, or within 25px of the other three edges
+```
+
+```alpine
+<div x-intersect.margin.-100px="visible = true">...</div> // Mark as visible when element is more than 100 pixels into the viewport.
+```
diff --git a/alpinejs/packages/docs/src/en/plugins/morph.md b/alpinejs/packages/docs/src/en/plugins/morph.md
new file mode 100644
index 0000000..030074b
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/plugins/morph.md
@@ -0,0 +1,252 @@
+---
+order: 5
+title: Morph
+description: Morph an element into the provided HTML
+graph_image: https://alpinejs.dev/social_morph.jpg
+---
+
+# Morph Plugin
+
+Alpine's Morph plugin allows you to "morph" an element on the page into the provided HTML template, all while preserving any browser or Alpine state within the "morphed" element.
+
+This is useful for updating HTML from a server request without loosing Alpine's on-page state. A utility like this is at the core of full-stack frameworks like [Laravel Livewire](https://laravel-livewire.com/) and [Phoenix LiveView](https://dockyard.com/blog/2018/12/12/phoenix-liveview-interactive-real-time-apps-no-need-to-write-javascript).
+
+The best way to understand its purpose is with the following interactive visualization. Give it a try!
+
+<!-- START_VERBATIM -->
+<div x-data="{ slide: 1 }" class="border rounded">
+ <div>
+ <img :src="'/img/morphs/morph'+slide+'.png'">
+ </div>
+
+ <div class="flex w-full justify-between" style="padding-bottom: 1rem">
+ <div class="w-1/2 px-4">
+ <button @click="slide = (slide === 1) ? 13 : slide - 1" class="w-full bg-aqua-400 rounded-full text-center py-3 font-bold text-white">Previous</button>
+ </div>
+ <div class="w-1/2 px-4">
+ <button @click="slide = (slide % 13) + 1" class="w-full bg-aqua-400 rounded-full text-center py-3 font-bold text-white">Next</button>
+ </div>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+<a name="installation"></a>
+## Installation
+
+You can use this plugin by either including it from a `<script>` tag or installing it via NPM:
+
+### Via CDN
+
+You can include the CDN build of this plugin as a `<script>` tag, just make sure to include it BEFORE Alpine's core JS file.
+
+```alpine
+<!-- Alpine Plugins -->
+<script defer src="https://unpkg.com/@alpinejs/morph@3.x.x/dist/cdn.min.js"></script>
+
+<!-- Alpine Core -->
+<script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>
+```
+
+### Via NPM
+
+You can install Morph from NPM for use inside your bundle like so:
+
+```shell
+npm install @alpinejs/morph
+```
+
+Then initialize it from your bundle:
+
+```js
+import Alpine from 'alpinejs'
+import morph from '@alpinejs/morph'
+
+window.Alpine = Alpine
+Alpine.plugin(morph)
+
+...
+```
+
+<a name="alpine-morph"></a>
+## Alpine.morph()
+
+The `Alpine.morph(el, newHtml)` allows you to imperatively morph a dom node based on passed in HTML. It accepts the following parameters:
+
+| Parameter | Description |
+| --- | --- |
+| `el` | A DOM element on the page. |
+| `newHtml` | A string of HTML to use as the template to morph the dom element into. |
+| `options` (optional) | An options object used mainly for [injecting lifecycle hooks](#lifecycle-hooks). |
+
+Here's an example of using `Alpine.morph()` to update an Alpine component with new HTML: (In real apps, this new HTML would likely be coming from the server)
+
+```alpine
+<div x-data="{ message: 'Change me, then press the button!' }">
+ <input type="text" x-model="message">
+ <span x-text="message"></span>
+</div>
+
+<button>Run Morph</button>
+
+<script>
+ document.querySelector('button').addEventListener('click', () => {
+ let el = document.querySelector('div')
+
+ Alpine.morph(el, `
+ <div x-data="{ message: 'Change me, then press the button!' }">
+ <h2>See how new elements have been added</h2>
+
+ <input type="text" x-model="message">
+ <span x-text="message"></span>
+
+ <h2>but the state of this component hasn't changed? Magical.</h2>
+ </div>
+ `)
+ })
+</script>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <div x-data="{ message: 'Change me, then press the button!' }" id="morph-demo-1" class="space-y-2">
+ <input type="text" x-model="message" class="w-full">
+ <span x-text="message"></span>
+ </div>
+
+ <button id="morph-button-1" class="mt-4">Run Morph</button>
+</div>
+
+<script>
+ document.querySelector('#morph-button-1').addEventListener('click', () => {
+ let el = document.querySelector('#morph-demo-1')
+
+ Alpine.morph(el, `
+ <div x-data="{ message: 'Change me, then press the button!' }" id="morph-demo-1" class="space-y-2">
+ <h4>See how new elements have been added</h4>
+ <input type="text" x-model="message" class="w-full">
+ <span x-text="message"></span>
+ <h4>but the state of this component hasn't changed? Magical.</h4>
+ </div>
+ `)
+ })
+</script>
+<!-- END_VERBATIM -->
+
+<a name="lifecycle-hooks"></a>
+### Lifecycle Hooks
+
+The "Morph" plugin works by comparing two DOM trees, the live element, and the passed in HTML.
+
+Morph walks both trees simultaneusly and compares each node and its children. If it finds differences, it "patches" (changes) the current DOM tree to match the passed in HTML's tree.
+
+While the default algorithm is very capable, there are cases where you may want to hook into its lifecycle and observe or change its behavior as it's happening.
+
+Before we jump into the available Lifecycle hooks themselves, let's first list out all the potential parameters they receive and explain what each one is:
+
+| Parameter | Description |
+| --- | --- |
+| `el` | This is always the actual, current, DOM element on the page that will be "patched" (changed by Morph). |
+| `toEl` | This is a "template element". It's a temporary element representing what the live `el` will be patched to. It will never actually live on the page and should only be used for reference purposes. |
+| `childrenOnly()` | This is a function that can be called inside the hook to tell Morph to skip the current element and only "patch" its children. |
+| `skip()` | A function that when called within the hook will "skip" comparing/patching itself and the children of the current element. |
+
+Here are the available lifecycle hooks (passed in as the third parameter to `Alpine.morph(..., options)`):
+
+| Option | Description |
+| --- | --- |
+| `updating(el, toEl, childrenOnly, skip)` | Called before patching the `el` with the comparison `toEl`. |
+| `updated(el, toEl)` | Called after Morph has patched `el`. |
+| `removing(el, skip)` | Called before Morph removes an element from the live DOM. |
+| `removed(el)` | Called after Morph has removed an element from the live DOM. |
+| `adding(el, skip)` | Called before adding a new element. |
+| `added(el)` | Called after adding a new element to the live DOM tree. |
+| `key(el)` | A re-usable function to determine how Morph "keys" elements in the tree before comparing/patching. [More on that here](#keys) |
+| `lookahead` | A boolean value telling Morph to enable an extra feature in its algorithm that "looks ahead" to make sure a DOM element that's about to be removed should instead just be "moved" to a later sibling. |
+
+Here is code of all these lifecycle hooks for a more concrete reference:
+
+```js
+Alpine.morph(el, newHtml, {
+ updating(el, toEl, childrenOnly, skip) {
+ //
+ },
+
+ updated(el, toEl) {
+ //
+ },
+
+ removing(el, skip) {
+ //
+ },
+
+ removed(el) {
+ //
+ },
+
+ adding(el, skip) {
+ //
+ },
+
+ added(el) {
+ //
+ },
+
+ key(el) {
+ // By default Alpine uses the `key=""` HTML attribute.
+ return el.id
+ },
+
+ lookahead: true, // Default: false
+})
+```
+
+<a name="keys"></a>
+### Keys
+
+Dom-diffing utilities like Morph try their best to accurately "morph" the original DOM into the new HTML. However, there are cases where it's impossible to determine if an element should be just changed, or replaced completely.
+
+Because of this limitation, Morph has a "key" system that allows developers to "force" preserving certain elements rather than replacing them.
+
+The most common use-case for them is a list of siblings within a loop. Below is an example of why keys are necessary sometimes:
+
+```html
+<!-- "Live" Dom on the page: -->
+<ul>
+ <li>Mark</li>
+ <li>Tom</li>
+ <li>Travis</li>
+</ul>
+
+<!-- New HTML to "morph to": -->
+<ul>
+ <li>Travis</li>
+ <li>Mark</li>
+ <li>Tom</li>
+</ul>
+```
+
+Given the above situation, Morph has no way to know that the "Travis" node has been moved in the DOM tree. It just thinks that "Mark" has been changed to "Travis" and "Travis" changed to "Tom".
+
+This is not what we actually want, we want Morph to preserve the original elements and instead of changing them, MOVE them within the `<ul>`.
+
+By adding keys to each node, we can accomplish this like so:
+
+```html
+<!-- "Live" Dom on the page: -->
+<ul>
+ <li key="1">Mark</li>
+ <li key="2">Tom</li>
+ <li key="3">Travis</li>
+</ul>
+
+<!-- New HTML to "morph to": -->
+<ul>
+ <li key="3">Travis</li>
+ <li key="1">Mark</li>
+ <li key="2">Tom</li>
+</ul>
+```
+
+Now that there are "keys" on the `<li>`s, Morph will match them in both trees and move them accordingly.
+
+You can configure what Morph considers a "key" with the `key:` configutation option. [More on that here](#lifecycle-hooks)
diff --git a/alpinejs/packages/docs/src/en/plugins/persist.md b/alpinejs/packages/docs/src/en/plugins/persist.md
new file mode 100644
index 0000000..d08bd76
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/plugins/persist.md
@@ -0,0 +1,207 @@
+---
+order: 2
+title: Persist
+description: Easily persist data across page loads using localStorage
+graph_image: https://alpinejs.dev/social_persist.jpg
+---
+
+# Persist Plugin
+
+Alpine's Persist plugin allows you to persist Alpine state across page loads.
+
+This is useful for persisting search filters, active tabs, and other features where users will be frustrated if their configuration is reset after refreshing or leaving and revisiting a page.
+
+<a name="installation"></a>
+## Installation
+
+You can use this plugin by either including it from a `<script>` tag or installing it via NPM:
+
+### Via CDN
+
+You can include the CDN build of this plugin as a `<script>` tag, just make sure to include it BEFORE Alpine's core JS file.
+
+```alpine
+<!-- Alpine Plugins -->
+<script defer src="https://unpkg.com/@alpinejs/persist@3.x.x/dist/cdn.min.js"></script>
+
+<!-- Alpine Core -->
+<script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>
+```
+
+### Via NPM
+
+You can install Persist from NPM for use inside your bundle like so:
+
+```shell
+npm install @alpinejs/persist
+```
+
+Then initialize it from your bundle:
+
+```js
+import Alpine from 'alpinejs'
+import persist from '@alpinejs/persist'
+
+Alpine.plugin(persist)
+
+...
+```
+
+<a name="magic-persist"></a>
+## $persist
+
+The primary API for using this plugin is the magic `$persist` method.
+
+You can wrap any value inside `x-data` with `$persist` like below to persist its value across page loads:
+
+```alpine
+<div x-data="{ count: $persist(0) }">
+ <button x-on:click="count++">Increment</button>
+
+ <span x-text="count"></span>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <div x-data="{ count: $persist(0) }">
+ <button x-on:click="count++">Increment</button>
+ <span x-text="count"></span>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+In the above example, because we wrapped `0` in `$persist()`, Alpine will now intercept changes made to `count` and persist them across page loads.
+
+You can try this for yourself by incrementing the "count" in the above example, then refreshing this page and observing that the "count" maintains its state and isn't reset to "0".
+
+<a name="how-it-works"></a>
+## How does it work?
+
+If a value is wrapped in `$persist`, on initialization Alpine will register its own watcher for that value. Now everytime that value changes for any reason, Alpine will store the new value in [localStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage).
+
+Now when a page is reloaded, Alpine will check localStorage (using the name of the property as the key) for a value. If it finds one, it will set the property value from localStorage immediately.
+
+You can observe this behavior by opening your browser devtool's localStorage viewer:
+
+<a href="https://developer.chrome.com/docs/devtools/storage/localstorage/"><img src="/img/persist_devtools.png" alt="Chrome devtools showing the localStorage view with count set to 0"></a>
+
+You'll observe that by simply visiting this page, Alpine already set the value of "count" in localStorage. You'll also notice it prefixes the property name "count" with "_x_" as a way of namespacing these values so Alpine doesn't conflict with other tools using localStorage.
+
+Now change the "count" in the following example and observe the changes made by Alpine to localStorage:
+
+```alpine
+<div x-data="{ count: $persist(0) }">
+ <button x-on:click="count++">Increment</button>
+
+ <span x-text="count"></span>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <div x-data="{ count: $persist(0) }">
+ <button x-on:click="count++">Increment</button>
+ <span x-text="count"></span>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+> `$persist` works with primitive values as well as with arrays and objects.
+However, it is worth noting that localStorage must be cleared when the type of the variable changes.<br>
+> Given the previous example, if we change count to a value of `$persist({ value: 0 })`, then localStorage must be cleared or the variable 'count' renamed.
+
+<a name="custom-key"></a>
+## Setting a custom key
+
+By default, Alpine uses the property key that `$persist(...)` is being assigned to ("count" in the above examples).
+
+Consider the scenario where you have multiple Alpine components across pages or even on the same page that all use "count" as the property key.
+
+Alpine will have no way of differentiating between these components.
+
+In these cases, you can set your own custom key for any persisted value using the `.as` modifier like so:
+
+
+```alpine
+<div x-data="{ count: $persist(0).as('other-count') }">
+ <button x-on:click="count++">Increment</button>
+
+ <span x-text="count"></span>
+</div>
+```
+
+Now Alpine will store and retrieve the above "count" value using the key "other-count".
+
+Here's a view of Chrome Devtools to see for yourself:
+
+<img src="/img/persist_custom_key_devtools.png" alt="Chrome devtools showing the localStorage view with count set to 0">
+
+<a name="custom-storage"></a>
+## Using a custom storage
+
+By default, data is saved to localStorage, it does not have an expiration time and it's kept even when the page is closed.
+
+Consider the scenario where you want to clear the data once the user close the tab. In this case you can persist data to sessionStorage using the `.using` modifier like so:
+
+
+```alpine
+<div x-data="{ count: $persist(0).using(sessionStorage) }">
+ <button x-on:click="count++">Increment</button>
+
+ <span x-text="count"></span>
+</div>
+```
+
+You can also define your custom storage object exposing a getItem function and a setItem function. For example, you can decide to use a session cookie as storage doing so:
+
+
+```alpine
+<script>
+ window.cookieStorage = {
+ getItem(key) {
+ let cookies = document.cookie.split(";");
+ for (let i = 0; i < cookies.length; i++) {
+ let cookie = cookies[i].split("=");
+ if (key == cookie[0].trim()) {
+ return decodeURIComponent(cookie[1]);
+ }
+ }
+ return null;
+ },
+ setItem(key, value) {
+ document.cookie = key+' = '+encodeURIComponent(value)
+ }
+ }
+</script>
+
+<div x-data="{ count: $persist(0).using(cookieStorage) }">
+ <button x-on:click="count++">Increment</button>
+
+ <span x-text="count"></span>
+</div>
+```
+
+<a name="using-persist-with-alpine-data"></a>
+## Using $persist with Alpine.data
+
+If you want to use `$persist` with `Alpine.data`, you need to use a standard function instead of an arrow function so Alpine can bind a custom `this` context when it initially evaluates the component scope.
+
+```js
+Alpine.data('dropdown', function () {
+ return {
+ open: this.$persist(false)
+ }
+})
+```
+
+<a name="using-alpine-persist-global"></a>
+## Using the Alpine.$persist global
+
+`Alpine.$persist` is exposed globally so it can be used outside of `x-data` contexts. This is useful to persist data from other sources such as `Alpine.store`.
+
+```js
+Alpine.store('darkMode', {
+ on: Alpine.$persist(true).as('darkMode_on')
+});
+``` \ No newline at end of file
diff --git a/alpinejs/packages/docs/src/en/start-here.md b/alpinejs/packages/docs/src/en/start-here.md
new file mode 100644
index 0000000..f3e9ef5
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/start-here.md
@@ -0,0 +1,326 @@
+---
+order: 1
+title: Start Here
+---
+
+# Start Here
+
+Create a blank HTML file somewhere on your computer with a name like: `i-love-alpine.html`
+
+Using a text editor, fill the file with these contents:
+
+```alpine
+<html>
+<head>
+ <script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>
+</head>
+<body>
+ <h1 x-data="{ message: 'I ❤️ Alpine' }" x-text="message"></h1>
+</body>
+</html>
+```
+
+Open your file in a web browser, if you see `I ❤️ Alpine`, you're ready to rumble!
+
+Now that you're all set up to play around, let's look at three practical examples as a foundation for teaching you the basics of Alpine. By the end of this exercise, you should be more than equipped to start building stuff on your own. Let's goooooo.
+
+<!-- START_VERBATIM -->
+<ul class="flex flex-col space-y-2 list-inside !list-decimal">
+ <li><a href="#building-a-counter">Building a counter</a></li>
+ <li><a href="#building-a-dropdown">Building a dropdown</a></li>
+ <li><a href="#building-a-search-input">Building a search Input</a></li>
+</ul>
+<!-- END_VERBATIM -->
+
+<a name="building-a-counter"></a>
+## Building a counter
+
+Let's start with a simple "counter" component to demonstrate the basics of state and event listening in Alpine, two core features.
+
+Insert the following into the `<body>` tag:
+
+```alpine
+<div x-data="{ count: 0 }">
+ <button x-on:click="count++">Increment</button>
+
+ <span x-text="count"></span>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <div x-data="{ count: 0 }">
+ <button x-on:click="count++">Increment</button>
+ <span x-text="count"></span>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+Now, you can see with 3 bits of Alpine sprinkled into this HTML, we've created an interactive "counter" component.
+
+Let's walk through what's happening briefly:
+
+<a name="declaring-data"></a>
+### Declaring data
+
+```alpine
+<div x-data="{ count: 0 }">
+```
+
+Everything in Alpine starts with an `x-data` directive. Inside of `x-data`, in plain JavaScript, you declare an object of data that Alpine will track.
+
+Every property inside this object will be made available to other directives inside this HTML element. In addition, when one of these properties changes, everything that relies on it will change as well.
+
+[→ Read more about `x-data`](/directives/data)
+
+Let's look at `x-on` and see how it can access and modify the `count` property from above:
+
+<a name="listening-for-events"></a>
+### Listening for events
+
+```alpine
+<button x-on:click="count++">Increment</button>
+```
+
+`x-on` is a directive you can use to listen for any event on an element. We're listening for a `click` event in this case, so ours looks like `x-on:click`.
+
+You can listen for other events as you'd imagine. For example, listening for a `mouseenter` event would look like this: `x-on:mouseenter`.
+
+When a `click` event happens, Alpine will call the associated JavaScript expression, `count++` in our case. As you can see, we have direct access to data declared in the `x-data` expression.
+
+> You will often see `@` instead of `x-on:`. This is a shorter, friendlier syntax that many prefer. From now on, this documentation will likely use `@` instead of `x-on:`.
+
+[→ Read more about `x-on`](/directives/on)
+
+<a name="reacting-to-changes"></a>
+### Reacting to changes
+
+```alpine
+<h1 x-text="count"></h1>
+```
+
+`x-text` is an Alpine directive you can use to set the text content of an element to the result of a JavaScript expression.
+
+In this case, we're telling Alpine to always make sure that the contents of this `h1` tag reflect the value of the `count` property.
+
+In case it's not clear, `x-text`, like most directives accepts a plain JavaScript expression as an argument. So for example, you could instead set its contents to: `x-text="count * 2"` and the text content of the `h1` will now always be 2 times the value of `count`.
+
+[→ Read more about `x-text`](/directives/text)
+
+<a name="building-a-dropdown"></a>
+## Building a dropdown
+
+Now that we've seen some basic functionality, let's keep going and look at an important directive in Alpine: `x-show`, by building a contrived "dropdown" component.
+
+Insert the following code into the `<body>` tag:
+
+```alpine
+<div x-data="{ open: false }">
+ <button @click="open = ! open">Toggle</button>
+
+ <div x-show="open" @click.outside="open = false">Contents...</div>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <div x-data="{ open: false }">
+ <button @click="open = ! open">Toggle</button>
+ <div x-show="open" @click.outside="open = false">Contents...</div>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+If you load this component, you should see that the "Contents..." are hidden by default. You can toggle showing them on the page by clicking the "Toggle" button.
+
+The `x-data` and `x-on` directives should be familiar to you from the previous example, so we'll skip those explanations.
+
+<a name="toggling-elements"></a>
+### Toggling elements
+
+```alpine
+<div x-show="open" ...>Contents...</div>
+```
+
+`x-show` is an extremely powerful directive in Alpine that can be used to show and hide a block of HTML on a page based on the result of a JavaScript expression, in our case: `open`.
+
+[→ Read more about `x-show`](/directives/show)
+
+<a name="listening-for-a-click-outside"></a>
+### Listening for a click outside
+
+```alpine
+<div ... @click.outside="open = false">Contents...</div>
+```
+
+You'll notice something new in this example: `.outside`. Many directives in Alpine accept "modifiers" that are chained onto the end of the directive and are separated by periods.
+
+In this case, `.outside` tells Alpine to instead of listening for a click INSIDE the `<div>`, to listen for the click only if it happens OUTSIDE the `<div>`.
+
+This is a convenience helper built into Alpine because this is a common need and implementing it by hand is annoying and complex.
+
+[→ Read more about `x-on` modifiers](/directives/on#modifiers)
+
+<a name="building-a-search-input"></a>
+## Building a search input
+
+Let's now build a more complex component and introduce a handful of other directives and patterns.
+
+Insert the following code into the `<body>` tag:
+
+```alpine
+<div
+ x-data="{
+ search: '',
+
+ items: ['foo', 'bar', 'baz'],
+
+ get filteredItems() {
+ return this.items.filter(
+ i => i.startsWith(this.search)
+ )
+ }
+ }"
+>
+ <input x-model="search" placeholder="Search...">
+
+ <ul>
+ <template x-for="item in filteredItems" :key="item">
+ <li x-text="item"></li>
+ </template>
+ </ul>
+</div>
+```
+
+<!-- START_VERBATIM -->
+<div class="demo">
+ <div
+ x-data="{
+ search: '',
+
+ items: ['foo', 'bar', 'baz'],
+
+ get filteredItems() {
+ return this.items.filter(
+ i => i.startsWith(this.search)
+ )
+ }
+ }"
+ >
+ <input x-model="search" placeholder="Search...">
+
+ <ul class="pl-6 pt-2">
+ <template x-for="item in filteredItems" :key="item">
+ <li x-text="item"></li>
+ </template>
+ </ul>
+ </div>
+</div>
+<!-- END_VERBATIM -->
+
+By default, all of the "items" (foo, bar, and baz) will be shown on the page, but you can filter them by typing into the text input. As you type, the list of items will change to reflect what you're searching for.
+
+Now there's quite a bit happening here, so let's go through this snippet piece by piece.
+
+<a name="multi-line-formatting"></a>
+### Multi line formatting
+
+The first thing I'd like to point out is that `x-data` now has a lot more going on in it than before. To make it easier to write and read, we've split it up into multiple lines in our HTML. This is completely optional and we'll talk more in a bit about how to avoid this problem altogether, but for now, we'll keep all of this JavaScript directly in the HTML.
+
+<a name="binding-to-inputs"></a>
+### Binding to inputs
+
+```alpine
+<input x-model="search" placeholder="Search...">
+```
+
+You'll notice a new directive we haven't seen yet: `x-model`.
+
+`x-model` is used to "bind" the value of an input element with a data property: "search" from `x-data="{ search: '', ... }"` in our case.
+
+This means that anytime the value of the input changes, the value of "search" will change to reflect that.
+
+`x-model` is capable of much more than this simple example.
+
+[→ Read more about `x-model`](/directives/model)
+
+<a name="computed-properties-using-getters"></a>
+### Computed properties using getters
+
+The next bit I'd like to draw your attention to is the `items` and `filteredItems` properties from the `x-data` directive.
+
+```js
+{
+ ...
+ items: ['foo', 'bar', 'baz'],
+
+ get filteredItems() {
+ return this.items.filter(
+ i => i.startsWith(this.search)
+ )
+ }
+}
+```
+
+The `items` property should be self-explanatory. Here we are setting the value of `items` to a JavaScript array of 3 different items (foo, bar, and baz).
+
+The interesting part of this snippet is the `filteredItems` property.
+
+Denoted by the `get` prefix for this property, `filteredItems` is a "getter" property in this object. This means we can access `filteredItems` as if it was a normal property in our data object, but when we do, JavaScript will evaluate the provided function under the hood and return the result.
+
+It's completely acceptable to forgo the `get` and just make this a method that you can call from the template, but some prefer the nicer syntax of the getter.
+
+[→ Read more about JavaScript getters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get)
+
+Now let's look inside the `filteredItems` getter and make sure we understand what's going on there:
+
+```js
+return this.items.filter(
+ i => i.startsWith(this.search)
+)
+```
+
+This is all plain JavaScript. We are first getting the array of items (foo, bar, and baz) and filtering them using the provided callback: `i => i.startsWith(this.search)`.
+
+By passing in this callback to `filter`, we are telling JavaScript to only return the items that start with the string: `this.search`, which like we saw with `x-model` will always reflect the value of the input.
+
+You may notice that up until now, we haven't had to use `this.` to reference properties. However, because we are working directly inside the `x-data` object, we must reference any properties using `this.[property]` instead of simply `[property]`.
+
+Because Alpine is a "reactive" framework. Any time the value of `this.search` changes, parts of the template that use `filteredItems` will automatically be updated.
+
+<a name="looping-elements"></a>
+### Looping elements
+
+Now that we understand the data part of our component, let's understand what's happening in the template that allows us to loop through `filteredItems` on the page.
+
+```alpine
+<ul>
+ <template x-for="item in filteredItems">
+ <li x-text="item"></li>
+ </template>
+</ul>
+```
+
+The first thing to notice here is the `x-for` directive. `x-for` expressions take the following form: `[item] in [items]` where [items] is any array of data, and [item] is the name of the variable that will be assigned to an iteration inside the loop.
+
+Also notice that `x-for` is declared on a `<template>` element and not directly on the `<li>`. This is a requirement of using `x-for`. It allows Alpine to leverage the existing behavior of `<template>` tags in the browser to its advantage.
+
+Now any element inside the `<template>` tag will be repeated for every item inside `filteredItems` and all expressions evaluated inside the loop will have direct access to the iteration variable (`item` in this case).
+
+[→ Read more about `x-for`](/directives/for)
+
+<a name="recap"></a>
+## Recap
+
+If you've made it this far, you've been exposed to the following directives in Alpine:
+
+* x-data
+* x-on
+* x-text
+* x-show
+* x-model
+* x-for
+
+That's a great start, however, there are many more directives to sink your teeth into. The best way to absorb Alpine is to read through this documentation. No need to comb over every word, but if you at least glance through every page you will be MUCH more effective when using Alpine.
+
+Happy Coding!
diff --git a/alpinejs/packages/docs/src/en/upgrade-guide.md b/alpinejs/packages/docs/src/en/upgrade-guide.md
new file mode 100644
index 0000000..011a594
--- /dev/null
+++ b/alpinejs/packages/docs/src/en/upgrade-guide.md
@@ -0,0 +1,360 @@
+---
+order: 2
+title: Upgrade From V2
+---
+
+# Upgrade from V2
+
+Below is an exhaustive guide on the breaking changes in Alpine V3, but if you'd prefer something more lively, you can review all the changes as well as new features in V3 by watching the Alpine Day 2021 "Future of Alpine" keynote:
+
+<!-- START_VERBATIM -->
+<div class="relative w-full" style="padding-bottom: 56.25%; padding-top: 30px; height: 0; overflow: hidden;">
+ <iframe
+ class="absolute top-0 left-0 right-0 bottom-0 w-full h-full"
+ src="https://www.youtube.com/embed/WixS4JXMwIQ?modestbranding=1&autoplay=1"
+ allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
+ allowfullscreen
+ ></iframe>
+</div>
+<!-- END_VERBATIM -->
+
+Upgrading from Alpine V2 to V3 should be fairly painless. In many cases, NOTHING has to be done to your codebase to use V3. Below is an exhaustive list of breaking changes and deprecations in descending order of how likely users are to be affected by them:
+
+> Note if you use Laravel Livewire and Alpine together, to use V3 of Alpine, you will need to upgrade to Livewire v2.5.1 or greater.
+
+<a name="breaking-changes"></a>
+## Breaking Changes
+* [`$el` is now always the current element](#el-no-longer-root)
+* [Automatically evaluate `init()` functions defined on data object](#auto-init)
+* [Need to call `Alpine.start()` after import](#need-to-call-alpine-start)
+* [`x-show.transition` is now `x-transition`](#removed-show-dot-transition)
+* [`x-if` no longer supports `x-transition`](#x-if-no-transitions)
+* [`x-data` cascading scope](#x-data-scope)
+* [`x-init` no longer accepts a callback return](#x-init-no-callback)
+* [Returning `false` from event handlers no longer implicitly "preventDefault"s](#no-false-return-from-event-handlers)
+* [`x-spread` is now `x-bind`](#x-spread-now-x-bind)
+* [`x-ref` no longer supports binding](#x-ref-no-more-dynamic)
+* [Use global lifecycle events instead of `Alpine.deferLoadingAlpine()`](#use-global-events-now)
+* [IE11 no longer supported](#no-ie-11)
+
+<a name="el-no-longer-root"></a>
+### `$el` is now always the current element
+
+`$el` now always represents the element that an expression was executed on, not the root element of the component. This will replace most usages of `x-ref` and in the cases where you still want to access the root of a component, you can do so using `$root`. For example:
+
+```alpine
+<!-- 🚫 Before -->
+<div x-data>
+ <button @click="console.log($el)"></button>
+ <!-- In V2, $el would have been the <div>, now it's the <button> -->
+</div>
+
+<!-- ✅ After -->
+<div x-data>
+ <button @click="console.log($root)"></button>
+</div>
+```
+
+For a smoother upgrade experience, you can replace all instances of `$el` with a custom magic called `$root`.
+
+[→ Read more about $el in V3](/magics/el)
+[→ Read more about $root in V3](/magics/root)
+
+<a name="auto-init"></a>
+### Automatically evaluate `init()` functions defined on data object
+
+A common pattern in V2 was to manually call an `init()` (or similarly named method) on an `x-data` object.
+
+In V3, Alpine will automatically call `init()` methods on data objects.
+
+```alpine
+<!-- 🚫 Before -->
+<div x-data="foo()" x-init="init()"></div>
+
+<!-- ✅ After -->
+<div x-data="foo()"></div>
+
+<script>
+ function foo() {
+ return {
+ init() {
+ //
+ }
+ }
+ }
+</script>
+```
+
+[→ Read more about auto-evaluating init functions](/globals/alpine-data#init-functions)
+
+<a name="need-to-call-alpine-start"></a>
+### Need to call Alpine.start() after import
+
+If you were importing Alpine V2 from NPM, you will now need to manually call `Alpine.start()` for V3. This doesn't affect you if you use Alpine's build file or CDN from a `<template>` tag.
+
+```js
+// 🚫 Before
+import 'alpinejs'
+
+// ✅ After
+import Alpine from 'alpinejs'
+
+window.Alpine = Alpine
+
+Alpine.start()
+```
+
+[→ Read more about initializing Alpine V3](/essentials/installation#as-a-module)
+
+<a name="removed-show-dot-transition"></a>
+### `x-show.transition` is now `x-transition`
+
+All of the conveniences provided by `x-show.transition...` helpers are still available, but now from a more unified API: `x-transition`:
+
+```alpine
+<!-- 🚫 Before -->
+<div x-show.transition="open"></div>
+<!-- ✅ After -->
+<div x-show="open" x-transition></div>
+
+<!-- 🚫 Before -->
+<div x-show.transition.duration.500ms="open"></div>
+<!-- ✅ After -->
+<div x-show="open" x-transition.duration.500ms></div>
+
+<!-- 🚫 Before -->
+<div x-show.transition.in.duration.500ms.out.duration.750ms="open"></div>
+<!-- ✅ After -->
+<div
+ x-show="open"
+ x-transition:enter.duration.500ms
+ x-transition:leave.duration.750ms
+></div>
+```
+
+[→ Read more about x-transition](/directives/transition)
+
+<a name="x-if-no-transitions"></a>
+### `x-if` no longer supports `x-transition`
+
+The ability to transition elements in and add before/after being removed from the DOM is no longer available in Alpine.
+
+This was a feature very few people even knew existed let alone used.
+
+Because the transition system is complex, it makes more sense from a maintenance perspective to only support transitioning elements with `x-show`.
+
+```alpine
+<!-- 🚫 Before -->
+<template x-if.transition="open">
+ <div>...</div>
+</template>
+
+<!-- ✅ After -->
+<div x-show="open" x-transition>...</div>
+```
+
+[→ Read more about x-if](/directives/if)
+
+<a name="x-data-scope"></a>
+### `x-data` cascading scope
+
+Scope defined in `x-data` is now available to all children unless overwritten by a nested `x-data` expression.
+
+```alpine
+<!-- 🚫 Before -->
+<div x-data="{ foo: 'bar' }">
+ <div x-data="{}">
+ <!-- foo is undefined -->
+ </div>
+</div>
+
+<!-- ✅ After -->
+<div x-data="{ foo: 'bar' }">
+ <div x-data="{}">
+ <!-- foo is 'bar' -->
+ </div>
+</div>
+```
+
+[→ Read more about x-data scoping](/directives/data#scope)
+
+<a name="x-init-no-callback"></a>
+### `x-init` no longer accepts a callback return
+
+Before V3, if `x-init` received a return value that is `typeof` "function", it would execute the callback after Alpine finished initializing all other directives in the tree. Now, you must manually call `$nextTick()` to achieve that behavior. `x-init` is no longer "return value aware".
+
+```alpine
+<!-- 🚫 Before -->
+<div x-data x-init="() => { ... }">...</div>
+
+<!-- ✅ After -->
+<div x-data x-init="$nextTick(() => { ... })">...</div>
+```
+
+[→ Read more about $nextTick](/magics/next-tick)
+
+<a name="no-false-return-from-event-handlers"></a>
+### Returning `false` from event handlers no longer implicitly "preventDefault"s
+
+Alpine V2 observes a return value of `false` as a desire to run `preventDefault` on the event. This conforms to the standard behavior of native, inline listeners: `<... oninput="someFunctionThatReturnsFalse()">`. Alpine V3 no longer supports this API. Most people don't know it exists and therefore is surprising behavior.
+
+```alpine
+<!-- 🚫 Before -->
+<div x-data="{ blockInput() { return false } }">
+ <input type="text" @input="blockInput()">
+</div>
+
+<!-- ✅ After -->
+<div x-data="{ blockInput(e) { e.preventDefault() }">
+ <input type="text" @input="blockInput($event)">
+</div>
+```
+
+[→ Read more about x-on](/directives/on)
+
+<a name="x-spread-now-x-bind"></a>
+### `x-spread` is now `x-bind`
+
+One of Alpine's stories for re-using functionality is abstracting Alpine directives into objects and applying them to elements with `x-spread`. This behavior is still the same, except now `x-bind` (with no specified attribute) is the API instead of `x-spread`.
+
+```alpine
+<!-- 🚫 Before -->
+<div x-data="dropdown()">
+ <button x-spread="trigger">Toggle</button>
+
+ <div x-spread="dialogue">...</div>
+</div>
+
+<!-- ✅ After -->
+<div x-data="dropdown()">
+ <button x-bind="trigger">Toggle</button>
+
+ <div x-bind="dialogue">...</div>
+</div>
+
+
+<script>
+ function dropdown() {
+ return {
+ open: false,
+
+ trigger: {
+ 'x-on:click'() { this.open = ! this.open },
+ },
+
+ dialogue: {
+ 'x-show'() { return this.open },
+ 'x-bind:class'() { return 'foo bar' },
+ },
+ }
+ }
+</script>
+```
+
+[→ Read more about binding directives using x-bind](/directives/bind#bind-directives)
+
+<a name="use-global-events-now"></a>
+### Use global lifecycle events instead of `Alpine.deferLoadingAlpine()`
+
+```alpine
+<!-- 🚫 Before -->
+<script>
+ window.deferLoadingAlpine = startAlpine => {
+ // Will be executed before initializing Alpine.
+
+ startAlpine()
+
+ // Will be executed after initializing Alpine.
+ }
+</script>
+
+<!-- ✅ After -->
+<script>
+ document.addEventListener('alpine:init', () => {
+ // Will be executed before initializing Alpine.
+ })
+
+ document.addEventListener('alpine:initialized', () => {
+ // Will be executed after initializing Alpine.
+ })
+</script>
+```
+
+[→ Read more about Alpine lifecycle events](/essentials/lifecycle#alpine-initialization)
+
+
+<a name="x-ref-no-more-dynamic"></a>
+### `x-ref` no longer supports binding
+
+In Alpine V2 for below code
+
+```alpine
+<div x-data="{options: [{value: 1}, {value: 2}, {value: 3}] }">
+ <div x-ref="0">0</div>
+ <template x-for="option in options">
+ <div :x-ref="option.value" x-text="option.value"></div>
+ </template>
+
+ <button @click="console.log($refs[0], $refs[1], $refs[2], $refs[3]);">Display $refs</button>
+</div>
+```
+
+after clicking button all `$refs` were displayed. However in Alpine V3 it's possible to access only `$refs` for elements created statically, so only first ref will be returned as expected.
+
+
+<a name="no-ie-11"></a>
+### IE11 no longer supported
+
+Alpine will no longer officially support Internet Explorer 11. If you need support for IE11, we recommend still using Alpine V2.
+
+## Deprecated APIs
+
+The following 2 APIs will still work in V3, but are considered deprecated and are likely to be removed at some point in the future.
+
+<a name="away-replace-with-outside"></a>
+### Event listener modifier `.away` should be replaced with `.outside`
+
+```alpine
+<!-- 🚫 Before -->
+<div x-show="open" @click.away="open = false">
+ ...
+</div>
+
+<!-- ✅ After -->
+<div x-show="open" @click.outside="open = false">
+ ...
+</div>
+```
+
+<a name="alpine-data-instead-of-global-functions"></a>
+### Prefer `Alpine.data()` to global Alpine function data providers
+
+```alpine
+<!-- 🚫 Before -->
+<div x-data="dropdown()">
+ ...
+</div>
+
+<script>
+ function dropdown() {
+ return {
+ ...
+ }
+ }
+</script>
+
+<!-- ✅ After -->
+<div x-data="dropdown">
+ ...
+</div>
+
+<script>
+ document.addEventListener('alpine:init', () => {
+ Alpine.data('dropdown', () => ({
+ ...
+ }))
+ })
+</script>
+```
+
+> Note that you need to define `Alpine.data()` extensions BEFORE you call `Alpine.start()`. For more information, refer to the [Lifecycle Concerns](https://alpinejs.dev/advanced/extending#lifecycle-concerns) and [Installation as a Module](https://alpinejs.dev/essentials/installation#as-a-module) documentation pages.
diff --git a/alpinejs/packages/focus/.gitignore b/alpinejs/packages/focus/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/alpinejs/packages/focus/.gitignore
diff --git a/alpinejs/packages/focus/builds/cdn.js b/alpinejs/packages/focus/builds/cdn.js
new file mode 100644
index 0000000..4d17037
--- /dev/null
+++ b/alpinejs/packages/focus/builds/cdn.js
@@ -0,0 +1,5 @@
+import trap from '../src/index.js'
+
+document.addEventListener('alpine:init', () => {
+ window.Alpine.plugin(trap)
+})
diff --git a/alpinejs/packages/focus/builds/module.js b/alpinejs/packages/focus/builds/module.js
new file mode 100644
index 0000000..765ebbf
--- /dev/null
+++ b/alpinejs/packages/focus/builds/module.js
@@ -0,0 +1,3 @@
+import registerFocusPlugin from '../src/index.js'
+
+export default registerFocusPlugin
diff --git a/alpinejs/packages/focus/dist/cdn.js b/alpinejs/packages/focus/dist/cdn.js
new file mode 100644
index 0000000..4f5b2ff
--- /dev/null
+++ b/alpinejs/packages/focus/dist/cdn.js
@@ -0,0 +1,821 @@
+(() => {
+ // node_modules/tabbable/dist/index.esm.js
+ /*!
+ * tabbable 5.2.1
+ * @license MIT, https://github.com/focus-trap/tabbable/blob/master/LICENSE
+ */
+ var candidateSelectors = ["input", "select", "textarea", "a[href]", "button", "[tabindex]", "audio[controls]", "video[controls]", '[contenteditable]:not([contenteditable="false"])', "details>summary:first-of-type", "details"];
+ var candidateSelector = /* @__PURE__ */ candidateSelectors.join(",");
+ var matches = typeof Element === "undefined" ? function() {
+ } : Element.prototype.matches || Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
+ var getCandidates = function getCandidates2(el, includeContainer, filter) {
+ var candidates = Array.prototype.slice.apply(el.querySelectorAll(candidateSelector));
+ if (includeContainer && matches.call(el, candidateSelector)) {
+ candidates.unshift(el);
+ }
+ candidates = candidates.filter(filter);
+ return candidates;
+ };
+ var isContentEditable = function isContentEditable2(node) {
+ return node.contentEditable === "true";
+ };
+ var getTabindex = function getTabindex2(node) {
+ var tabindexAttr = parseInt(node.getAttribute("tabindex"), 10);
+ if (!isNaN(tabindexAttr)) {
+ return tabindexAttr;
+ }
+ if (isContentEditable(node)) {
+ return 0;
+ }
+ if ((node.nodeName === "AUDIO" || node.nodeName === "VIDEO" || node.nodeName === "DETAILS") && node.getAttribute("tabindex") === null) {
+ return 0;
+ }
+ return node.tabIndex;
+ };
+ var sortOrderedTabbables = function sortOrderedTabbables2(a, b) {
+ return a.tabIndex === b.tabIndex ? a.documentOrder - b.documentOrder : a.tabIndex - b.tabIndex;
+ };
+ var isInput = function isInput2(node) {
+ return node.tagName === "INPUT";
+ };
+ var isHiddenInput = function isHiddenInput2(node) {
+ return isInput(node) && node.type === "hidden";
+ };
+ var isDetailsWithSummary = function isDetailsWithSummary2(node) {
+ var r = node.tagName === "DETAILS" && Array.prototype.slice.apply(node.children).some(function(child) {
+ return child.tagName === "SUMMARY";
+ });
+ return r;
+ };
+ var getCheckedRadio = function getCheckedRadio2(nodes, form) {
+ for (var i = 0; i < nodes.length; i++) {
+ if (nodes[i].checked && nodes[i].form === form) {
+ return nodes[i];
+ }
+ }
+ };
+ var isTabbableRadio = function isTabbableRadio2(node) {
+ if (!node.name) {
+ return true;
+ }
+ var radioScope = node.form || node.ownerDocument;
+ var queryRadios = function queryRadios2(name) {
+ return radioScope.querySelectorAll('input[type="radio"][name="' + name + '"]');
+ };
+ var radioSet;
+ if (typeof window !== "undefined" && typeof window.CSS !== "undefined" && typeof window.CSS.escape === "function") {
+ radioSet = queryRadios(window.CSS.escape(node.name));
+ } else {
+ try {
+ radioSet = queryRadios(node.name);
+ } catch (err) {
+ console.error("Looks like you have a radio button with a name attribute containing invalid CSS selector characters and need the CSS.escape polyfill: %s", err.message);
+ return false;
+ }
+ }
+ var checked = getCheckedRadio(radioSet, node.form);
+ return !checked || checked === node;
+ };
+ var isRadio = function isRadio2(node) {
+ return isInput(node) && node.type === "radio";
+ };
+ var isNonTabbableRadio = function isNonTabbableRadio2(node) {
+ return isRadio(node) && !isTabbableRadio(node);
+ };
+ var isHidden = function isHidden2(node, displayCheck) {
+ if (getComputedStyle(node).visibility === "hidden") {
+ return true;
+ }
+ var isDirectSummary = matches.call(node, "details>summary:first-of-type");
+ var nodeUnderDetails = isDirectSummary ? node.parentElement : node;
+ if (matches.call(nodeUnderDetails, "details:not([open]) *")) {
+ return true;
+ }
+ if (!displayCheck || displayCheck === "full") {
+ while (node) {
+ if (getComputedStyle(node).display === "none") {
+ return true;
+ }
+ node = node.parentElement;
+ }
+ } else if (displayCheck === "non-zero-area") {
+ var _node$getBoundingClie = node.getBoundingClientRect(), width = _node$getBoundingClie.width, height = _node$getBoundingClie.height;
+ return width === 0 && height === 0;
+ }
+ return false;
+ };
+ var isDisabledFromFieldset = function isDisabledFromFieldset2(node) {
+ if (isInput(node) || node.tagName === "SELECT" || node.tagName === "TEXTAREA" || node.tagName === "BUTTON") {
+ var parentNode = node.parentElement;
+ while (parentNode) {
+ if (parentNode.tagName === "FIELDSET" && parentNode.disabled) {
+ for (var i = 0; i < parentNode.children.length; i++) {
+ var child = parentNode.children.item(i);
+ if (child.tagName === "LEGEND") {
+ if (child.contains(node)) {
+ return false;
+ }
+ return true;
+ }
+ }
+ return true;
+ }
+ parentNode = parentNode.parentElement;
+ }
+ }
+ return false;
+ };
+ var isNodeMatchingSelectorFocusable = function isNodeMatchingSelectorFocusable2(options, node) {
+ if (node.disabled || isHiddenInput(node) || isHidden(node, options.displayCheck) || isDetailsWithSummary(node) || isDisabledFromFieldset(node)) {
+ return false;
+ }
+ return true;
+ };
+ var isNodeMatchingSelectorTabbable = function isNodeMatchingSelectorTabbable2(options, node) {
+ if (!isNodeMatchingSelectorFocusable(options, node) || isNonTabbableRadio(node) || getTabindex(node) < 0) {
+ return false;
+ }
+ return true;
+ };
+ var tabbable = function tabbable2(el, options) {
+ options = options || {};
+ var regularTabbables = [];
+ var orderedTabbables = [];
+ var candidates = getCandidates(el, options.includeContainer, isNodeMatchingSelectorTabbable.bind(null, options));
+ candidates.forEach(function(candidate, i) {
+ var candidateTabindex = getTabindex(candidate);
+ if (candidateTabindex === 0) {
+ regularTabbables.push(candidate);
+ } else {
+ orderedTabbables.push({
+ documentOrder: i,
+ tabIndex: candidateTabindex,
+ node: candidate
+ });
+ }
+ });
+ var tabbableNodes = orderedTabbables.sort(sortOrderedTabbables).map(function(a) {
+ return a.node;
+ }).concat(regularTabbables);
+ return tabbableNodes;
+ };
+ var focusable = function focusable2(el, options) {
+ options = options || {};
+ var candidates = getCandidates(el, options.includeContainer, isNodeMatchingSelectorFocusable.bind(null, options));
+ return candidates;
+ };
+ var focusableCandidateSelector = /* @__PURE__ */ candidateSelectors.concat("iframe").join(",");
+ var isFocusable = function isFocusable2(node, options) {
+ options = options || {};
+ if (!node) {
+ throw new Error("No node provided");
+ }
+ if (matches.call(node, focusableCandidateSelector) === false) {
+ return false;
+ }
+ return isNodeMatchingSelectorFocusable(options, node);
+ };
+
+ // node_modules/focus-trap/dist/focus-trap.esm.js
+ /*!
+ * focus-trap 6.6.1
+ * @license MIT, https://github.com/focus-trap/focus-trap/blob/master/LICENSE
+ */
+ 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;
+ }
+ function _defineProperty(obj, key, value) {
+ if (key in obj) {
+ Object.defineProperty(obj, key, {
+ value,
+ enumerable: true,
+ configurable: true,
+ writable: true
+ });
+ } else {
+ obj[key] = value;
+ }
+ return obj;
+ }
+ var activeFocusTraps = function() {
+ var trapQueue = [];
+ return {
+ activateTrap: function activateTrap(trap) {
+ if (trapQueue.length > 0) {
+ var activeTrap = trapQueue[trapQueue.length - 1];
+ if (activeTrap !== trap) {
+ activeTrap.pause();
+ }
+ }
+ var trapIndex = trapQueue.indexOf(trap);
+ if (trapIndex === -1) {
+ trapQueue.push(trap);
+ } else {
+ trapQueue.splice(trapIndex, 1);
+ trapQueue.push(trap);
+ }
+ },
+ deactivateTrap: function deactivateTrap(trap) {
+ var trapIndex = trapQueue.indexOf(trap);
+ if (trapIndex !== -1) {
+ trapQueue.splice(trapIndex, 1);
+ }
+ if (trapQueue.length > 0) {
+ trapQueue[trapQueue.length - 1].unpause();
+ }
+ }
+ };
+ }();
+ var isSelectableInput = function isSelectableInput2(node) {
+ return node.tagName && node.tagName.toLowerCase() === "input" && typeof node.select === "function";
+ };
+ var isEscapeEvent = function isEscapeEvent2(e) {
+ return e.key === "Escape" || e.key === "Esc" || e.keyCode === 27;
+ };
+ var isTabEvent = function isTabEvent2(e) {
+ return e.key === "Tab" || e.keyCode === 9;
+ };
+ var delay = function delay2(fn) {
+ return setTimeout(fn, 0);
+ };
+ var findIndex = function findIndex2(arr, fn) {
+ var idx = -1;
+ arr.every(function(value, i) {
+ if (fn(value)) {
+ idx = i;
+ return false;
+ }
+ return true;
+ });
+ return idx;
+ };
+ var valueOrHandler = function valueOrHandler2(value) {
+ for (var _len = arguments.length, params = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
+ params[_key - 1] = arguments[_key];
+ }
+ return typeof value === "function" ? value.apply(void 0, params) : value;
+ };
+ var createFocusTrap = function createFocusTrap2(elements, userOptions) {
+ var doc = document;
+ var config = _objectSpread2({
+ returnFocusOnDeactivate: true,
+ escapeDeactivates: true,
+ delayInitialFocus: true
+ }, userOptions);
+ var state = {
+ containers: [],
+ tabbableGroups: [],
+ nodeFocusedBeforeActivation: null,
+ mostRecentlyFocusedNode: null,
+ active: false,
+ paused: false,
+ delayInitialFocusTimer: void 0
+ };
+ var trap;
+ var getOption = function getOption2(configOverrideOptions, optionName, configOptionName) {
+ return configOverrideOptions && configOverrideOptions[optionName] !== void 0 ? configOverrideOptions[optionName] : config[configOptionName || optionName];
+ };
+ var containersContain = function containersContain2(element) {
+ return state.containers.some(function(container) {
+ return container.contains(element);
+ });
+ };
+ var getNodeForOption = function getNodeForOption2(optionName) {
+ var optionValue = config[optionName];
+ if (!optionValue) {
+ return null;
+ }
+ var node = optionValue;
+ if (typeof optionValue === "string") {
+ node = doc.querySelector(optionValue);
+ if (!node) {
+ throw new Error("`".concat(optionName, "` refers to no known node"));
+ }
+ }
+ if (typeof optionValue === "function") {
+ node = optionValue();
+ if (!node) {
+ throw new Error("`".concat(optionName, "` did not return a node"));
+ }
+ }
+ return node;
+ };
+ var getInitialFocusNode = function getInitialFocusNode2() {
+ var node;
+ if (getOption({}, "initialFocus") === false) {
+ return false;
+ }
+ if (getNodeForOption("initialFocus") !== null) {
+ node = getNodeForOption("initialFocus");
+ } else if (containersContain(doc.activeElement)) {
+ node = doc.activeElement;
+ } else {
+ var firstTabbableGroup = state.tabbableGroups[0];
+ var firstTabbableNode = firstTabbableGroup && firstTabbableGroup.firstTabbableNode;
+ node = firstTabbableNode || getNodeForOption("fallbackFocus");
+ }
+ if (!node) {
+ throw new Error("Your focus-trap needs to have at least one focusable element");
+ }
+ return node;
+ };
+ var updateTabbableNodes = function updateTabbableNodes2() {
+ state.tabbableGroups = state.containers.map(function(container) {
+ var tabbableNodes = tabbable(container);
+ if (tabbableNodes.length > 0) {
+ return {
+ container,
+ firstTabbableNode: tabbableNodes[0],
+ lastTabbableNode: tabbableNodes[tabbableNodes.length - 1]
+ };
+ }
+ return void 0;
+ }).filter(function(group) {
+ return !!group;
+ });
+ if (state.tabbableGroups.length <= 0 && !getNodeForOption("fallbackFocus")) {
+ throw new Error("Your focus-trap must have at least one container with at least one tabbable node in it at all times");
+ }
+ };
+ var tryFocus = function tryFocus2(node) {
+ if (node === false) {
+ return;
+ }
+ if (node === doc.activeElement) {
+ return;
+ }
+ if (!node || !node.focus) {
+ tryFocus2(getInitialFocusNode());
+ return;
+ }
+ node.focus({
+ preventScroll: !!config.preventScroll
+ });
+ state.mostRecentlyFocusedNode = node;
+ if (isSelectableInput(node)) {
+ node.select();
+ }
+ };
+ var getReturnFocusNode = function getReturnFocusNode2(previousActiveElement) {
+ var node = getNodeForOption("setReturnFocus");
+ return node ? node : previousActiveElement;
+ };
+ var checkPointerDown = function checkPointerDown2(e) {
+ if (containersContain(e.target)) {
+ return;
+ }
+ if (valueOrHandler(config.clickOutsideDeactivates, e)) {
+ trap.deactivate({
+ returnFocus: config.returnFocusOnDeactivate && !isFocusable(e.target)
+ });
+ return;
+ }
+ if (valueOrHandler(config.allowOutsideClick, e)) {
+ return;
+ }
+ e.preventDefault();
+ };
+ var checkFocusIn = function checkFocusIn2(e) {
+ var targetContained = containersContain(e.target);
+ if (targetContained || e.target instanceof Document) {
+ if (targetContained) {
+ state.mostRecentlyFocusedNode = e.target;
+ }
+ } else {
+ e.stopImmediatePropagation();
+ tryFocus(state.mostRecentlyFocusedNode || getInitialFocusNode());
+ }
+ };
+ var checkTab = function checkTab2(e) {
+ updateTabbableNodes();
+ var destinationNode = null;
+ if (state.tabbableGroups.length > 0) {
+ var containerIndex = findIndex(state.tabbableGroups, function(_ref) {
+ var container = _ref.container;
+ return container.contains(e.target);
+ });
+ if (containerIndex < 0) {
+ if (e.shiftKey) {
+ destinationNode = state.tabbableGroups[state.tabbableGroups.length - 1].lastTabbableNode;
+ } else {
+ destinationNode = state.tabbableGroups[0].firstTabbableNode;
+ }
+ } else if (e.shiftKey) {
+ var startOfGroupIndex = findIndex(state.tabbableGroups, function(_ref2) {
+ var firstTabbableNode = _ref2.firstTabbableNode;
+ return e.target === firstTabbableNode;
+ });
+ if (startOfGroupIndex < 0 && state.tabbableGroups[containerIndex].container === e.target) {
+ startOfGroupIndex = containerIndex;
+ }
+ if (startOfGroupIndex >= 0) {
+ var destinationGroupIndex = startOfGroupIndex === 0 ? state.tabbableGroups.length - 1 : startOfGroupIndex - 1;
+ var destinationGroup = state.tabbableGroups[destinationGroupIndex];
+ destinationNode = destinationGroup.lastTabbableNode;
+ }
+ } else {
+ var lastOfGroupIndex = findIndex(state.tabbableGroups, function(_ref3) {
+ var lastTabbableNode = _ref3.lastTabbableNode;
+ return e.target === lastTabbableNode;
+ });
+ if (lastOfGroupIndex < 0 && state.tabbableGroups[containerIndex].container === e.target) {
+ lastOfGroupIndex = containerIndex;
+ }
+ if (lastOfGroupIndex >= 0) {
+ var _destinationGroupIndex = lastOfGroupIndex === state.tabbableGroups.length - 1 ? 0 : lastOfGroupIndex + 1;
+ var _destinationGroup = state.tabbableGroups[_destinationGroupIndex];
+ destinationNode = _destinationGroup.firstTabbableNode;
+ }
+ }
+ } else {
+ destinationNode = getNodeForOption("fallbackFocus");
+ }
+ if (destinationNode) {
+ e.preventDefault();
+ tryFocus(destinationNode);
+ }
+ };
+ var checkKey = function checkKey2(e) {
+ if (isEscapeEvent(e) && valueOrHandler(config.escapeDeactivates) !== false) {
+ e.preventDefault();
+ trap.deactivate();
+ return;
+ }
+ if (isTabEvent(e)) {
+ checkTab(e);
+ return;
+ }
+ };
+ var checkClick = function checkClick2(e) {
+ if (valueOrHandler(config.clickOutsideDeactivates, e)) {
+ return;
+ }
+ if (containersContain(e.target)) {
+ return;
+ }
+ if (valueOrHandler(config.allowOutsideClick, e)) {
+ return;
+ }
+ e.preventDefault();
+ e.stopImmediatePropagation();
+ };
+ var addListeners = function addListeners2() {
+ if (!state.active) {
+ return;
+ }
+ activeFocusTraps.activateTrap(trap);
+ state.delayInitialFocusTimer = config.delayInitialFocus ? delay(function() {
+ tryFocus(getInitialFocusNode());
+ }) : tryFocus(getInitialFocusNode());
+ doc.addEventListener("focusin", checkFocusIn, true);
+ doc.addEventListener("mousedown", checkPointerDown, {
+ capture: true,
+ passive: false
+ });
+ doc.addEventListener("touchstart", checkPointerDown, {
+ capture: true,
+ passive: false
+ });
+ doc.addEventListener("click", checkClick, {
+ capture: true,
+ passive: false
+ });
+ doc.addEventListener("keydown", checkKey, {
+ capture: true,
+ passive: false
+ });
+ return trap;
+ };
+ var removeListeners = function removeListeners2() {
+ if (!state.active) {
+ return;
+ }
+ doc.removeEventListener("focusin", checkFocusIn, true);
+ doc.removeEventListener("mousedown", checkPointerDown, true);
+ doc.removeEventListener("touchstart", checkPointerDown, true);
+ doc.removeEventListener("click", checkClick, true);
+ doc.removeEventListener("keydown", checkKey, true);
+ return trap;
+ };
+ trap = {
+ activate: function activate(activateOptions) {
+ if (state.active) {
+ return this;
+ }
+ var onActivate = getOption(activateOptions, "onActivate");
+ var onPostActivate = getOption(activateOptions, "onPostActivate");
+ var checkCanFocusTrap = getOption(activateOptions, "checkCanFocusTrap");
+ if (!checkCanFocusTrap) {
+ updateTabbableNodes();
+ }
+ state.active = true;
+ state.paused = false;
+ state.nodeFocusedBeforeActivation = doc.activeElement;
+ if (onActivate) {
+ onActivate();
+ }
+ var finishActivation = function finishActivation2() {
+ if (checkCanFocusTrap) {
+ updateTabbableNodes();
+ }
+ addListeners();
+ if (onPostActivate) {
+ onPostActivate();
+ }
+ };
+ if (checkCanFocusTrap) {
+ checkCanFocusTrap(state.containers.concat()).then(finishActivation, finishActivation);
+ return this;
+ }
+ finishActivation();
+ return this;
+ },
+ deactivate: function deactivate(deactivateOptions) {
+ if (!state.active) {
+ return this;
+ }
+ clearTimeout(state.delayInitialFocusTimer);
+ state.delayInitialFocusTimer = void 0;
+ removeListeners();
+ state.active = false;
+ state.paused = false;
+ activeFocusTraps.deactivateTrap(trap);
+ var onDeactivate = getOption(deactivateOptions, "onDeactivate");
+ var onPostDeactivate = getOption(deactivateOptions, "onPostDeactivate");
+ var checkCanReturnFocus = getOption(deactivateOptions, "checkCanReturnFocus");
+ if (onDeactivate) {
+ onDeactivate();
+ }
+ var returnFocus = getOption(deactivateOptions, "returnFocus", "returnFocusOnDeactivate");
+ var finishDeactivation = function finishDeactivation2() {
+ delay(function() {
+ if (returnFocus) {
+ tryFocus(getReturnFocusNode(state.nodeFocusedBeforeActivation));
+ }
+ if (onPostDeactivate) {
+ onPostDeactivate();
+ }
+ });
+ };
+ if (returnFocus && checkCanReturnFocus) {
+ checkCanReturnFocus(getReturnFocusNode(state.nodeFocusedBeforeActivation)).then(finishDeactivation, finishDeactivation);
+ return this;
+ }
+ finishDeactivation();
+ return this;
+ },
+ pause: function pause() {
+ if (state.paused || !state.active) {
+ return this;
+ }
+ state.paused = true;
+ removeListeners();
+ return this;
+ },
+ unpause: function unpause() {
+ if (!state.paused || !state.active) {
+ return this;
+ }
+ state.paused = false;
+ updateTabbableNodes();
+ addListeners();
+ return this;
+ },
+ updateContainerElements: function updateContainerElements(containerElements) {
+ var elementsAsArray = [].concat(containerElements).filter(Boolean);
+ state.containers = elementsAsArray.map(function(element) {
+ return typeof element === "string" ? doc.querySelector(element) : element;
+ });
+ if (state.active) {
+ updateTabbableNodes();
+ }
+ return this;
+ }
+ };
+ trap.updateContainerElements(elements);
+ return trap;
+ };
+
+ // packages/focus/src/index.js
+ function src_default(Alpine) {
+ let lastFocused;
+ let currentFocused;
+ window.addEventListener("focusin", () => {
+ lastFocused = currentFocused;
+ currentFocused = document.activeElement;
+ });
+ Alpine.magic("focus", (el) => {
+ let within = el;
+ return {
+ __noscroll: false,
+ __wrapAround: false,
+ within(el2) {
+ within = el2;
+ return this;
+ },
+ withoutScrolling() {
+ this.__noscroll = true;
+ return this;
+ },
+ noscroll() {
+ this.__noscroll = true;
+ return this;
+ },
+ withWrapAround() {
+ this.__wrapAround = true;
+ return this;
+ },
+ wrap() {
+ return this.withWrapAround();
+ },
+ focusable(el2) {
+ return isFocusable(el2);
+ },
+ previouslyFocused() {
+ return lastFocused;
+ },
+ lastFocused() {
+ return lastFocused;
+ },
+ focused() {
+ return currentFocused;
+ },
+ focusables() {
+ if (Array.isArray(within))
+ return within;
+ return focusable(within, {displayCheck: "none"});
+ },
+ all() {
+ return this.focusables();
+ },
+ isFirst(el2) {
+ let els = this.all();
+ return els[0] && els[0].isSameNode(el2);
+ },
+ isLast(el2) {
+ let els = this.all();
+ return els.length && els.slice(-1)[0].isSameNode(el2);
+ },
+ getFirst() {
+ return this.all()[0];
+ },
+ getLast() {
+ return this.all().slice(-1)[0];
+ },
+ getNext() {
+ let list = this.all();
+ let current = document.activeElement;
+ if (list.indexOf(current) === -1)
+ return;
+ if (this.__wrapAround && list.indexOf(current) === list.length - 1) {
+ return list[0];
+ }
+ return list[list.indexOf(current) + 1];
+ },
+ getPrevious() {
+ let list = this.all();
+ let current = document.activeElement;
+ if (list.indexOf(current) === -1)
+ return;
+ if (this.__wrapAround && list.indexOf(current) === 0) {
+ return list.slice(-1)[0];
+ }
+ return list[list.indexOf(current) - 1];
+ },
+ first() {
+ this.focus(this.getFirst());
+ },
+ last() {
+ this.focus(this.getLast());
+ },
+ next() {
+ this.focus(this.getNext());
+ },
+ previous() {
+ this.focus(this.getPrevious());
+ },
+ prev() {
+ return this.previous();
+ },
+ focus(el2) {
+ if (!el2)
+ return;
+ setTimeout(() => {
+ if (!el2.hasAttribute("tabindex"))
+ el2.setAttribute("tabindex", "0");
+ el2.focus({preventScroll: this._noscroll});
+ });
+ }
+ };
+ });
+ Alpine.directive("trap", Alpine.skipDuringClone((el, {expression, modifiers}, {effect, evaluateLater, cleanup}) => {
+ let evaluator = evaluateLater(expression);
+ let oldValue = false;
+ let trap = createFocusTrap(el, {
+ escapeDeactivates: false,
+ allowOutsideClick: true,
+ fallbackFocus: () => el
+ });
+ let undoInert = () => {
+ };
+ let undoDisableScrolling = () => {
+ };
+ const releaseFocus = () => {
+ undoInert();
+ undoInert = () => {
+ };
+ undoDisableScrolling();
+ undoDisableScrolling = () => {
+ };
+ trap.deactivate({
+ returnFocus: !modifiers.includes("noreturn")
+ });
+ };
+ effect(() => evaluator((value) => {
+ if (oldValue === value)
+ return;
+ if (value && !oldValue) {
+ setTimeout(() => {
+ if (modifiers.includes("inert"))
+ undoInert = setInert(el);
+ if (modifiers.includes("noscroll"))
+ undoDisableScrolling = disableScrolling();
+ trap.activate();
+ });
+ }
+ if (!value && oldValue) {
+ releaseFocus();
+ }
+ oldValue = !!value;
+ }));
+ cleanup(releaseFocus);
+ }, (el, {expression, modifiers}, {evaluate}) => {
+ if (modifiers.includes("inert") && evaluate(expression))
+ setInert(el);
+ }));
+ }
+ function setInert(el) {
+ let undos = [];
+ crawlSiblingsUp(el, (sibling) => {
+ let cache = sibling.hasAttribute("aria-hidden");
+ sibling.setAttribute("aria-hidden", "true");
+ undos.push(() => cache || sibling.removeAttribute("aria-hidden"));
+ });
+ return () => {
+ while (undos.length)
+ undos.pop()();
+ };
+ }
+ function crawlSiblingsUp(el, callback) {
+ if (el.isSameNode(document.body) || !el.parentNode)
+ return;
+ Array.from(el.parentNode.children).forEach((sibling) => {
+ if (!sibling.isSameNode(el))
+ callback(sibling);
+ crawlSiblingsUp(el.parentNode, callback);
+ });
+ }
+ function disableScrolling() {
+ let overflow = document.documentElement.style.overflow;
+ let paddingRight = document.documentElement.style.paddingRight;
+ let scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
+ document.documentElement.style.overflow = "hidden";
+ document.documentElement.style.paddingRight = `${scrollbarWidth}px`;
+ return () => {
+ document.documentElement.style.overflow = overflow;
+ document.documentElement.style.paddingRight = paddingRight;
+ };
+ }
+
+ // packages/focus/builds/cdn.js
+ document.addEventListener("alpine:init", () => {
+ window.Alpine.plugin(src_default);
+ });
+})();
diff --git a/alpinejs/packages/focus/dist/cdn.min.js b/alpinejs/packages/focus/dist/cdn.min.js
new file mode 100644
index 0000000..781dfb8
--- /dev/null
+++ b/alpinejs/packages/focus/dist/cdn.min.js
@@ -0,0 +1,9 @@
+(()=>{var j=["input","select","textarea","a[href]","button","[tabindex]","audio[controls]","video[controls]",'[contenteditable]:not([contenteditable="false"])',"details>summary:first-of-type","details"],_=j.join(","),A=typeof Element=="undefined"?function(){}:Element.prototype.matches||Element.prototype.msMatchesSelector||Element.prototype.webkitMatchesSelector,G=function(e,t,n){var u=Array.prototype.slice.apply(e.querySelectorAll(_));return t&&A.call(e,_)&&u.unshift(e),u=u.filter(n),u},Z=function(e){return e.contentEditable==="true"},M=function(e){var t=parseInt(e.getAttribute("tabindex"),10);return isNaN(t)?Z(e)||(e.nodeName==="AUDIO"||e.nodeName==="VIDEO"||e.nodeName==="DETAILS")&&e.getAttribute("tabindex")===null?0:e.tabIndex:t},$=function(e,t){return e.tabIndex===t.tabIndex?e.documentOrder-t.documentOrder:e.tabIndex-t.tabIndex},C=function(e){return e.tagName==="INPUT"},ee=function(e){return C(e)&&e.type==="hidden"},te=function(e){var t=e.tagName==="DETAILS"&&Array.prototype.slice.apply(e.children).some(function(n){return n.tagName==="SUMMARY"});return t},re=function(e,t){for(var n=0;n<e.length;n++)if(e[n].checked&&e[n].form===t)return e[n]},ae=function(e){if(!e.name)return!0;var t=e.form||e.ownerDocument,n=function(l){return t.querySelectorAll('input[type="radio"][name="'+l+'"]')},u;if(typeof window!="undefined"&&typeof window.CSS!="undefined"&&typeof window.CSS.escape=="function")u=n(window.CSS.escape(e.name));else try{u=n(e.name)}catch(s){return console.error("Looks like you have a radio button with a name attribute containing invalid CSS selector characters and need the CSS.escape polyfill: %s",s.message),!1}var r=re(u,e.form);return!r||r===e},ne=function(e){return C(e)&&e.type==="radio"},ie=function(e){return ne(e)&&!ae(e)},ue=function(e,t){if(getComputedStyle(e).visibility==="hidden")return!0;var n=A.call(e,"details>summary:first-of-type"),u=n?e.parentElement:e;if(A.call(u,"details:not([open]) *"))return!0;if(!t||t==="full")for(;e;){if(getComputedStyle(e).display==="none")return!0;e=e.parentElement}else if(t==="non-zero-area"){var r=e.getBoundingClientRect(),s=r.width,l=r.height;return s===0&&l===0}return!1},oe=function(e){if(C(e)||e.tagName==="SELECT"||e.tagName==="TEXTAREA"||e.tagName==="BUTTON")for(var t=e.parentElement;t;){if(t.tagName==="FIELDSET"&&t.disabled){for(var n=0;n<t.children.length;n++){var u=t.children.item(n);if(u.tagName==="LEGEND")return!u.contains(e)}return!0}t=t.parentElement}return!1},O=function(e,t){return!(t.disabled||ee(t)||ue(t,e.displayCheck)||te(t)||oe(t))},se=function(e,t){return!(!O(e,t)||ie(t)||M(t)<0)},W=function(e,t){t=t||{};var n=[],u=[],r=G(e,t.includeContainer,se.bind(null,t));r.forEach(function(l,h){var b=M(l);b===0?n.push(l):u.push({documentOrder:h,tabIndex:b,node:l})});var s=u.sort($).map(function(l){return l.node}).concat(n);return s},q=function(e,t){t=t||{};var n=G(e,t.includeContainer,O.bind(null,t));return n};var ce=j.concat("iframe").join(","),k=function(e,t){if(t=t||{},!e)throw new Error("No node provided");return A.call(e,ce)===!1?!1:O(t,e)};function B(i,e){var t=Object.keys(i);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(i);e&&(n=n.filter(function(u){return Object.getOwnPropertyDescriptor(i,u).enumerable})),t.push.apply(t,n)}return t}function fe(i){for(var e=1;e<arguments.length;e++){var t=arguments[e]!=null?arguments[e]:{};e%2?B(Object(t),!0).forEach(function(n){le(i,n,t[n])}):Object.getOwnPropertyDescriptors?Object.defineProperties(i,Object.getOwnPropertyDescriptors(t)):B(Object(t)).forEach(function(n){Object.defineProperty(i,n,Object.getOwnPropertyDescriptor(t,n))})}return i}function le(i,e,t){return e in i?Object.defineProperty(i,e,{value:t,enumerable:!0,configurable:!0,writable:!0}):i[e]=t,i}var H=function(){var i=[];return{activateTrap:function(t){if(i.length>0){var n=i[i.length-1];n!==t&&n.pause()}var u=i.indexOf(t);u===-1||i.splice(u,1),i.push(t)},deactivateTrap:function(t){var n=i.indexOf(t);n!==-1&&i.splice(n,1),i.length>0&&i[i.length-1].unpause()}}}(),de=function(e){return e.tagName&&e.tagName.toLowerCase()==="input"&&typeof e.select=="function"},be=function(e){return e.key==="Escape"||e.key==="Esc"||e.keyCode===27},ve=function(e){return e.key==="Tab"||e.keyCode===9},U=function(e){return setTimeout(e,0)},L=function(e,t){var n=-1;return e.every(function(u,r){return t(u)?(n=r,!1):!0}),n},D=function(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),u=1;u<t;u++)n[u-1]=arguments[u];return typeof e=="function"?e.apply(void 0,n):e},K=function(e,t){var n=document,u=fe({returnFocusOnDeactivate:!0,escapeDeactivates:!0,delayInitialFocus:!0},t),r={containers:[],tabbableGroups:[],nodeFocusedBeforeActivation:null,mostRecentlyFocusedNode:null,active:!1,paused:!1,delayInitialFocusTimer:void 0},s,l=function(a,o,c){return a&&a[o]!==void 0?a[o]:u[c||o]},h=function(a){return r.containers.some(function(o){return o.contains(a)})},b=function(a){var o=u[a];if(!o)return null;var c=o;if(typeof o=="string"&&(c=n.querySelector(o),!c))throw new Error("`".concat(a,"` refers to no known node"));if(typeof o=="function"&&(c=o(),!c))throw new Error("`".concat(a,"` did not return a node"));return c},v=function(){var a;if(l({},"initialFocus")===!1)return!1;if(b("initialFocus")!==null)a=b("initialFocus");else if(h(n.activeElement))a=n.activeElement;else{var o=r.tabbableGroups[0],c=o&&o.firstTabbableNode;a=c||b("fallbackFocus")}if(!a)throw new Error("Your focus-trap needs to have at least one focusable element");return a},m=function(){if(r.tabbableGroups=r.containers.map(function(a){var o=W(a);if(o.length>0)return{container:a,firstTabbableNode:o[0],lastTabbableNode:o[o.length-1]}}).filter(function(a){return!!a}),r.tabbableGroups.length<=0&&!b("fallbackFocus"))throw new Error("Your focus-trap must have at least one container with at least one tabbable node in it at all times")},p=function f(a){if(a!==!1&&a!==n.activeElement){if(!a||!a.focus){f(v());return}a.focus({preventScroll:!!u.preventScroll}),r.mostRecentlyFocusedNode=a,de(a)&&a.select()}},E=function(a){var o=b("setReturnFocus");return o||a},y=function(a){if(!h(a.target)){if(D(u.clickOutsideDeactivates,a)){s.deactivate({returnFocus:u.returnFocusOnDeactivate&&!k(a.target)});return}D(u.allowOutsideClick,a)||a.preventDefault()}},w=function(a){var o=h(a.target);o||a.target instanceof Document?o&&(r.mostRecentlyFocusedNode=a.target):(a.stopImmediatePropagation(),p(r.mostRecentlyFocusedNode||v()))},Q=function(a){m();var o=null;if(r.tabbableGroups.length>0){var c=L(r.tabbableGroups,function(N){var S=N.container;return S.contains(a.target)});if(c<0)a.shiftKey?o=r.tabbableGroups[r.tabbableGroups.length-1].lastTabbableNode:o=r.tabbableGroups[0].firstTabbableNode;else if(a.shiftKey){var d=L(r.tabbableGroups,function(N){var S=N.firstTabbableNode;return a.target===S});if(d<0&&r.tabbableGroups[c].container===a.target&&(d=c),d>=0){var g=d===0?r.tabbableGroups.length-1:d-1,F=r.tabbableGroups[g];o=F.lastTabbableNode}}else{var T=L(r.tabbableGroups,function(N){var S=N.lastTabbableNode;return a.target===S});if(T<0&&r.tabbableGroups[c].container===a.target&&(T=c),T>=0){var X=T===r.tabbableGroups.length-1?0:T+1,J=r.tabbableGroups[X];o=J.firstTabbableNode}}}else o=b("fallbackFocus");o&&(a.preventDefault(),p(o))},R=function(a){if(be(a)&&D(u.escapeDeactivates)!==!1){a.preventDefault(),s.deactivate();return}if(ve(a)){Q(a);return}},x=function(a){D(u.clickOutsideDeactivates,a)||h(a.target)||D(u.allowOutsideClick,a)||(a.preventDefault(),a.stopImmediatePropagation())},I=function(){if(!!r.active)return H.activateTrap(s),r.delayInitialFocusTimer=u.delayInitialFocus?U(function(){p(v())}):p(v()),n.addEventListener("focusin",w,!0),n.addEventListener("mousedown",y,{capture:!0,passive:!1}),n.addEventListener("touchstart",y,{capture:!0,passive:!1}),n.addEventListener("click",x,{capture:!0,passive:!1}),n.addEventListener("keydown",R,{capture:!0,passive:!1}),s},P=function(){if(!!r.active)return n.removeEventListener("focusin",w,!0),n.removeEventListener("mousedown",y,!0),n.removeEventListener("touchstart",y,!0),n.removeEventListener("click",x,!0),n.removeEventListener("keydown",R,!0),s};return s={activate:function(a){if(r.active)return this;var o=l(a,"onActivate"),c=l(a,"onPostActivate"),d=l(a,"checkCanFocusTrap");d||m(),r.active=!0,r.paused=!1,r.nodeFocusedBeforeActivation=n.activeElement,o&&o();var g=function(){d&&m(),I(),c&&c()};return d?(d(r.containers.concat()).then(g,g),this):(g(),this)},deactivate:function(a){if(!r.active)return this;clearTimeout(r.delayInitialFocusTimer),r.delayInitialFocusTimer=void 0,P(),r.active=!1,r.paused=!1,H.deactivateTrap(s);var o=l(a,"onDeactivate"),c=l(a,"onPostDeactivate"),d=l(a,"checkCanReturnFocus");o&&o();var g=l(a,"returnFocus","returnFocusOnDeactivate"),F=function(){U(function(){g&&p(E(r.nodeFocusedBeforeActivation)),c&&c()})};return g&&d?(d(E(r.nodeFocusedBeforeActivation)).then(F,F),this):(F(),this)},pause:function(){return r.paused||!r.active?this:(r.paused=!0,P(),this)},unpause:function(){return!r.paused||!r.active?this:(r.paused=!1,m(),I(),this)},updateContainerElements:function(a){var o=[].concat(a).filter(Boolean);return r.containers=o.map(function(c){return typeof c=="string"?n.querySelector(c):c}),r.active&&m(),this}},s.updateContainerElements(e),s};function Y(i){let e,t;window.addEventListener("focusin",()=>{e=t,t=document.activeElement}),i.magic("focus",n=>{let u=n;return{__noscroll:!1,__wrapAround:!1,within(r){return u=r,this},withoutScrolling(){return this.__noscroll=!0,this},noscroll(){return this.__noscroll=!0,this},withWrapAround(){return this.__wrapAround=!0,this},wrap(){return this.withWrapAround()},focusable(r){return k(r)},previouslyFocused(){return e},lastFocused(){return e},focused(){return t},focusables(){return Array.isArray(u)?u:q(u,{displayCheck:"none"})},all(){return this.focusables()},isFirst(r){let s=this.all();return s[0]&&s[0].isSameNode(r)},isLast(r){let s=this.all();return s.length&&s.slice(-1)[0].isSameNode(r)},getFirst(){return this.all()[0]},getLast(){return this.all().slice(-1)[0]},getNext(){let r=this.all(),s=document.activeElement;if(r.indexOf(s)!==-1)return this.__wrapAround&&r.indexOf(s)===r.length-1?r[0]:r[r.indexOf(s)+1]},getPrevious(){let r=this.all(),s=document.activeElement;if(r.indexOf(s)!==-1)return this.__wrapAround&&r.indexOf(s)===0?r.slice(-1)[0]:r[r.indexOf(s)-1]},first(){this.focus(this.getFirst())},last(){this.focus(this.getLast())},next(){this.focus(this.getNext())},previous(){this.focus(this.getPrevious())},prev(){return this.previous()},focus(r){!r||setTimeout(()=>{r.hasAttribute("tabindex")||r.setAttribute("tabindex","0"),r.focus({preventScroll:this._noscroll})})}}}),i.directive("trap",i.skipDuringClone((n,{expression:u,modifiers:r},{effect:s,evaluateLater:l,cleanup:h})=>{let b=l(u),v=!1,m=K(n,{escapeDeactivates:!1,allowOutsideClick:!0,fallbackFocus:()=>n}),p=()=>{},E=()=>{},y=()=>{p(),p=()=>{},E(),E=()=>{},m.deactivate({returnFocus:!r.includes("noreturn")})};s(()=>b(w=>{v!==w&&(w&&!v&&setTimeout(()=>{r.includes("inert")&&(p=V(n)),r.includes("noscroll")&&(E=pe()),m.activate()}),!w&&v&&y(),v=!!w)})),h(y)},(n,{expression:u,modifiers:r},{evaluate:s})=>{r.includes("inert")&&s(u)&&V(n)}))}function V(i){let e=[];return z(i,t=>{let n=t.hasAttribute("aria-hidden");t.setAttribute("aria-hidden","true"),e.push(()=>n||t.removeAttribute("aria-hidden"))}),()=>{for(;e.length;)e.pop()()}}function z(i,e){i.isSameNode(document.body)||!i.parentNode||Array.from(i.parentNode.children).forEach(t=>{t.isSameNode(i)||e(t),z(i.parentNode,e)})}function pe(){let i=document.documentElement.style.overflow,e=document.documentElement.style.paddingRight,t=window.innerWidth-document.documentElement.clientWidth;return document.documentElement.style.overflow="hidden",document.documentElement.style.paddingRight=`${t}px`,()=>{document.documentElement.style.overflow=i,document.documentElement.style.paddingRight=e}}document.addEventListener("alpine:init",()=>{window.Alpine.plugin(Y)});})();
+/*!
+* focus-trap 6.6.1
+* @license MIT, https://github.com/focus-trap/focus-trap/blob/master/LICENSE
+*/
+/*!
+* tabbable 5.2.1
+* @license MIT, https://github.com/focus-trap/tabbable/blob/master/LICENSE
+*/
diff --git a/alpinejs/packages/focus/dist/module.cjs.js b/alpinejs/packages/focus/dist/module.cjs.js
new file mode 100644
index 0000000..83df455
--- /dev/null
+++ b/alpinejs/packages/focus/dist/module.cjs.js
@@ -0,0 +1,879 @@
+var __create = Object.create;
+var __defProp = Object.defineProperty;
+var __getProtoOf = Object.getPrototypeOf;
+var __hasOwnProp = Object.prototype.hasOwnProperty;
+var __getOwnPropNames = Object.getOwnPropertyNames;
+var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
+var __markAsModule = (target) => __defProp(target, "__esModule", {value: true});
+var __commonJS = (callback, module2) => () => {
+ if (!module2) {
+ module2 = {exports: {}};
+ callback(module2.exports, module2);
+ }
+ return module2.exports;
+};
+var __export = (target, all) => {
+ for (var name in all)
+ __defProp(target, name, {get: all[name], enumerable: true});
+};
+var __exportStar = (target, module2, desc) => {
+ if (module2 && typeof module2 === "object" || typeof module2 === "function") {
+ for (let key of __getOwnPropNames(module2))
+ if (!__hasOwnProp.call(target, key) && key !== "default")
+ __defProp(target, key, {get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable});
+ }
+ return target;
+};
+var __toModule = (module2) => {
+ return __exportStar(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? {get: () => module2.default, enumerable: true} : {value: module2, enumerable: true})), module2);
+};
+
+// node_modules/tabbable/dist/index.js
+var require_dist = __commonJS((exports2) => {
+ /*!
+ * tabbable 5.2.1
+ * @license MIT, https://github.com/focus-trap/tabbable/blob/master/LICENSE
+ */
+ "use strict";
+ Object.defineProperty(exports2, "__esModule", {value: true});
+ var candidateSelectors = ["input", "select", "textarea", "a[href]", "button", "[tabindex]", "audio[controls]", "video[controls]", '[contenteditable]:not([contenteditable="false"])', "details>summary:first-of-type", "details"];
+ var candidateSelector = /* @__PURE__ */ candidateSelectors.join(",");
+ var matches = typeof Element === "undefined" ? function() {
+ } : Element.prototype.matches || Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
+ var getCandidates = function getCandidates2(el, includeContainer, filter) {
+ var candidates = Array.prototype.slice.apply(el.querySelectorAll(candidateSelector));
+ if (includeContainer && matches.call(el, candidateSelector)) {
+ candidates.unshift(el);
+ }
+ candidates = candidates.filter(filter);
+ return candidates;
+ };
+ var isContentEditable = function isContentEditable2(node) {
+ return node.contentEditable === "true";
+ };
+ var getTabindex = function getTabindex2(node) {
+ var tabindexAttr = parseInt(node.getAttribute("tabindex"), 10);
+ if (!isNaN(tabindexAttr)) {
+ return tabindexAttr;
+ }
+ if (isContentEditable(node)) {
+ return 0;
+ }
+ if ((node.nodeName === "AUDIO" || node.nodeName === "VIDEO" || node.nodeName === "DETAILS") && node.getAttribute("tabindex") === null) {
+ return 0;
+ }
+ return node.tabIndex;
+ };
+ var sortOrderedTabbables = function sortOrderedTabbables2(a, b) {
+ return a.tabIndex === b.tabIndex ? a.documentOrder - b.documentOrder : a.tabIndex - b.tabIndex;
+ };
+ var isInput = function isInput2(node) {
+ return node.tagName === "INPUT";
+ };
+ var isHiddenInput = function isHiddenInput2(node) {
+ return isInput(node) && node.type === "hidden";
+ };
+ var isDetailsWithSummary = function isDetailsWithSummary2(node) {
+ var r = node.tagName === "DETAILS" && Array.prototype.slice.apply(node.children).some(function(child) {
+ return child.tagName === "SUMMARY";
+ });
+ return r;
+ };
+ var getCheckedRadio = function getCheckedRadio2(nodes, form) {
+ for (var i = 0; i < nodes.length; i++) {
+ if (nodes[i].checked && nodes[i].form === form) {
+ return nodes[i];
+ }
+ }
+ };
+ var isTabbableRadio = function isTabbableRadio2(node) {
+ if (!node.name) {
+ return true;
+ }
+ var radioScope = node.form || node.ownerDocument;
+ var queryRadios = function queryRadios2(name) {
+ return radioScope.querySelectorAll('input[type="radio"][name="' + name + '"]');
+ };
+ var radioSet;
+ if (typeof window !== "undefined" && typeof window.CSS !== "undefined" && typeof window.CSS.escape === "function") {
+ radioSet = queryRadios(window.CSS.escape(node.name));
+ } else {
+ try {
+ radioSet = queryRadios(node.name);
+ } catch (err) {
+ console.error("Looks like you have a radio button with a name attribute containing invalid CSS selector characters and need the CSS.escape polyfill: %s", err.message);
+ return false;
+ }
+ }
+ var checked = getCheckedRadio(radioSet, node.form);
+ return !checked || checked === node;
+ };
+ var isRadio = function isRadio2(node) {
+ return isInput(node) && node.type === "radio";
+ };
+ var isNonTabbableRadio = function isNonTabbableRadio2(node) {
+ return isRadio(node) && !isTabbableRadio(node);
+ };
+ var isHidden = function isHidden2(node, displayCheck) {
+ if (getComputedStyle(node).visibility === "hidden") {
+ return true;
+ }
+ var isDirectSummary = matches.call(node, "details>summary:first-of-type");
+ var nodeUnderDetails = isDirectSummary ? node.parentElement : node;
+ if (matches.call(nodeUnderDetails, "details:not([open]) *")) {
+ return true;
+ }
+ if (!displayCheck || displayCheck === "full") {
+ while (node) {
+ if (getComputedStyle(node).display === "none") {
+ return true;
+ }
+ node = node.parentElement;
+ }
+ } else if (displayCheck === "non-zero-area") {
+ var _node$getBoundingClie = node.getBoundingClientRect(), width = _node$getBoundingClie.width, height = _node$getBoundingClie.height;
+ return width === 0 && height === 0;
+ }
+ return false;
+ };
+ var isDisabledFromFieldset = function isDisabledFromFieldset2(node) {
+ if (isInput(node) || node.tagName === "SELECT" || node.tagName === "TEXTAREA" || node.tagName === "BUTTON") {
+ var parentNode = node.parentElement;
+ while (parentNode) {
+ if (parentNode.tagName === "FIELDSET" && parentNode.disabled) {
+ for (var i = 0; i < parentNode.children.length; i++) {
+ var child = parentNode.children.item(i);
+ if (child.tagName === "LEGEND") {
+ if (child.contains(node)) {
+ return false;
+ }
+ return true;
+ }
+ }
+ return true;
+ }
+ parentNode = parentNode.parentElement;
+ }
+ }
+ return false;
+ };
+ var isNodeMatchingSelectorFocusable = function isNodeMatchingSelectorFocusable2(options, node) {
+ if (node.disabled || isHiddenInput(node) || isHidden(node, options.displayCheck) || isDetailsWithSummary(node) || isDisabledFromFieldset(node)) {
+ return false;
+ }
+ return true;
+ };
+ var isNodeMatchingSelectorTabbable = function isNodeMatchingSelectorTabbable2(options, node) {
+ if (!isNodeMatchingSelectorFocusable(options, node) || isNonTabbableRadio(node) || getTabindex(node) < 0) {
+ return false;
+ }
+ return true;
+ };
+ var tabbable2 = function tabbable3(el, options) {
+ options = options || {};
+ var regularTabbables = [];
+ var orderedTabbables = [];
+ var candidates = getCandidates(el, options.includeContainer, isNodeMatchingSelectorTabbable.bind(null, options));
+ candidates.forEach(function(candidate, i) {
+ var candidateTabindex = getTabindex(candidate);
+ if (candidateTabindex === 0) {
+ regularTabbables.push(candidate);
+ } else {
+ orderedTabbables.push({
+ documentOrder: i,
+ tabIndex: candidateTabindex,
+ node: candidate
+ });
+ }
+ });
+ var tabbableNodes = orderedTabbables.sort(sortOrderedTabbables).map(function(a) {
+ return a.node;
+ }).concat(regularTabbables);
+ return tabbableNodes;
+ };
+ var focusable2 = function focusable3(el, options) {
+ options = options || {};
+ var candidates = getCandidates(el, options.includeContainer, isNodeMatchingSelectorFocusable.bind(null, options));
+ return candidates;
+ };
+ var isTabbable = function isTabbable2(node, options) {
+ options = options || {};
+ if (!node) {
+ throw new Error("No node provided");
+ }
+ if (matches.call(node, candidateSelector) === false) {
+ return false;
+ }
+ return isNodeMatchingSelectorTabbable(options, node);
+ };
+ var focusableCandidateSelector = /* @__PURE__ */ candidateSelectors.concat("iframe").join(",");
+ var isFocusable2 = function isFocusable3(node, options) {
+ options = options || {};
+ if (!node) {
+ throw new Error("No node provided");
+ }
+ if (matches.call(node, focusableCandidateSelector) === false) {
+ return false;
+ }
+ return isNodeMatchingSelectorFocusable(options, node);
+ };
+ exports2.focusable = focusable2;
+ exports2.isFocusable = isFocusable2;
+ exports2.isTabbable = isTabbable;
+ exports2.tabbable = tabbable2;
+});
+
+// node_modules/focus-trap/dist/focus-trap.js
+var require_focus_trap = __commonJS((exports2) => {
+ /*!
+ * focus-trap 6.6.1
+ * @license MIT, https://github.com/focus-trap/focus-trap/blob/master/LICENSE
+ */
+ "use strict";
+ Object.defineProperty(exports2, "__esModule", {value: true});
+ var tabbable2 = require_dist();
+ 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;
+ }
+ function _defineProperty(obj, key, value) {
+ if (key in obj) {
+ Object.defineProperty(obj, key, {
+ value,
+ enumerable: true,
+ configurable: true,
+ writable: true
+ });
+ } else {
+ obj[key] = value;
+ }
+ return obj;
+ }
+ var activeFocusTraps = function() {
+ var trapQueue = [];
+ return {
+ activateTrap: function activateTrap(trap) {
+ if (trapQueue.length > 0) {
+ var activeTrap = trapQueue[trapQueue.length - 1];
+ if (activeTrap !== trap) {
+ activeTrap.pause();
+ }
+ }
+ var trapIndex = trapQueue.indexOf(trap);
+ if (trapIndex === -1) {
+ trapQueue.push(trap);
+ } else {
+ trapQueue.splice(trapIndex, 1);
+ trapQueue.push(trap);
+ }
+ },
+ deactivateTrap: function deactivateTrap(trap) {
+ var trapIndex = trapQueue.indexOf(trap);
+ if (trapIndex !== -1) {
+ trapQueue.splice(trapIndex, 1);
+ }
+ if (trapQueue.length > 0) {
+ trapQueue[trapQueue.length - 1].unpause();
+ }
+ }
+ };
+ }();
+ var isSelectableInput = function isSelectableInput2(node) {
+ return node.tagName && node.tagName.toLowerCase() === "input" && typeof node.select === "function";
+ };
+ var isEscapeEvent = function isEscapeEvent2(e) {
+ return e.key === "Escape" || e.key === "Esc" || e.keyCode === 27;
+ };
+ var isTabEvent = function isTabEvent2(e) {
+ return e.key === "Tab" || e.keyCode === 9;
+ };
+ var delay = function delay2(fn) {
+ return setTimeout(fn, 0);
+ };
+ var findIndex = function findIndex2(arr, fn) {
+ var idx = -1;
+ arr.every(function(value, i) {
+ if (fn(value)) {
+ idx = i;
+ return false;
+ }
+ return true;
+ });
+ return idx;
+ };
+ var valueOrHandler = function valueOrHandler2(value) {
+ for (var _len = arguments.length, params = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
+ params[_key - 1] = arguments[_key];
+ }
+ return typeof value === "function" ? value.apply(void 0, params) : value;
+ };
+ var createFocusTrap2 = function createFocusTrap3(elements, userOptions) {
+ var doc = document;
+ var config = _objectSpread2({
+ returnFocusOnDeactivate: true,
+ escapeDeactivates: true,
+ delayInitialFocus: true
+ }, userOptions);
+ var state = {
+ containers: [],
+ tabbableGroups: [],
+ nodeFocusedBeforeActivation: null,
+ mostRecentlyFocusedNode: null,
+ active: false,
+ paused: false,
+ delayInitialFocusTimer: void 0
+ };
+ var trap;
+ var getOption = function getOption2(configOverrideOptions, optionName, configOptionName) {
+ return configOverrideOptions && configOverrideOptions[optionName] !== void 0 ? configOverrideOptions[optionName] : config[configOptionName || optionName];
+ };
+ var containersContain = function containersContain2(element) {
+ return state.containers.some(function(container) {
+ return container.contains(element);
+ });
+ };
+ var getNodeForOption = function getNodeForOption2(optionName) {
+ var optionValue = config[optionName];
+ if (!optionValue) {
+ return null;
+ }
+ var node = optionValue;
+ if (typeof optionValue === "string") {
+ node = doc.querySelector(optionValue);
+ if (!node) {
+ throw new Error("`".concat(optionName, "` refers to no known node"));
+ }
+ }
+ if (typeof optionValue === "function") {
+ node = optionValue();
+ if (!node) {
+ throw new Error("`".concat(optionName, "` did not return a node"));
+ }
+ }
+ return node;
+ };
+ var getInitialFocusNode = function getInitialFocusNode2() {
+ var node;
+ if (getOption({}, "initialFocus") === false) {
+ return false;
+ }
+ if (getNodeForOption("initialFocus") !== null) {
+ node = getNodeForOption("initialFocus");
+ } else if (containersContain(doc.activeElement)) {
+ node = doc.activeElement;
+ } else {
+ var firstTabbableGroup = state.tabbableGroups[0];
+ var firstTabbableNode = firstTabbableGroup && firstTabbableGroup.firstTabbableNode;
+ node = firstTabbableNode || getNodeForOption("fallbackFocus");
+ }
+ if (!node) {
+ throw new Error("Your focus-trap needs to have at least one focusable element");
+ }
+ return node;
+ };
+ var updateTabbableNodes = function updateTabbableNodes2() {
+ state.tabbableGroups = state.containers.map(function(container) {
+ var tabbableNodes = tabbable2.tabbable(container);
+ if (tabbableNodes.length > 0) {
+ return {
+ container,
+ firstTabbableNode: tabbableNodes[0],
+ lastTabbableNode: tabbableNodes[tabbableNodes.length - 1]
+ };
+ }
+ return void 0;
+ }).filter(function(group) {
+ return !!group;
+ });
+ if (state.tabbableGroups.length <= 0 && !getNodeForOption("fallbackFocus")) {
+ throw new Error("Your focus-trap must have at least one container with at least one tabbable node in it at all times");
+ }
+ };
+ var tryFocus = function tryFocus2(node) {
+ if (node === false) {
+ return;
+ }
+ if (node === doc.activeElement) {
+ return;
+ }
+ if (!node || !node.focus) {
+ tryFocus2(getInitialFocusNode());
+ return;
+ }
+ node.focus({
+ preventScroll: !!config.preventScroll
+ });
+ state.mostRecentlyFocusedNode = node;
+ if (isSelectableInput(node)) {
+ node.select();
+ }
+ };
+ var getReturnFocusNode = function getReturnFocusNode2(previousActiveElement) {
+ var node = getNodeForOption("setReturnFocus");
+ return node ? node : previousActiveElement;
+ };
+ var checkPointerDown = function checkPointerDown2(e) {
+ if (containersContain(e.target)) {
+ return;
+ }
+ if (valueOrHandler(config.clickOutsideDeactivates, e)) {
+ trap.deactivate({
+ returnFocus: config.returnFocusOnDeactivate && !tabbable2.isFocusable(e.target)
+ });
+ return;
+ }
+ if (valueOrHandler(config.allowOutsideClick, e)) {
+ return;
+ }
+ e.preventDefault();
+ };
+ var checkFocusIn = function checkFocusIn2(e) {
+ var targetContained = containersContain(e.target);
+ if (targetContained || e.target instanceof Document) {
+ if (targetContained) {
+ state.mostRecentlyFocusedNode = e.target;
+ }
+ } else {
+ e.stopImmediatePropagation();
+ tryFocus(state.mostRecentlyFocusedNode || getInitialFocusNode());
+ }
+ };
+ var checkTab = function checkTab2(e) {
+ updateTabbableNodes();
+ var destinationNode = null;
+ if (state.tabbableGroups.length > 0) {
+ var containerIndex = findIndex(state.tabbableGroups, function(_ref) {
+ var container = _ref.container;
+ return container.contains(e.target);
+ });
+ if (containerIndex < 0) {
+ if (e.shiftKey) {
+ destinationNode = state.tabbableGroups[state.tabbableGroups.length - 1].lastTabbableNode;
+ } else {
+ destinationNode = state.tabbableGroups[0].firstTabbableNode;
+ }
+ } else if (e.shiftKey) {
+ var startOfGroupIndex = findIndex(state.tabbableGroups, function(_ref2) {
+ var firstTabbableNode = _ref2.firstTabbableNode;
+ return e.target === firstTabbableNode;
+ });
+ if (startOfGroupIndex < 0 && state.tabbableGroups[containerIndex].container === e.target) {
+ startOfGroupIndex = containerIndex;
+ }
+ if (startOfGroupIndex >= 0) {
+ var destinationGroupIndex = startOfGroupIndex === 0 ? state.tabbableGroups.length - 1 : startOfGroupIndex - 1;
+ var destinationGroup = state.tabbableGroups[destinationGroupIndex];
+ destinationNode = destinationGroup.lastTabbableNode;
+ }
+ } else {
+ var lastOfGroupIndex = findIndex(state.tabbableGroups, function(_ref3) {
+ var lastTabbableNode = _ref3.lastTabbableNode;
+ return e.target === lastTabbableNode;
+ });
+ if (lastOfGroupIndex < 0 && state.tabbableGroups[containerIndex].container === e.target) {
+ lastOfGroupIndex = containerIndex;
+ }
+ if (lastOfGroupIndex >= 0) {
+ var _destinationGroupIndex = lastOfGroupIndex === state.tabbableGroups.length - 1 ? 0 : lastOfGroupIndex + 1;
+ var _destinationGroup = state.tabbableGroups[_destinationGroupIndex];
+ destinationNode = _destinationGroup.firstTabbableNode;
+ }
+ }
+ } else {
+ destinationNode = getNodeForOption("fallbackFocus");
+ }
+ if (destinationNode) {
+ e.preventDefault();
+ tryFocus(destinationNode);
+ }
+ };
+ var checkKey = function checkKey2(e) {
+ if (isEscapeEvent(e) && valueOrHandler(config.escapeDeactivates) !== false) {
+ e.preventDefault();
+ trap.deactivate();
+ return;
+ }
+ if (isTabEvent(e)) {
+ checkTab(e);
+ return;
+ }
+ };
+ var checkClick = function checkClick2(e) {
+ if (valueOrHandler(config.clickOutsideDeactivates, e)) {
+ return;
+ }
+ if (containersContain(e.target)) {
+ return;
+ }
+ if (valueOrHandler(config.allowOutsideClick, e)) {
+ return;
+ }
+ e.preventDefault();
+ e.stopImmediatePropagation();
+ };
+ var addListeners = function addListeners2() {
+ if (!state.active) {
+ return;
+ }
+ activeFocusTraps.activateTrap(trap);
+ state.delayInitialFocusTimer = config.delayInitialFocus ? delay(function() {
+ tryFocus(getInitialFocusNode());
+ }) : tryFocus(getInitialFocusNode());
+ doc.addEventListener("focusin", checkFocusIn, true);
+ doc.addEventListener("mousedown", checkPointerDown, {
+ capture: true,
+ passive: false
+ });
+ doc.addEventListener("touchstart", checkPointerDown, {
+ capture: true,
+ passive: false
+ });
+ doc.addEventListener("click", checkClick, {
+ capture: true,
+ passive: false
+ });
+ doc.addEventListener("keydown", checkKey, {
+ capture: true,
+ passive: false
+ });
+ return trap;
+ };
+ var removeListeners = function removeListeners2() {
+ if (!state.active) {
+ return;
+ }
+ doc.removeEventListener("focusin", checkFocusIn, true);
+ doc.removeEventListener("mousedown", checkPointerDown, true);
+ doc.removeEventListener("touchstart", checkPointerDown, true);
+ doc.removeEventListener("click", checkClick, true);
+ doc.removeEventListener("keydown", checkKey, true);
+ return trap;
+ };
+ trap = {
+ activate: function activate(activateOptions) {
+ if (state.active) {
+ return this;
+ }
+ var onActivate = getOption(activateOptions, "onActivate");
+ var onPostActivate = getOption(activateOptions, "onPostActivate");
+ var checkCanFocusTrap = getOption(activateOptions, "checkCanFocusTrap");
+ if (!checkCanFocusTrap) {
+ updateTabbableNodes();
+ }
+ state.active = true;
+ state.paused = false;
+ state.nodeFocusedBeforeActivation = doc.activeElement;
+ if (onActivate) {
+ onActivate();
+ }
+ var finishActivation = function finishActivation2() {
+ if (checkCanFocusTrap) {
+ updateTabbableNodes();
+ }
+ addListeners();
+ if (onPostActivate) {
+ onPostActivate();
+ }
+ };
+ if (checkCanFocusTrap) {
+ checkCanFocusTrap(state.containers.concat()).then(finishActivation, finishActivation);
+ return this;
+ }
+ finishActivation();
+ return this;
+ },
+ deactivate: function deactivate(deactivateOptions) {
+ if (!state.active) {
+ return this;
+ }
+ clearTimeout(state.delayInitialFocusTimer);
+ state.delayInitialFocusTimer = void 0;
+ removeListeners();
+ state.active = false;
+ state.paused = false;
+ activeFocusTraps.deactivateTrap(trap);
+ var onDeactivate = getOption(deactivateOptions, "onDeactivate");
+ var onPostDeactivate = getOption(deactivateOptions, "onPostDeactivate");
+ var checkCanReturnFocus = getOption(deactivateOptions, "checkCanReturnFocus");
+ if (onDeactivate) {
+ onDeactivate();
+ }
+ var returnFocus = getOption(deactivateOptions, "returnFocus", "returnFocusOnDeactivate");
+ var finishDeactivation = function finishDeactivation2() {
+ delay(function() {
+ if (returnFocus) {
+ tryFocus(getReturnFocusNode(state.nodeFocusedBeforeActivation));
+ }
+ if (onPostDeactivate) {
+ onPostDeactivate();
+ }
+ });
+ };
+ if (returnFocus && checkCanReturnFocus) {
+ checkCanReturnFocus(getReturnFocusNode(state.nodeFocusedBeforeActivation)).then(finishDeactivation, finishDeactivation);
+ return this;
+ }
+ finishDeactivation();
+ return this;
+ },
+ pause: function pause() {
+ if (state.paused || !state.active) {
+ return this;
+ }
+ state.paused = true;
+ removeListeners();
+ return this;
+ },
+ unpause: function unpause() {
+ if (!state.paused || !state.active) {
+ return this;
+ }
+ state.paused = false;
+ updateTabbableNodes();
+ addListeners();
+ return this;
+ },
+ updateContainerElements: function updateContainerElements(containerElements) {
+ var elementsAsArray = [].concat(containerElements).filter(Boolean);
+ state.containers = elementsAsArray.map(function(element) {
+ return typeof element === "string" ? doc.querySelector(element) : element;
+ });
+ if (state.active) {
+ updateTabbableNodes();
+ }
+ return this;
+ }
+ };
+ trap.updateContainerElements(elements);
+ return trap;
+ };
+ exports2.createFocusTrap = createFocusTrap2;
+});
+
+// packages/focus/builds/module.js
+__markAsModule(exports);
+__export(exports, {
+ default: () => module_default
+});
+
+// packages/focus/src/index.js
+var import_focus_trap = __toModule(require_focus_trap());
+var import_tabbable = __toModule(require_dist());
+function src_default(Alpine) {
+ let lastFocused;
+ let currentFocused;
+ window.addEventListener("focusin", () => {
+ lastFocused = currentFocused;
+ currentFocused = document.activeElement;
+ });
+ Alpine.magic("focus", (el) => {
+ let within = el;
+ return {
+ __noscroll: false,
+ __wrapAround: false,
+ within(el2) {
+ within = el2;
+ return this;
+ },
+ withoutScrolling() {
+ this.__noscroll = true;
+ return this;
+ },
+ noscroll() {
+ this.__noscroll = true;
+ return this;
+ },
+ withWrapAround() {
+ this.__wrapAround = true;
+ return this;
+ },
+ wrap() {
+ return this.withWrapAround();
+ },
+ focusable(el2) {
+ return (0, import_tabbable.isFocusable)(el2);
+ },
+ previouslyFocused() {
+ return lastFocused;
+ },
+ lastFocused() {
+ return lastFocused;
+ },
+ focused() {
+ return currentFocused;
+ },
+ focusables() {
+ if (Array.isArray(within))
+ return within;
+ return (0, import_tabbable.focusable)(within, {displayCheck: "none"});
+ },
+ all() {
+ return this.focusables();
+ },
+ isFirst(el2) {
+ let els = this.all();
+ return els[0] && els[0].isSameNode(el2);
+ },
+ isLast(el2) {
+ let els = this.all();
+ return els.length && els.slice(-1)[0].isSameNode(el2);
+ },
+ getFirst() {
+ return this.all()[0];
+ },
+ getLast() {
+ return this.all().slice(-1)[0];
+ },
+ getNext() {
+ let list = this.all();
+ let current = document.activeElement;
+ if (list.indexOf(current) === -1)
+ return;
+ if (this.__wrapAround && list.indexOf(current) === list.length - 1) {
+ return list[0];
+ }
+ return list[list.indexOf(current) + 1];
+ },
+ getPrevious() {
+ let list = this.all();
+ let current = document.activeElement;
+ if (list.indexOf(current) === -1)
+ return;
+ if (this.__wrapAround && list.indexOf(current) === 0) {
+ return list.slice(-1)[0];
+ }
+ return list[list.indexOf(current) - 1];
+ },
+ first() {
+ this.focus(this.getFirst());
+ },
+ last() {
+ this.focus(this.getLast());
+ },
+ next() {
+ this.focus(this.getNext());
+ },
+ previous() {
+ this.focus(this.getPrevious());
+ },
+ prev() {
+ return this.previous();
+ },
+ focus(el2) {
+ if (!el2)
+ return;
+ setTimeout(() => {
+ if (!el2.hasAttribute("tabindex"))
+ el2.setAttribute("tabindex", "0");
+ el2.focus({preventScroll: this._noscroll});
+ });
+ }
+ };
+ });
+ Alpine.directive("trap", Alpine.skipDuringClone((el, {expression, modifiers}, {effect, evaluateLater, cleanup}) => {
+ let evaluator = evaluateLater(expression);
+ let oldValue = false;
+ let trap = (0, import_focus_trap.createFocusTrap)(el, {
+ escapeDeactivates: false,
+ allowOutsideClick: true,
+ fallbackFocus: () => el
+ });
+ let undoInert = () => {
+ };
+ let undoDisableScrolling = () => {
+ };
+ const releaseFocus = () => {
+ undoInert();
+ undoInert = () => {
+ };
+ undoDisableScrolling();
+ undoDisableScrolling = () => {
+ };
+ trap.deactivate({
+ returnFocus: !modifiers.includes("noreturn")
+ });
+ };
+ effect(() => evaluator((value) => {
+ if (oldValue === value)
+ return;
+ if (value && !oldValue) {
+ setTimeout(() => {
+ if (modifiers.includes("inert"))
+ undoInert = setInert(el);
+ if (modifiers.includes("noscroll"))
+ undoDisableScrolling = disableScrolling();
+ trap.activate();
+ });
+ }
+ if (!value && oldValue) {
+ releaseFocus();
+ }
+ oldValue = !!value;
+ }));
+ cleanup(releaseFocus);
+ }, (el, {expression, modifiers}, {evaluate}) => {
+ if (modifiers.includes("inert") && evaluate(expression))
+ setInert(el);
+ }));
+}
+function setInert(el) {
+ let undos = [];
+ crawlSiblingsUp(el, (sibling) => {
+ let cache = sibling.hasAttribute("aria-hidden");
+ sibling.setAttribute("aria-hidden", "true");
+ undos.push(() => cache || sibling.removeAttribute("aria-hidden"));
+ });
+ return () => {
+ while (undos.length)
+ undos.pop()();
+ };
+}
+function crawlSiblingsUp(el, callback) {
+ if (el.isSameNode(document.body) || !el.parentNode)
+ return;
+ Array.from(el.parentNode.children).forEach((sibling) => {
+ if (!sibling.isSameNode(el))
+ callback(sibling);
+ crawlSiblingsUp(el.parentNode, callback);
+ });
+}
+function disableScrolling() {
+ let overflow = document.documentElement.style.overflow;
+ let paddingRight = document.documentElement.style.paddingRight;
+ let scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
+ document.documentElement.style.overflow = "hidden";
+ document.documentElement.style.paddingRight = `${scrollbarWidth}px`;
+ return () => {
+ document.documentElement.style.overflow = overflow;
+ document.documentElement.style.paddingRight = paddingRight;
+ };
+}
+
+// packages/focus/builds/module.js
+var module_default = src_default;
diff --git a/alpinejs/packages/focus/dist/module.esm.js b/alpinejs/packages/focus/dist/module.esm.js
new file mode 100644
index 0000000..343b920
--- /dev/null
+++ b/alpinejs/packages/focus/dist/module.esm.js
@@ -0,0 +1,872 @@
+var __create = Object.create;
+var __defProp = Object.defineProperty;
+var __getProtoOf = Object.getPrototypeOf;
+var __hasOwnProp = Object.prototype.hasOwnProperty;
+var __getOwnPropNames = Object.getOwnPropertyNames;
+var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
+var __markAsModule = (target) => __defProp(target, "__esModule", {value: true});
+var __commonJS = (callback, module) => () => {
+ if (!module) {
+ module = {exports: {}};
+ callback(module.exports, module);
+ }
+ return module.exports;
+};
+var __exportStar = (target, module, desc) => {
+ if (module && typeof module === "object" || typeof module === "function") {
+ for (let key of __getOwnPropNames(module))
+ if (!__hasOwnProp.call(target, key) && key !== "default")
+ __defProp(target, key, {get: () => module[key], enumerable: !(desc = __getOwnPropDesc(module, key)) || desc.enumerable});
+ }
+ return target;
+};
+var __toModule = (module) => {
+ return __exportStar(__markAsModule(__defProp(module != null ? __create(__getProtoOf(module)) : {}, "default", module && module.__esModule && "default" in module ? {get: () => module.default, enumerable: true} : {value: module, enumerable: true})), module);
+};
+
+// node_modules/tabbable/dist/index.js
+var require_dist = __commonJS((exports) => {
+ /*!
+ * tabbable 5.2.1
+ * @license MIT, https://github.com/focus-trap/tabbable/blob/master/LICENSE
+ */
+ "use strict";
+ Object.defineProperty(exports, "__esModule", {value: true});
+ var candidateSelectors = ["input", "select", "textarea", "a[href]", "button", "[tabindex]", "audio[controls]", "video[controls]", '[contenteditable]:not([contenteditable="false"])', "details>summary:first-of-type", "details"];
+ var candidateSelector = /* @__PURE__ */ candidateSelectors.join(",");
+ var matches = typeof Element === "undefined" ? function() {
+ } : Element.prototype.matches || Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
+ var getCandidates = function getCandidates2(el, includeContainer, filter) {
+ var candidates = Array.prototype.slice.apply(el.querySelectorAll(candidateSelector));
+ if (includeContainer && matches.call(el, candidateSelector)) {
+ candidates.unshift(el);
+ }
+ candidates = candidates.filter(filter);
+ return candidates;
+ };
+ var isContentEditable = function isContentEditable2(node) {
+ return node.contentEditable === "true";
+ };
+ var getTabindex = function getTabindex2(node) {
+ var tabindexAttr = parseInt(node.getAttribute("tabindex"), 10);
+ if (!isNaN(tabindexAttr)) {
+ return tabindexAttr;
+ }
+ if (isContentEditable(node)) {
+ return 0;
+ }
+ if ((node.nodeName === "AUDIO" || node.nodeName === "VIDEO" || node.nodeName === "DETAILS") && node.getAttribute("tabindex") === null) {
+ return 0;
+ }
+ return node.tabIndex;
+ };
+ var sortOrderedTabbables = function sortOrderedTabbables2(a, b) {
+ return a.tabIndex === b.tabIndex ? a.documentOrder - b.documentOrder : a.tabIndex - b.tabIndex;
+ };
+ var isInput = function isInput2(node) {
+ return node.tagName === "INPUT";
+ };
+ var isHiddenInput = function isHiddenInput2(node) {
+ return isInput(node) && node.type === "hidden";
+ };
+ var isDetailsWithSummary = function isDetailsWithSummary2(node) {
+ var r = node.tagName === "DETAILS" && Array.prototype.slice.apply(node.children).some(function(child) {
+ return child.tagName === "SUMMARY";
+ });
+ return r;
+ };
+ var getCheckedRadio = function getCheckedRadio2(nodes, form) {
+ for (var i = 0; i < nodes.length; i++) {
+ if (nodes[i].checked && nodes[i].form === form) {
+ return nodes[i];
+ }
+ }
+ };
+ var isTabbableRadio = function isTabbableRadio2(node) {
+ if (!node.name) {
+ return true;
+ }
+ var radioScope = node.form || node.ownerDocument;
+ var queryRadios = function queryRadios2(name) {
+ return radioScope.querySelectorAll('input[type="radio"][name="' + name + '"]');
+ };
+ var radioSet;
+ if (typeof window !== "undefined" && typeof window.CSS !== "undefined" && typeof window.CSS.escape === "function") {
+ radioSet = queryRadios(window.CSS.escape(node.name));
+ } else {
+ try {
+ radioSet = queryRadios(node.name);
+ } catch (err) {
+ console.error("Looks like you have a radio button with a name attribute containing invalid CSS selector characters and need the CSS.escape polyfill: %s", err.message);
+ return false;
+ }
+ }
+ var checked = getCheckedRadio(radioSet, node.form);
+ return !checked || checked === node;
+ };
+ var isRadio = function isRadio2(node) {
+ return isInput(node) && node.type === "radio";
+ };
+ var isNonTabbableRadio = function isNonTabbableRadio2(node) {
+ return isRadio(node) && !isTabbableRadio(node);
+ };
+ var isHidden = function isHidden2(node, displayCheck) {
+ if (getComputedStyle(node).visibility === "hidden") {
+ return true;
+ }
+ var isDirectSummary = matches.call(node, "details>summary:first-of-type");
+ var nodeUnderDetails = isDirectSummary ? node.parentElement : node;
+ if (matches.call(nodeUnderDetails, "details:not([open]) *")) {
+ return true;
+ }
+ if (!displayCheck || displayCheck === "full") {
+ while (node) {
+ if (getComputedStyle(node).display === "none") {
+ return true;
+ }
+ node = node.parentElement;
+ }
+ } else if (displayCheck === "non-zero-area") {
+ var _node$getBoundingClie = node.getBoundingClientRect(), width = _node$getBoundingClie.width, height = _node$getBoundingClie.height;
+ return width === 0 && height === 0;
+ }
+ return false;
+ };
+ var isDisabledFromFieldset = function isDisabledFromFieldset2(node) {
+ if (isInput(node) || node.tagName === "SELECT" || node.tagName === "TEXTAREA" || node.tagName === "BUTTON") {
+ var parentNode = node.parentElement;
+ while (parentNode) {
+ if (parentNode.tagName === "FIELDSET" && parentNode.disabled) {
+ for (var i = 0; i < parentNode.children.length; i++) {
+ var child = parentNode.children.item(i);
+ if (child.tagName === "LEGEND") {
+ if (child.contains(node)) {
+ return false;
+ }
+ return true;
+ }
+ }
+ return true;
+ }
+ parentNode = parentNode.parentElement;
+ }
+ }
+ return false;
+ };
+ var isNodeMatchingSelectorFocusable = function isNodeMatchingSelectorFocusable2(options, node) {
+ if (node.disabled || isHiddenInput(node) || isHidden(node, options.displayCheck) || isDetailsWithSummary(node) || isDisabledFromFieldset(node)) {
+ return false;
+ }
+ return true;
+ };
+ var isNodeMatchingSelectorTabbable = function isNodeMatchingSelectorTabbable2(options, node) {
+ if (!isNodeMatchingSelectorFocusable(options, node) || isNonTabbableRadio(node) || getTabindex(node) < 0) {
+ return false;
+ }
+ return true;
+ };
+ var tabbable2 = function tabbable3(el, options) {
+ options = options || {};
+ var regularTabbables = [];
+ var orderedTabbables = [];
+ var candidates = getCandidates(el, options.includeContainer, isNodeMatchingSelectorTabbable.bind(null, options));
+ candidates.forEach(function(candidate, i) {
+ var candidateTabindex = getTabindex(candidate);
+ if (candidateTabindex === 0) {
+ regularTabbables.push(candidate);
+ } else {
+ orderedTabbables.push({
+ documentOrder: i,
+ tabIndex: candidateTabindex,
+ node: candidate
+ });
+ }
+ });
+ var tabbableNodes = orderedTabbables.sort(sortOrderedTabbables).map(function(a) {
+ return a.node;
+ }).concat(regularTabbables);
+ return tabbableNodes;
+ };
+ var focusable2 = function focusable3(el, options) {
+ options = options || {};
+ var candidates = getCandidates(el, options.includeContainer, isNodeMatchingSelectorFocusable.bind(null, options));
+ return candidates;
+ };
+ var isTabbable = function isTabbable2(node, options) {
+ options = options || {};
+ if (!node) {
+ throw new Error("No node provided");
+ }
+ if (matches.call(node, candidateSelector) === false) {
+ return false;
+ }
+ return isNodeMatchingSelectorTabbable(options, node);
+ };
+ var focusableCandidateSelector = /* @__PURE__ */ candidateSelectors.concat("iframe").join(",");
+ var isFocusable2 = function isFocusable3(node, options) {
+ options = options || {};
+ if (!node) {
+ throw new Error("No node provided");
+ }
+ if (matches.call(node, focusableCandidateSelector) === false) {
+ return false;
+ }
+ return isNodeMatchingSelectorFocusable(options, node);
+ };
+ exports.focusable = focusable2;
+ exports.isFocusable = isFocusable2;
+ exports.isTabbable = isTabbable;
+ exports.tabbable = tabbable2;
+});
+
+// node_modules/focus-trap/dist/focus-trap.js
+var require_focus_trap = __commonJS((exports) => {
+ /*!
+ * focus-trap 6.6.1
+ * @license MIT, https://github.com/focus-trap/focus-trap/blob/master/LICENSE
+ */
+ "use strict";
+ Object.defineProperty(exports, "__esModule", {value: true});
+ var tabbable2 = require_dist();
+ 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;
+ }
+ function _defineProperty(obj, key, value) {
+ if (key in obj) {
+ Object.defineProperty(obj, key, {
+ value,
+ enumerable: true,
+ configurable: true,
+ writable: true
+ });
+ } else {
+ obj[key] = value;
+ }
+ return obj;
+ }
+ var activeFocusTraps = function() {
+ var trapQueue = [];
+ return {
+ activateTrap: function activateTrap(trap) {
+ if (trapQueue.length > 0) {
+ var activeTrap = trapQueue[trapQueue.length - 1];
+ if (activeTrap !== trap) {
+ activeTrap.pause();
+ }
+ }
+ var trapIndex = trapQueue.indexOf(trap);
+ if (trapIndex === -1) {
+ trapQueue.push(trap);
+ } else {
+ trapQueue.splice(trapIndex, 1);
+ trapQueue.push(trap);
+ }
+ },
+ deactivateTrap: function deactivateTrap(trap) {
+ var trapIndex = trapQueue.indexOf(trap);
+ if (trapIndex !== -1) {
+ trapQueue.splice(trapIndex, 1);
+ }
+ if (trapQueue.length > 0) {
+ trapQueue[trapQueue.length - 1].unpause();
+ }
+ }
+ };
+ }();
+ var isSelectableInput = function isSelectableInput2(node) {
+ return node.tagName && node.tagName.toLowerCase() === "input" && typeof node.select === "function";
+ };
+ var isEscapeEvent = function isEscapeEvent2(e) {
+ return e.key === "Escape" || e.key === "Esc" || e.keyCode === 27;
+ };
+ var isTabEvent = function isTabEvent2(e) {
+ return e.key === "Tab" || e.keyCode === 9;
+ };
+ var delay = function delay2(fn) {
+ return setTimeout(fn, 0);
+ };
+ var findIndex = function findIndex2(arr, fn) {
+ var idx = -1;
+ arr.every(function(value, i) {
+ if (fn(value)) {
+ idx = i;
+ return false;
+ }
+ return true;
+ });
+ return idx;
+ };
+ var valueOrHandler = function valueOrHandler2(value) {
+ for (var _len = arguments.length, params = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
+ params[_key - 1] = arguments[_key];
+ }
+ return typeof value === "function" ? value.apply(void 0, params) : value;
+ };
+ var createFocusTrap2 = function createFocusTrap3(elements, userOptions) {
+ var doc = document;
+ var config = _objectSpread2({
+ returnFocusOnDeactivate: true,
+ escapeDeactivates: true,
+ delayInitialFocus: true
+ }, userOptions);
+ var state = {
+ containers: [],
+ tabbableGroups: [],
+ nodeFocusedBeforeActivation: null,
+ mostRecentlyFocusedNode: null,
+ active: false,
+ paused: false,
+ delayInitialFocusTimer: void 0
+ };
+ var trap;
+ var getOption = function getOption2(configOverrideOptions, optionName, configOptionName) {
+ return configOverrideOptions && configOverrideOptions[optionName] !== void 0 ? configOverrideOptions[optionName] : config[configOptionName || optionName];
+ };
+ var containersContain = function containersContain2(element) {
+ return state.containers.some(function(container) {
+ return container.contains(element);
+ });
+ };
+ var getNodeForOption = function getNodeForOption2(optionName) {
+ var optionValue = config[optionName];
+ if (!optionValue) {
+ return null;
+ }
+ var node = optionValue;
+ if (typeof optionValue === "string") {
+ node = doc.querySelector(optionValue);
+ if (!node) {
+ throw new Error("`".concat(optionName, "` refers to no known node"));
+ }
+ }
+ if (typeof optionValue === "function") {
+ node = optionValue();
+ if (!node) {
+ throw new Error("`".concat(optionName, "` did not return a node"));
+ }
+ }
+ return node;
+ };
+ var getInitialFocusNode = function getInitialFocusNode2() {
+ var node;
+ if (getOption({}, "initialFocus") === false) {
+ return false;
+ }
+ if (getNodeForOption("initialFocus") !== null) {
+ node = getNodeForOption("initialFocus");
+ } else if (containersContain(doc.activeElement)) {
+ node = doc.activeElement;
+ } else {
+ var firstTabbableGroup = state.tabbableGroups[0];
+ var firstTabbableNode = firstTabbableGroup && firstTabbableGroup.firstTabbableNode;
+ node = firstTabbableNode || getNodeForOption("fallbackFocus");
+ }
+ if (!node) {
+ throw new Error("Your focus-trap needs to have at least one focusable element");
+ }
+ return node;
+ };
+ var updateTabbableNodes = function updateTabbableNodes2() {
+ state.tabbableGroups = state.containers.map(function(container) {
+ var tabbableNodes = tabbable2.tabbable(container);
+ if (tabbableNodes.length > 0) {
+ return {
+ container,
+ firstTabbableNode: tabbableNodes[0],
+ lastTabbableNode: tabbableNodes[tabbableNodes.length - 1]
+ };
+ }
+ return void 0;
+ }).filter(function(group) {
+ return !!group;
+ });
+ if (state.tabbableGroups.length <= 0 && !getNodeForOption("fallbackFocus")) {
+ throw new Error("Your focus-trap must have at least one container with at least one tabbable node in it at all times");
+ }
+ };
+ var tryFocus = function tryFocus2(node) {
+ if (node === false) {
+ return;
+ }
+ if (node === doc.activeElement) {
+ return;
+ }
+ if (!node || !node.focus) {
+ tryFocus2(getInitialFocusNode());
+ return;
+ }
+ node.focus({
+ preventScroll: !!config.preventScroll
+ });
+ state.mostRecentlyFocusedNode = node;
+ if (isSelectableInput(node)) {
+ node.select();
+ }
+ };
+ var getReturnFocusNode = function getReturnFocusNode2(previousActiveElement) {
+ var node = getNodeForOption("setReturnFocus");
+ return node ? node : previousActiveElement;
+ };
+ var checkPointerDown = function checkPointerDown2(e) {
+ if (containersContain(e.target)) {
+ return;
+ }
+ if (valueOrHandler(config.clickOutsideDeactivates, e)) {
+ trap.deactivate({
+ returnFocus: config.returnFocusOnDeactivate && !tabbable2.isFocusable(e.target)
+ });
+ return;
+ }
+ if (valueOrHandler(config.allowOutsideClick, e)) {
+ return;
+ }
+ e.preventDefault();
+ };
+ var checkFocusIn = function checkFocusIn2(e) {
+ var targetContained = containersContain(e.target);
+ if (targetContained || e.target instanceof Document) {
+ if (targetContained) {
+ state.mostRecentlyFocusedNode = e.target;
+ }
+ } else {
+ e.stopImmediatePropagation();
+ tryFocus(state.mostRecentlyFocusedNode || getInitialFocusNode());
+ }
+ };
+ var checkTab = function checkTab2(e) {
+ updateTabbableNodes();
+ var destinationNode = null;
+ if (state.tabbableGroups.length > 0) {
+ var containerIndex = findIndex(state.tabbableGroups, function(_ref) {
+ var container = _ref.container;
+ return container.contains(e.target);
+ });
+ if (containerIndex < 0) {
+ if (e.shiftKey) {
+ destinationNode = state.tabbableGroups[state.tabbableGroups.length - 1].lastTabbableNode;
+ } else {
+ destinationNode = state.tabbableGroups[0].firstTabbableNode;
+ }
+ } else if (e.shiftKey) {
+ var startOfGroupIndex = findIndex(state.tabbableGroups, function(_ref2) {
+ var firstTabbableNode = _ref2.firstTabbableNode;
+ return e.target === firstTabbableNode;
+ });
+ if (startOfGroupIndex < 0 && state.tabbableGroups[containerIndex].container === e.target) {
+ startOfGroupIndex = containerIndex;
+ }
+ if (startOfGroupIndex >= 0) {
+ var destinationGroupIndex = startOfGroupIndex === 0 ? state.tabbableGroups.length - 1 : startOfGroupIndex - 1;
+ var destinationGroup = state.tabbableGroups[destinationGroupIndex];
+ destinationNode = destinationGroup.lastTabbableNode;
+ }
+ } else {
+ var lastOfGroupIndex = findIndex(state.tabbableGroups, function(_ref3) {
+ var lastTabbableNode = _ref3.lastTabbableNode;
+ return e.target === lastTabbableNode;
+ });
+ if (lastOfGroupIndex < 0 && state.tabbableGroups[containerIndex].container === e.target) {
+ lastOfGroupIndex = containerIndex;
+ }
+ if (lastOfGroupIndex >= 0) {
+ var _destinationGroupIndex = lastOfGroupIndex === state.tabbableGroups.length - 1 ? 0 : lastOfGroupIndex + 1;
+ var _destinationGroup = state.tabbableGroups[_destinationGroupIndex];
+ destinationNode = _destinationGroup.firstTabbableNode;
+ }
+ }
+ } else {
+ destinationNode = getNodeForOption("fallbackFocus");
+ }
+ if (destinationNode) {
+ e.preventDefault();
+ tryFocus(destinationNode);
+ }
+ };
+ var checkKey = function checkKey2(e) {
+ if (isEscapeEvent(e) && valueOrHandler(config.escapeDeactivates) !== false) {
+ e.preventDefault();
+ trap.deactivate();
+ return;
+ }
+ if (isTabEvent(e)) {
+ checkTab(e);
+ return;
+ }
+ };
+ var checkClick = function checkClick2(e) {
+ if (valueOrHandler(config.clickOutsideDeactivates, e)) {
+ return;
+ }
+ if (containersContain(e.target)) {
+ return;
+ }
+ if (valueOrHandler(config.allowOutsideClick, e)) {
+ return;
+ }
+ e.preventDefault();
+ e.stopImmediatePropagation();
+ };
+ var addListeners = function addListeners2() {
+ if (!state.active) {
+ return;
+ }
+ activeFocusTraps.activateTrap(trap);
+ state.delayInitialFocusTimer = config.delayInitialFocus ? delay(function() {
+ tryFocus(getInitialFocusNode());
+ }) : tryFocus(getInitialFocusNode());
+ doc.addEventListener("focusin", checkFocusIn, true);
+ doc.addEventListener("mousedown", checkPointerDown, {
+ capture: true,
+ passive: false
+ });
+ doc.addEventListener("touchstart", checkPointerDown, {
+ capture: true,
+ passive: false
+ });
+ doc.addEventListener("click", checkClick, {
+ capture: true,
+ passive: false
+ });
+ doc.addEventListener("keydown", checkKey, {
+ capture: true,
+ passive: false
+ });
+ return trap;
+ };
+ var removeListeners = function removeListeners2() {
+ if (!state.active) {
+ return;
+ }
+ doc.removeEventListener("focusin", checkFocusIn, true);
+ doc.removeEventListener("mousedown", checkPointerDown, true);
+ doc.removeEventListener("touchstart", checkPointerDown, true);
+ doc.removeEventListener("click", checkClick, true);
+ doc.removeEventListener("keydown", checkKey, true);
+ return trap;
+ };
+ trap = {
+ activate: function activate(activateOptions) {
+ if (state.active) {
+ return this;
+ }
+ var onActivate = getOption(activateOptions, "onActivate");
+ var onPostActivate = getOption(activateOptions, "onPostActivate");
+ var checkCanFocusTrap = getOption(activateOptions, "checkCanFocusTrap");
+ if (!checkCanFocusTrap) {
+ updateTabbableNodes();
+ }
+ state.active = true;
+ state.paused = false;
+ state.nodeFocusedBeforeActivation = doc.activeElement;
+ if (onActivate) {
+ onActivate();
+ }
+ var finishActivation = function finishActivation2() {
+ if (checkCanFocusTrap) {
+ updateTabbableNodes();
+ }
+ addListeners();
+ if (onPostActivate) {
+ onPostActivate();
+ }
+ };
+ if (checkCanFocusTrap) {
+ checkCanFocusTrap(state.containers.concat()).then(finishActivation, finishActivation);
+ return this;
+ }
+ finishActivation();
+ return this;
+ },
+ deactivate: function deactivate(deactivateOptions) {
+ if (!state.active) {
+ return this;
+ }
+ clearTimeout(state.delayInitialFocusTimer);
+ state.delayInitialFocusTimer = void 0;
+ removeListeners();
+ state.active = false;
+ state.paused = false;
+ activeFocusTraps.deactivateTrap(trap);
+ var onDeactivate = getOption(deactivateOptions, "onDeactivate");
+ var onPostDeactivate = getOption(deactivateOptions, "onPostDeactivate");
+ var checkCanReturnFocus = getOption(deactivateOptions, "checkCanReturnFocus");
+ if (onDeactivate) {
+ onDeactivate();
+ }
+ var returnFocus = getOption(deactivateOptions, "returnFocus", "returnFocusOnDeactivate");
+ var finishDeactivation = function finishDeactivation2() {
+ delay(function() {
+ if (returnFocus) {
+ tryFocus(getReturnFocusNode(state.nodeFocusedBeforeActivation));
+ }
+ if (onPostDeactivate) {
+ onPostDeactivate();
+ }
+ });
+ };
+ if (returnFocus && checkCanReturnFocus) {
+ checkCanReturnFocus(getReturnFocusNode(state.nodeFocusedBeforeActivation)).then(finishDeactivation, finishDeactivation);
+ return this;
+ }
+ finishDeactivation();
+ return this;
+ },
+ pause: function pause() {
+ if (state.paused || !state.active) {
+ return this;
+ }
+ state.paused = true;
+ removeListeners();
+ return this;
+ },
+ unpause: function unpause() {
+ if (!state.paused || !state.active) {
+ return this;
+ }
+ state.paused = false;
+ updateTabbableNodes();
+ addListeners();
+ return this;
+ },
+ updateContainerElements: function updateContainerElements(containerElements) {
+ var elementsAsArray = [].concat(containerElements).filter(Boolean);
+ state.containers = elementsAsArray.map(function(element) {
+ return typeof element === "string" ? doc.querySelector(element) : element;
+ });
+ if (state.active) {
+ updateTabbableNodes();
+ }
+ return this;
+ }
+ };
+ trap.updateContainerElements(elements);
+ return trap;
+ };
+ exports.createFocusTrap = createFocusTrap2;
+});
+
+// packages/focus/src/index.js
+var import_focus_trap = __toModule(require_focus_trap());
+var import_tabbable = __toModule(require_dist());
+function src_default(Alpine) {
+ let lastFocused;
+ let currentFocused;
+ window.addEventListener("focusin", () => {
+ lastFocused = currentFocused;
+ currentFocused = document.activeElement;
+ });
+ Alpine.magic("focus", (el) => {
+ let within = el;
+ return {
+ __noscroll: false,
+ __wrapAround: false,
+ within(el2) {
+ within = el2;
+ return this;
+ },
+ withoutScrolling() {
+ this.__noscroll = true;
+ return this;
+ },
+ noscroll() {
+ this.__noscroll = true;
+ return this;
+ },
+ withWrapAround() {
+ this.__wrapAround = true;
+ return this;
+ },
+ wrap() {
+ return this.withWrapAround();
+ },
+ focusable(el2) {
+ return (0, import_tabbable.isFocusable)(el2);
+ },
+ previouslyFocused() {
+ return lastFocused;
+ },
+ lastFocused() {
+ return lastFocused;
+ },
+ focused() {
+ return currentFocused;
+ },
+ focusables() {
+ if (Array.isArray(within))
+ return within;
+ return (0, import_tabbable.focusable)(within, {displayCheck: "none"});
+ },
+ all() {
+ return this.focusables();
+ },
+ isFirst(el2) {
+ let els = this.all();
+ return els[0] && els[0].isSameNode(el2);
+ },
+ isLast(el2) {
+ let els = this.all();
+ return els.length && els.slice(-1)[0].isSameNode(el2);
+ },
+ getFirst() {
+ return this.all()[0];
+ },
+ getLast() {
+ return this.all().slice(-1)[0];
+ },
+ getNext() {
+ let list = this.all();
+ let current = document.activeElement;
+ if (list.indexOf(current) === -1)
+ return;
+ if (this.__wrapAround && list.indexOf(current) === list.length - 1) {
+ return list[0];
+ }
+ return list[list.indexOf(current) + 1];
+ },
+ getPrevious() {
+ let list = this.all();
+ let current = document.activeElement;
+ if (list.indexOf(current) === -1)
+ return;
+ if (this.__wrapAround && list.indexOf(current) === 0) {
+ return list.slice(-1)[0];
+ }
+ return list[list.indexOf(current) - 1];
+ },
+ first() {
+ this.focus(this.getFirst());
+ },
+ last() {
+ this.focus(this.getLast());
+ },
+ next() {
+ this.focus(this.getNext());
+ },
+ previous() {
+ this.focus(this.getPrevious());
+ },
+ prev() {
+ return this.previous();
+ },
+ focus(el2) {
+ if (!el2)
+ return;
+ setTimeout(() => {
+ if (!el2.hasAttribute("tabindex"))
+ el2.setAttribute("tabindex", "0");
+ el2.focus({preventScroll: this._noscroll});
+ });
+ }
+ };
+ });
+ Alpine.directive("trap", Alpine.skipDuringClone((el, {expression, modifiers}, {effect, evaluateLater, cleanup}) => {
+ let evaluator = evaluateLater(expression);
+ let oldValue = false;
+ let trap = (0, import_focus_trap.createFocusTrap)(el, {
+ escapeDeactivates: false,
+ allowOutsideClick: true,
+ fallbackFocus: () => el
+ });
+ let undoInert = () => {
+ };
+ let undoDisableScrolling = () => {
+ };
+ const releaseFocus = () => {
+ undoInert();
+ undoInert = () => {
+ };
+ undoDisableScrolling();
+ undoDisableScrolling = () => {
+ };
+ trap.deactivate({
+ returnFocus: !modifiers.includes("noreturn")
+ });
+ };
+ effect(() => evaluator((value) => {
+ if (oldValue === value)
+ return;
+ if (value && !oldValue) {
+ setTimeout(() => {
+ if (modifiers.includes("inert"))
+ undoInert = setInert(el);
+ if (modifiers.includes("noscroll"))
+ undoDisableScrolling = disableScrolling();
+ trap.activate();
+ });
+ }
+ if (!value && oldValue) {
+ releaseFocus();
+ }
+ oldValue = !!value;
+ }));
+ cleanup(releaseFocus);
+ }, (el, {expression, modifiers}, {evaluate}) => {
+ if (modifiers.includes("inert") && evaluate(expression))
+ setInert(el);
+ }));
+}
+function setInert(el) {
+ let undos = [];
+ crawlSiblingsUp(el, (sibling) => {
+ let cache = sibling.hasAttribute("aria-hidden");
+ sibling.setAttribute("aria-hidden", "true");
+ undos.push(() => cache || sibling.removeAttribute("aria-hidden"));
+ });
+ return () => {
+ while (undos.length)
+ undos.pop()();
+ };
+}
+function crawlSiblingsUp(el, callback) {
+ if (el.isSameNode(document.body) || !el.parentNode)
+ return;
+ Array.from(el.parentNode.children).forEach((sibling) => {
+ if (!sibling.isSameNode(el))
+ callback(sibling);
+ crawlSiblingsUp(el.parentNode, callback);
+ });
+}
+function disableScrolling() {
+ let overflow = document.documentElement.style.overflow;
+ let paddingRight = document.documentElement.style.paddingRight;
+ let scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
+ document.documentElement.style.overflow = "hidden";
+ document.documentElement.style.paddingRight = `${scrollbarWidth}px`;
+ return () => {
+ document.documentElement.style.overflow = overflow;
+ document.documentElement.style.paddingRight = paddingRight;
+ };
+}
+
+// packages/focus/builds/module.js
+var module_default = src_default;
+export {
+ module_default as default
+};
diff --git a/alpinejs/packages/focus/package.json b/alpinejs/packages/focus/package.json
new file mode 100644
index 0000000..8ca4f91
--- /dev/null
+++ b/alpinejs/packages/focus/package.json
@@ -0,0 +1,13 @@
+{
+ "name": "@alpinejs/focus",
+ "version": "3.9.1",
+ "description": "Manage focus within a page",
+ "author": "Caleb Porzio",
+ "license": "MIT",
+ "main": "dist/module.cjs.js",
+ "module": "dist/module.esm.js",
+ "unpkg": "dist/cdn.min.js",
+ "dependencies": {
+ "focus-trap": "^6.6.1"
+ }
+}
diff --git a/alpinejs/packages/focus/src/index.js b/alpinejs/packages/focus/src/index.js
new file mode 100644
index 0000000..240c1b9
--- /dev/null
+++ b/alpinejs/packages/focus/src/index.js
@@ -0,0 +1,197 @@
+import { createFocusTrap } from 'focus-trap'
+import { focusable, tabbable, isFocusable } from 'tabbable'
+
+export default function (Alpine) {
+ let lastFocused
+ let currentFocused
+
+ window.addEventListener('focusin', () => {
+ lastFocused = currentFocused
+ currentFocused = document.activeElement
+ })
+
+ Alpine.magic('focus', el => {
+ let within = el
+
+ return {
+ __noscroll: false,
+ __wrapAround: false,
+ within(el) { within = el; return this },
+ withoutScrolling() { this.__noscroll = true; return this },
+ noscroll() { this.__noscroll = true; return this },
+ withWrapAround() { this.__wrapAround = true; return this },
+ wrap() { return this.withWrapAround() },
+ focusable(el) {
+ return isFocusable(el)
+ },
+ previouslyFocused() {
+ return lastFocused
+ },
+ lastFocused() {
+ return lastFocused
+ },
+ focused() {
+ return currentFocused
+ },
+ focusables() {
+ if (Array.isArray(within)) return within
+
+ return focusable(within, { displayCheck: 'none' })
+ },
+ all() { return this.focusables() },
+ isFirst(el) {
+ let els = this.all()
+
+ return els[0] && els[0].isSameNode(el)
+ },
+ isLast(el) {
+ let els = this.all()
+
+ return els.length && els.slice(-1)[0].isSameNode(el)
+ },
+ getFirst() { return this.all()[0] },
+ getLast() { return this.all().slice(-1)[0] },
+ getNext() {
+ let list = this.all()
+ let current = document.activeElement
+
+ // Can't find currently focusable element in list.
+ if (list.indexOf(current) === -1) return
+
+ // This is the last element in the list and we want to wrap around.
+ if (this.__wrapAround && list.indexOf(current) === list.length - 1) {
+ return list[0]
+ }
+
+ return list[list.indexOf(current) + 1]
+ },
+ getPrevious() {
+ let list = this.all()
+ let current = document.activeElement
+
+ // Can't find currently focusable element in list.
+ if (list.indexOf(current) === -1) return
+
+ // This is the first element in the list and we want to wrap around.
+ if (this.__wrapAround && list.indexOf(current) === 0) {
+ return list.slice(-1)[0]
+ }
+
+ return list[list.indexOf(current) - 1]
+ },
+ first() { this.focus(this.getFirst()) },
+ last() { this.focus(this.getLast()) },
+ next() { this.focus(this.getNext()) },
+ previous() { this.focus(this.getPrevious()) },
+ prev() { return this.previous() },
+ focus(el) {
+ if (! el) return
+
+ setTimeout(() => {
+ if (! el.hasAttribute('tabindex')) el.setAttribute('tabindex', '0')
+
+ el.focus({ preventScroll: this._noscroll })
+ })
+ }
+ }
+ })
+
+ Alpine.directive('trap', Alpine.skipDuringClone(
+ (el, { expression, modifiers }, { effect, evaluateLater, cleanup }) => {
+ let evaluator = evaluateLater(expression)
+
+ let oldValue = false
+
+ let trap = createFocusTrap(el, {
+ escapeDeactivates: false,
+ allowOutsideClick: true,
+ fallbackFocus: () => el,
+ })
+
+ let undoInert = () => {}
+ let undoDisableScrolling = () => {}
+
+ const releaseFocus = () => {
+ undoInert()
+ undoInert = () => {}
+
+ undoDisableScrolling()
+ undoDisableScrolling = () => {}
+
+ trap.deactivate({
+ returnFocus: !modifiers.includes('noreturn')
+ })
+ }
+
+ effect(() => evaluator(value => {
+ if (oldValue === value) return
+
+ // Start trapping.
+ if (value && ! oldValue) {
+ setTimeout(() => {
+ if (modifiers.includes('inert')) undoInert = setInert(el)
+ if (modifiers.includes('noscroll')) undoDisableScrolling = disableScrolling()
+
+ trap.activate()
+ });
+ }
+
+ // Stop trapping.
+ if (! value && oldValue) {
+ releaseFocus()
+ }
+
+ oldValue = !! value
+ }))
+
+ cleanup(releaseFocus)
+ },
+ // When cloning, we only want to add aria-hidden attributes to the
+ // DOM and not try to actually trap, as trapping can mess with the
+ // live DOM and isn't just isolated to the cloned DOM.
+ (el, { expression, modifiers }, { evaluate }) => {
+ if (modifiers.includes('inert') && evaluate(expression)) setInert(el)
+ },
+ ))
+}
+
+function setInert(el) {
+ let undos = []
+
+ crawlSiblingsUp(el, (sibling) => {
+ let cache = sibling.hasAttribute('aria-hidden')
+
+ sibling.setAttribute('aria-hidden', 'true')
+
+ undos.push(() => cache || sibling.removeAttribute('aria-hidden'))
+ })
+
+ return () => {
+ while(undos.length) undos.pop()()
+ }
+}
+
+function crawlSiblingsUp(el, callback) {
+ if (el.isSameNode(document.body) || ! el.parentNode) return
+
+ Array.from(el.parentNode.children).forEach(sibling => {
+ if (! sibling.isSameNode(el)) callback(sibling)
+
+ crawlSiblingsUp(el.parentNode, callback)
+ })
+}
+
+function disableScrolling() {
+ let overflow = document.documentElement.style.overflow
+ let paddingRight = document.documentElement.style.paddingRight
+
+ let scrollbarWidth = window.innerWidth - document.documentElement.clientWidth
+
+ document.documentElement.style.overflow = 'hidden'
+ document.documentElement.style.paddingRight = `${scrollbarWidth}px`
+
+ return () => {
+ document.documentElement.style.overflow = overflow
+ document.documentElement.style.paddingRight = paddingRight
+ }
+}
diff --git a/alpinejs/packages/history/builds/cdn.js b/alpinejs/packages/history/builds/cdn.js
new file mode 100644
index 0000000..869edb2
--- /dev/null
+++ b/alpinejs/packages/history/builds/cdn.js
@@ -0,0 +1,5 @@
+import history from '../src/index.js'
+
+document.addEventListener('alpine:init', () => {
+ window.Alpine.plugin(history)
+})
diff --git a/alpinejs/packages/history/builds/module.js b/alpinejs/packages/history/builds/module.js
new file mode 100644
index 0000000..a7d9aba
--- /dev/null
+++ b/alpinejs/packages/history/builds/module.js
@@ -0,0 +1,3 @@
+import history from '../src/index.js'
+
+export default history
diff --git a/alpinejs/packages/history/package.json b/alpinejs/packages/history/package.json
new file mode 100644
index 0000000..08355c2
--- /dev/null
+++ b/alpinejs/packages/history/package.json
@@ -0,0 +1,12 @@
+{
+ "name": "@alpinejs/history",
+ "version": "3.0.0-alpha.0",
+ "description": "Sync Alpine data with the browser's query string",
+ "author": "Caleb Porzio",
+ "license": "MIT",
+ "main": "dist/module.cjs.js",
+ "module": "dist/module.esm.js",
+ "dependencies": {
+ "@vue/reactivity": "^3.0.2"
+ }
+}
diff --git a/alpinejs/packages/history/src/index.js b/alpinejs/packages/history/src/index.js
new file mode 100644
index 0000000..f230d80
--- /dev/null
+++ b/alpinejs/packages/history/src/index.js
@@ -0,0 +1,76 @@
+export default function history(Alpine) {
+ Alpine.magic('queryString', (el, { interceptor }) => {
+ let alias
+
+ return interceptor((initialValue, getter, setter, path, key) => {
+ let pause = false
+ let queryKey = alias || path
+
+ let value = initialValue
+ let url = new URL(window.location.href)
+
+ if (url.searchParams.has(queryKey)) {
+ value = url.searchParams.get(queryKey)
+ }
+
+ setter(value)
+
+ let object = { value }
+
+ url.searchParams.set(queryKey, value)
+
+ replace(url.toString(), path, object)
+
+ window.addEventListener('popstate', (e) => {
+ if (! e.state) return
+ if (! e.state.alpine) return
+
+ Object.entries(e.state.alpine).forEach(([newKey, { value }]) => {
+ if (newKey !== key) return
+
+ pause = true
+
+ Alpine.disableEffectScheduling(() => {
+ setter(value)
+ })
+
+ pause = false
+ })
+ })
+
+ Alpine.effect(() => {
+ let value = getter()
+
+ if (pause) return
+
+ let object = { value }
+
+ let url = new URL(window.location.href)
+
+ url.searchParams.set(queryKey, value)
+
+ push(url.toString(), path, object)
+ })
+
+ return value
+ }, func => {
+ func.as = key => { alias = key; return func }
+ })
+ })
+}
+
+function replace(url, key, object) {
+ let state = window.history.state || {}
+
+ if (! state.alpine) state.alpine = {}
+
+ state.alpine[key] = object
+
+ window.history.replaceState(state, '', url)
+}
+
+function push(url, key, object) {
+ let state = { alpine: {...window.history.state.alpine, ...{[key]: object}} }
+
+ window.history.pushState(state, '', url)
+}
diff --git a/alpinejs/packages/history/src/url.js b/alpinejs/packages/history/src/url.js
new file mode 100644
index 0000000..7e2b4b6
--- /dev/null
+++ b/alpinejs/packages/history/src/url.js
@@ -0,0 +1,36 @@
+
+export function hasQueryParam(param) {
+ let queryParams = new URLSearchParams(window.location.search);
+
+ return queryParams.has(param)
+}
+
+export function getQueryParam(param) {
+ let queryParams = new URLSearchParams(window.location.search);
+
+ return queryParams.get(param)
+}
+
+export function setQueryParam(param, value) {
+ let queryParams = new URLSearchParams(window.location.search);
+
+ queryParams.set(param, value)
+
+ let url = urlFromQueryParams(queryParams)
+
+ history.replaceState(history.state, '', url)
+}
+
+function urlFromParams(params = {}) {
+ let queryParams = new URLSearchParams(window.location.search);
+
+ Object.entries(params).forEach(([key, value]) => {
+ queryParams.set(key, value)
+ })
+
+ let queryString = Array.from(queryParams.entries()).length > 0
+ ? '?'+params.toString()
+ : ''
+
+ return window.location.origin + window.location.pathname + '?'+queryString + window.location.hash
+}
diff --git a/alpinejs/packages/intersect/builds/cdn.js b/alpinejs/packages/intersect/builds/cdn.js
new file mode 100644
index 0000000..11f6360
--- /dev/null
+++ b/alpinejs/packages/intersect/builds/cdn.js
@@ -0,0 +1,5 @@
+import intersect from '../src/index.js'
+
+document.addEventListener('alpine:init', () => {
+ window.Alpine.plugin(intersect)
+})
diff --git a/alpinejs/packages/intersect/builds/module.js b/alpinejs/packages/intersect/builds/module.js
new file mode 100644
index 0000000..e33db04
--- /dev/null
+++ b/alpinejs/packages/intersect/builds/module.js
@@ -0,0 +1,3 @@
+import intersect from './../src/index.js'
+
+export default intersect
diff --git a/alpinejs/packages/intersect/dist/cdn.js b/alpinejs/packages/intersect/dist/cdn.js
index ddf68bb..ed524d5 100644
--- a/alpinejs/packages/intersect/dist/cdn.js
+++ b/alpinejs/packages/intersect/dist/cdn.js
@@ -4,11 +4,12 @@
Alpine.directive("intersect", (el, {value, expression, modifiers}, {evaluateLater, cleanup}) => {
let evaluate = evaluateLater(expression);
let options = {
+ rootMargin: getRootMargin(modifiers),
threshold: getThreshhold(modifiers)
};
let observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
- if (!entry.isIntersecting && value === "enter" || entry.isIntersecting && value === "leave" || entry.intersectionRatio === 0 && !value)
+ if (entry.isIntersecting === (value === "leave"))
return;
evaluate();
modifiers.includes("once") && observer.disconnect();
@@ -27,6 +28,23 @@
return 0.5;
return 0;
}
+ function getLengthValue(rawValue) {
+ let match = rawValue.match(/^(-?[0-9]+)(px|%)?$/);
+ return match ? match[1] + (match[2] || "px") : void 0;
+ }
+ function getRootMargin(modifiers) {
+ const key = "margin";
+ const fallback = "0px 0px 0px 0px";
+ const index = modifiers.indexOf(key);
+ if (index === -1)
+ return fallback;
+ let values = [];
+ for (let i = 1; i < 5; i++) {
+ values.push(getLengthValue(modifiers[index + i] || ""));
+ }
+ values = values.filter((v) => v !== void 0);
+ return values.length ? values.join(" ").trim() : fallback;
+ }
// packages/intersect/builds/cdn.js
document.addEventListener("alpine:init", () => {
diff --git a/alpinejs/packages/intersect/dist/cdn.min.js b/alpinejs/packages/intersect/dist/cdn.min.js
index 6adbb58..f8b0554 100644
--- a/alpinejs/packages/intersect/dist/cdn.min.js
+++ b/alpinejs/packages/intersect/dist/cdn.min.js
@@ -1 +1 @@
-(()=>{function c(e){e.directive("intersect",(s,{value:n,expression:o,modifiers:r},{evaluateLater:l,cleanup:d})=>{let u=l(o),f={threshold:h(r)},t=new IntersectionObserver(a=>{a.forEach(i=>{!i.isIntersecting&&n==="enter"||i.isIntersecting&&n==="leave"||i.intersectionRatio===0&&!n||(u(),r.includes("once")&&t.disconnect())})},f);t.observe(s),d(()=>{t.disconnect()})})}function h(e){return e.includes("full")?.99:e.includes("half")?.5:0}document.addEventListener("alpine:init",()=>{window.Alpine.plugin(c)});})();
+(()=>{function l(e){e.directive("intersect",(t,{value:i,expression:o,modifiers:n},{evaluateLater:r,cleanup:u})=>{let s=r(o),a={rootMargin:h(n),threshold:p(n)},c=new IntersectionObserver(d=>{d.forEach(f=>{f.isIntersecting!==(i==="leave")&&(s(),n.includes("once")&&c.disconnect())})},a);c.observe(t),u(()=>{c.disconnect()})})}function p(e){return e.includes("full")?.99:e.includes("half")?.5:0}function x(e){let t=e.match(/^(-?[0-9]+)(px|%)?$/);return t?t[1]+(t[2]||"px"):void 0}function h(e){let t="margin",i="0px 0px 0px 0px",o=e.indexOf(t);if(o===-1)return i;let n=[];for(let r=1;r<5;r++)n.push(x(e[o+r]||""));return n=n.filter(r=>r!==void 0),n.length?n.join(" ").trim():i}document.addEventListener("alpine:init",()=>{window.Alpine.plugin(l)});})();
diff --git a/alpinejs/packages/intersect/dist/module.cjs.js b/alpinejs/packages/intersect/dist/module.cjs.js
index e136fa2..737d082 100644
--- a/alpinejs/packages/intersect/dist/module.cjs.js
+++ b/alpinejs/packages/intersect/dist/module.cjs.js
@@ -16,11 +16,12 @@ function src_default(Alpine) {
Alpine.directive("intersect", (el, {value, expression, modifiers}, {evaluateLater, cleanup}) => {
let evaluate = evaluateLater(expression);
let options = {
+ rootMargin: getRootMargin(modifiers),
threshold: getThreshhold(modifiers)
};
let observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
- if (!entry.isIntersecting && value === "enter" || entry.isIntersecting && value === "leave" || entry.intersectionRatio === 0 && !value)
+ if (entry.isIntersecting === (value === "leave"))
return;
evaluate();
modifiers.includes("once") && observer.disconnect();
@@ -39,6 +40,23 @@ function getThreshhold(modifiers) {
return 0.5;
return 0;
}
+function getLengthValue(rawValue) {
+ let match = rawValue.match(/^(-?[0-9]+)(px|%)?$/);
+ return match ? match[1] + (match[2] || "px") : void 0;
+}
+function getRootMargin(modifiers) {
+ const key = "margin";
+ const fallback = "0px 0px 0px 0px";
+ const index = modifiers.indexOf(key);
+ if (index === -1)
+ return fallback;
+ let values = [];
+ for (let i = 1; i < 5; i++) {
+ values.push(getLengthValue(modifiers[index + i] || ""));
+ }
+ values = values.filter((v) => v !== void 0);
+ return values.length ? values.join(" ").trim() : fallback;
+}
// packages/intersect/builds/module.js
var module_default = src_default;
diff --git a/alpinejs/packages/intersect/dist/module.esm.js b/alpinejs/packages/intersect/dist/module.esm.js
index 84aa068..d89a47c 100644
--- a/alpinejs/packages/intersect/dist/module.esm.js
+++ b/alpinejs/packages/intersect/dist/module.esm.js
@@ -3,11 +3,12 @@ function src_default(Alpine) {
Alpine.directive("intersect", (el, {value, expression, modifiers}, {evaluateLater, cleanup}) => {
let evaluate = evaluateLater(expression);
let options = {
+ rootMargin: getRootMargin(modifiers),
threshold: getThreshhold(modifiers)
};
let observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
- if (!entry.isIntersecting && value === "enter" || entry.isIntersecting && value === "leave" || entry.intersectionRatio === 0 && !value)
+ if (entry.isIntersecting === (value === "leave"))
return;
evaluate();
modifiers.includes("once") && observer.disconnect();
@@ -26,6 +27,23 @@ function getThreshhold(modifiers) {
return 0.5;
return 0;
}
+function getLengthValue(rawValue) {
+ let match = rawValue.match(/^(-?[0-9]+)(px|%)?$/);
+ return match ? match[1] + (match[2] || "px") : void 0;
+}
+function getRootMargin(modifiers) {
+ const key = "margin";
+ const fallback = "0px 0px 0px 0px";
+ const index = modifiers.indexOf(key);
+ if (index === -1)
+ return fallback;
+ let values = [];
+ for (let i = 1; i < 5; i++) {
+ values.push(getLengthValue(modifiers[index + i] || ""));
+ }
+ values = values.filter((v) => v !== void 0);
+ return values.length ? values.join(" ").trim() : fallback;
+}
// packages/intersect/builds/module.js
var module_default = src_default;
diff --git a/alpinejs/packages/intersect/package.json b/alpinejs/packages/intersect/package.json
new file mode 100644
index 0000000..387a4fb
--- /dev/null
+++ b/alpinejs/packages/intersect/package.json
@@ -0,0 +1,11 @@
+{
+ "name": "@alpinejs/intersect",
+ "version": "3.9.1",
+ "description": "Trigger JavaScript when an element enters the viewport",
+ "author": "Caleb Porzio",
+ "license": "MIT",
+ "main": "dist/module.cjs.js",
+ "module": "dist/module.esm.js",
+ "unpkg": "dist/cdn.min.js",
+ "dependencies": {}
+}
diff --git a/alpinejs/packages/intersect/src/index.js b/alpinejs/packages/intersect/src/index.js
new file mode 100644
index 0000000..bd9b57b
--- /dev/null
+++ b/alpinejs/packages/intersect/src/index.js
@@ -0,0 +1,60 @@
+export default function (Alpine) {
+ Alpine.directive('intersect', (el, { value, expression, modifiers }, { evaluateLater, cleanup }) => {
+ let evaluate = evaluateLater(expression)
+
+ let options = {
+ rootMargin: getRootMargin(modifiers),
+ threshold: getThreshhold(modifiers),
+ }
+
+ let observer = new IntersectionObserver(entries => {
+ entries.forEach(entry => {
+ // Ignore entry if intersecting in leave mode, or not intersecting in enter mode
+ if (entry.isIntersecting === (value === 'leave')) return
+
+ evaluate()
+
+ modifiers.includes('once') && observer.disconnect()
+ })
+ }, options)
+
+ observer.observe(el)
+
+ cleanup(() => {
+ observer.disconnect()
+ })
+ })
+}
+
+function getThreshhold(modifiers) {
+ if (modifiers.includes('full')) return 0.99
+ if (modifiers.includes('half')) return 0.5
+
+ return 0
+}
+
+export function getLengthValue(rawValue) {
+ // Supported: -10px, -20 (implied px), 30 (implied px), 40px, 50%
+ let match = rawValue.match(/^(-?[0-9]+)(px|%)?$/)
+ return match ? match[1] + (match[2] || 'px') : undefined
+}
+
+export function getRootMargin(modifiers) {
+ const key = 'margin'
+ const fallback = '0px 0px 0px 0px'
+ const index = modifiers.indexOf(key)
+
+ // If the modifier isn't present, use the default.
+ if (index === -1) return fallback
+
+ // Grab the 4 subsequent length values after it: x-intersect.margin.300px.0.50%.0
+ let values = []
+ for (let i = 1; i < 5; i++) {
+ values.push(getLengthValue(modifiers[index + i] || ''))
+ }
+
+ // Filter out undefined values (not a valid length)
+ values = values.filter((v) => v !== undefined)
+
+ return values.length ? values.join(' ').trim() : fallback
+}
diff --git a/alpinejs/packages/morph/builds/cdn.js b/alpinejs/packages/morph/builds/cdn.js
new file mode 100644
index 0000000..3f1414c
--- /dev/null
+++ b/alpinejs/packages/morph/builds/cdn.js
@@ -0,0 +1,5 @@
+import morph from '../src/index.js'
+
+document.addEventListener('alpine:init', () => {
+ window.Alpine.plugin(morph)
+})
diff --git a/alpinejs/packages/morph/builds/module.js b/alpinejs/packages/morph/builds/module.js
new file mode 100644
index 0000000..0359ad7
--- /dev/null
+++ b/alpinejs/packages/morph/builds/module.js
@@ -0,0 +1,5 @@
+import morphPlugin, { morph } from '../src/index.js'
+
+export default morphPlugin
+
+export { morph }
diff --git a/alpinejs/packages/morph/dist/cdn.js b/alpinejs/packages/morph/dist/cdn.js
index e023c91..947a47d 100644
--- a/alpinejs/packages/morph/dist/cdn.js
+++ b/alpinejs/packages/morph/dist/cdn.js
@@ -1,10 +1,35 @@
(() => {
// packages/morph/src/morph.js
- function morph(dom, toHtml, options) {
+ var resolveStep = () => {
+ };
+ var logger = () => {
+ };
+ var fromEl;
+ var toEl;
+ function breakpoint(message) {
+ if (!debug)
+ return;
+ logger((message || "").replace("\n", "\\n"), fromEl, toEl);
+ return new Promise((resolve) => resolveStep = () => resolve());
+ }
+ async function morph(from, toHtml, options) {
assignOptions(options);
- patch(dom, createElement(toHtml));
- return dom;
+ fromEl = from;
+ toEl = createElement(toHtml);
+ if (window.Alpine && !from._x_dataStack) {
+ toEl._x_dataStack = window.Alpine.closestDataStack(from);
+ toEl._x_dataStack && window.Alpine.clone(from, toEl);
+ }
+ await breakpoint();
+ await patch(from, toEl);
+ fromEl = void 0;
+ toEl = void 0;
+ return from;
}
+ morph.step = () => resolveStep();
+ morph.log = (theLogger) => {
+ logger = theLogger;
+ };
var key;
var lookahead;
var updating;
@@ -13,91 +38,100 @@
var removed;
var adding;
var added;
+ var debug;
var noop = () => {
};
function assignOptions(options = {}) {
let defaultGetKey = (el) => el.getAttribute("key");
- key = options.key || defaultGetKey;
- lookahead = options.lookahead || false;
updating = options.updating || noop;
updated = options.updated || noop;
removing = options.removing || noop;
removed = options.removed || noop;
adding = options.adding || noop;
added = options.added || noop;
+ key = options.key || defaultGetKey;
+ lookahead = options.lookahead || false;
+ debug = options.debug || false;
}
function createElement(html) {
return document.createRange().createContextualFragment(html).firstElementChild;
}
- function patch(dom, to) {
- if (dom.isEqualNode(to))
- return;
- if (differentElementNamesTypesOrKeys(dom, to)) {
- return patchElement(dom, to);
+ async function patch(from, to) {
+ if (differentElementNamesTypesOrKeys(from, to)) {
+ let result = patchElement(from, to);
+ await breakpoint("Swap elements");
+ return result;
}
let updateChildrenOnly = false;
- if (shouldSkip(updating, dom, to, () => updateChildrenOnly = true))
+ if (shouldSkip(updating, from, to, () => updateChildrenOnly = true))
return;
+ window.Alpine && initializeAlpineOnTo(from, to, () => updateChildrenOnly = true);
if (textOrComment(to)) {
- patchNodeValue(dom, to);
- updated(dom, to);
+ await patchNodeValue(from, to);
+ updated(from, to);
return;
}
if (!updateChildrenOnly) {
- patchAttributes(dom, to);
+ await patchAttributes(from, to);
}
- updated(dom, to);
- patchChildren(dom, to);
+ updated(from, to);
+ await patchChildren(from, to);
}
- function differentElementNamesTypesOrKeys(dom, to) {
- return dom.nodeType != to.nodeType || dom.nodeName != to.nodeName || getKey(dom) != getKey(to);
+ function differentElementNamesTypesOrKeys(from, to) {
+ return from.nodeType != to.nodeType || from.nodeName != to.nodeName || getKey(from) != getKey(to);
}
function textOrComment(el) {
return el.nodeType === 3 || el.nodeType === 8;
}
- function patchElement(dom, to) {
- if (shouldSkip(removing, dom))
+ function patchElement(from, to) {
+ if (shouldSkip(removing, from))
return;
let toCloned = to.cloneNode(true);
if (shouldSkip(adding, toCloned))
return;
- dom.parentNode.replaceChild(toCloned, dom);
- removed(dom);
+ dom(from).replace(toCloned);
+ removed(from);
added(toCloned);
}
- function patchNodeValue(dom, to) {
+ async function patchNodeValue(from, to) {
let value = to.nodeValue;
- if (dom.nodeValue !== value)
- dom.nodeValue = value;
+ if (from.nodeValue !== value) {
+ from.nodeValue = value;
+ await breakpoint("Change text node to: " + value);
+ }
}
- function patchAttributes(dom, to) {
- if (dom._x_isShown && !to._x_isShown) {
+ async function patchAttributes(from, to) {
+ if (from._x_isShown && !to._x_isShown) {
return;
}
- if (!dom._x_isShown && to._x_isShown) {
+ if (!from._x_isShown && to._x_isShown) {
return;
}
- let domAttributes = Array.from(dom.attributes);
+ let domAttributes = Array.from(from.attributes);
let toAttributes = Array.from(to.attributes);
for (let i = domAttributes.length - 1; i >= 0; i--) {
let name = domAttributes[i].name;
- if (!to.hasAttribute(name))
- dom.removeAttribute(name);
+ if (!to.hasAttribute(name)) {
+ from.removeAttribute(name);
+ await breakpoint("Remove attribute");
+ }
}
for (let i = toAttributes.length - 1; i >= 0; i--) {
let name = toAttributes[i].name;
let value = toAttributes[i].value;
- if (dom.getAttribute(name) !== value)
- dom.setAttribute(name, value);
+ if (from.getAttribute(name) !== value) {
+ from.setAttribute(name, value);
+ await breakpoint(`Set [${name}] attribute to: "${value}"`);
+ }
}
}
- function patchChildren(dom, to) {
- let domChildren = dom.childNodes;
+ async function patchChildren(from, to) {
+ let domChildren = from.childNodes;
let toChildren = to.childNodes;
let toKeyToNodeMap = keyToMap(toChildren);
let domKeyDomNodeMap = keyToMap(domChildren);
- let currentTo = to.firstChild;
- let currentFrom = dom.firstChild;
+ let currentTo = dom(to).nodes().first();
+ let currentFrom = dom(from).nodes().first();
let domKeyHoldovers = {};
while (currentTo) {
let toKey = getKey(currentTo);
@@ -105,19 +139,27 @@
if (!currentFrom) {
if (toKey && domKeyHoldovers[toKey]) {
let holdover = domKeyHoldovers[toKey];
- dom.appendChild(holdover);
+ dom(from).append(holdover);
currentFrom = holdover;
+ await breakpoint("Add element (from key)");
} else {
- addNodeTo(currentTo, dom);
- currentTo = currentTo.nextSibling;
+ let added2 = addNodeTo(currentTo, from) || {};
+ await breakpoint("Add element: " + added2.outerHTML || added2.nodeValue);
+ currentTo = dom(currentTo).nodes().next();
continue;
}
}
if (lookahead) {
- let nextToElementSibling = currentTo.nextElementSibling;
- if (nextToElementSibling && currentFrom.isEqualNode(nextToElementSibling)) {
- currentFrom = addNodeBefore(currentTo, currentFrom);
- domKey = getKey(currentFrom);
+ let nextToElementSibling = dom(currentTo).next();
+ let found = false;
+ while (!found && nextToElementSibling) {
+ if (currentFrom.isEqualNode(nextToElementSibling)) {
+ found = true;
+ currentFrom = addNodeBefore(currentTo, currentFrom);
+ domKey = getKey(currentFrom);
+ await breakpoint("Move element (lookahead)");
+ }
+ nextToElementSibling = dom(nextToElementSibling).next();
}
}
if (toKey !== domKey) {
@@ -125,43 +167,49 @@
domKeyHoldovers[domKey] = currentFrom;
currentFrom = addNodeBefore(currentTo, currentFrom);
domKeyHoldovers[domKey].remove();
- currentFrom = currentFrom.nextSibling;
- currentTo = currentTo.nextSibling;
+ currentFrom = dom(currentFrom).nodes().next();
+ currentTo = dom(currentTo).nodes().next();
+ await breakpoint('No "to" key');
continue;
}
if (toKey && !domKey) {
if (domKeyDomNodeMap[toKey]) {
- currentFrom.parentElement.replaceChild(domKeyDomNodeMap[toKey], currentFrom);
- currentFrom = domKeyDomNodeMap[toKey];
+ currentFrom = dom(currentFrom).replace(domKeyDomNodeMap[toKey]);
+ await breakpoint('No "from" key');
}
}
if (toKey && domKey) {
domKeyHoldovers[domKey] = currentFrom;
let domKeyNode = domKeyDomNodeMap[toKey];
if (domKeyNode) {
- currentFrom.parentElement.replaceChild(domKeyNode, currentFrom);
- currentFrom = domKeyNode;
+ currentFrom = dom(currentFrom).replace(domKeyNode);
+ await breakpoint('Move "from" key');
} else {
domKeyHoldovers[domKey] = currentFrom;
currentFrom = addNodeBefore(currentTo, currentFrom);
domKeyHoldovers[domKey].remove();
- currentFrom = currentFrom.nextSibling;
- currentTo = currentTo.nextSibling;
+ currentFrom = dom(currentFrom).next();
+ currentTo = dom(currentTo).next();
+ await breakpoint("I dont even know what this does");
continue;
}
}
}
- patch(currentFrom, currentTo);
- currentTo = currentTo && currentTo.nextSibling;
- currentFrom = currentFrom && currentFrom.nextSibling;
+ await patch(currentFrom, currentTo);
+ currentTo = currentTo && dom(currentTo).nodes().next();
+ currentFrom = currentFrom && dom(currentFrom).nodes().next();
}
+ let removals = [];
while (currentFrom) {
- if (!shouldSkip(removing, currentFrom)) {
- let domForRemoval = currentFrom;
- dom.removeChild(domForRemoval);
- removed(domForRemoval);
- }
- currentFrom = currentFrom.nextSibling;
+ if (!shouldSkip(removing, currentFrom))
+ removals.push(currentFrom);
+ currentFrom = dom(currentFrom).nodes().next();
+ }
+ while (removals.length) {
+ let domForRemoval = removals.pop();
+ domForRemoval.remove();
+ await breakpoint("remove el");
+ removed(domForRemoval);
}
}
function getKey(el) {
@@ -185,31 +233,86 @@
function addNodeTo(node, parent) {
if (!shouldSkip(adding, node)) {
let clone = node.cloneNode(true);
- parent.appendChild(clone);
+ dom(parent).append(clone);
added(clone);
+ return clone;
}
+ return null;
}
function addNodeBefore(node, beforeMe) {
if (!shouldSkip(adding, node)) {
let clone = node.cloneNode(true);
- beforeMe.parentElement.insertBefore(clone, beforeMe);
+ dom(beforeMe).before(clone);
added(clone);
return clone;
}
return beforeMe;
}
+ function initializeAlpineOnTo(from, to, childrenOnly) {
+ if (from.nodeType !== 1)
+ return;
+ if (from._x_dataStack) {
+ window.Alpine.clone(from, to);
+ }
+ }
+ function dom(el) {
+ return new DomManager(el);
+ }
+ var DomManager = class {
+ el = void 0;
+ constructor(el) {
+ this.el = el;
+ }
+ traversals = {
+ first: "firstElementChild",
+ next: "nextElementSibling",
+ parent: "parentElement"
+ };
+ nodes() {
+ this.traversals = {
+ first: "firstChild",
+ next: "nextSibling",
+ parent: "parentNode"
+ };
+ return this;
+ }
+ first() {
+ return this.teleportTo(this.el[this.traversals["first"]]);
+ }
+ next() {
+ return this.teleportTo(this.teleportBack(this.el[this.traversals["next"]]));
+ }
+ before(insertee) {
+ this.el[this.traversals["parent"]].insertBefore(insertee, this.el);
+ return insertee;
+ }
+ replace(replacement) {
+ this.el[this.traversals["parent"]].replaceChild(replacement, this.el);
+ return replacement;
+ }
+ append(appendee) {
+ this.el.appendChild(appendee);
+ return appendee;
+ }
+ teleportTo(el) {
+ if (!el)
+ return el;
+ if (el._x_teleport)
+ return el._x_teleport;
+ return el;
+ }
+ teleportBack(el) {
+ if (!el)
+ return el;
+ if (el._x_teleportBack)
+ return el._x_teleportBack;
+ return el;
+ }
+ };
// packages/morph/src/index.js
function src_default(Alpine) {
- Alpine.directive("morph", (el, {expression}, {effect, evaluateLater}) => {
- let evaluate = evaluateLater(expression);
- effect(() => {
- evaluate((value) => {
- let child = el.firstElementChild || el.firstChild || el.appendChild(document.createTextNode(""));
- morph(child, value);
- });
- });
- });
+ Alpine.morph = morph;
}
// packages/morph/builds/cdn.js
diff --git a/alpinejs/packages/morph/dist/cdn.min.js b/alpinejs/packages/morph/dist/cdn.min.js
index cad56f2..dff89d4 100644
--- a/alpinejs/packages/morph/dist/cdn.min.js
+++ b/alpinejs/packages/morph/dist/cdn.min.js
@@ -1 +1,2 @@
-(()=>{function C(e,t,i){return T(i),b(e,K(t)),e}var N,v,w,g,y,S,m,x,h=()=>{};function T(e={}){let t=i=>i.getAttribute("key");N=e.key||t,v=e.lookahead||!1,w=e.updating||h,g=e.updated||h,y=e.removing||h,S=e.removed||h,m=e.adding||h,x=e.added||h}function K(e){return document.createRange().createContextualFragment(e).firstElementChild}function b(e,t){if(e.isEqualNode(t))return;if(k(e,t))return V(e,t);let i=!1;if(!p(w,e,t,()=>i=!0)){if(O(t)){F(e,t),g(e,t);return}i||q(e,t),g(e,t),B(e,t)}}function k(e,t){return e.nodeType!=t.nodeType||e.nodeName!=t.nodeName||s(e)!=s(t)}function O(e){return e.nodeType===3||e.nodeType===8}function V(e,t){if(p(y,e))return;let i=t.cloneNode(!0);p(m,i)||(e.parentNode.replaceChild(i,e),S(e),x(i))}function F(e,t){let i=t.nodeValue;e.nodeValue!==i&&(e.nodeValue=i)}function q(e,t){if(e._x_isShown&&!t._x_isShown||!e._x_isShown&&t._x_isShown)return;let i=Array.from(e.attributes),o=Array.from(t.attributes);for(let u=i.length-1;u>=0;u--){let a=i[u].name;t.hasAttribute(a)||e.removeAttribute(a)}for(let u=o.length-1;u>=0;u--){let a=o[u].name,r=o[u].value;e.getAttribute(a)!==r&&e.setAttribute(a,r)}}function B(e,t){let i=e.childNodes,o=t.childNodes,u=A(o),a=A(i),r=t.firstChild,n=e.firstChild,c={};for(;r;){let l=s(r),d=s(n);if(!n)if(l&&c[l]){let f=c[l];e.appendChild(f),n=f}else{H(r,e),r=r.nextSibling;continue}if(v){let f=r.nextElementSibling;f&&n.isEqualNode(f)&&(n=_(r,n),d=s(n))}if(l!==d){if(!l&&d){c[d]=n,n=_(r,n),c[d].remove(),n=n.nextSibling,r=r.nextSibling;continue}if(l&&!d&&a[l]&&(n.parentElement.replaceChild(a[l],n),n=a[l]),l&&d){c[d]=n;let f=a[l];if(f)n.parentElement.replaceChild(f,n),n=f;else{c[d]=n,n=_(r,n),c[d].remove(),n=n.nextSibling,r=r.nextSibling;continue}}}b(n,r),r=r&&r.nextSibling,n=n&&n.nextSibling}for(;n;){if(!p(y,n)){let l=n;e.removeChild(l),S(l)}n=n.nextSibling}}function s(e){return e&&e.nodeType===1&&N(e)}function A(e){let t={};return e.forEach(i=>{let o=s(i);o&&(t[o]=i)}),t}function p(e,...t){let i=!1;return e(...t,()=>i=!0),i}function H(e,t){if(!p(m,e)){let i=e.cloneNode(!0);t.appendChild(i),x(i)}}function _(e,t){if(!p(m,e)){let i=e.cloneNode(!0);return t.parentElement.insertBefore(i,t),x(i),i}return t}function E(e){e.directive("morph",(t,{expression:i},{effect:o,evaluateLater:u})=>{let a=u(i);o(()=>{a(r=>{let n=t.firstElementChild||t.firstChild||t.appendChild(document.createTextNode(""));C(n,r)})})})}document.addEventListener("alpine:init",()=>{window.Alpine.plugin(E)});})();
+(()=>{var C=()=>{},E=()=>{},_,f;function d(e){if(!!K)return E((e||"").replace(`
+`,"\\n"),_,f),new Promise(t=>C=()=>t())}async function y(e,t,n){return H(n),_=e,f=L(t),window.Alpine&&!e._x_dataStack&&(f._x_dataStack=window.Alpine.closestDataStack(e),f._x_dataStack&&window.Alpine.clone(e,f)),await d(),await B(e,f),_=void 0,f=void 0,e}y.step=()=>C();y.log=e=>{E=e};var O,M,V,b,A,N,v,g,K,w=()=>{};function H(e={}){let t=n=>n.getAttribute("key");V=e.updating||w,b=e.updated||w,A=e.removing||w,N=e.removed||w,v=e.adding||w,g=e.added||w,O=e.key||t,M=e.lookahead||!1,K=e.debug||!1}function L(e){return document.createRange().createContextualFragment(e).firstElementChild}async function B(e,t){if($(e,t)){let u=q(e,t);return await d("Swap elements"),u}let n=!1;if(!x(V,e,t,()=>n=!0)){if(window.Alpine&&P(e,t,()=>n=!0),j(t)){await z(e,t),b(e,t);return}n||await G(e,t),b(e,t),await I(e,t)}}function $(e,t){return e.nodeType!=t.nodeType||e.nodeName!=t.nodeName||m(e)!=m(t)}function j(e){return e.nodeType===3||e.nodeType===8}function q(e,t){if(x(A,e))return;let n=t.cloneNode(!0);x(v,n)||(a(e).replace(n),N(e),g(n))}async function z(e,t){let n=t.nodeValue;e.nodeValue!==n&&(e.nodeValue=n,await d("Change text node to: "+n))}async function G(e,t){if(e._x_isShown&&!t._x_isShown||!e._x_isShown&&t._x_isShown)return;let n=Array.from(e.attributes),u=Array.from(t.attributes);for(let p=n.length-1;p>=0;p--){let s=n[p].name;t.hasAttribute(s)||(e.removeAttribute(s),await d("Remove attribute"))}for(let p=u.length-1;p>=0;p--){let s=u[p].name,r=u[p].value;e.getAttribute(s)!==r&&(e.setAttribute(s,r),await d(`Set [${s}] attribute to: "${r}"`))}}async function I(e,t){let n=e.childNodes,u=t.childNodes,p=F(u),s=F(n),r=a(t).nodes().first(),i=a(e).nodes().first(),h={};for(;r;){let l=m(r),c=m(i);if(!i)if(l&&h[l]){let o=h[l];a(e).append(o),i=o,await d("Add element (from key)")}else{let o=J(r,e)||{};await d("Add element: "+o.outerHTML||o.nodeValue),r=a(r).nodes().next();continue}if(M){let o=a(r).next(),S=!1;for(;!S&&o;)i.isEqualNode(o)&&(S=!0,i=T(r,i),c=m(i),await d("Move element (lookahead)")),o=a(o).next()}if(l!==c){if(!l&&c){h[c]=i,i=T(r,i),h[c].remove(),i=a(i).nodes().next(),r=a(r).nodes().next(),await d('No "to" key');continue}if(l&&!c&&s[l]&&(i=a(i).replace(s[l]),await d('No "from" key')),l&&c){h[c]=i;let o=s[l];if(o)i=a(i).replace(o),await d('Move "from" key');else{h[c]=i,i=T(r,i),h[c].remove(),i=a(i).next(),r=a(r).next(),await d("I dont even know what this does");continue}}}await B(i,r),r=r&&a(r).nodes().next(),i=i&&a(i).nodes().next()}let k=[];for(;i;)x(A,i)||k.push(i),i=a(i).nodes().next();for(;k.length;){let l=k.pop();l.remove(),await d("remove el"),N(l)}}function m(e){return e&&e.nodeType===1&&O(e)}function F(e){let t={};return e.forEach(n=>{let u=m(n);u&&(t[u]=n)}),t}function x(e,...t){let n=!1;return e(...t,()=>n=!0),n}function J(e,t){if(!x(v,e)){let n=e.cloneNode(!0);return a(t).append(n),g(n),n}return null}function T(e,t){if(!x(v,e)){let n=e.cloneNode(!0);return a(t).before(n),g(n),n}return t}function P(e,t,n){e.nodeType===1&&e._x_dataStack&&window.Alpine.clone(e,t)}function a(e){return new R(e)}var R=class{el=void 0;constructor(t){this.el=t}traversals={first:"firstElementChild",next:"nextElementSibling",parent:"parentElement"};nodes(){return this.traversals={first:"firstChild",next:"nextSibling",parent:"parentNode"},this}first(){return this.teleportTo(this.el[this.traversals.first])}next(){return this.teleportTo(this.teleportBack(this.el[this.traversals.next]))}before(t){return this.el[this.traversals.parent].insertBefore(t,this.el),t}replace(t){return this.el[this.traversals.parent].replaceChild(t,this.el),t}append(t){return this.el.appendChild(t),t}teleportTo(t){return t&&(t._x_teleport?t._x_teleport:t)}teleportBack(t){return t&&(t._x_teleportBack?t._x_teleportBack:t)}};function D(e){e.morph=y}document.addEventListener("alpine:init",()=>{window.Alpine.plugin(D)});})();
diff --git a/alpinejs/packages/morph/dist/module.cjs.js b/alpinejs/packages/morph/dist/module.cjs.js
index d3b7faa..260bf1f 100644
--- a/alpinejs/packages/morph/dist/module.cjs.js
+++ b/alpinejs/packages/morph/dist/module.cjs.js
@@ -4,6 +4,13 @@ var __export = (target, all) => {
for (var name in all)
__defProp(target, name, {get: all[name], enumerable: true});
};
+var __publicField = (obj, key2, value) => {
+ if (typeof key2 !== "symbol")
+ key2 += "";
+ if (key2 in obj)
+ return __defProp(obj, key2, {enumerable: true, configurable: true, writable: true, value});
+ return obj[key2] = value;
+};
// packages/morph/builds/module.js
__markAsModule(exports);
@@ -13,11 +20,36 @@ __export(exports, {
});
// packages/morph/src/morph.js
-function morph(dom, toHtml, options) {
+var resolveStep = () => {
+};
+var logger = () => {
+};
+var fromEl;
+var toEl;
+function breakpoint(message) {
+ if (!debug)
+ return;
+ logger((message || "").replace("\n", "\\n"), fromEl, toEl);
+ return new Promise((resolve) => resolveStep = () => resolve());
+}
+async function morph(from, toHtml, options) {
assignOptions(options);
- patch(dom, createElement(toHtml));
- return dom;
+ fromEl = from;
+ toEl = createElement(toHtml);
+ if (window.Alpine && !from._x_dataStack) {
+ toEl._x_dataStack = window.Alpine.closestDataStack(from);
+ toEl._x_dataStack && window.Alpine.clone(from, toEl);
+ }
+ await breakpoint();
+ await patch(from, toEl);
+ fromEl = void 0;
+ toEl = void 0;
+ return from;
}
+morph.step = () => resolveStep();
+morph.log = (theLogger) => {
+ logger = theLogger;
+};
var key;
var lookahead;
var updating;
@@ -26,91 +58,100 @@ var removing;
var removed;
var adding;
var added;
+var debug;
var noop = () => {
};
function assignOptions(options = {}) {
let defaultGetKey = (el) => el.getAttribute("key");
- key = options.key || defaultGetKey;
- lookahead = options.lookahead || false;
updating = options.updating || noop;
updated = options.updated || noop;
removing = options.removing || noop;
removed = options.removed || noop;
adding = options.adding || noop;
added = options.added || noop;
+ key = options.key || defaultGetKey;
+ lookahead = options.lookahead || false;
+ debug = options.debug || false;
}
function createElement(html) {
return document.createRange().createContextualFragment(html).firstElementChild;
}
-function patch(dom, to) {
- if (dom.isEqualNode(to))
- return;
- if (differentElementNamesTypesOrKeys(dom, to)) {
- return patchElement(dom, to);
+async function patch(from, to) {
+ if (differentElementNamesTypesOrKeys(from, to)) {
+ let result = patchElement(from, to);
+ await breakpoint("Swap elements");
+ return result;
}
let updateChildrenOnly = false;
- if (shouldSkip(updating, dom, to, () => updateChildrenOnly = true))
+ if (shouldSkip(updating, from, to, () => updateChildrenOnly = true))
return;
+ window.Alpine && initializeAlpineOnTo(from, to, () => updateChildrenOnly = true);
if (textOrComment(to)) {
- patchNodeValue(dom, to);
- updated(dom, to);
+ await patchNodeValue(from, to);
+ updated(from, to);
return;
}
if (!updateChildrenOnly) {
- patchAttributes(dom, to);
+ await patchAttributes(from, to);
}
- updated(dom, to);
- patchChildren(dom, to);
+ updated(from, to);
+ await patchChildren(from, to);
}
-function differentElementNamesTypesOrKeys(dom, to) {
- return dom.nodeType != to.nodeType || dom.nodeName != to.nodeName || getKey(dom) != getKey(to);
+function differentElementNamesTypesOrKeys(from, to) {
+ return from.nodeType != to.nodeType || from.nodeName != to.nodeName || getKey(from) != getKey(to);
}
function textOrComment(el) {
return el.nodeType === 3 || el.nodeType === 8;
}
-function patchElement(dom, to) {
- if (shouldSkip(removing, dom))
+function patchElement(from, to) {
+ if (shouldSkip(removing, from))
return;
let toCloned = to.cloneNode(true);
if (shouldSkip(adding, toCloned))
return;
- dom.parentNode.replaceChild(toCloned, dom);
- removed(dom);
+ dom(from).replace(toCloned);
+ removed(from);
added(toCloned);
}
-function patchNodeValue(dom, to) {
+async function patchNodeValue(from, to) {
let value = to.nodeValue;
- if (dom.nodeValue !== value)
- dom.nodeValue = value;
+ if (from.nodeValue !== value) {
+ from.nodeValue = value;
+ await breakpoint("Change text node to: " + value);
+ }
}
-function patchAttributes(dom, to) {
- if (dom._x_isShown && !to._x_isShown) {
+async function patchAttributes(from, to) {
+ if (from._x_isShown && !to._x_isShown) {
return;
}
- if (!dom._x_isShown && to._x_isShown) {
+ if (!from._x_isShown && to._x_isShown) {
return;
}
- let domAttributes = Array.from(dom.attributes);
+ let domAttributes = Array.from(from.attributes);
let toAttributes = Array.from(to.attributes);
for (let i = domAttributes.length - 1; i >= 0; i--) {
let name = domAttributes[i].name;
- if (!to.hasAttribute(name))
- dom.removeAttribute(name);
+ if (!to.hasAttribute(name)) {
+ from.removeAttribute(name);
+ await breakpoint("Remove attribute");
+ }
}
for (let i = toAttributes.length - 1; i >= 0; i--) {
let name = toAttributes[i].name;
let value = toAttributes[i].value;
- if (dom.getAttribute(name) !== value)
- dom.setAttribute(name, value);
+ if (from.getAttribute(name) !== value) {
+ from.setAttribute(name, value);
+ await breakpoint(`Set [${name}] attribute to: "${value}"`);
+ }
}
}
-function patchChildren(dom, to) {
- let domChildren = dom.childNodes;
+async function patchChildren(from, to) {
+ let domChildren = from.childNodes;
let toChildren = to.childNodes;
let toKeyToNodeMap = keyToMap(toChildren);
let domKeyDomNodeMap = keyToMap(domChildren);
- let currentTo = to.firstChild;
- let currentFrom = dom.firstChild;
+ let currentTo = dom(to).nodes().first();
+ let currentFrom = dom(from).nodes().first();
let domKeyHoldovers = {};
while (currentTo) {
let toKey = getKey(currentTo);
@@ -118,19 +159,27 @@ function patchChildren(dom, to) {
if (!currentFrom) {
if (toKey && domKeyHoldovers[toKey]) {
let holdover = domKeyHoldovers[toKey];
- dom.appendChild(holdover);
+ dom(from).append(holdover);
currentFrom = holdover;
+ await breakpoint("Add element (from key)");
} else {
- addNodeTo(currentTo, dom);
- currentTo = currentTo.nextSibling;
+ let added2 = addNodeTo(currentTo, from) || {};
+ await breakpoint("Add element: " + added2.outerHTML || added2.nodeValue);
+ currentTo = dom(currentTo).nodes().next();
continue;
}
}
if (lookahead) {
- let nextToElementSibling = currentTo.nextElementSibling;
- if (nextToElementSibling && currentFrom.isEqualNode(nextToElementSibling)) {
- currentFrom = addNodeBefore(currentTo, currentFrom);
- domKey = getKey(currentFrom);
+ let nextToElementSibling = dom(currentTo).next();
+ let found = false;
+ while (!found && nextToElementSibling) {
+ if (currentFrom.isEqualNode(nextToElementSibling)) {
+ found = true;
+ currentFrom = addNodeBefore(currentTo, currentFrom);
+ domKey = getKey(currentFrom);
+ await breakpoint("Move element (lookahead)");
+ }
+ nextToElementSibling = dom(nextToElementSibling).next();
}
}
if (toKey !== domKey) {
@@ -138,43 +187,49 @@ function patchChildren(dom, to) {
domKeyHoldovers[domKey] = currentFrom;
currentFrom = addNodeBefore(currentTo, currentFrom);
domKeyHoldovers[domKey].remove();
- currentFrom = currentFrom.nextSibling;
- currentTo = currentTo.nextSibling;
+ currentFrom = dom(currentFrom).nodes().next();
+ currentTo = dom(currentTo).nodes().next();
+ await breakpoint('No "to" key');
continue;
}
if (toKey && !domKey) {
if (domKeyDomNodeMap[toKey]) {
- currentFrom.parentElement.replaceChild(domKeyDomNodeMap[toKey], currentFrom);
- currentFrom = domKeyDomNodeMap[toKey];
+ currentFrom = dom(currentFrom).replace(domKeyDomNodeMap[toKey]);
+ await breakpoint('No "from" key');
}
}
if (toKey && domKey) {
domKeyHoldovers[domKey] = currentFrom;
let domKeyNode = domKeyDomNodeMap[toKey];
if (domKeyNode) {
- currentFrom.parentElement.replaceChild(domKeyNode, currentFrom);
- currentFrom = domKeyNode;
+ currentFrom = dom(currentFrom).replace(domKeyNode);
+ await breakpoint('Move "from" key');
} else {
domKeyHoldovers[domKey] = currentFrom;
currentFrom = addNodeBefore(currentTo, currentFrom);
domKeyHoldovers[domKey].remove();
- currentFrom = currentFrom.nextSibling;
- currentTo = currentTo.nextSibling;
+ currentFrom = dom(currentFrom).next();
+ currentTo = dom(currentTo).next();
+ await breakpoint("I dont even know what this does");
continue;
}
}
}
- patch(currentFrom, currentTo);
- currentTo = currentTo && currentTo.nextSibling;
- currentFrom = currentFrom && currentFrom.nextSibling;
+ await patch(currentFrom, currentTo);
+ currentTo = currentTo && dom(currentTo).nodes().next();
+ currentFrom = currentFrom && dom(currentFrom).nodes().next();
}
+ let removals = [];
while (currentFrom) {
- if (!shouldSkip(removing, currentFrom)) {
- let domForRemoval = currentFrom;
- dom.removeChild(domForRemoval);
- removed(domForRemoval);
- }
- currentFrom = currentFrom.nextSibling;
+ if (!shouldSkip(removing, currentFrom))
+ removals.push(currentFrom);
+ currentFrom = dom(currentFrom).nodes().next();
+ }
+ while (removals.length) {
+ let domForRemoval = removals.pop();
+ domForRemoval.remove();
+ await breakpoint("remove el");
+ removed(domForRemoval);
}
}
function getKey(el) {
@@ -198,31 +253,86 @@ function shouldSkip(hook, ...args) {
function addNodeTo(node, parent) {
if (!shouldSkip(adding, node)) {
let clone = node.cloneNode(true);
- parent.appendChild(clone);
+ dom(parent).append(clone);
added(clone);
+ return clone;
}
+ return null;
}
function addNodeBefore(node, beforeMe) {
if (!shouldSkip(adding, node)) {
let clone = node.cloneNode(true);
- beforeMe.parentElement.insertBefore(clone, beforeMe);
+ dom(beforeMe).before(clone);
added(clone);
return clone;
}
return beforeMe;
}
+function initializeAlpineOnTo(from, to, childrenOnly) {
+ if (from.nodeType !== 1)
+ return;
+ if (from._x_dataStack) {
+ window.Alpine.clone(from, to);
+ }
+}
+function dom(el) {
+ return new DomManager(el);
+}
+var DomManager = class {
+ constructor(el) {
+ __publicField(this, "el");
+ __publicField(this, "traversals", {
+ first: "firstElementChild",
+ next: "nextElementSibling",
+ parent: "parentElement"
+ });
+ this.el = el;
+ }
+ nodes() {
+ this.traversals = {
+ first: "firstChild",
+ next: "nextSibling",
+ parent: "parentNode"
+ };
+ return this;
+ }
+ first() {
+ return this.teleportTo(this.el[this.traversals["first"]]);
+ }
+ next() {
+ return this.teleportTo(this.teleportBack(this.el[this.traversals["next"]]));
+ }
+ before(insertee) {
+ this.el[this.traversals["parent"]].insertBefore(insertee, this.el);
+ return insertee;
+ }
+ replace(replacement) {
+ this.el[this.traversals["parent"]].replaceChild(replacement, this.el);
+ return replacement;
+ }
+ append(appendee) {
+ this.el.appendChild(appendee);
+ return appendee;
+ }
+ teleportTo(el) {
+ if (!el)
+ return el;
+ if (el._x_teleport)
+ return el._x_teleport;
+ return el;
+ }
+ teleportBack(el) {
+ if (!el)
+ return el;
+ if (el._x_teleportBack)
+ return el._x_teleportBack;
+ return el;
+ }
+};
// packages/morph/src/index.js
function src_default(Alpine) {
- Alpine.directive("morph", (el, {expression}, {effect, evaluateLater}) => {
- let evaluate = evaluateLater(expression);
- effect(() => {
- evaluate((value) => {
- let child = el.firstElementChild || el.firstChild || el.appendChild(document.createTextNode(""));
- morph(child, value);
- });
- });
- });
+ Alpine.morph = morph;
}
// packages/morph/builds/module.js
diff --git a/alpinejs/packages/morph/dist/module.esm.js b/alpinejs/packages/morph/dist/module.esm.js
index 14fae59..b0be17a 100644
--- a/alpinejs/packages/morph/dist/module.esm.js
+++ b/alpinejs/packages/morph/dist/module.esm.js
@@ -1,9 +1,34 @@
// packages/morph/src/morph.js
-function morph(dom, toHtml, options) {
+var resolveStep = () => {
+};
+var logger = () => {
+};
+var fromEl;
+var toEl;
+function breakpoint(message) {
+ if (!debug)
+ return;
+ logger((message || "").replace("\n", "\\n"), fromEl, toEl);
+ return new Promise((resolve) => resolveStep = () => resolve());
+}
+async function morph(from, toHtml, options) {
assignOptions(options);
- patch(dom, createElement(toHtml));
- return dom;
+ fromEl = from;
+ toEl = createElement(toHtml);
+ if (window.Alpine && !from._x_dataStack) {
+ toEl._x_dataStack = window.Alpine.closestDataStack(from);
+ toEl._x_dataStack && window.Alpine.clone(from, toEl);
+ }
+ await breakpoint();
+ await patch(from, toEl);
+ fromEl = void 0;
+ toEl = void 0;
+ return from;
}
+morph.step = () => resolveStep();
+morph.log = (theLogger) => {
+ logger = theLogger;
+};
var key;
var lookahead;
var updating;
@@ -12,91 +37,100 @@ var removing;
var removed;
var adding;
var added;
+var debug;
var noop = () => {
};
function assignOptions(options = {}) {
let defaultGetKey = (el) => el.getAttribute("key");
- key = options.key || defaultGetKey;
- lookahead = options.lookahead || false;
updating = options.updating || noop;
updated = options.updated || noop;
removing = options.removing || noop;
removed = options.removed || noop;
adding = options.adding || noop;
added = options.added || noop;
+ key = options.key || defaultGetKey;
+ lookahead = options.lookahead || false;
+ debug = options.debug || false;
}
function createElement(html) {
return document.createRange().createContextualFragment(html).firstElementChild;
}
-function patch(dom, to) {
- if (dom.isEqualNode(to))
- return;
- if (differentElementNamesTypesOrKeys(dom, to)) {
- return patchElement(dom, to);
+async function patch(from, to) {
+ if (differentElementNamesTypesOrKeys(from, to)) {
+ let result = patchElement(from, to);
+ await breakpoint("Swap elements");
+ return result;
}
let updateChildrenOnly = false;
- if (shouldSkip(updating, dom, to, () => updateChildrenOnly = true))
+ if (shouldSkip(updating, from, to, () => updateChildrenOnly = true))
return;
+ window.Alpine && initializeAlpineOnTo(from, to, () => updateChildrenOnly = true);
if (textOrComment(to)) {
- patchNodeValue(dom, to);
- updated(dom, to);
+ await patchNodeValue(from, to);
+ updated(from, to);
return;
}
if (!updateChildrenOnly) {
- patchAttributes(dom, to);
+ await patchAttributes(from, to);
}
- updated(dom, to);
- patchChildren(dom, to);
+ updated(from, to);
+ await patchChildren(from, to);
}
-function differentElementNamesTypesOrKeys(dom, to) {
- return dom.nodeType != to.nodeType || dom.nodeName != to.nodeName || getKey(dom) != getKey(to);
+function differentElementNamesTypesOrKeys(from, to) {
+ return from.nodeType != to.nodeType || from.nodeName != to.nodeName || getKey(from) != getKey(to);
}
function textOrComment(el) {
return el.nodeType === 3 || el.nodeType === 8;
}
-function patchElement(dom, to) {
- if (shouldSkip(removing, dom))
+function patchElement(from, to) {
+ if (shouldSkip(removing, from))
return;
let toCloned = to.cloneNode(true);
if (shouldSkip(adding, toCloned))
return;
- dom.parentNode.replaceChild(toCloned, dom);
- removed(dom);
+ dom(from).replace(toCloned);
+ removed(from);
added(toCloned);
}
-function patchNodeValue(dom, to) {
+async function patchNodeValue(from, to) {
let value = to.nodeValue;
- if (dom.nodeValue !== value)
- dom.nodeValue = value;
+ if (from.nodeValue !== value) {
+ from.nodeValue = value;
+ await breakpoint("Change text node to: " + value);
+ }
}
-function patchAttributes(dom, to) {
- if (dom._x_isShown && !to._x_isShown) {
+async function patchAttributes(from, to) {
+ if (from._x_isShown && !to._x_isShown) {
return;
}
- if (!dom._x_isShown && to._x_isShown) {
+ if (!from._x_isShown && to._x_isShown) {
return;
}
- let domAttributes = Array.from(dom.attributes);
+ let domAttributes = Array.from(from.attributes);
let toAttributes = Array.from(to.attributes);
for (let i = domAttributes.length - 1; i >= 0; i--) {
let name = domAttributes[i].name;
- if (!to.hasAttribute(name))
- dom.removeAttribute(name);
+ if (!to.hasAttribute(name)) {
+ from.removeAttribute(name);
+ await breakpoint("Remove attribute");
+ }
}
for (let i = toAttributes.length - 1; i >= 0; i--) {
let name = toAttributes[i].name;
let value = toAttributes[i].value;
- if (dom.getAttribute(name) !== value)
- dom.setAttribute(name, value);
+ if (from.getAttribute(name) !== value) {
+ from.setAttribute(name, value);
+ await breakpoint(`Set [${name}] attribute to: "${value}"`);
+ }
}
}
-function patchChildren(dom, to) {
- let domChildren = dom.childNodes;
+async function patchChildren(from, to) {
+ let domChildren = from.childNodes;
let toChildren = to.childNodes;
let toKeyToNodeMap = keyToMap(toChildren);
let domKeyDomNodeMap = keyToMap(domChildren);
- let currentTo = to.firstChild;
- let currentFrom = dom.firstChild;
+ let currentTo = dom(to).nodes().first();
+ let currentFrom = dom(from).nodes().first();
let domKeyHoldovers = {};
while (currentTo) {
let toKey = getKey(currentTo);
@@ -104,19 +138,27 @@ function patchChildren(dom, to) {
if (!currentFrom) {
if (toKey && domKeyHoldovers[toKey]) {
let holdover = domKeyHoldovers[toKey];
- dom.appendChild(holdover);
+ dom(from).append(holdover);
currentFrom = holdover;
+ await breakpoint("Add element (from key)");
} else {
- addNodeTo(currentTo, dom);
- currentTo = currentTo.nextSibling;
+ let added2 = addNodeTo(currentTo, from) || {};
+ await breakpoint("Add element: " + added2.outerHTML || added2.nodeValue);
+ currentTo = dom(currentTo).nodes().next();
continue;
}
}
if (lookahead) {
- let nextToElementSibling = currentTo.nextElementSibling;
- if (nextToElementSibling && currentFrom.isEqualNode(nextToElementSibling)) {
- currentFrom = addNodeBefore(currentTo, currentFrom);
- domKey = getKey(currentFrom);
+ let nextToElementSibling = dom(currentTo).next();
+ let found = false;
+ while (!found && nextToElementSibling) {
+ if (currentFrom.isEqualNode(nextToElementSibling)) {
+ found = true;
+ currentFrom = addNodeBefore(currentTo, currentFrom);
+ domKey = getKey(currentFrom);
+ await breakpoint("Move element (lookahead)");
+ }
+ nextToElementSibling = dom(nextToElementSibling).next();
}
}
if (toKey !== domKey) {
@@ -124,43 +166,49 @@ function patchChildren(dom, to) {
domKeyHoldovers[domKey] = currentFrom;
currentFrom = addNodeBefore(currentTo, currentFrom);
domKeyHoldovers[domKey].remove();
- currentFrom = currentFrom.nextSibling;
- currentTo = currentTo.nextSibling;
+ currentFrom = dom(currentFrom).nodes().next();
+ currentTo = dom(currentTo).nodes().next();
+ await breakpoint('No "to" key');
continue;
}
if (toKey && !domKey) {
if (domKeyDomNodeMap[toKey]) {
- currentFrom.parentElement.replaceChild(domKeyDomNodeMap[toKey], currentFrom);
- currentFrom = domKeyDomNodeMap[toKey];
+ currentFrom = dom(currentFrom).replace(domKeyDomNodeMap[toKey]);
+ await breakpoint('No "from" key');
}
}
if (toKey && domKey) {
domKeyHoldovers[domKey] = currentFrom;
let domKeyNode = domKeyDomNodeMap[toKey];
if (domKeyNode) {
- currentFrom.parentElement.replaceChild(domKeyNode, currentFrom);
- currentFrom = domKeyNode;
+ currentFrom = dom(currentFrom).replace(domKeyNode);
+ await breakpoint('Move "from" key');
} else {
domKeyHoldovers[domKey] = currentFrom;
currentFrom = addNodeBefore(currentTo, currentFrom);
domKeyHoldovers[domKey].remove();
- currentFrom = currentFrom.nextSibling;
- currentTo = currentTo.nextSibling;
+ currentFrom = dom(currentFrom).next();
+ currentTo = dom(currentTo).next();
+ await breakpoint("I dont even know what this does");
continue;
}
}
}
- patch(currentFrom, currentTo);
- currentTo = currentTo && currentTo.nextSibling;
- currentFrom = currentFrom && currentFrom.nextSibling;
+ await patch(currentFrom, currentTo);
+ currentTo = currentTo && dom(currentTo).nodes().next();
+ currentFrom = currentFrom && dom(currentFrom).nodes().next();
}
+ let removals = [];
while (currentFrom) {
- if (!shouldSkip(removing, currentFrom)) {
- let domForRemoval = currentFrom;
- dom.removeChild(domForRemoval);
- removed(domForRemoval);
- }
- currentFrom = currentFrom.nextSibling;
+ if (!shouldSkip(removing, currentFrom))
+ removals.push(currentFrom);
+ currentFrom = dom(currentFrom).nodes().next();
+ }
+ while (removals.length) {
+ let domForRemoval = removals.pop();
+ domForRemoval.remove();
+ await breakpoint("remove el");
+ removed(domForRemoval);
}
}
function getKey(el) {
@@ -184,31 +232,86 @@ function shouldSkip(hook, ...args) {
function addNodeTo(node, parent) {
if (!shouldSkip(adding, node)) {
let clone = node.cloneNode(true);
- parent.appendChild(clone);
+ dom(parent).append(clone);
added(clone);
+ return clone;
}
+ return null;
}
function addNodeBefore(node, beforeMe) {
if (!shouldSkip(adding, node)) {
let clone = node.cloneNode(true);
- beforeMe.parentElement.insertBefore(clone, beforeMe);
+ dom(beforeMe).before(clone);
added(clone);
return clone;
}
return beforeMe;
}
+function initializeAlpineOnTo(from, to, childrenOnly) {
+ if (from.nodeType !== 1)
+ return;
+ if (from._x_dataStack) {
+ window.Alpine.clone(from, to);
+ }
+}
+function dom(el) {
+ return new DomManager(el);
+}
+var DomManager = class {
+ el = void 0;
+ constructor(el) {
+ this.el = el;
+ }
+ traversals = {
+ first: "firstElementChild",
+ next: "nextElementSibling",
+ parent: "parentElement"
+ };
+ nodes() {
+ this.traversals = {
+ first: "firstChild",
+ next: "nextSibling",
+ parent: "parentNode"
+ };
+ return this;
+ }
+ first() {
+ return this.teleportTo(this.el[this.traversals["first"]]);
+ }
+ next() {
+ return this.teleportTo(this.teleportBack(this.el[this.traversals["next"]]));
+ }
+ before(insertee) {
+ this.el[this.traversals["parent"]].insertBefore(insertee, this.el);
+ return insertee;
+ }
+ replace(replacement) {
+ this.el[this.traversals["parent"]].replaceChild(replacement, this.el);
+ return replacement;
+ }
+ append(appendee) {
+ this.el.appendChild(appendee);
+ return appendee;
+ }
+ teleportTo(el) {
+ if (!el)
+ return el;
+ if (el._x_teleport)
+ return el._x_teleport;
+ return el;
+ }
+ teleportBack(el) {
+ if (!el)
+ return el;
+ if (el._x_teleportBack)
+ return el._x_teleportBack;
+ return el;
+ }
+};
// packages/morph/src/index.js
function src_default(Alpine) {
- Alpine.directive("morph", (el, {expression}, {effect, evaluateLater}) => {
- let evaluate = evaluateLater(expression);
- effect(() => {
- evaluate((value) => {
- let child = el.firstElementChild || el.firstChild || el.appendChild(document.createTextNode(""));
- morph(child, value);
- });
- });
- });
+ Alpine.morph = morph;
}
// packages/morph/builds/module.js
diff --git a/alpinejs/packages/morph/package.json b/alpinejs/packages/morph/package.json
new file mode 100644
index 0000000..cb1e3fa
--- /dev/null
+++ b/alpinejs/packages/morph/package.json
@@ -0,0 +1,9 @@
+{
+ "name": "@alpinejs/morph",
+ "version": "3.9.1",
+ "description": "Diff and patch a block of HTML on a page with an HTML template",
+ "author": "Caleb Porzio",
+ "license": "MIT",
+ "main": "dist/module.cjs.js",
+ "module": "dist/module.esm.js"
+}
diff --git a/alpinejs/packages/morph/src/index.js b/alpinejs/packages/morph/src/index.js
new file mode 100644
index 0000000..93c46b2
--- /dev/null
+++ b/alpinejs/packages/morph/src/index.js
@@ -0,0 +1,7 @@
+import { morph } from './morph'
+
+export default function (Alpine) {
+ Alpine.morph = morph
+}
+
+export { morph }
diff --git a/alpinejs/packages/morph/src/morph.js b/alpinejs/packages/morph/src/morph.js
new file mode 100644
index 0000000..112a9cf
--- /dev/null
+++ b/alpinejs/packages/morph/src/morph.js
@@ -0,0 +1,432 @@
+let resolveStep = () => {}
+
+let logger = () => {}
+
+// Keep these global so that we can access them
+// from hooks while debugging.
+let fromEl
+let toEl
+
+function breakpoint(message) {
+ if (! debug) return
+
+ logger((message || '').replace('\n', '\\n'), fromEl, toEl)
+
+ return new Promise(resolve => resolveStep = () => resolve())
+}
+
+export async function morph(from, toHtml, options) {
+ assignOptions(options)
+
+ fromEl = from
+ toEl = createElement(toHtml)
+
+ // If there is no x-data on the element we're morphing,
+ // let's seed it with the outer Alpine scope on the page.
+ if (window.Alpine && ! from._x_dataStack) {
+ toEl._x_dataStack = window.Alpine.closestDataStack(from)
+
+ toEl._x_dataStack && window.Alpine.clone(from, toEl)
+ }
+
+ await breakpoint()
+
+ await patch(from, toEl)
+
+ // Release these for the garbage collector.
+ fromEl = undefined
+ toEl = undefined
+
+ return from
+}
+
+morph.step = () => resolveStep()
+morph.log = (theLogger) => {
+ logger = theLogger
+}
+
+let key
+,lookahead
+,updating
+,updated
+,removing
+,removed
+,adding
+,added
+,debug
+
+let noop = () => {}
+
+function assignOptions(options = {}) {
+ let defaultGetKey = el => el.getAttribute('key')
+
+ updating = options.updating || noop
+ updated = options.updated || noop
+ removing = options.removing || noop
+ removed = options.removed || noop
+ adding = options.adding || noop
+ added = options.added || noop
+ key = options.key || defaultGetKey
+ lookahead = options.lookahead || false
+ debug = options.debug || false
+}
+
+function createElement(html) {
+ return document.createRange().createContextualFragment(html).firstElementChild
+}
+
+async function patch(from, to) {
+ // This is a time saver, however, it won't catch differences in nested <template> tags.
+ // I'm leaving this here as I believe it's an important speed improvement, I just
+ // don't see a way to enable it currently:
+ //
+ // if (from.isEqualNode(to)) return
+
+ if (differentElementNamesTypesOrKeys(from, to)) {
+ let result = patchElement(from, to)
+
+ await breakpoint('Swap elements')
+
+ return result
+ }
+
+ let updateChildrenOnly = false
+
+ if (shouldSkip(updating, from, to, () => updateChildrenOnly = true)) return
+
+ window.Alpine && initializeAlpineOnTo(from, to, () => updateChildrenOnly = true)
+
+ if (textOrComment(to)) {
+ await patchNodeValue(from, to)
+ updated(from, to)
+
+ return
+ }
+
+ if (! updateChildrenOnly) {
+ await patchAttributes(from, to)
+ }
+
+ updated(from, to)
+
+ await patchChildren(from, to)
+}
+
+function differentElementNamesTypesOrKeys(from, to) {
+ return from.nodeType != to.nodeType
+ || from.nodeName != to.nodeName
+ || getKey(from) != getKey(to)
+}
+
+function textOrComment(el) {
+ return el.nodeType === 3
+ || el.nodeType === 8
+}
+
+function patchElement(from, to) {
+ if (shouldSkip(removing, from)) return
+
+ let toCloned = to.cloneNode(true)
+
+ if (shouldSkip(adding, toCloned)) return
+
+ dom(from).replace(toCloned)
+
+ removed(from)
+ added(toCloned)
+}
+
+async function patchNodeValue(from, to) {
+ let value = to.nodeValue
+
+ if (from.nodeValue !== value) {
+ from.nodeValue = value
+
+ await breakpoint('Change text node to: ' + value)
+ }
+}
+
+async function patchAttributes(from, to) {
+ if (from._x_isShown && ! to._x_isShown) {
+ return
+ }
+ if (! from._x_isShown && to._x_isShown) {
+ return
+ }
+
+ let domAttributes = Array.from(from.attributes)
+ let toAttributes = Array.from(to.attributes)
+
+ for (let i = domAttributes.length - 1; i >= 0; i--) {
+ let name = domAttributes[i].name;
+
+ if (! to.hasAttribute(name)) {
+ from.removeAttribute(name)
+
+ await breakpoint('Remove attribute')
+ }
+ }
+
+ for (let i = toAttributes.length - 1; i >= 0; i--) {
+ let name = toAttributes[i].name
+ let value = toAttributes[i].value
+
+ if (from.getAttribute(name) !== value) {
+ from.setAttribute(name, value)
+
+ await breakpoint(`Set [${name}] attribute to: "${value}"`)
+ }
+ }
+}
+
+async function patchChildren(from, to) {
+ let domChildren = from.childNodes
+ let toChildren = to.childNodes
+
+ let toKeyToNodeMap = keyToMap(toChildren)
+ let domKeyDomNodeMap = keyToMap(domChildren)
+
+ let currentTo = dom(to).nodes().first()
+ let currentFrom = dom(from).nodes().first()
+
+ let domKeyHoldovers = {}
+
+ while (currentTo) {
+ let toKey = getKey(currentTo)
+ let domKey = getKey(currentFrom)
+
+ // Add new elements
+ if (! currentFrom) {
+ if (toKey && domKeyHoldovers[toKey]) {
+ let holdover = domKeyHoldovers[toKey]
+
+ dom(from).append(holdover)
+ currentFrom = holdover
+
+ await breakpoint('Add element (from key)')
+ } else {
+ let added = addNodeTo(currentTo, from) || {}
+
+ await breakpoint('Add element: ' + added.outerHTML || added.nodeValue)
+
+ currentTo = dom(currentTo).nodes().next()
+
+ continue
+ }
+ }
+
+ if (lookahead) {
+ let nextToElementSibling = dom(currentTo).next()
+
+ let found = false
+
+ while (!found && nextToElementSibling) {
+ if (currentFrom.isEqualNode(nextToElementSibling)) {
+ found = true
+
+ currentFrom = addNodeBefore(currentTo, currentFrom)
+
+ domKey = getKey(currentFrom)
+
+ await breakpoint('Move element (lookahead)')
+ }
+
+ nextToElementSibling = dom(nextToElementSibling).next()
+ }
+ }
+
+ if (toKey !== domKey) {
+ if (! toKey && domKey) {
+ domKeyHoldovers[domKey] = currentFrom
+ currentFrom = addNodeBefore(currentTo, currentFrom)
+ domKeyHoldovers[domKey].remove()
+ currentFrom = dom(currentFrom).nodes().next()
+ currentTo = dom(currentTo).nodes().next()
+
+ await breakpoint('No "to" key')
+
+ continue
+ }
+
+ if (toKey && ! domKey) {
+ if (domKeyDomNodeMap[toKey]) {
+ currentFrom = dom(currentFrom).replace(domKeyDomNodeMap[toKey])
+
+ await breakpoint('No "from" key')
+ }
+ }
+
+ if (toKey && domKey) {
+ domKeyHoldovers[domKey] = currentFrom
+ let domKeyNode = domKeyDomNodeMap[toKey]
+
+ if (domKeyNode) {
+ currentFrom = dom(currentFrom).replace(domKeyNode)
+
+ await breakpoint('Move "from" key')
+ } else {
+ domKeyHoldovers[domKey] = currentFrom
+ currentFrom = addNodeBefore(currentTo, currentFrom)
+ domKeyHoldovers[domKey].remove()
+ currentFrom = dom(currentFrom).next()
+ currentTo = dom(currentTo).next()
+
+ await breakpoint('I dont even know what this does')
+
+ continue
+ }
+ }
+ }
+
+ // Patch elements
+ await patch(currentFrom, currentTo)
+
+ currentTo = currentTo && dom(currentTo).nodes().next()
+ currentFrom = currentFrom && dom(currentFrom).nodes().next()
+ }
+
+ // Cleanup extra froms.
+ let removals = []
+
+ // We need to collect the "removals" first before actually
+ // removing them so we don't mess with the order of things.
+ while (currentFrom) {
+ if(! shouldSkip(removing, currentFrom)) removals.push(currentFrom)
+
+ currentFrom = dom(currentFrom).nodes().next()
+ }
+
+ // Now we can do the actual removals.
+ while (removals.length) {
+ let domForRemoval = removals.pop()
+
+ domForRemoval.remove()
+
+ await breakpoint('remove el')
+
+ removed(domForRemoval)
+ }
+}
+
+function getKey(el) {
+ return el && el.nodeType === 1 && key(el)
+}
+
+function keyToMap(els) {
+ let map = {}
+
+ els.forEach(el => {
+ let theKey = getKey(el)
+
+ if (theKey) {
+ map[theKey] = el
+ }
+ })
+
+ return map
+}
+
+function shouldSkip(hook, ...args) {
+ let skip = false
+
+ hook(...args, () => skip = true)
+
+ return skip
+}
+
+function addNodeTo(node, parent) {
+ if(! shouldSkip(adding, node)) {
+ let clone = node.cloneNode(true)
+
+ dom(parent).append(clone)
+
+ added(clone)
+
+ return clone
+ }
+
+ return null;
+}
+
+function addNodeBefore(node, beforeMe) {
+ if(! shouldSkip(adding, node)) {
+ let clone = node.cloneNode(true)
+
+ dom(beforeMe).before(clone)
+
+ added(clone)
+
+ return clone
+ }
+
+ return beforeMe
+}
+
+function initializeAlpineOnTo(from, to, childrenOnly) {
+ if (from.nodeType !== 1) return
+
+ // If the element we are updating is an Alpine component...
+ if (from._x_dataStack) {
+ // Then temporarily clone it (with it's data) to the "to" element.
+ // This should simulate backend Livewire being aware of Alpine changes.
+ window.Alpine.clone(from, to)
+ }
+}
+
+function dom(el) {
+ return new DomManager(el)
+}
+
+class DomManager {
+ el = undefined
+
+ constructor(el) {
+ this.el = el
+ }
+
+ traversals = {
+ 'first': 'firstElementChild',
+ 'next': 'nextElementSibling',
+ 'parent': 'parentElement',
+ }
+
+ nodes() {
+ this.traversals = {
+ 'first': 'firstChild',
+ 'next': 'nextSibling',
+ 'parent': 'parentNode',
+ }; return this
+ }
+
+ first() {
+ return this.teleportTo(this.el[this.traversals['first']])
+ }
+
+ next() {
+ return this.teleportTo(this.teleportBack(this.el[this.traversals['next']]))
+ }
+
+ before(insertee) {
+ this.el[this.traversals['parent']].insertBefore(insertee, this.el); return insertee
+ }
+
+ replace(replacement) {
+ this.el[this.traversals['parent']].replaceChild(replacement, this.el); return replacement
+ }
+
+ append(appendee) {
+ this.el.appendChild(appendee); return appendee
+ }
+
+ teleportTo(el) {
+ if (! el) return el
+ if (el._x_teleport) return el._x_teleport
+ return el
+ }
+
+ teleportBack(el) {
+ if (! el) return el
+ if (el._x_teleportBack) return el._x_teleportBack
+ return el
+ }
+}
diff --git a/alpinejs/packages/persist/builds/cdn.js b/alpinejs/packages/persist/builds/cdn.js
new file mode 100644
index 0000000..c113e1a
--- /dev/null
+++ b/alpinejs/packages/persist/builds/cdn.js
@@ -0,0 +1,5 @@
+import persist from '../src/index.js'
+
+document.addEventListener('alpine:init', () => {
+ window.Alpine.plugin(persist)
+})
diff --git a/alpinejs/packages/persist/builds/module.js b/alpinejs/packages/persist/builds/module.js
new file mode 100644
index 0000000..2872c9f
--- /dev/null
+++ b/alpinejs/packages/persist/builds/module.js
@@ -0,0 +1,3 @@
+import persist from '../src/index.js'
+
+export default persist
diff --git a/alpinejs/packages/persist/package.json b/alpinejs/packages/persist/package.json
new file mode 100644
index 0000000..f0ca184
--- /dev/null
+++ b/alpinejs/packages/persist/package.json
@@ -0,0 +1,11 @@
+{
+ "name": "@alpinejs/persist",
+ "version": "3.9.1",
+ "description": "Persist Alpine data across page loads",
+ "author": "Caleb Porzio",
+ "license": "MIT",
+ "main": "dist/module.cjs.js",
+ "module": "dist/module.esm.js",
+ "unpkg": "dist/cdn.min.js",
+ "dependencies": {}
+}
diff --git a/alpinejs/packages/persist/src/index.js b/alpinejs/packages/persist/src/index.js
new file mode 100644
index 0000000..096ac70
--- /dev/null
+++ b/alpinejs/packages/persist/src/index.js
@@ -0,0 +1,44 @@
+export default function (Alpine) {
+ let persist = () => {
+ let alias
+ let storage = localStorage
+
+ return Alpine.interceptor((initialValue, getter, setter, path, key) => {
+ let lookup = alias || `_x_${path}`
+
+ let initial = storageHas(lookup, storage)
+ ? storageGet(lookup, storage)
+ : initialValue
+
+ setter(initial)
+
+ Alpine.effect(() => {
+ let value = getter()
+
+ storageSet(lookup, value, storage)
+
+ setter(value)
+ })
+
+ return initial
+ }, func => {
+ func.as = key => { alias = key; return func },
+ func.using = target => { storage = target; return func }
+ })
+ }
+
+ Object.defineProperty(Alpine, '$persist', { get: () => persist() })
+ Alpine.magic('persist', persist)
+}
+
+function storageHas(key, storage) {
+ return storage.getItem(key) !== null
+}
+
+function storageGet(key, storage) {
+ return JSON.parse(storage.getItem(key, storage))
+}
+
+function storageSet(key, value, storage) {
+ storage.setItem(key, JSON.stringify(value))
+}
diff --git a/alpinejs/packages/portal/builds/cdn.js b/alpinejs/packages/portal/builds/cdn.js
new file mode 100644
index 0000000..e3529e7
--- /dev/null
+++ b/alpinejs/packages/portal/builds/cdn.js
@@ -0,0 +1,5 @@
+import portal from '../src/index.js'
+
+document.addEventListener('alpine:init', () => {
+ window.Alpine.plugin(portal)
+})
diff --git a/alpinejs/packages/portal/builds/module.js b/alpinejs/packages/portal/builds/module.js
new file mode 100644
index 0000000..bc39614
--- /dev/null
+++ b/alpinejs/packages/portal/builds/module.js
@@ -0,0 +1,3 @@
+import portal from './../src/index.js'
+
+export default portal
diff --git a/alpinejs/packages/portal/package.json b/alpinejs/packages/portal/package.json
new file mode 100644
index 0000000..7e65407
--- /dev/null
+++ b/alpinejs/packages/portal/package.json
@@ -0,0 +1,11 @@
+{
+ "name": "@alpinejs/portal",
+ "version": "3.6.1-beta.0",
+ "description": "Send Alpine templates to other parts of the DOM",
+ "author": "Caleb Porzio",
+ "license": "MIT",
+ "main": "dist/module.cjs.js",
+ "module": "dist/module.esm.js",
+ "unpkg": "dist/cdn.min.js",
+ "dependencies": {}
+}
diff --git a/alpinejs/packages/portal/src/index.js b/alpinejs/packages/portal/src/index.js
new file mode 100644
index 0000000..fd45bad
--- /dev/null
+++ b/alpinejs/packages/portal/src/index.js
@@ -0,0 +1,62 @@
+export default function (Alpine) {
+ let portals = new MapSet
+
+ Alpine.directive('portal', (el, { expression }, { effect, cleanup }) => {
+ let clone = el.content.cloneNode(true).firstElementChild
+ // Add reference to element on <template x-portal, and visa versa.
+ el._x_portal = clone
+ clone._x_portal_back = el
+
+ let init = (target) => {
+ // Forward event listeners:
+ if (el._x_forwardEvents) {
+ el._x_forwardEvents.forEach(eventName => {
+ clone.addEventListener(eventName, e => {
+ e.stopPropagation()
+
+ el.dispatchEvent(new e.constructor(e.type, e))
+ })
+ })
+ }
+
+ Alpine.addScopeToNode(clone, {}, el)
+
+ Alpine.mutateDom(() => {
+ target.before(clone)
+
+ Alpine.initTree(clone)
+ })
+
+ cleanup(() => {
+ clone.remove()
+
+ portals.delete(expression, init)
+ })
+ }
+
+ portals.add(expression, init)
+ })
+
+ Alpine.addInitSelector(() => `[${Alpine.prefixed('portal-target')}]`)
+ Alpine.directive('portal-target', (el, { expression }) => {
+ portals.each(expression, initPortal => initPortal(el))
+ })
+}
+
+class MapSet {
+ map = new Map
+
+ get(name) {
+ if (! this.map.has(name)) this.map.set(name, new Set)
+
+ return this.map.get(name)
+ }
+
+ add(name, value) { this.get(name).add(value) }
+
+ each(name, callback) { this.map.get(name).forEach(callback) }
+
+ delete(name, value) {
+ this.map.get(name).delete(value)
+ }
+}