diff --git a/examples/alpinejs/README.md b/examples/alpinejs/README.md
new file mode 100644
index 0000000000..6fe1a1cf36
--- /dev/null
+++ b/examples/alpinejs/README.md
@@ -0,0 +1,20 @@
+# Alpine.js TodoMVC Example
+
+> Alpine is a rugged, minimal tool for composing behavior directly in your markup. Think of it like jQuery for the modern web. Plop in a script tag and get going. [Caleb Porzio](https://calebporzio.com/)
+
+> _[Alpine.js - alpinejs.dev](https://alpinejs.dev/)_
+
+## Learning Alpine.js
+
+The [Alpine.js website](https://alpinejs.dev/) is a great resource to get started.
+
+Get help from other Alpine.js users:
+
+* [Alpine.js on Twitter](https://twitter.com/Alpine_JS)
+* [Creator of Alpine.js on Twitter](https://twitter.com/Alpine_JS)
+* [Code with Hugo (core contributor)](https://alpinejs.codewithhugo.com/)
+* [Alpine Toolbox](https://www.alpinetoolbox.com/)
+
+## Credit
+
+This TodoMVC application was created by [Mansoor Khan](https://twitter.com/i_mansoorkhan).
diff --git a/examples/alpinejs/index.html b/examples/alpinejs/index.html
new file mode 100644
index 0000000000..c778fccb58
--- /dev/null
+++ b/examples/alpinejs/index.html
@@ -0,0 +1,147 @@
+
+
+
+
+
+ Alpine.js • TodoMVC
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/alpinejs/node_modules/alpinejs/builds/cdn.js b/examples/alpinejs/node_modules/alpinejs/builds/cdn.js
new file mode 100644
index 0000000000..a54e7e050b
--- /dev/null
+++ b/examples/alpinejs/node_modules/alpinejs/builds/cdn.js
@@ -0,0 +1,7 @@
+import Alpine from './../src/index'
+
+window.Alpine = Alpine
+
+queueMicrotask(() => {
+ Alpine.start()
+})
diff --git a/examples/alpinejs/node_modules/alpinejs/builds/module.js b/examples/alpinejs/node_modules/alpinejs/builds/module.js
new file mode 100644
index 0000000000..03820803dd
--- /dev/null
+++ b/examples/alpinejs/node_modules/alpinejs/builds/module.js
@@ -0,0 +1,3 @@
+import Alpine from './../src/index'
+
+export default Alpine
diff --git a/examples/alpinejs/node_modules/alpinejs/dist/cdn.js b/examples/alpinejs/node_modules/alpinejs/dist/cdn.js
new file mode 100644
index 0000000000..c7b585a0bf
--- /dev/null
+++ b/examples/alpinejs/node_modules/alpinejs/dist/cdn.js
@@ -0,0 +1,2515 @@
+(() => {
+ // packages/alpinejs/src/scheduler.js
+ var flushPending = false;
+ var flushing = false;
+ var queue = [];
+ function scheduler(callback) {
+ queueJob(callback);
+ }
+ function queueJob(job) {
+ if (!queue.includes(job))
+ queue.push(job);
+ queueFlush();
+ }
+ function queueFlush() {
+ if (!flushing && !flushPending) {
+ flushPending = true;
+ queueMicrotask(flushJobs);
+ }
+ }
+ function flushJobs() {
+ flushPending = false;
+ flushing = true;
+ for (let i = 0; i < queue.length; i++) {
+ queue[i]();
+ }
+ queue.length = 0;
+ flushing = false;
+ }
+
+ // packages/alpinejs/src/reactivity.js
+ var reactive;
+ var effect;
+ var release;
+ var raw;
+ var shouldSchedule = true;
+ function disableEffectScheduling(callback) {
+ shouldSchedule = false;
+ callback();
+ shouldSchedule = true;
+ }
+ 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;
+ }
+ function overrideEffect(override) {
+ effect = override;
+ }
+ function elementBoundEffect(el) {
+ let cleanup2 = () => {
+ };
+ let wrappedEffect = (callback) => {
+ let effectReference = effect(callback);
+ if (!el._x_effects) {
+ el._x_effects = new Set();
+ el._x_runEffects = () => {
+ el._x_effects.forEach((i) => i());
+ };
+ }
+ el._x_effects.add(effectReference);
+ cleanup2 = () => {
+ if (effectReference === void 0)
+ return;
+ el._x_effects.delete(effectReference);
+ release(effectReference);
+ };
+ };
+ return [wrappedEffect, () => {
+ cleanup2();
+ }];
+ }
+
+ // packages/alpinejs/src/mutation.js
+ var onAttributeAddeds = [];
+ var onElRemoveds = [];
+ var onElAddeds = [];
+ function onElAdded(callback) {
+ onElAddeds.push(callback);
+ }
+ function onElRemoved(callback) {
+ onElRemoveds.push(callback);
+ }
+ function onAttributesAdded(callback) {
+ onAttributeAddeds.push(callback);
+ }
+ 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);
+ }
+ function cleanupAttributes(el, names) {
+ if (!el._x_attributeCleanups)
+ return;
+ Object.entries(el._x_attributeCleanups).forEach(([name, value]) => {
+ (names === void 0 || names.includes(name)) && value.forEach((i) => i());
+ delete el._x_attributeCleanups[name];
+ });
+ }
+ var observer = new MutationObserver(onMutate);
+ var currentlyObserving = false;
+ function startObservingMutations() {
+ observer.observe(document, {subtree: true, childList: true, attributes: true, attributeOldValue: true});
+ currentlyObserving = true;
+ }
+ function stopObservingMutations() {
+ observer.disconnect();
+ currentlyObserving = false;
+ }
+ var recordQueue = [];
+ var willProcessRecordQueue = false;
+ function flushObserver() {
+ recordQueue = recordQueue.concat(observer.takeRecords());
+ if (recordQueue.length && !willProcessRecordQueue) {
+ willProcessRecordQueue = true;
+ queueMicrotask(() => {
+ processRecordQueue();
+ willProcessRecordQueue = false;
+ });
+ }
+ }
+ function processRecordQueue() {
+ onMutate(recordQueue);
+ recordQueue.length = 0;
+ }
+ function mutateDom(callback) {
+ if (!currentlyObserving)
+ return callback();
+ flushObserver();
+ stopObservingMutations();
+ let result = callback();
+ startObservingMutations();
+ return result;
+ }
+ function onMutate(mutations) {
+ 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 add2 = () => {
+ 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);
+ };
+ if (el.hasAttribute(name) && oldValue === null) {
+ add2();
+ } else if (el.hasAttribute(name)) {
+ remove();
+ add2();
+ } else {
+ remove();
+ }
+ }
+ }
+ removedAttributes.forEach((attrs, el) => {
+ cleanupAttributes(el, attrs);
+ });
+ 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));
+ }
+ addedNodes = null;
+ removedNodes = null;
+ addedAttributes = null;
+ removedAttributes = null;
+ }
+
+ // packages/alpinejs/src/scope.js
+ 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) {
+ let existingScope = element._x_dataStack[0];
+ Object.entries(scope).forEach(([key, value]) => {
+ existingScope[key] = value;
+ });
+ }
+ function closestDataStack(node) {
+ if (node._x_dataStack)
+ return node._x_dataStack;
+ if (node instanceof ShadowRoot) {
+ return closestDataStack(node.host);
+ }
+ if (!node.parentNode) {
+ return [];
+ }
+ return closestDataStack(node.parentNode);
+ }
+ function mergeProxies(objects) {
+ return 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) => obj.hasOwnProperty(name)) || {})[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;
+ }
+ });
+ }
+
+ // packages/alpinejs/src/interceptor.js
+ function initInterceptors(data2) {
+ let isObject2 = (val) => typeof val === "object" && !Array.isArray(val) && val !== null;
+ let recurse = (obj, basePath = "") => {
+ Object.entries(obj).forEach(([key, value]) => {
+ let path = basePath === "" ? key : `${basePath}.${key}`;
+ if (typeof value === "object" && value !== null && value._x_interceptor) {
+ obj[key] = value.initialize(data2, path, key);
+ } else {
+ if (isObject2(value) && value !== obj && !(value instanceof Element)) {
+ recurse(value, path);
+ }
+ }
+ });
+ };
+ return recurse(data2);
+ }
+ function interceptor(callback, mutateObj = () => {
+ }) {
+ let obj = {
+ initialValue: void 0,
+ _x_interceptor: true,
+ initialize(data2, path, key) {
+ return callback(this.initialValue, () => get(data2, path), (value) => set(data2, path, value), path, key);
+ }
+ };
+ mutateObj(obj);
+ return (initialValue) => {
+ if (typeof initialValue === "object" && initialValue !== null && initialValue._x_interceptor) {
+ let initialize = obj.initialize.bind(obj);
+ obj.initialize = (data2, path, key) => {
+ let innerValue = initialValue.initialize(data2, path, key);
+ obj.initialValue = innerValue;
+ return initialize(data2, 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);
+ }
+ }
+ }
+
+ // packages/alpinejs/src/magics.js
+ var magics = {};
+ function magic(name, callback) {
+ magics[name] = callback;
+ }
+ function injectMagics(obj, el) {
+ Object.entries(magics).forEach(([name, callback]) => {
+ Object.defineProperty(obj, `$${name}`, {
+ get() {
+ return callback(el, {Alpine: alpine_default, interceptor});
+ },
+ enumerable: false
+ });
+ });
+ return obj;
+ }
+
+ // packages/alpinejs/src/evaluator.js
+ function evaluate(el, expression, extras = {}) {
+ let result;
+ evaluateLater(el, expression)((value) => result = value, extras);
+ return result;
+ }
+ function evaluateLater(...args) {
+ return theEvaluatorFunction(...args);
+ }
+ var theEvaluatorFunction = normalEvaluator;
+ function setEvaluator(newEvaluator) {
+ theEvaluatorFunction = newEvaluator;
+ }
+ function normalEvaluator(el, expression) {
+ let overriddenMagics = {};
+ injectMagics(overriddenMagics, el);
+ let dataStack = [overriddenMagics, ...closestDataStack(el)];
+ if (typeof expression === "function") {
+ return generateEvaluatorFromFunction(dataStack, expression);
+ }
+ let evaluator = generateEvaluatorFromString(dataStack, expression);
+ return tryCatch.bind(null, el, expression, evaluator);
+ }
+ function generateEvaluatorFromFunction(dataStack, func) {
+ return (receiver = () => {
+ }, {scope = {}, params = []} = {}) => {
+ let result = func.apply(mergeProxies([scope, ...dataStack]), params);
+ runIfTypeOfFunction(receiver, result);
+ };
+ }
+ var evaluatorMemo = {};
+ function generateFunctionFromString(expression) {
+ if (evaluatorMemo[expression]) {
+ return evaluatorMemo[expression];
+ }
+ let AsyncFunction = Object.getPrototypeOf(async function() {
+ }).constructor;
+ let rightSideSafeExpression = /^[\n\s]*if.*\(.*\)/.test(expression) || /^(let|const)/.test(expression) ? `(() => { ${expression} })()` : expression;
+ let func = new AsyncFunction(["__self", "scope"], `with (scope) { __self.result = ${rightSideSafeExpression} }; __self.finished = true; return __self.result;`);
+ evaluatorMemo[expression] = func;
+ return func;
+ }
+ function generateEvaluatorFromString(dataStack, expression) {
+ let func = generateFunctionFromString(expression);
+ return (receiver = () => {
+ }, {scope = {}, params = []} = {}) => {
+ func.result = void 0;
+ func.finished = false;
+ let completeScope = mergeProxies([scope, ...dataStack]);
+ let promise = func(func, completeScope);
+ if (func.finished) {
+ runIfTypeOfFunction(receiver, func.result, completeScope, params);
+ } else {
+ promise.then((result) => {
+ runIfTypeOfFunction(receiver, result, completeScope, params);
+ });
+ }
+ };
+ }
+ function runIfTypeOfFunction(receiver, value, scope, params) {
+ if (typeof value === "function") {
+ let result = value.apply(scope, params);
+ if (result instanceof Promise) {
+ result.then((i) => runIfTypeOfFunction(receiver, i, scope, params));
+ } else {
+ receiver(result);
+ }
+ } else {
+ receiver(value);
+ }
+ }
+ function tryCatch(el, expression, callback, ...args) {
+ try {
+ return callback(...args);
+ } catch (e) {
+ console.warn(`Alpine Expression Error: ${e.message}
+
+Expression: "${expression}"
+
+`, el);
+ throw e;
+ }
+ }
+
+ // packages/alpinejs/src/directives.js
+ var prefixAsString = "x-";
+ function prefix(subject = "") {
+ return prefixAsString + subject;
+ }
+ function setPrefix(newPrefix) {
+ prefixAsString = newPrefix;
+ }
+ var directiveHandlers = {};
+ function directive(name, callback) {
+ directiveHandlers[name] = callback;
+ }
+ function directives(el, attributes, originalAttributeOverride) {
+ let transformedAttributeMap = {};
+ let directives2 = Array.from(attributes).map(toTransformedAttributes((newName, oldName) => transformedAttributeMap[newName] = oldName)).filter(outNonAlpineAttributes).map(toParsedDirectives(transformedAttributeMap, originalAttributeOverride)).sort(byPriority);
+ return directives2.map((directive2) => {
+ return getDirectiveHandler(el, directive2);
+ });
+ }
+ var isDeferringHandlers = false;
+ var directiveHandlerStack = [];
+ function deferHandlingDirectives(callback) {
+ isDeferringHandlers = true;
+ let flushHandlers = () => {
+ while (directiveHandlerStack.length)
+ directiveHandlerStack.shift()();
+ };
+ let stopDeferring = () => {
+ isDeferringHandlers = false;
+ flushHandlers();
+ };
+ callback(flushHandlers);
+ stopDeferring();
+ }
+ function getDirectiveHandler(el, directive2) {
+ let noop = () => {
+ };
+ let handler3 = directiveHandlers[directive2.type] || noop;
+ let cleanups = [];
+ let cleanup2 = (callback) => cleanups.push(callback);
+ let [effect3, cleanupEffect] = elementBoundEffect(el);
+ cleanups.push(cleanupEffect);
+ let utilities = {
+ Alpine: alpine_default,
+ effect: effect3,
+ cleanup: cleanup2,
+ evaluateLater: evaluateLater.bind(evaluateLater, el),
+ evaluate: evaluate.bind(evaluate, el)
+ };
+ let doCleanup = () => cleanups.forEach((i) => i());
+ onAttributeRemoved(el, directive2.original, doCleanup);
+ let fullHandler = () => {
+ if (el._x_ignore || el._x_ignoreSelf)
+ return;
+ handler3.inline && handler3.inline(el, directive2, utilities);
+ handler3 = handler3.bind(handler3, el, directive2, utilities);
+ isDeferringHandlers ? directiveHandlerStack.push(handler3) : handler3();
+ };
+ fullHandler.runCleanups = doCleanup;
+ return fullHandler;
+ }
+ var startingWith = (subject, replacement) => ({name, value}) => {
+ if (name.startsWith(subject))
+ name = name.replace(subject, replacement);
+ return {name, value};
+ };
+ var 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};
+ };
+ }
+ var attributeTransformers = [];
+ function mapAttributes(callback) {
+ attributeTransformers.push(callback);
+ }
+ function outNonAlpineAttributes({name}) {
+ return alpineAttributeRegex().test(name);
+ }
+ var 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
+ };
+ };
+ }
+ var DEFAULT = "DEFAULT";
+ var directiveOrder = [
+ "ignore",
+ "ref",
+ "data",
+ "bind",
+ "init",
+ "for",
+ "model",
+ "transition",
+ "show",
+ "if",
+ DEFAULT,
+ "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);
+ }
+
+ // packages/alpinejs/src/utils/dispatch.js
+ function dispatch(el, name, detail = {}) {
+ el.dispatchEvent(new CustomEvent(name, {
+ detail,
+ bubbles: true,
+ composed: true,
+ cancelable: true
+ }));
+ }
+
+ // packages/alpinejs/src/nextTick.js
+ var tickStack = [];
+ var isHolding = false;
+ function nextTick(callback) {
+ tickStack.push(callback);
+ queueMicrotask(() => {
+ isHolding || setTimeout(() => {
+ releaseNextTicks();
+ });
+ });
+ }
+ function releaseNextTicks() {
+ isHolding = false;
+ while (tickStack.length)
+ tickStack.shift()();
+ }
+ function holdNextTicks() {
+ isHolding = true;
+ }
+
+ // packages/alpinejs/src/utils/walk.js
+ function walk(el, callback) {
+ if (el instanceof ShadowRoot) {
+ Array.from(el.children).forEach((el2) => walk(el2, 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;
+ }
+ }
+
+ // packages/alpinejs/src/utils/warn.js
+ function warn(message, ...args) {
+ console.warn(`Alpine Warning: ${message}`, ...args);
+ }
+
+ // packages/alpinejs/src/lifecycle.js
+ function start() {
+ if (!document.body)
+ warn("Unable to initialize. Trying to load Alpine before `` is available. Did you forget to add `defer` in Alpine's `