@alivecss/aliveui 1.2.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +44 -13
- package/dist/index.js +44 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +44 -13
- package/dist/index.mjs.map +1 -1
- package/dist/runtime.js +74 -0
- package/dist/runtime.js.map +1 -1
- package/dist/runtime.mjs +74 -0
- package/dist/runtime.mjs.map +1 -1
- package/dist/vite.js +44 -13
- package/dist/vite.js.map +1 -1
- package/dist/vite.mjs +44 -13
- package/dist/vite.mjs.map +1 -1
- package/package.json +1 -1
package/dist/runtime.js
CHANGED
|
@@ -268,6 +268,79 @@ function wireMagnetic(el, root) {
|
|
|
268
268
|
registerCleanup(root, moveCleanup);
|
|
269
269
|
registerCleanup(root, leaveCleanup);
|
|
270
270
|
}
|
|
271
|
+
function resetSceneAnimations(scene) {
|
|
272
|
+
const animated = scene.querySelectorAll(
|
|
273
|
+
'[class*="alive-enter"], [class*="alive-loop"], .alive-typewriter, .alive-typewriter-fast, .alive-typewriter-slow, .alive-word-reveal > *, .alive-kinetic-slam, .alive-metric-card, .alive-toast, .alive-badge-pulse, .alive-spotlight, .alive-code-block'
|
|
274
|
+
);
|
|
275
|
+
animated.forEach((el) => {
|
|
276
|
+
const saved = el.style.animationName;
|
|
277
|
+
el.style.animationName = "none";
|
|
278
|
+
void el.offsetHeight;
|
|
279
|
+
el.style.animationName = saved;
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
function wireVideoSequence(container, root) {
|
|
283
|
+
const scenes = [...container.querySelectorAll(":scope > [data-alive-scene]")];
|
|
284
|
+
if (scenes.length === 0) return;
|
|
285
|
+
const loop = container.hasAttribute("data-alive-loop");
|
|
286
|
+
let current = 0;
|
|
287
|
+
let timeoutId = null;
|
|
288
|
+
const containerEl = container;
|
|
289
|
+
if (getComputedStyle(containerEl).position === "static") {
|
|
290
|
+
containerEl.style.position = "relative";
|
|
291
|
+
}
|
|
292
|
+
containerEl.style.overflow = "hidden";
|
|
293
|
+
scenes.forEach((s) => {
|
|
294
|
+
s.style.position = "absolute";
|
|
295
|
+
s.style.inset = "0";
|
|
296
|
+
s.classList.remove("is-active");
|
|
297
|
+
});
|
|
298
|
+
function activate(index) {
|
|
299
|
+
const scene = scenes[index];
|
|
300
|
+
resetSceneAnimations(scene);
|
|
301
|
+
scene.classList.add("is-active");
|
|
302
|
+
scene.style.zIndex = "1";
|
|
303
|
+
}
|
|
304
|
+
function scheduleNext(fromIndex) {
|
|
305
|
+
const scene = scenes[fromIndex];
|
|
306
|
+
const duration = parseInt(scene.getAttribute("data-alive-duration") ?? "3000", 10);
|
|
307
|
+
timeoutId = setTimeout(() => {
|
|
308
|
+
const nextIndex = fromIndex + 1;
|
|
309
|
+
const toIndex = nextIndex >= scenes.length ? loop ? 0 : -1 : nextIndex;
|
|
310
|
+
if (toIndex === -1) return;
|
|
311
|
+
doTransition(fromIndex, toIndex);
|
|
312
|
+
}, duration);
|
|
313
|
+
}
|
|
314
|
+
function doTransition(fromIndex, toIndex) {
|
|
315
|
+
const outScene = scenes[fromIndex];
|
|
316
|
+
const inScene = scenes[toIndex];
|
|
317
|
+
const transType = outScene.getAttribute("data-alive-transition") ?? "fade";
|
|
318
|
+
const transDur = parseInt(outScene.getAttribute("data-alive-trans-duration") ?? "600", 10);
|
|
319
|
+
const outClass = `alive-transition-${transType}-out`;
|
|
320
|
+
const inClass = `alive-transition-${transType}-in`;
|
|
321
|
+
outScene.style.setProperty("--alive-tr-dur", `${transDur}ms`);
|
|
322
|
+
inScene.style.setProperty("--alive-tr-dur", `${transDur}ms`);
|
|
323
|
+
outScene.style.zIndex = "2";
|
|
324
|
+
outScene.classList.add(outClass);
|
|
325
|
+
inScene.style.zIndex = "1";
|
|
326
|
+
resetSceneAnimations(inScene);
|
|
327
|
+
inScene.classList.add("is-active", inClass);
|
|
328
|
+
timeoutId = setTimeout(() => {
|
|
329
|
+
outScene.classList.remove("is-active", outClass);
|
|
330
|
+
outScene.style.zIndex = "";
|
|
331
|
+
outScene.style.removeProperty("--alive-tr-dur");
|
|
332
|
+
inScene.classList.remove(inClass);
|
|
333
|
+
inScene.style.removeProperty("--alive-tr-dur");
|
|
334
|
+
current = toIndex;
|
|
335
|
+
scheduleNext(current);
|
|
336
|
+
}, transDur);
|
|
337
|
+
}
|
|
338
|
+
activate(current);
|
|
339
|
+
scheduleNext(current);
|
|
340
|
+
registerCleanup(root, () => {
|
|
341
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
342
|
+
});
|
|
343
|
+
}
|
|
271
344
|
function init(root = document.documentElement) {
|
|
272
345
|
root.querySelectorAll("[data-alive-accordion]").forEach((el) => wireAccordion(el, root));
|
|
273
346
|
root.querySelectorAll("[data-alive-modal]").forEach((el) => wireModal(el, root));
|
|
@@ -278,6 +351,7 @@ function init(root = document.documentElement) {
|
|
|
278
351
|
root.querySelectorAll("[data-alive-stagger]").forEach((el) => wireStagger(el));
|
|
279
352
|
root.querySelectorAll("[data-alive-tilt]").forEach((el) => wireTilt(el, root));
|
|
280
353
|
root.querySelectorAll("[data-alive-magnetic]").forEach((el) => wireMagnetic(el, root));
|
|
354
|
+
root.querySelectorAll("[data-alive-sequence]").forEach((el) => wireVideoSequence(el, root));
|
|
281
355
|
}
|
|
282
356
|
function destroy(root = document.documentElement) {
|
|
283
357
|
const cleanups = cleanupRegistry.get(root) ?? [];
|
package/dist/runtime.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/runtime.ts"],"sourcesContent":["/**\n * AliveUI Runtime\n *\n * Provides data-attribute-driven interactivity for accordion, modal, drawer,\n * dropdown, and tabs components — zero dependencies, ~2 KB.\n *\n * Usage:\n * import { init } from '@alivecss/aliveui/runtime'\n * init() // wire everything in document\n * init(myRootElement) // wire a subtree\n */\n\ntype Cleanup = () => void\n\nconst cleanupRegistry = new WeakMap<Element, Cleanup[]>()\n\nfunction registerCleanup(root: Element, fn: Cleanup): void {\n const existing = cleanupRegistry.get(root) ?? []\n existing.push(fn)\n cleanupRegistry.set(root, existing)\n}\n\nfunction addListener<K extends keyof HTMLElementEventMap>(\n el: EventTarget,\n type: K,\n handler: (e: HTMLElementEventMap[K]) => void,\n options?: AddEventListenerOptions,\n): Cleanup {\n el.addEventListener(type, handler as EventListener, options)\n return () => el.removeEventListener(type, handler as EventListener, options)\n}\n\n// ── Accordion ─────────────────────────────────────────────────────────────────\n\nfunction wireAccordion(container: Element, root: Element): void {\n const triggers = container.querySelectorAll<HTMLElement>('[data-alive-trigger]')\n triggers.forEach(trigger => {\n const item = trigger.closest('[data-alive-accordion-item]') ?? trigger.parentElement\n if (!item) return\n\n const cleanup = addListener(trigger, 'click', () => {\n const isOpen = item.classList.contains('is-open')\n // Close all items if not multi-open\n if (!container.hasAttribute('data-alive-multi')) {\n container.querySelectorAll('[data-alive-accordion-item]').forEach(i => {\n i.classList.remove('is-open')\n i.querySelector('[data-alive-trigger]')?.setAttribute('aria-expanded', 'false')\n })\n }\n if (!isOpen) {\n item.classList.add('is-open')\n trigger.setAttribute('aria-expanded', 'true')\n }\n })\n registerCleanup(root, cleanup)\n })\n}\n\n// ── Modal ─────────────────────────────────────────────────────────────────────\n\nfunction wireModal(modal: Element, root: Element): void {\n const id = modal.getAttribute('data-alive-modal')\n if (!id) return\n\n // Open triggers\n const openers = document.querySelectorAll<HTMLElement>(`[data-alive-open=\"${id}\"]`)\n openers.forEach(opener => {\n const cleanup = addListener(opener, 'click', () => openModal(id))\n registerCleanup(root, cleanup)\n })\n\n // Close triggers inside the modal\n modal.querySelectorAll<HTMLElement>('[data-alive-close]').forEach(closer => {\n const cleanup = addListener(closer, 'click', () => closeModal(id))\n registerCleanup(root, cleanup)\n })\n\n // Backdrop click to close (click on the modal wrapper, not the content)\n const cleanup = addListener(modal, 'click', (e) => {\n if (e.target === modal) closeModal(id)\n })\n registerCleanup(root, cleanup)\n\n // ESC key\n const escCleanup = addListener(document, 'keydown', (e) => {\n if (e.key === 'Escape' && modal.classList.contains('is-open')) closeModal(id)\n })\n registerCleanup(root, escCleanup)\n}\n\nexport function openModal(id: string): void {\n const modal = document.querySelector<HTMLElement>(`[data-alive-modal=\"${id}\"]`)\n if (!modal) return\n modal.classList.add('is-open')\n modal.setAttribute('aria-hidden', 'false')\n document.body.style.overflow = 'hidden'\n // Focus first focusable element\n const focusable = modal.querySelector<HTMLElement>(\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])',\n )\n focusable?.focus()\n}\n\nexport function closeModal(id: string): void {\n const modal = document.querySelector<HTMLElement>(`[data-alive-modal=\"${id}\"]`)\n if (!modal) return\n modal.classList.remove('is-open')\n modal.setAttribute('aria-hidden', 'true')\n document.body.style.overflow = ''\n}\n\n// ── Drawer ────────────────────────────────────────────────────────────────────\n\nfunction wireDrawer(drawer: Element, root: Element): void {\n const id = drawer.getAttribute('data-alive-drawer')\n if (!id) return\n\n const openers = document.querySelectorAll<HTMLElement>(`[data-alive-open=\"${id}\"]`)\n openers.forEach(opener => {\n const cleanup = addListener(opener, 'click', () => openDrawer(id))\n registerCleanup(root, cleanup)\n })\n\n drawer.querySelectorAll<HTMLElement>('[data-alive-close]').forEach(closer => {\n const cleanup = addListener(closer, 'click', () => closeDrawer(id))\n registerCleanup(root, cleanup)\n })\n\n const backdropCleanup = addListener(drawer, 'click', (e) => {\n if (e.target === drawer) closeDrawer(id)\n })\n registerCleanup(root, backdropCleanup)\n\n const escCleanup = addListener(document, 'keydown', (e) => {\n if (e.key === 'Escape' && drawer.classList.contains('is-open')) closeDrawer(id)\n })\n registerCleanup(root, escCleanup)\n}\n\nexport function openDrawer(id: string): void {\n const drawer = document.querySelector<HTMLElement>(`[data-alive-drawer=\"${id}\"]`)\n if (!drawer) return\n drawer.classList.add('is-open')\n drawer.setAttribute('aria-hidden', 'false')\n document.body.style.overflow = 'hidden'\n}\n\nexport function closeDrawer(id: string): void {\n const drawer = document.querySelector<HTMLElement>(`[data-alive-drawer=\"${id}\"]`)\n if (!drawer) return\n drawer.classList.remove('is-open')\n drawer.setAttribute('aria-hidden', 'true')\n document.body.style.overflow = ''\n}\n\n// ── Dropdown ──────────────────────────────────────────────────────────────────\n\nfunction wireDropdown(container: Element, root: Element): void {\n const trigger = container.querySelector<HTMLElement>('[data-alive-trigger]')\n const menu = container.querySelector<HTMLElement>('[data-alive-dropdown-menu]')\n if (!trigger || !menu) return\n\n const toggleCleanup = addListener(trigger, 'click', (e) => {\n e.stopPropagation()\n toggleDropdown(container)\n })\n registerCleanup(root, toggleCleanup)\n\n // Close on outside click\n const outsideCleanup = addListener(document, 'click', (e) => {\n if (!container.contains(e.target as Node)) {\n menu.classList.remove('is-open')\n trigger.setAttribute('aria-expanded', 'false')\n }\n })\n registerCleanup(root, outsideCleanup)\n\n // Close on ESC\n const escCleanup = addListener(document, 'keydown', (e) => {\n if (e.key === 'Escape' && menu.classList.contains('is-open')) {\n menu.classList.remove('is-open')\n trigger.setAttribute('aria-expanded', 'false')\n trigger.focus()\n }\n })\n registerCleanup(root, escCleanup)\n}\n\nexport function toggleDropdown(container: Element): void {\n const trigger = container.querySelector<HTMLElement>('[data-alive-trigger]')\n const menu = container.querySelector<HTMLElement>('[data-alive-dropdown-menu]')\n if (!menu) return\n const isOpen = menu.classList.toggle('is-open')\n trigger?.setAttribute('aria-expanded', String(isOpen))\n if (isOpen) {\n // Focus first item\n menu.querySelector<HTMLElement>('[role=\"menuitem\"], button, a')?.focus()\n }\n}\n\n// ── Tabs ──────────────────────────────────────────────────────────────────────\n\nfunction wireTabs(container: Element, root: Element): void {\n const tabs = container.querySelectorAll<HTMLElement>('[data-alive-tab]')\n tabs.forEach(tab => {\n const cleanup = addListener(tab, 'click', () => {\n const panelId = tab.getAttribute('data-alive-tab')\n if (!panelId) return\n activateTab(container, panelId)\n })\n registerCleanup(root, cleanup)\n\n // Keyboard navigation\n const keyCleanup = addListener(tab, 'keydown', (e) => {\n const allTabs = [...container.querySelectorAll<HTMLElement>('[data-alive-tab]')]\n const idx = allTabs.indexOf(tab)\n if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {\n e.preventDefault()\n allTabs[(idx + 1) % allTabs.length]?.focus()\n } else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {\n e.preventDefault()\n allTabs[(idx - 1 + allTabs.length) % allTabs.length]?.focus()\n }\n })\n registerCleanup(root, keyCleanup)\n })\n}\n\nfunction activateTab(container: Element, panelId: string): void {\n // Deactivate all tabs + panels within this tabs container\n container.querySelectorAll('[data-alive-tab]').forEach(t => {\n t.classList.remove('is-active')\n t.setAttribute('aria-selected', 'false')\n t.setAttribute('tabindex', '-1')\n })\n\n // Find panels — look in the container, then in the whole document\n const searchRoot = container.closest('[data-alive-tabs-panels]') ?? document\n searchRoot.querySelectorAll('[data-alive-panel]').forEach(p => {\n p.classList.remove('is-active')\n p.setAttribute('aria-hidden', 'true')\n })\n\n // Activate the selected tab\n const activeTab = container.querySelector<HTMLElement>(`[data-alive-tab=\"${panelId}\"]`)\n activeTab?.classList.add('is-active')\n activeTab?.setAttribute('aria-selected', 'true')\n activeTab?.setAttribute('tabindex', '0')\n\n // Activate the matching panel\n const activePanel = searchRoot.querySelector<HTMLElement>(`[data-alive-panel=\"${panelId}\"]`)\n activePanel?.classList.add('is-active')\n activePanel?.setAttribute('aria-hidden', 'false')\n}\n\n// ── Scroll Reveal ──────────────────────────────────────────────────────────────\n\nfunction wireScroll(el: Element, root: Element): void {\n const obs = new IntersectionObserver(\n (entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n entry.target.classList.add('is-visible')\n obs.unobserve(entry.target)\n }\n })\n },\n { threshold: 0.1, rootMargin: '0px 0px -40px 0px' },\n )\n obs.observe(el)\n registerCleanup(root, () => obs.disconnect())\n}\n\n// ── Auto-Stagger ───────────────────────────────────────────────────────────────\n\nfunction wireStagger(container: Element): void {\n const children = [...container.children] as HTMLElement[]\n children.forEach((child, i) => {\n child.style.setProperty('--alive-index', String(i))\n })\n}\n\n// ── 3D Tilt ────────────────────────────────────────────────────────────────────\n\nfunction wireTilt(el: Element, root: Element): void {\n const htmlEl = el as HTMLElement\n const STRENGTH = 8\n\n const moveCleanup = addListener(htmlEl, 'mousemove', (e) => {\n const rect = htmlEl.getBoundingClientRect()\n const x = (e.clientX - rect.left) / rect.width - 0.5\n const y = (e.clientY - rect.top) / rect.height - 0.5\n htmlEl.style.transform = `perspective(800px) rotateY(${x * STRENGTH}deg) rotateX(${-y * STRENGTH}deg) scale(1.01)`\n htmlEl.style.transition = 'transform 0.1s ease-out'\n })\n\n const leaveCleanup = addListener(htmlEl, 'mouseleave', () => {\n htmlEl.style.transform = ''\n htmlEl.style.transition = 'transform 0.4s cubic-bezier(0.16, 1, 0.3, 1)'\n })\n\n registerCleanup(root, moveCleanup)\n registerCleanup(root, leaveCleanup)\n}\n\n// ── Magnetic Follow ────────────────────────────────────────────────────────────\n\nfunction wireMagnetic(el: Element, root: Element): void {\n const htmlEl = el as HTMLElement\n const PULL = 0.35\n\n const moveCleanup = addListener(htmlEl, 'mousemove', (e) => {\n const rect = htmlEl.getBoundingClientRect()\n const cx = rect.left + rect.width / 2\n const cy = rect.top + rect.height / 2\n const dx = (e.clientX - cx) * PULL\n const dy = (e.clientY - cy) * PULL\n htmlEl.style.transform = `translate(${dx}px, ${dy}px)`\n htmlEl.style.transition = 'transform 0.2s cubic-bezier(0.16, 1, 0.3, 1)'\n })\n\n const leaveCleanup = addListener(htmlEl, 'mouseleave', () => {\n htmlEl.style.transform = ''\n htmlEl.style.transition = 'transform 0.5s cubic-bezier(0.16, 1, 0.3, 1)'\n })\n\n registerCleanup(root, moveCleanup)\n registerCleanup(root, leaveCleanup)\n}\n\n// ── Public API ────────────────────────────────────────────────────────────────\n\n/**\n * Wire all data-alive-* components within `root` (defaults to document.documentElement).\n * Safe to call multiple times — existing listeners are tracked and replaced on `destroy()`.\n */\nexport function init(root: Element = document.documentElement): void {\n // Accordion\n root.querySelectorAll('[data-alive-accordion]').forEach(el => wireAccordion(el, root))\n\n // Modal\n root.querySelectorAll('[data-alive-modal]').forEach(el => wireModal(el, root))\n\n // Drawer\n root.querySelectorAll('[data-alive-drawer]').forEach(el => wireDrawer(el, root))\n\n // Dropdown\n root.querySelectorAll('[data-alive-dropdown]').forEach(el => wireDropdown(el, root))\n\n // Tabs\n root.querySelectorAll('[data-alive-tabs]').forEach(el => wireTabs(el, root))\n\n // Scroll reveal\n root.querySelectorAll('[data-alive-scroll]').forEach(el => wireScroll(el, root))\n\n // Auto-stagger children\n root.querySelectorAll('[data-alive-stagger]').forEach(el => wireStagger(el))\n\n // 3D tilt\n root.querySelectorAll('[data-alive-tilt]').forEach(el => wireTilt(el, root))\n\n // Magnetic follow\n root.querySelectorAll('[data-alive-magnetic]').forEach(el => wireMagnetic(el, root))\n}\n\n/**\n * Remove all event listeners registered by `init(root)`.\n */\nexport function destroy(root: Element = document.documentElement): void {\n const cleanups = cleanupRegistry.get(root) ?? []\n cleanups.forEach(fn => fn())\n cleanupRegistry.delete(root)\n}\n"],"mappings":"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","names":["cleanup"]}
|
|
1
|
+
{"version":3,"sources":["../src/runtime.ts"],"sourcesContent":["/**\n * AliveUI Runtime\n *\n * Provides data-attribute-driven interactivity for accordion, modal, drawer,\n * dropdown, and tabs components — zero dependencies, ~2 KB.\n *\n * Usage:\n * import { init } from '@alivecss/aliveui/runtime'\n * init() // wire everything in document\n * init(myRootElement) // wire a subtree\n */\n\ntype Cleanup = () => void\n\nconst cleanupRegistry = new WeakMap<Element, Cleanup[]>()\n\nfunction registerCleanup(root: Element, fn: Cleanup): void {\n const existing = cleanupRegistry.get(root) ?? []\n existing.push(fn)\n cleanupRegistry.set(root, existing)\n}\n\nfunction addListener<K extends keyof HTMLElementEventMap>(\n el: EventTarget,\n type: K,\n handler: (e: HTMLElementEventMap[K]) => void,\n options?: AddEventListenerOptions,\n): Cleanup {\n el.addEventListener(type, handler as EventListener, options)\n return () => el.removeEventListener(type, handler as EventListener, options)\n}\n\n// ── Accordion ─────────────────────────────────────────────────────────────────\n\nfunction wireAccordion(container: Element, root: Element): void {\n const triggers = container.querySelectorAll<HTMLElement>('[data-alive-trigger]')\n triggers.forEach(trigger => {\n const item = trigger.closest('[data-alive-accordion-item]') ?? trigger.parentElement\n if (!item) return\n\n const cleanup = addListener(trigger, 'click', () => {\n const isOpen = item.classList.contains('is-open')\n // Close all items if not multi-open\n if (!container.hasAttribute('data-alive-multi')) {\n container.querySelectorAll('[data-alive-accordion-item]').forEach(i => {\n i.classList.remove('is-open')\n i.querySelector('[data-alive-trigger]')?.setAttribute('aria-expanded', 'false')\n })\n }\n if (!isOpen) {\n item.classList.add('is-open')\n trigger.setAttribute('aria-expanded', 'true')\n }\n })\n registerCleanup(root, cleanup)\n })\n}\n\n// ── Modal ─────────────────────────────────────────────────────────────────────\n\nfunction wireModal(modal: Element, root: Element): void {\n const id = modal.getAttribute('data-alive-modal')\n if (!id) return\n\n // Open triggers\n const openers = document.querySelectorAll<HTMLElement>(`[data-alive-open=\"${id}\"]`)\n openers.forEach(opener => {\n const cleanup = addListener(opener, 'click', () => openModal(id))\n registerCleanup(root, cleanup)\n })\n\n // Close triggers inside the modal\n modal.querySelectorAll<HTMLElement>('[data-alive-close]').forEach(closer => {\n const cleanup = addListener(closer, 'click', () => closeModal(id))\n registerCleanup(root, cleanup)\n })\n\n // Backdrop click to close (click on the modal wrapper, not the content)\n const cleanup = addListener(modal, 'click', (e) => {\n if (e.target === modal) closeModal(id)\n })\n registerCleanup(root, cleanup)\n\n // ESC key\n const escCleanup = addListener(document, 'keydown', (e) => {\n if (e.key === 'Escape' && modal.classList.contains('is-open')) closeModal(id)\n })\n registerCleanup(root, escCleanup)\n}\n\nexport function openModal(id: string): void {\n const modal = document.querySelector<HTMLElement>(`[data-alive-modal=\"${id}\"]`)\n if (!modal) return\n modal.classList.add('is-open')\n modal.setAttribute('aria-hidden', 'false')\n document.body.style.overflow = 'hidden'\n // Focus first focusable element\n const focusable = modal.querySelector<HTMLElement>(\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])',\n )\n focusable?.focus()\n}\n\nexport function closeModal(id: string): void {\n const modal = document.querySelector<HTMLElement>(`[data-alive-modal=\"${id}\"]`)\n if (!modal) return\n modal.classList.remove('is-open')\n modal.setAttribute('aria-hidden', 'true')\n document.body.style.overflow = ''\n}\n\n// ── Drawer ────────────────────────────────────────────────────────────────────\n\nfunction wireDrawer(drawer: Element, root: Element): void {\n const id = drawer.getAttribute('data-alive-drawer')\n if (!id) return\n\n const openers = document.querySelectorAll<HTMLElement>(`[data-alive-open=\"${id}\"]`)\n openers.forEach(opener => {\n const cleanup = addListener(opener, 'click', () => openDrawer(id))\n registerCleanup(root, cleanup)\n })\n\n drawer.querySelectorAll<HTMLElement>('[data-alive-close]').forEach(closer => {\n const cleanup = addListener(closer, 'click', () => closeDrawer(id))\n registerCleanup(root, cleanup)\n })\n\n const backdropCleanup = addListener(drawer, 'click', (e) => {\n if (e.target === drawer) closeDrawer(id)\n })\n registerCleanup(root, backdropCleanup)\n\n const escCleanup = addListener(document, 'keydown', (e) => {\n if (e.key === 'Escape' && drawer.classList.contains('is-open')) closeDrawer(id)\n })\n registerCleanup(root, escCleanup)\n}\n\nexport function openDrawer(id: string): void {\n const drawer = document.querySelector<HTMLElement>(`[data-alive-drawer=\"${id}\"]`)\n if (!drawer) return\n drawer.classList.add('is-open')\n drawer.setAttribute('aria-hidden', 'false')\n document.body.style.overflow = 'hidden'\n}\n\nexport function closeDrawer(id: string): void {\n const drawer = document.querySelector<HTMLElement>(`[data-alive-drawer=\"${id}\"]`)\n if (!drawer) return\n drawer.classList.remove('is-open')\n drawer.setAttribute('aria-hidden', 'true')\n document.body.style.overflow = ''\n}\n\n// ── Dropdown ──────────────────────────────────────────────────────────────────\n\nfunction wireDropdown(container: Element, root: Element): void {\n const trigger = container.querySelector<HTMLElement>('[data-alive-trigger]')\n const menu = container.querySelector<HTMLElement>('[data-alive-dropdown-menu]')\n if (!trigger || !menu) return\n\n const toggleCleanup = addListener(trigger, 'click', (e) => {\n e.stopPropagation()\n toggleDropdown(container)\n })\n registerCleanup(root, toggleCleanup)\n\n // Close on outside click\n const outsideCleanup = addListener(document, 'click', (e) => {\n if (!container.contains(e.target as Node)) {\n menu.classList.remove('is-open')\n trigger.setAttribute('aria-expanded', 'false')\n }\n })\n registerCleanup(root, outsideCleanup)\n\n // Close on ESC\n const escCleanup = addListener(document, 'keydown', (e) => {\n if (e.key === 'Escape' && menu.classList.contains('is-open')) {\n menu.classList.remove('is-open')\n trigger.setAttribute('aria-expanded', 'false')\n trigger.focus()\n }\n })\n registerCleanup(root, escCleanup)\n}\n\nexport function toggleDropdown(container: Element): void {\n const trigger = container.querySelector<HTMLElement>('[data-alive-trigger]')\n const menu = container.querySelector<HTMLElement>('[data-alive-dropdown-menu]')\n if (!menu) return\n const isOpen = menu.classList.toggle('is-open')\n trigger?.setAttribute('aria-expanded', String(isOpen))\n if (isOpen) {\n // Focus first item\n menu.querySelector<HTMLElement>('[role=\"menuitem\"], button, a')?.focus()\n }\n}\n\n// ── Tabs ──────────────────────────────────────────────────────────────────────\n\nfunction wireTabs(container: Element, root: Element): void {\n const tabs = container.querySelectorAll<HTMLElement>('[data-alive-tab]')\n tabs.forEach(tab => {\n const cleanup = addListener(tab, 'click', () => {\n const panelId = tab.getAttribute('data-alive-tab')\n if (!panelId) return\n activateTab(container, panelId)\n })\n registerCleanup(root, cleanup)\n\n // Keyboard navigation\n const keyCleanup = addListener(tab, 'keydown', (e) => {\n const allTabs = [...container.querySelectorAll<HTMLElement>('[data-alive-tab]')]\n const idx = allTabs.indexOf(tab)\n if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {\n e.preventDefault()\n allTabs[(idx + 1) % allTabs.length]?.focus()\n } else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {\n e.preventDefault()\n allTabs[(idx - 1 + allTabs.length) % allTabs.length]?.focus()\n }\n })\n registerCleanup(root, keyCleanup)\n })\n}\n\nfunction activateTab(container: Element, panelId: string): void {\n // Deactivate all tabs + panels within this tabs container\n container.querySelectorAll('[data-alive-tab]').forEach(t => {\n t.classList.remove('is-active')\n t.setAttribute('aria-selected', 'false')\n t.setAttribute('tabindex', '-1')\n })\n\n // Find panels — look in the container, then in the whole document\n const searchRoot = container.closest('[data-alive-tabs-panels]') ?? document\n searchRoot.querySelectorAll('[data-alive-panel]').forEach(p => {\n p.classList.remove('is-active')\n p.setAttribute('aria-hidden', 'true')\n })\n\n // Activate the selected tab\n const activeTab = container.querySelector<HTMLElement>(`[data-alive-tab=\"${panelId}\"]`)\n activeTab?.classList.add('is-active')\n activeTab?.setAttribute('aria-selected', 'true')\n activeTab?.setAttribute('tabindex', '0')\n\n // Activate the matching panel\n const activePanel = searchRoot.querySelector<HTMLElement>(`[data-alive-panel=\"${panelId}\"]`)\n activePanel?.classList.add('is-active')\n activePanel?.setAttribute('aria-hidden', 'false')\n}\n\n// ── Scroll Reveal ──────────────────────────────────────────────────────────────\n\nfunction wireScroll(el: Element, root: Element): void {\n const obs = new IntersectionObserver(\n (entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n entry.target.classList.add('is-visible')\n obs.unobserve(entry.target)\n }\n })\n },\n { threshold: 0.1, rootMargin: '0px 0px -40px 0px' },\n )\n obs.observe(el)\n registerCleanup(root, () => obs.disconnect())\n}\n\n// ── Auto-Stagger ───────────────────────────────────────────────────────────────\n\nfunction wireStagger(container: Element): void {\n const children = [...container.children] as HTMLElement[]\n children.forEach((child, i) => {\n child.style.setProperty('--alive-index', String(i))\n })\n}\n\n// ── 3D Tilt ────────────────────────────────────────────────────────────────────\n\nfunction wireTilt(el: Element, root: Element): void {\n const htmlEl = el as HTMLElement\n const STRENGTH = 8\n\n const moveCleanup = addListener(htmlEl, 'mousemove', (e) => {\n const rect = htmlEl.getBoundingClientRect()\n const x = (e.clientX - rect.left) / rect.width - 0.5\n const y = (e.clientY - rect.top) / rect.height - 0.5\n htmlEl.style.transform = `perspective(800px) rotateY(${x * STRENGTH}deg) rotateX(${-y * STRENGTH}deg) scale(1.01)`\n htmlEl.style.transition = 'transform 0.1s ease-out'\n })\n\n const leaveCleanup = addListener(htmlEl, 'mouseleave', () => {\n htmlEl.style.transform = ''\n htmlEl.style.transition = 'transform 0.4s cubic-bezier(0.16, 1, 0.3, 1)'\n })\n\n registerCleanup(root, moveCleanup)\n registerCleanup(root, leaveCleanup)\n}\n\n// ── Magnetic Follow ────────────────────────────────────────────────────────────\n\nfunction wireMagnetic(el: Element, root: Element): void {\n const htmlEl = el as HTMLElement\n const PULL = 0.35\n\n const moveCleanup = addListener(htmlEl, 'mousemove', (e) => {\n const rect = htmlEl.getBoundingClientRect()\n const cx = rect.left + rect.width / 2\n const cy = rect.top + rect.height / 2\n const dx = (e.clientX - cx) * PULL\n const dy = (e.clientY - cy) * PULL\n htmlEl.style.transform = `translate(${dx}px, ${dy}px)`\n htmlEl.style.transition = 'transform 0.2s cubic-bezier(0.16, 1, 0.3, 1)'\n })\n\n const leaveCleanup = addListener(htmlEl, 'mouseleave', () => {\n htmlEl.style.transform = ''\n htmlEl.style.transition = 'transform 0.5s cubic-bezier(0.16, 1, 0.3, 1)'\n })\n\n registerCleanup(root, moveCleanup)\n registerCleanup(root, leaveCleanup)\n}\n\n// ── Video Scene Sequencer ──────────────────────────────────────────────────────\n\n/**\n * Force-restart CSS animations on all animated children of a scene element.\n * This ensures stagger delays are relative to scene activation, not page load.\n */\nfunction resetSceneAnimations(scene: HTMLElement): void {\n const animated = scene.querySelectorAll<HTMLElement>(\n '[class*=\"alive-enter\"], [class*=\"alive-loop\"], ' +\n '.alive-typewriter, .alive-typewriter-fast, .alive-typewriter-slow, ' +\n '.alive-word-reveal > *, .alive-kinetic-slam, ' +\n '.alive-metric-card, .alive-toast, .alive-badge-pulse, ' +\n '.alive-spotlight, .alive-code-block',\n )\n animated.forEach(el => {\n const saved = el.style.animationName\n el.style.animationName = 'none'\n void el.offsetHeight // force reflow — restarts animation from t=0\n el.style.animationName = saved\n })\n}\n\n/**\n * Wire a [data-alive-sequence] container.\n *\n * Markup:\n * <div data-alive-sequence data-alive-loop style=\"position:relative; width:800px; height:500px;\">\n * <div data-alive-scene data-alive-duration=\"3000\" data-alive-transition=\"wipe-left\">…</div>\n * <div data-alive-scene data-alive-duration=\"2500\" data-alive-transition=\"fade\">…</div>\n * </div>\n *\n * Scene attributes:\n * data-alive-duration — how long to show the scene (ms, default 3000)\n * data-alive-transition — transition type (default \"fade\"; matches alive-transition-* classes)\n * data-alive-trans-duration — transition animation duration (ms, default 600)\n *\n * Sequence attributes:\n * data-alive-loop — loop back to the first scene after the last\n */\nfunction wireVideoSequence(container: Element, root: Element): void {\n const scenes = [...container.querySelectorAll<HTMLElement>(':scope > [data-alive-scene]')]\n if (scenes.length === 0) return\n\n const loop = container.hasAttribute('data-alive-loop')\n let current = 0\n let timeoutId: ReturnType<typeof setTimeout> | null = null\n\n const containerEl = container as HTMLElement\n if (getComputedStyle(containerEl).position === 'static') {\n containerEl.style.position = 'relative'\n }\n containerEl.style.overflow = 'hidden'\n\n scenes.forEach(s => {\n s.style.position = 'absolute'\n s.style.inset = '0'\n s.classList.remove('is-active')\n })\n\n function activate(index: number): void {\n const scene = scenes[index]\n resetSceneAnimations(scene)\n scene.classList.add('is-active')\n scene.style.zIndex = '1'\n }\n\n function scheduleNext(fromIndex: number): void {\n const scene = scenes[fromIndex]\n const duration = parseInt(scene.getAttribute('data-alive-duration') ?? '3000', 10)\n\n timeoutId = setTimeout(() => {\n const nextIndex = fromIndex + 1\n const toIndex = nextIndex >= scenes.length ? (loop ? 0 : -1) : nextIndex\n if (toIndex === -1) return\n doTransition(fromIndex, toIndex)\n }, duration)\n }\n\n function doTransition(fromIndex: number, toIndex: number): void {\n const outScene = scenes[fromIndex]\n const inScene = scenes[toIndex]\n const transType = outScene.getAttribute('data-alive-transition') ?? 'fade'\n const transDur = parseInt(outScene.getAttribute('data-alive-trans-duration') ?? '600', 10)\n\n const outClass = `alive-transition-${transType}-out`\n const inClass = `alive-transition-${transType}-in`\n\n // Sync CSS animation duration with the JS timer\n outScene.style.setProperty('--alive-tr-dur', `${transDur}ms`)\n inScene.style.setProperty('--alive-tr-dur', `${transDur}ms`)\n\n // Outgoing goes on top (required for wipe/clip-path transitions)\n outScene.style.zIndex = '2'\n outScene.classList.add(outClass)\n\n // Activate incoming beneath, reset its child animations\n inScene.style.zIndex = '1'\n resetSceneAnimations(inScene)\n inScene.classList.add('is-active', inClass)\n\n timeoutId = setTimeout(() => {\n outScene.classList.remove('is-active', outClass)\n outScene.style.zIndex = ''\n outScene.style.removeProperty('--alive-tr-dur')\n inScene.classList.remove(inClass)\n inScene.style.removeProperty('--alive-tr-dur')\n current = toIndex\n scheduleNext(current)\n }, transDur)\n }\n\n activate(current)\n scheduleNext(current)\n\n registerCleanup(root, () => {\n if (timeoutId) clearTimeout(timeoutId)\n })\n}\n\n// ── Public API ────────────────────────────────────────────────────────────────\n\n/**\n * Wire all data-alive-* components within `root` (defaults to document.documentElement).\n * Safe to call multiple times — existing listeners are tracked and replaced on `destroy()`.\n */\nexport function init(root: Element = document.documentElement): void {\n // Accordion\n root.querySelectorAll('[data-alive-accordion]').forEach(el => wireAccordion(el, root))\n\n // Modal\n root.querySelectorAll('[data-alive-modal]').forEach(el => wireModal(el, root))\n\n // Drawer\n root.querySelectorAll('[data-alive-drawer]').forEach(el => wireDrawer(el, root))\n\n // Dropdown\n root.querySelectorAll('[data-alive-dropdown]').forEach(el => wireDropdown(el, root))\n\n // Tabs\n root.querySelectorAll('[data-alive-tabs]').forEach(el => wireTabs(el, root))\n\n // Scroll reveal\n root.querySelectorAll('[data-alive-scroll]').forEach(el => wireScroll(el, root))\n\n // Auto-stagger children\n root.querySelectorAll('[data-alive-stagger]').forEach(el => wireStagger(el))\n\n // 3D tilt\n root.querySelectorAll('[data-alive-tilt]').forEach(el => wireTilt(el, root))\n\n // Magnetic follow\n root.querySelectorAll('[data-alive-magnetic]').forEach(el => wireMagnetic(el, root))\n\n // Video scene sequencer\n root.querySelectorAll('[data-alive-sequence]').forEach(el => wireVideoSequence(el, root))\n}\n\n/**\n * Remove all event listeners registered by `init(root)`.\n */\nexport function destroy(root: Element = document.documentElement): void {\n const cleanups = cleanupRegistry.get(root) ?? []\n cleanups.forEach(fn => fn())\n cleanupRegistry.delete(root)\n}\n"],"mappings":"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","names":["cleanup"]}
|
package/dist/runtime.mjs
CHANGED
|
@@ -238,6 +238,79 @@ function wireMagnetic(el, root) {
|
|
|
238
238
|
registerCleanup(root, moveCleanup);
|
|
239
239
|
registerCleanup(root, leaveCleanup);
|
|
240
240
|
}
|
|
241
|
+
function resetSceneAnimations(scene) {
|
|
242
|
+
const animated = scene.querySelectorAll(
|
|
243
|
+
'[class*="alive-enter"], [class*="alive-loop"], .alive-typewriter, .alive-typewriter-fast, .alive-typewriter-slow, .alive-word-reveal > *, .alive-kinetic-slam, .alive-metric-card, .alive-toast, .alive-badge-pulse, .alive-spotlight, .alive-code-block'
|
|
244
|
+
);
|
|
245
|
+
animated.forEach((el) => {
|
|
246
|
+
const saved = el.style.animationName;
|
|
247
|
+
el.style.animationName = "none";
|
|
248
|
+
void el.offsetHeight;
|
|
249
|
+
el.style.animationName = saved;
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
function wireVideoSequence(container, root) {
|
|
253
|
+
const scenes = [...container.querySelectorAll(":scope > [data-alive-scene]")];
|
|
254
|
+
if (scenes.length === 0) return;
|
|
255
|
+
const loop = container.hasAttribute("data-alive-loop");
|
|
256
|
+
let current = 0;
|
|
257
|
+
let timeoutId = null;
|
|
258
|
+
const containerEl = container;
|
|
259
|
+
if (getComputedStyle(containerEl).position === "static") {
|
|
260
|
+
containerEl.style.position = "relative";
|
|
261
|
+
}
|
|
262
|
+
containerEl.style.overflow = "hidden";
|
|
263
|
+
scenes.forEach((s) => {
|
|
264
|
+
s.style.position = "absolute";
|
|
265
|
+
s.style.inset = "0";
|
|
266
|
+
s.classList.remove("is-active");
|
|
267
|
+
});
|
|
268
|
+
function activate(index) {
|
|
269
|
+
const scene = scenes[index];
|
|
270
|
+
resetSceneAnimations(scene);
|
|
271
|
+
scene.classList.add("is-active");
|
|
272
|
+
scene.style.zIndex = "1";
|
|
273
|
+
}
|
|
274
|
+
function scheduleNext(fromIndex) {
|
|
275
|
+
const scene = scenes[fromIndex];
|
|
276
|
+
const duration = parseInt(scene.getAttribute("data-alive-duration") ?? "3000", 10);
|
|
277
|
+
timeoutId = setTimeout(() => {
|
|
278
|
+
const nextIndex = fromIndex + 1;
|
|
279
|
+
const toIndex = nextIndex >= scenes.length ? loop ? 0 : -1 : nextIndex;
|
|
280
|
+
if (toIndex === -1) return;
|
|
281
|
+
doTransition(fromIndex, toIndex);
|
|
282
|
+
}, duration);
|
|
283
|
+
}
|
|
284
|
+
function doTransition(fromIndex, toIndex) {
|
|
285
|
+
const outScene = scenes[fromIndex];
|
|
286
|
+
const inScene = scenes[toIndex];
|
|
287
|
+
const transType = outScene.getAttribute("data-alive-transition") ?? "fade";
|
|
288
|
+
const transDur = parseInt(outScene.getAttribute("data-alive-trans-duration") ?? "600", 10);
|
|
289
|
+
const outClass = `alive-transition-${transType}-out`;
|
|
290
|
+
const inClass = `alive-transition-${transType}-in`;
|
|
291
|
+
outScene.style.setProperty("--alive-tr-dur", `${transDur}ms`);
|
|
292
|
+
inScene.style.setProperty("--alive-tr-dur", `${transDur}ms`);
|
|
293
|
+
outScene.style.zIndex = "2";
|
|
294
|
+
outScene.classList.add(outClass);
|
|
295
|
+
inScene.style.zIndex = "1";
|
|
296
|
+
resetSceneAnimations(inScene);
|
|
297
|
+
inScene.classList.add("is-active", inClass);
|
|
298
|
+
timeoutId = setTimeout(() => {
|
|
299
|
+
outScene.classList.remove("is-active", outClass);
|
|
300
|
+
outScene.style.zIndex = "";
|
|
301
|
+
outScene.style.removeProperty("--alive-tr-dur");
|
|
302
|
+
inScene.classList.remove(inClass);
|
|
303
|
+
inScene.style.removeProperty("--alive-tr-dur");
|
|
304
|
+
current = toIndex;
|
|
305
|
+
scheduleNext(current);
|
|
306
|
+
}, transDur);
|
|
307
|
+
}
|
|
308
|
+
activate(current);
|
|
309
|
+
scheduleNext(current);
|
|
310
|
+
registerCleanup(root, () => {
|
|
311
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
312
|
+
});
|
|
313
|
+
}
|
|
241
314
|
function init(root = document.documentElement) {
|
|
242
315
|
root.querySelectorAll("[data-alive-accordion]").forEach((el) => wireAccordion(el, root));
|
|
243
316
|
root.querySelectorAll("[data-alive-modal]").forEach((el) => wireModal(el, root));
|
|
@@ -248,6 +321,7 @@ function init(root = document.documentElement) {
|
|
|
248
321
|
root.querySelectorAll("[data-alive-stagger]").forEach((el) => wireStagger(el));
|
|
249
322
|
root.querySelectorAll("[data-alive-tilt]").forEach((el) => wireTilt(el, root));
|
|
250
323
|
root.querySelectorAll("[data-alive-magnetic]").forEach((el) => wireMagnetic(el, root));
|
|
324
|
+
root.querySelectorAll("[data-alive-sequence]").forEach((el) => wireVideoSequence(el, root));
|
|
251
325
|
}
|
|
252
326
|
function destroy(root = document.documentElement) {
|
|
253
327
|
const cleanups = cleanupRegistry.get(root) ?? [];
|
package/dist/runtime.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/runtime.ts"],"sourcesContent":["/**\n * AliveUI Runtime\n *\n * Provides data-attribute-driven interactivity for accordion, modal, drawer,\n * dropdown, and tabs components — zero dependencies, ~2 KB.\n *\n * Usage:\n * import { init } from '@alivecss/aliveui/runtime'\n * init() // wire everything in document\n * init(myRootElement) // wire a subtree\n */\n\ntype Cleanup = () => void\n\nconst cleanupRegistry = new WeakMap<Element, Cleanup[]>()\n\nfunction registerCleanup(root: Element, fn: Cleanup): void {\n const existing = cleanupRegistry.get(root) ?? []\n existing.push(fn)\n cleanupRegistry.set(root, existing)\n}\n\nfunction addListener<K extends keyof HTMLElementEventMap>(\n el: EventTarget,\n type: K,\n handler: (e: HTMLElementEventMap[K]) => void,\n options?: AddEventListenerOptions,\n): Cleanup {\n el.addEventListener(type, handler as EventListener, options)\n return () => el.removeEventListener(type, handler as EventListener, options)\n}\n\n// ── Accordion ─────────────────────────────────────────────────────────────────\n\nfunction wireAccordion(container: Element, root: Element): void {\n const triggers = container.querySelectorAll<HTMLElement>('[data-alive-trigger]')\n triggers.forEach(trigger => {\n const item = trigger.closest('[data-alive-accordion-item]') ?? trigger.parentElement\n if (!item) return\n\n const cleanup = addListener(trigger, 'click', () => {\n const isOpen = item.classList.contains('is-open')\n // Close all items if not multi-open\n if (!container.hasAttribute('data-alive-multi')) {\n container.querySelectorAll('[data-alive-accordion-item]').forEach(i => {\n i.classList.remove('is-open')\n i.querySelector('[data-alive-trigger]')?.setAttribute('aria-expanded', 'false')\n })\n }\n if (!isOpen) {\n item.classList.add('is-open')\n trigger.setAttribute('aria-expanded', 'true')\n }\n })\n registerCleanup(root, cleanup)\n })\n}\n\n// ── Modal ─────────────────────────────────────────────────────────────────────\n\nfunction wireModal(modal: Element, root: Element): void {\n const id = modal.getAttribute('data-alive-modal')\n if (!id) return\n\n // Open triggers\n const openers = document.querySelectorAll<HTMLElement>(`[data-alive-open=\"${id}\"]`)\n openers.forEach(opener => {\n const cleanup = addListener(opener, 'click', () => openModal(id))\n registerCleanup(root, cleanup)\n })\n\n // Close triggers inside the modal\n modal.querySelectorAll<HTMLElement>('[data-alive-close]').forEach(closer => {\n const cleanup = addListener(closer, 'click', () => closeModal(id))\n registerCleanup(root, cleanup)\n })\n\n // Backdrop click to close (click on the modal wrapper, not the content)\n const cleanup = addListener(modal, 'click', (e) => {\n if (e.target === modal) closeModal(id)\n })\n registerCleanup(root, cleanup)\n\n // ESC key\n const escCleanup = addListener(document, 'keydown', (e) => {\n if (e.key === 'Escape' && modal.classList.contains('is-open')) closeModal(id)\n })\n registerCleanup(root, escCleanup)\n}\n\nexport function openModal(id: string): void {\n const modal = document.querySelector<HTMLElement>(`[data-alive-modal=\"${id}\"]`)\n if (!modal) return\n modal.classList.add('is-open')\n modal.setAttribute('aria-hidden', 'false')\n document.body.style.overflow = 'hidden'\n // Focus first focusable element\n const focusable = modal.querySelector<HTMLElement>(\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])',\n )\n focusable?.focus()\n}\n\nexport function closeModal(id: string): void {\n const modal = document.querySelector<HTMLElement>(`[data-alive-modal=\"${id}\"]`)\n if (!modal) return\n modal.classList.remove('is-open')\n modal.setAttribute('aria-hidden', 'true')\n document.body.style.overflow = ''\n}\n\n// ── Drawer ────────────────────────────────────────────────────────────────────\n\nfunction wireDrawer(drawer: Element, root: Element): void {\n const id = drawer.getAttribute('data-alive-drawer')\n if (!id) return\n\n const openers = document.querySelectorAll<HTMLElement>(`[data-alive-open=\"${id}\"]`)\n openers.forEach(opener => {\n const cleanup = addListener(opener, 'click', () => openDrawer(id))\n registerCleanup(root, cleanup)\n })\n\n drawer.querySelectorAll<HTMLElement>('[data-alive-close]').forEach(closer => {\n const cleanup = addListener(closer, 'click', () => closeDrawer(id))\n registerCleanup(root, cleanup)\n })\n\n const backdropCleanup = addListener(drawer, 'click', (e) => {\n if (e.target === drawer) closeDrawer(id)\n })\n registerCleanup(root, backdropCleanup)\n\n const escCleanup = addListener(document, 'keydown', (e) => {\n if (e.key === 'Escape' && drawer.classList.contains('is-open')) closeDrawer(id)\n })\n registerCleanup(root, escCleanup)\n}\n\nexport function openDrawer(id: string): void {\n const drawer = document.querySelector<HTMLElement>(`[data-alive-drawer=\"${id}\"]`)\n if (!drawer) return\n drawer.classList.add('is-open')\n drawer.setAttribute('aria-hidden', 'false')\n document.body.style.overflow = 'hidden'\n}\n\nexport function closeDrawer(id: string): void {\n const drawer = document.querySelector<HTMLElement>(`[data-alive-drawer=\"${id}\"]`)\n if (!drawer) return\n drawer.classList.remove('is-open')\n drawer.setAttribute('aria-hidden', 'true')\n document.body.style.overflow = ''\n}\n\n// ── Dropdown ──────────────────────────────────────────────────────────────────\n\nfunction wireDropdown(container: Element, root: Element): void {\n const trigger = container.querySelector<HTMLElement>('[data-alive-trigger]')\n const menu = container.querySelector<HTMLElement>('[data-alive-dropdown-menu]')\n if (!trigger || !menu) return\n\n const toggleCleanup = addListener(trigger, 'click', (e) => {\n e.stopPropagation()\n toggleDropdown(container)\n })\n registerCleanup(root, toggleCleanup)\n\n // Close on outside click\n const outsideCleanup = addListener(document, 'click', (e) => {\n if (!container.contains(e.target as Node)) {\n menu.classList.remove('is-open')\n trigger.setAttribute('aria-expanded', 'false')\n }\n })\n registerCleanup(root, outsideCleanup)\n\n // Close on ESC\n const escCleanup = addListener(document, 'keydown', (e) => {\n if (e.key === 'Escape' && menu.classList.contains('is-open')) {\n menu.classList.remove('is-open')\n trigger.setAttribute('aria-expanded', 'false')\n trigger.focus()\n }\n })\n registerCleanup(root, escCleanup)\n}\n\nexport function toggleDropdown(container: Element): void {\n const trigger = container.querySelector<HTMLElement>('[data-alive-trigger]')\n const menu = container.querySelector<HTMLElement>('[data-alive-dropdown-menu]')\n if (!menu) return\n const isOpen = menu.classList.toggle('is-open')\n trigger?.setAttribute('aria-expanded', String(isOpen))\n if (isOpen) {\n // Focus first item\n menu.querySelector<HTMLElement>('[role=\"menuitem\"], button, a')?.focus()\n }\n}\n\n// ── Tabs ──────────────────────────────────────────────────────────────────────\n\nfunction wireTabs(container: Element, root: Element): void {\n const tabs = container.querySelectorAll<HTMLElement>('[data-alive-tab]')\n tabs.forEach(tab => {\n const cleanup = addListener(tab, 'click', () => {\n const panelId = tab.getAttribute('data-alive-tab')\n if (!panelId) return\n activateTab(container, panelId)\n })\n registerCleanup(root, cleanup)\n\n // Keyboard navigation\n const keyCleanup = addListener(tab, 'keydown', (e) => {\n const allTabs = [...container.querySelectorAll<HTMLElement>('[data-alive-tab]')]\n const idx = allTabs.indexOf(tab)\n if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {\n e.preventDefault()\n allTabs[(idx + 1) % allTabs.length]?.focus()\n } else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {\n e.preventDefault()\n allTabs[(idx - 1 + allTabs.length) % allTabs.length]?.focus()\n }\n })\n registerCleanup(root, keyCleanup)\n })\n}\n\nfunction activateTab(container: Element, panelId: string): void {\n // Deactivate all tabs + panels within this tabs container\n container.querySelectorAll('[data-alive-tab]').forEach(t => {\n t.classList.remove('is-active')\n t.setAttribute('aria-selected', 'false')\n t.setAttribute('tabindex', '-1')\n })\n\n // Find panels — look in the container, then in the whole document\n const searchRoot = container.closest('[data-alive-tabs-panels]') ?? document\n searchRoot.querySelectorAll('[data-alive-panel]').forEach(p => {\n p.classList.remove('is-active')\n p.setAttribute('aria-hidden', 'true')\n })\n\n // Activate the selected tab\n const activeTab = container.querySelector<HTMLElement>(`[data-alive-tab=\"${panelId}\"]`)\n activeTab?.classList.add('is-active')\n activeTab?.setAttribute('aria-selected', 'true')\n activeTab?.setAttribute('tabindex', '0')\n\n // Activate the matching panel\n const activePanel = searchRoot.querySelector<HTMLElement>(`[data-alive-panel=\"${panelId}\"]`)\n activePanel?.classList.add('is-active')\n activePanel?.setAttribute('aria-hidden', 'false')\n}\n\n// ── Scroll Reveal ──────────────────────────────────────────────────────────────\n\nfunction wireScroll(el: Element, root: Element): void {\n const obs = new IntersectionObserver(\n (entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n entry.target.classList.add('is-visible')\n obs.unobserve(entry.target)\n }\n })\n },\n { threshold: 0.1, rootMargin: '0px 0px -40px 0px' },\n )\n obs.observe(el)\n registerCleanup(root, () => obs.disconnect())\n}\n\n// ── Auto-Stagger ───────────────────────────────────────────────────────────────\n\nfunction wireStagger(container: Element): void {\n const children = [...container.children] as HTMLElement[]\n children.forEach((child, i) => {\n child.style.setProperty('--alive-index', String(i))\n })\n}\n\n// ── 3D Tilt ────────────────────────────────────────────────────────────────────\n\nfunction wireTilt(el: Element, root: Element): void {\n const htmlEl = el as HTMLElement\n const STRENGTH = 8\n\n const moveCleanup = addListener(htmlEl, 'mousemove', (e) => {\n const rect = htmlEl.getBoundingClientRect()\n const x = (e.clientX - rect.left) / rect.width - 0.5\n const y = (e.clientY - rect.top) / rect.height - 0.5\n htmlEl.style.transform = `perspective(800px) rotateY(${x * STRENGTH}deg) rotateX(${-y * STRENGTH}deg) scale(1.01)`\n htmlEl.style.transition = 'transform 0.1s ease-out'\n })\n\n const leaveCleanup = addListener(htmlEl, 'mouseleave', () => {\n htmlEl.style.transform = ''\n htmlEl.style.transition = 'transform 0.4s cubic-bezier(0.16, 1, 0.3, 1)'\n })\n\n registerCleanup(root, moveCleanup)\n registerCleanup(root, leaveCleanup)\n}\n\n// ── Magnetic Follow ────────────────────────────────────────────────────────────\n\nfunction wireMagnetic(el: Element, root: Element): void {\n const htmlEl = el as HTMLElement\n const PULL = 0.35\n\n const moveCleanup = addListener(htmlEl, 'mousemove', (e) => {\n const rect = htmlEl.getBoundingClientRect()\n const cx = rect.left + rect.width / 2\n const cy = rect.top + rect.height / 2\n const dx = (e.clientX - cx) * PULL\n const dy = (e.clientY - cy) * PULL\n htmlEl.style.transform = `translate(${dx}px, ${dy}px)`\n htmlEl.style.transition = 'transform 0.2s cubic-bezier(0.16, 1, 0.3, 1)'\n })\n\n const leaveCleanup = addListener(htmlEl, 'mouseleave', () => {\n htmlEl.style.transform = ''\n htmlEl.style.transition = 'transform 0.5s cubic-bezier(0.16, 1, 0.3, 1)'\n })\n\n registerCleanup(root, moveCleanup)\n registerCleanup(root, leaveCleanup)\n}\n\n// ── Public API ────────────────────────────────────────────────────────────────\n\n/**\n * Wire all data-alive-* components within `root` (defaults to document.documentElement).\n * Safe to call multiple times — existing listeners are tracked and replaced on `destroy()`.\n */\nexport function init(root: Element = document.documentElement): void {\n // Accordion\n root.querySelectorAll('[data-alive-accordion]').forEach(el => wireAccordion(el, root))\n\n // Modal\n root.querySelectorAll('[data-alive-modal]').forEach(el => wireModal(el, root))\n\n // Drawer\n root.querySelectorAll('[data-alive-drawer]').forEach(el => wireDrawer(el, root))\n\n // Dropdown\n root.querySelectorAll('[data-alive-dropdown]').forEach(el => wireDropdown(el, root))\n\n // Tabs\n root.querySelectorAll('[data-alive-tabs]').forEach(el => wireTabs(el, root))\n\n // Scroll reveal\n root.querySelectorAll('[data-alive-scroll]').forEach(el => wireScroll(el, root))\n\n // Auto-stagger children\n root.querySelectorAll('[data-alive-stagger]').forEach(el => wireStagger(el))\n\n // 3D tilt\n root.querySelectorAll('[data-alive-tilt]').forEach(el => wireTilt(el, root))\n\n // Magnetic follow\n root.querySelectorAll('[data-alive-magnetic]').forEach(el => wireMagnetic(el, root))\n}\n\n/**\n * Remove all event listeners registered by `init(root)`.\n */\nexport function destroy(root: Element = document.documentElement): void {\n const cleanups = cleanupRegistry.get(root) ?? []\n cleanups.forEach(fn => fn())\n cleanupRegistry.delete(root)\n}\n"],"mappings":";AAcA,IAAM,kBAAkB,oBAAI,QAA4B;AAExD,SAAS,gBAAgB,MAAe,IAAmB;AACzD,QAAM,WAAW,gBAAgB,IAAI,IAAI,KAAK,CAAC;AAC/C,WAAS,KAAK,EAAE;AAChB,kBAAgB,IAAI,MAAM,QAAQ;AACpC;AAEA,SAAS,YACP,IACA,MACA,SACA,SACS;AACT,KAAG,iBAAiB,MAAM,SAA0B,OAAO;AAC3D,SAAO,MAAM,GAAG,oBAAoB,MAAM,SAA0B,OAAO;AAC7E;AAIA,SAAS,cAAc,WAAoB,MAAqB;AAC9D,QAAM,WAAW,UAAU,iBAA8B,sBAAsB;AAC/E,WAAS,QAAQ,aAAW;AAC1B,UAAM,OAAO,QAAQ,QAAQ,6BAA6B,KAAK,QAAQ;AACvE,QAAI,CAAC,KAAM;AAEX,UAAM,UAAU,YAAY,SAAS,SAAS,MAAM;AAClD,YAAM,SAAS,KAAK,UAAU,SAAS,SAAS;AAEhD,UAAI,CAAC,UAAU,aAAa,kBAAkB,GAAG;AAC/C,kBAAU,iBAAiB,6BAA6B,EAAE,QAAQ,OAAK;AACrE,YAAE,UAAU,OAAO,SAAS;AAC5B,YAAE,cAAc,sBAAsB,GAAG,aAAa,iBAAiB,OAAO;AAAA,QAChF,CAAC;AAAA,MACH;AACA,UAAI,CAAC,QAAQ;AACX,aAAK,UAAU,IAAI,SAAS;AAC5B,gBAAQ,aAAa,iBAAiB,MAAM;AAAA,MAC9C;AAAA,IACF,CAAC;AACD,oBAAgB,MAAM,OAAO;AAAA,EAC/B,CAAC;AACH;AAIA,SAAS,UAAU,OAAgB,MAAqB;AACtD,QAAM,KAAK,MAAM,aAAa,kBAAkB;AAChD,MAAI,CAAC,GAAI;AAGT,QAAM,UAAU,SAAS,iBAA8B,qBAAqB,EAAE,IAAI;AAClF,UAAQ,QAAQ,YAAU;AACxB,UAAMA,WAAU,YAAY,QAAQ,SAAS,MAAM,UAAU,EAAE,CAAC;AAChE,oBAAgB,MAAMA,QAAO;AAAA,EAC/B,CAAC;AAGD,QAAM,iBAA8B,oBAAoB,EAAE,QAAQ,YAAU;AAC1E,UAAMA,WAAU,YAAY,QAAQ,SAAS,MAAM,WAAW,EAAE,CAAC;AACjE,oBAAgB,MAAMA,QAAO;AAAA,EAC/B,CAAC;AAGD,QAAM,UAAU,YAAY,OAAO,SAAS,CAAC,MAAM;AACjD,QAAI,EAAE,WAAW,MAAO,YAAW,EAAE;AAAA,EACvC,CAAC;AACD,kBAAgB,MAAM,OAAO;AAG7B,QAAM,aAAa,YAAY,UAAU,WAAW,CAAC,MAAM;AACzD,QAAI,EAAE,QAAQ,YAAY,MAAM,UAAU,SAAS,SAAS,EAAG,YAAW,EAAE;AAAA,EAC9E,CAAC;AACD,kBAAgB,MAAM,UAAU;AAClC;AAEO,SAAS,UAAU,IAAkB;AAC1C,QAAM,QAAQ,SAAS,cAA2B,sBAAsB,EAAE,IAAI;AAC9E,MAAI,CAAC,MAAO;AACZ,QAAM,UAAU,IAAI,SAAS;AAC7B,QAAM,aAAa,eAAe,OAAO;AACzC,WAAS,KAAK,MAAM,WAAW;AAE/B,QAAM,YAAY,MAAM;AAAA,IACtB;AAAA,EACF;AACA,aAAW,MAAM;AACnB;AAEO,SAAS,WAAW,IAAkB;AAC3C,QAAM,QAAQ,SAAS,cAA2B,sBAAsB,EAAE,IAAI;AAC9E,MAAI,CAAC,MAAO;AACZ,QAAM,UAAU,OAAO,SAAS;AAChC,QAAM,aAAa,eAAe,MAAM;AACxC,WAAS,KAAK,MAAM,WAAW;AACjC;AAIA,SAAS,WAAW,QAAiB,MAAqB;AACxD,QAAM,KAAK,OAAO,aAAa,mBAAmB;AAClD,MAAI,CAAC,GAAI;AAET,QAAM,UAAU,SAAS,iBAA8B,qBAAqB,EAAE,IAAI;AAClF,UAAQ,QAAQ,YAAU;AACxB,UAAM,UAAU,YAAY,QAAQ,SAAS,MAAM,WAAW,EAAE,CAAC;AACjE,oBAAgB,MAAM,OAAO;AAAA,EAC/B,CAAC;AAED,SAAO,iBAA8B,oBAAoB,EAAE,QAAQ,YAAU;AAC3E,UAAM,UAAU,YAAY,QAAQ,SAAS,MAAM,YAAY,EAAE,CAAC;AAClE,oBAAgB,MAAM,OAAO;AAAA,EAC/B,CAAC;AAED,QAAM,kBAAkB,YAAY,QAAQ,SAAS,CAAC,MAAM;AAC1D,QAAI,EAAE,WAAW,OAAQ,aAAY,EAAE;AAAA,EACzC,CAAC;AACD,kBAAgB,MAAM,eAAe;AAErC,QAAM,aAAa,YAAY,UAAU,WAAW,CAAC,MAAM;AACzD,QAAI,EAAE,QAAQ,YAAY,OAAO,UAAU,SAAS,SAAS,EAAG,aAAY,EAAE;AAAA,EAChF,CAAC;AACD,kBAAgB,MAAM,UAAU;AAClC;AAEO,SAAS,WAAW,IAAkB;AAC3C,QAAM,SAAS,SAAS,cAA2B,uBAAuB,EAAE,IAAI;AAChF,MAAI,CAAC,OAAQ;AACb,SAAO,UAAU,IAAI,SAAS;AAC9B,SAAO,aAAa,eAAe,OAAO;AAC1C,WAAS,KAAK,MAAM,WAAW;AACjC;AAEO,SAAS,YAAY,IAAkB;AAC5C,QAAM,SAAS,SAAS,cAA2B,uBAAuB,EAAE,IAAI;AAChF,MAAI,CAAC,OAAQ;AACb,SAAO,UAAU,OAAO,SAAS;AACjC,SAAO,aAAa,eAAe,MAAM;AACzC,WAAS,KAAK,MAAM,WAAW;AACjC;AAIA,SAAS,aAAa,WAAoB,MAAqB;AAC7D,QAAM,UAAU,UAAU,cAA2B,sBAAsB;AAC3E,QAAM,OAAO,UAAU,cAA2B,4BAA4B;AAC9E,MAAI,CAAC,WAAW,CAAC,KAAM;AAEvB,QAAM,gBAAgB,YAAY,SAAS,SAAS,CAAC,MAAM;AACzD,MAAE,gBAAgB;AAClB,mBAAe,SAAS;AAAA,EAC1B,CAAC;AACD,kBAAgB,MAAM,aAAa;AAGnC,QAAM,iBAAiB,YAAY,UAAU,SAAS,CAAC,MAAM;AAC3D,QAAI,CAAC,UAAU,SAAS,EAAE,MAAc,GAAG;AACzC,WAAK,UAAU,OAAO,SAAS;AAC/B,cAAQ,aAAa,iBAAiB,OAAO;AAAA,IAC/C;AAAA,EACF,CAAC;AACD,kBAAgB,MAAM,cAAc;AAGpC,QAAM,aAAa,YAAY,UAAU,WAAW,CAAC,MAAM;AACzD,QAAI,EAAE,QAAQ,YAAY,KAAK,UAAU,SAAS,SAAS,GAAG;AAC5D,WAAK,UAAU,OAAO,SAAS;AAC/B,cAAQ,aAAa,iBAAiB,OAAO;AAC7C,cAAQ,MAAM;AAAA,IAChB;AAAA,EACF,CAAC;AACD,kBAAgB,MAAM,UAAU;AAClC;AAEO,SAAS,eAAe,WAA0B;AACvD,QAAM,UAAU,UAAU,cAA2B,sBAAsB;AAC3E,QAAM,OAAO,UAAU,cAA2B,4BAA4B;AAC9E,MAAI,CAAC,KAAM;AACX,QAAM,SAAS,KAAK,UAAU,OAAO,SAAS;AAC9C,WAAS,aAAa,iBAAiB,OAAO,MAAM,CAAC;AACrD,MAAI,QAAQ;AAEV,SAAK,cAA2B,8BAA8B,GAAG,MAAM;AAAA,EACzE;AACF;AAIA,SAAS,SAAS,WAAoB,MAAqB;AACzD,QAAM,OAAO,UAAU,iBAA8B,kBAAkB;AACvE,OAAK,QAAQ,SAAO;AAClB,UAAM,UAAU,YAAY,KAAK,SAAS,MAAM;AAC9C,YAAM,UAAU,IAAI,aAAa,gBAAgB;AACjD,UAAI,CAAC,QAAS;AACd,kBAAY,WAAW,OAAO;AAAA,IAChC,CAAC;AACD,oBAAgB,MAAM,OAAO;AAG7B,UAAM,aAAa,YAAY,KAAK,WAAW,CAAC,MAAM;AACpD,YAAM,UAAU,CAAC,GAAG,UAAU,iBAA8B,kBAAkB,CAAC;AAC/E,YAAM,MAAM,QAAQ,QAAQ,GAAG;AAC/B,UAAI,EAAE,QAAQ,gBAAgB,EAAE,QAAQ,aAAa;AACnD,UAAE,eAAe;AACjB,iBAAS,MAAM,KAAK,QAAQ,MAAM,GAAG,MAAM;AAAA,MAC7C,WAAW,EAAE,QAAQ,eAAe,EAAE,QAAQ,WAAW;AACvD,UAAE,eAAe;AACjB,iBAAS,MAAM,IAAI,QAAQ,UAAU,QAAQ,MAAM,GAAG,MAAM;AAAA,MAC9D;AAAA,IACF,CAAC;AACD,oBAAgB,MAAM,UAAU;AAAA,EAClC,CAAC;AACH;AAEA,SAAS,YAAY,WAAoB,SAAuB;AAE9D,YAAU,iBAAiB,kBAAkB,EAAE,QAAQ,OAAK;AAC1D,MAAE,UAAU,OAAO,WAAW;AAC9B,MAAE,aAAa,iBAAiB,OAAO;AACvC,MAAE,aAAa,YAAY,IAAI;AAAA,EACjC,CAAC;AAGD,QAAM,aAAa,UAAU,QAAQ,0BAA0B,KAAK;AACpE,aAAW,iBAAiB,oBAAoB,EAAE,QAAQ,OAAK;AAC7D,MAAE,UAAU,OAAO,WAAW;AAC9B,MAAE,aAAa,eAAe,MAAM;AAAA,EACtC,CAAC;AAGD,QAAM,YAAY,UAAU,cAA2B,oBAAoB,OAAO,IAAI;AACtF,aAAW,UAAU,IAAI,WAAW;AACpC,aAAW,aAAa,iBAAiB,MAAM;AAC/C,aAAW,aAAa,YAAY,GAAG;AAGvC,QAAM,cAAc,WAAW,cAA2B,sBAAsB,OAAO,IAAI;AAC3F,eAAa,UAAU,IAAI,WAAW;AACtC,eAAa,aAAa,eAAe,OAAO;AAClD;AAIA,SAAS,WAAW,IAAa,MAAqB;AACpD,QAAM,MAAM,IAAI;AAAA,IACd,CAAC,YAAY;AACX,cAAQ,QAAQ,WAAS;AACvB,YAAI,MAAM,gBAAgB;AACxB,gBAAM,OAAO,UAAU,IAAI,YAAY;AACvC,cAAI,UAAU,MAAM,MAAM;AAAA,QAC5B;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IACA,EAAE,WAAW,KAAK,YAAY,oBAAoB;AAAA,EACpD;AACA,MAAI,QAAQ,EAAE;AACd,kBAAgB,MAAM,MAAM,IAAI,WAAW,CAAC;AAC9C;AAIA,SAAS,YAAY,WAA0B;AAC7C,QAAM,WAAW,CAAC,GAAG,UAAU,QAAQ;AACvC,WAAS,QAAQ,CAAC,OAAO,MAAM;AAC7B,UAAM,MAAM,YAAY,iBAAiB,OAAO,CAAC,CAAC;AAAA,EACpD,CAAC;AACH;AAIA,SAAS,SAAS,IAAa,MAAqB;AAClD,QAAM,SAAS;AACf,QAAM,WAAW;AAEjB,QAAM,cAAc,YAAY,QAAQ,aAAa,CAAC,MAAM;AAC1D,UAAM,OAAO,OAAO,sBAAsB;AAC1C,UAAM,KAAK,EAAE,UAAU,KAAK,QAAQ,KAAK,QAAQ;AACjD,UAAM,KAAK,EAAE,UAAU,KAAK,OAAO,KAAK,SAAS;AACjD,WAAO,MAAM,YAAY,8BAA8B,IAAI,QAAQ,gBAAgB,CAAC,IAAI,QAAQ;AAChG,WAAO,MAAM,aAAa;AAAA,EAC5B,CAAC;AAED,QAAM,eAAe,YAAY,QAAQ,cAAc,MAAM;AAC3D,WAAO,MAAM,YAAY;AACzB,WAAO,MAAM,aAAa;AAAA,EAC5B,CAAC;AAED,kBAAgB,MAAM,WAAW;AACjC,kBAAgB,MAAM,YAAY;AACpC;AAIA,SAAS,aAAa,IAAa,MAAqB;AACtD,QAAM,SAAS;AACf,QAAM,OAAO;AAEb,QAAM,cAAc,YAAY,QAAQ,aAAa,CAAC,MAAM;AAC1D,UAAM,OAAO,OAAO,sBAAsB;AAC1C,UAAM,KAAK,KAAK,OAAO,KAAK,QAAQ;AACpC,UAAM,KAAK,KAAK,MAAM,KAAK,SAAS;AACpC,UAAM,MAAM,EAAE,UAAU,MAAM;AAC9B,UAAM,MAAM,EAAE,UAAU,MAAM;AAC9B,WAAO,MAAM,YAAY,aAAa,EAAE,OAAO,EAAE;AACjD,WAAO,MAAM,aAAa;AAAA,EAC5B,CAAC;AAED,QAAM,eAAe,YAAY,QAAQ,cAAc,MAAM;AAC3D,WAAO,MAAM,YAAY;AACzB,WAAO,MAAM,aAAa;AAAA,EAC5B,CAAC;AAED,kBAAgB,MAAM,WAAW;AACjC,kBAAgB,MAAM,YAAY;AACpC;AAQO,SAAS,KAAK,OAAgB,SAAS,iBAAuB;AAEnE,OAAK,iBAAiB,wBAAwB,EAAE,QAAQ,QAAM,cAAc,IAAI,IAAI,CAAC;AAGrF,OAAK,iBAAiB,oBAAoB,EAAE,QAAQ,QAAM,UAAU,IAAI,IAAI,CAAC;AAG7E,OAAK,iBAAiB,qBAAqB,EAAE,QAAQ,QAAM,WAAW,IAAI,IAAI,CAAC;AAG/E,OAAK,iBAAiB,uBAAuB,EAAE,QAAQ,QAAM,aAAa,IAAI,IAAI,CAAC;AAGnF,OAAK,iBAAiB,mBAAmB,EAAE,QAAQ,QAAM,SAAS,IAAI,IAAI,CAAC;AAG3E,OAAK,iBAAiB,qBAAqB,EAAE,QAAQ,QAAM,WAAW,IAAI,IAAI,CAAC;AAG/E,OAAK,iBAAiB,sBAAsB,EAAE,QAAQ,QAAM,YAAY,EAAE,CAAC;AAG3E,OAAK,iBAAiB,mBAAmB,EAAE,QAAQ,QAAM,SAAS,IAAI,IAAI,CAAC;AAG3E,OAAK,iBAAiB,uBAAuB,EAAE,QAAQ,QAAM,aAAa,IAAI,IAAI,CAAC;AACrF;AAKO,SAAS,QAAQ,OAAgB,SAAS,iBAAuB;AACtE,QAAM,WAAW,gBAAgB,IAAI,IAAI,KAAK,CAAC;AAC/C,WAAS,QAAQ,QAAM,GAAG,CAAC;AAC3B,kBAAgB,OAAO,IAAI;AAC7B;","names":["cleanup"]}
|
|
1
|
+
{"version":3,"sources":["../src/runtime.ts"],"sourcesContent":["/**\n * AliveUI Runtime\n *\n * Provides data-attribute-driven interactivity for accordion, modal, drawer,\n * dropdown, and tabs components — zero dependencies, ~2 KB.\n *\n * Usage:\n * import { init } from '@alivecss/aliveui/runtime'\n * init() // wire everything in document\n * init(myRootElement) // wire a subtree\n */\n\ntype Cleanup = () => void\n\nconst cleanupRegistry = new WeakMap<Element, Cleanup[]>()\n\nfunction registerCleanup(root: Element, fn: Cleanup): void {\n const existing = cleanupRegistry.get(root) ?? []\n existing.push(fn)\n cleanupRegistry.set(root, existing)\n}\n\nfunction addListener<K extends keyof HTMLElementEventMap>(\n el: EventTarget,\n type: K,\n handler: (e: HTMLElementEventMap[K]) => void,\n options?: AddEventListenerOptions,\n): Cleanup {\n el.addEventListener(type, handler as EventListener, options)\n return () => el.removeEventListener(type, handler as EventListener, options)\n}\n\n// ── Accordion ─────────────────────────────────────────────────────────────────\n\nfunction wireAccordion(container: Element, root: Element): void {\n const triggers = container.querySelectorAll<HTMLElement>('[data-alive-trigger]')\n triggers.forEach(trigger => {\n const item = trigger.closest('[data-alive-accordion-item]') ?? trigger.parentElement\n if (!item) return\n\n const cleanup = addListener(trigger, 'click', () => {\n const isOpen = item.classList.contains('is-open')\n // Close all items if not multi-open\n if (!container.hasAttribute('data-alive-multi')) {\n container.querySelectorAll('[data-alive-accordion-item]').forEach(i => {\n i.classList.remove('is-open')\n i.querySelector('[data-alive-trigger]')?.setAttribute('aria-expanded', 'false')\n })\n }\n if (!isOpen) {\n item.classList.add('is-open')\n trigger.setAttribute('aria-expanded', 'true')\n }\n })\n registerCleanup(root, cleanup)\n })\n}\n\n// ── Modal ─────────────────────────────────────────────────────────────────────\n\nfunction wireModal(modal: Element, root: Element): void {\n const id = modal.getAttribute('data-alive-modal')\n if (!id) return\n\n // Open triggers\n const openers = document.querySelectorAll<HTMLElement>(`[data-alive-open=\"${id}\"]`)\n openers.forEach(opener => {\n const cleanup = addListener(opener, 'click', () => openModal(id))\n registerCleanup(root, cleanup)\n })\n\n // Close triggers inside the modal\n modal.querySelectorAll<HTMLElement>('[data-alive-close]').forEach(closer => {\n const cleanup = addListener(closer, 'click', () => closeModal(id))\n registerCleanup(root, cleanup)\n })\n\n // Backdrop click to close (click on the modal wrapper, not the content)\n const cleanup = addListener(modal, 'click', (e) => {\n if (e.target === modal) closeModal(id)\n })\n registerCleanup(root, cleanup)\n\n // ESC key\n const escCleanup = addListener(document, 'keydown', (e) => {\n if (e.key === 'Escape' && modal.classList.contains('is-open')) closeModal(id)\n })\n registerCleanup(root, escCleanup)\n}\n\nexport function openModal(id: string): void {\n const modal = document.querySelector<HTMLElement>(`[data-alive-modal=\"${id}\"]`)\n if (!modal) return\n modal.classList.add('is-open')\n modal.setAttribute('aria-hidden', 'false')\n document.body.style.overflow = 'hidden'\n // Focus first focusable element\n const focusable = modal.querySelector<HTMLElement>(\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])',\n )\n focusable?.focus()\n}\n\nexport function closeModal(id: string): void {\n const modal = document.querySelector<HTMLElement>(`[data-alive-modal=\"${id}\"]`)\n if (!modal) return\n modal.classList.remove('is-open')\n modal.setAttribute('aria-hidden', 'true')\n document.body.style.overflow = ''\n}\n\n// ── Drawer ────────────────────────────────────────────────────────────────────\n\nfunction wireDrawer(drawer: Element, root: Element): void {\n const id = drawer.getAttribute('data-alive-drawer')\n if (!id) return\n\n const openers = document.querySelectorAll<HTMLElement>(`[data-alive-open=\"${id}\"]`)\n openers.forEach(opener => {\n const cleanup = addListener(opener, 'click', () => openDrawer(id))\n registerCleanup(root, cleanup)\n })\n\n drawer.querySelectorAll<HTMLElement>('[data-alive-close]').forEach(closer => {\n const cleanup = addListener(closer, 'click', () => closeDrawer(id))\n registerCleanup(root, cleanup)\n })\n\n const backdropCleanup = addListener(drawer, 'click', (e) => {\n if (e.target === drawer) closeDrawer(id)\n })\n registerCleanup(root, backdropCleanup)\n\n const escCleanup = addListener(document, 'keydown', (e) => {\n if (e.key === 'Escape' && drawer.classList.contains('is-open')) closeDrawer(id)\n })\n registerCleanup(root, escCleanup)\n}\n\nexport function openDrawer(id: string): void {\n const drawer = document.querySelector<HTMLElement>(`[data-alive-drawer=\"${id}\"]`)\n if (!drawer) return\n drawer.classList.add('is-open')\n drawer.setAttribute('aria-hidden', 'false')\n document.body.style.overflow = 'hidden'\n}\n\nexport function closeDrawer(id: string): void {\n const drawer = document.querySelector<HTMLElement>(`[data-alive-drawer=\"${id}\"]`)\n if (!drawer) return\n drawer.classList.remove('is-open')\n drawer.setAttribute('aria-hidden', 'true')\n document.body.style.overflow = ''\n}\n\n// ── Dropdown ──────────────────────────────────────────────────────────────────\n\nfunction wireDropdown(container: Element, root: Element): void {\n const trigger = container.querySelector<HTMLElement>('[data-alive-trigger]')\n const menu = container.querySelector<HTMLElement>('[data-alive-dropdown-menu]')\n if (!trigger || !menu) return\n\n const toggleCleanup = addListener(trigger, 'click', (e) => {\n e.stopPropagation()\n toggleDropdown(container)\n })\n registerCleanup(root, toggleCleanup)\n\n // Close on outside click\n const outsideCleanup = addListener(document, 'click', (e) => {\n if (!container.contains(e.target as Node)) {\n menu.classList.remove('is-open')\n trigger.setAttribute('aria-expanded', 'false')\n }\n })\n registerCleanup(root, outsideCleanup)\n\n // Close on ESC\n const escCleanup = addListener(document, 'keydown', (e) => {\n if (e.key === 'Escape' && menu.classList.contains('is-open')) {\n menu.classList.remove('is-open')\n trigger.setAttribute('aria-expanded', 'false')\n trigger.focus()\n }\n })\n registerCleanup(root, escCleanup)\n}\n\nexport function toggleDropdown(container: Element): void {\n const trigger = container.querySelector<HTMLElement>('[data-alive-trigger]')\n const menu = container.querySelector<HTMLElement>('[data-alive-dropdown-menu]')\n if (!menu) return\n const isOpen = menu.classList.toggle('is-open')\n trigger?.setAttribute('aria-expanded', String(isOpen))\n if (isOpen) {\n // Focus first item\n menu.querySelector<HTMLElement>('[role=\"menuitem\"], button, a')?.focus()\n }\n}\n\n// ── Tabs ──────────────────────────────────────────────────────────────────────\n\nfunction wireTabs(container: Element, root: Element): void {\n const tabs = container.querySelectorAll<HTMLElement>('[data-alive-tab]')\n tabs.forEach(tab => {\n const cleanup = addListener(tab, 'click', () => {\n const panelId = tab.getAttribute('data-alive-tab')\n if (!panelId) return\n activateTab(container, panelId)\n })\n registerCleanup(root, cleanup)\n\n // Keyboard navigation\n const keyCleanup = addListener(tab, 'keydown', (e) => {\n const allTabs = [...container.querySelectorAll<HTMLElement>('[data-alive-tab]')]\n const idx = allTabs.indexOf(tab)\n if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {\n e.preventDefault()\n allTabs[(idx + 1) % allTabs.length]?.focus()\n } else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {\n e.preventDefault()\n allTabs[(idx - 1 + allTabs.length) % allTabs.length]?.focus()\n }\n })\n registerCleanup(root, keyCleanup)\n })\n}\n\nfunction activateTab(container: Element, panelId: string): void {\n // Deactivate all tabs + panels within this tabs container\n container.querySelectorAll('[data-alive-tab]').forEach(t => {\n t.classList.remove('is-active')\n t.setAttribute('aria-selected', 'false')\n t.setAttribute('tabindex', '-1')\n })\n\n // Find panels — look in the container, then in the whole document\n const searchRoot = container.closest('[data-alive-tabs-panels]') ?? document\n searchRoot.querySelectorAll('[data-alive-panel]').forEach(p => {\n p.classList.remove('is-active')\n p.setAttribute('aria-hidden', 'true')\n })\n\n // Activate the selected tab\n const activeTab = container.querySelector<HTMLElement>(`[data-alive-tab=\"${panelId}\"]`)\n activeTab?.classList.add('is-active')\n activeTab?.setAttribute('aria-selected', 'true')\n activeTab?.setAttribute('tabindex', '0')\n\n // Activate the matching panel\n const activePanel = searchRoot.querySelector<HTMLElement>(`[data-alive-panel=\"${panelId}\"]`)\n activePanel?.classList.add('is-active')\n activePanel?.setAttribute('aria-hidden', 'false')\n}\n\n// ── Scroll Reveal ──────────────────────────────────────────────────────────────\n\nfunction wireScroll(el: Element, root: Element): void {\n const obs = new IntersectionObserver(\n (entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n entry.target.classList.add('is-visible')\n obs.unobserve(entry.target)\n }\n })\n },\n { threshold: 0.1, rootMargin: '0px 0px -40px 0px' },\n )\n obs.observe(el)\n registerCleanup(root, () => obs.disconnect())\n}\n\n// ── Auto-Stagger ───────────────────────────────────────────────────────────────\n\nfunction wireStagger(container: Element): void {\n const children = [...container.children] as HTMLElement[]\n children.forEach((child, i) => {\n child.style.setProperty('--alive-index', String(i))\n })\n}\n\n// ── 3D Tilt ────────────────────────────────────────────────────────────────────\n\nfunction wireTilt(el: Element, root: Element): void {\n const htmlEl = el as HTMLElement\n const STRENGTH = 8\n\n const moveCleanup = addListener(htmlEl, 'mousemove', (e) => {\n const rect = htmlEl.getBoundingClientRect()\n const x = (e.clientX - rect.left) / rect.width - 0.5\n const y = (e.clientY - rect.top) / rect.height - 0.5\n htmlEl.style.transform = `perspective(800px) rotateY(${x * STRENGTH}deg) rotateX(${-y * STRENGTH}deg) scale(1.01)`\n htmlEl.style.transition = 'transform 0.1s ease-out'\n })\n\n const leaveCleanup = addListener(htmlEl, 'mouseleave', () => {\n htmlEl.style.transform = ''\n htmlEl.style.transition = 'transform 0.4s cubic-bezier(0.16, 1, 0.3, 1)'\n })\n\n registerCleanup(root, moveCleanup)\n registerCleanup(root, leaveCleanup)\n}\n\n// ── Magnetic Follow ────────────────────────────────────────────────────────────\n\nfunction wireMagnetic(el: Element, root: Element): void {\n const htmlEl = el as HTMLElement\n const PULL = 0.35\n\n const moveCleanup = addListener(htmlEl, 'mousemove', (e) => {\n const rect = htmlEl.getBoundingClientRect()\n const cx = rect.left + rect.width / 2\n const cy = rect.top + rect.height / 2\n const dx = (e.clientX - cx) * PULL\n const dy = (e.clientY - cy) * PULL\n htmlEl.style.transform = `translate(${dx}px, ${dy}px)`\n htmlEl.style.transition = 'transform 0.2s cubic-bezier(0.16, 1, 0.3, 1)'\n })\n\n const leaveCleanup = addListener(htmlEl, 'mouseleave', () => {\n htmlEl.style.transform = ''\n htmlEl.style.transition = 'transform 0.5s cubic-bezier(0.16, 1, 0.3, 1)'\n })\n\n registerCleanup(root, moveCleanup)\n registerCleanup(root, leaveCleanup)\n}\n\n// ── Video Scene Sequencer ──────────────────────────────────────────────────────\n\n/**\n * Force-restart CSS animations on all animated children of a scene element.\n * This ensures stagger delays are relative to scene activation, not page load.\n */\nfunction resetSceneAnimations(scene: HTMLElement): void {\n const animated = scene.querySelectorAll<HTMLElement>(\n '[class*=\"alive-enter\"], [class*=\"alive-loop\"], ' +\n '.alive-typewriter, .alive-typewriter-fast, .alive-typewriter-slow, ' +\n '.alive-word-reveal > *, .alive-kinetic-slam, ' +\n '.alive-metric-card, .alive-toast, .alive-badge-pulse, ' +\n '.alive-spotlight, .alive-code-block',\n )\n animated.forEach(el => {\n const saved = el.style.animationName\n el.style.animationName = 'none'\n void el.offsetHeight // force reflow — restarts animation from t=0\n el.style.animationName = saved\n })\n}\n\n/**\n * Wire a [data-alive-sequence] container.\n *\n * Markup:\n * <div data-alive-sequence data-alive-loop style=\"position:relative; width:800px; height:500px;\">\n * <div data-alive-scene data-alive-duration=\"3000\" data-alive-transition=\"wipe-left\">…</div>\n * <div data-alive-scene data-alive-duration=\"2500\" data-alive-transition=\"fade\">…</div>\n * </div>\n *\n * Scene attributes:\n * data-alive-duration — how long to show the scene (ms, default 3000)\n * data-alive-transition — transition type (default \"fade\"; matches alive-transition-* classes)\n * data-alive-trans-duration — transition animation duration (ms, default 600)\n *\n * Sequence attributes:\n * data-alive-loop — loop back to the first scene after the last\n */\nfunction wireVideoSequence(container: Element, root: Element): void {\n const scenes = [...container.querySelectorAll<HTMLElement>(':scope > [data-alive-scene]')]\n if (scenes.length === 0) return\n\n const loop = container.hasAttribute('data-alive-loop')\n let current = 0\n let timeoutId: ReturnType<typeof setTimeout> | null = null\n\n const containerEl = container as HTMLElement\n if (getComputedStyle(containerEl).position === 'static') {\n containerEl.style.position = 'relative'\n }\n containerEl.style.overflow = 'hidden'\n\n scenes.forEach(s => {\n s.style.position = 'absolute'\n s.style.inset = '0'\n s.classList.remove('is-active')\n })\n\n function activate(index: number): void {\n const scene = scenes[index]\n resetSceneAnimations(scene)\n scene.classList.add('is-active')\n scene.style.zIndex = '1'\n }\n\n function scheduleNext(fromIndex: number): void {\n const scene = scenes[fromIndex]\n const duration = parseInt(scene.getAttribute('data-alive-duration') ?? '3000', 10)\n\n timeoutId = setTimeout(() => {\n const nextIndex = fromIndex + 1\n const toIndex = nextIndex >= scenes.length ? (loop ? 0 : -1) : nextIndex\n if (toIndex === -1) return\n doTransition(fromIndex, toIndex)\n }, duration)\n }\n\n function doTransition(fromIndex: number, toIndex: number): void {\n const outScene = scenes[fromIndex]\n const inScene = scenes[toIndex]\n const transType = outScene.getAttribute('data-alive-transition') ?? 'fade'\n const transDur = parseInt(outScene.getAttribute('data-alive-trans-duration') ?? '600', 10)\n\n const outClass = `alive-transition-${transType}-out`\n const inClass = `alive-transition-${transType}-in`\n\n // Sync CSS animation duration with the JS timer\n outScene.style.setProperty('--alive-tr-dur', `${transDur}ms`)\n inScene.style.setProperty('--alive-tr-dur', `${transDur}ms`)\n\n // Outgoing goes on top (required for wipe/clip-path transitions)\n outScene.style.zIndex = '2'\n outScene.classList.add(outClass)\n\n // Activate incoming beneath, reset its child animations\n inScene.style.zIndex = '1'\n resetSceneAnimations(inScene)\n inScene.classList.add('is-active', inClass)\n\n timeoutId = setTimeout(() => {\n outScene.classList.remove('is-active', outClass)\n outScene.style.zIndex = ''\n outScene.style.removeProperty('--alive-tr-dur')\n inScene.classList.remove(inClass)\n inScene.style.removeProperty('--alive-tr-dur')\n current = toIndex\n scheduleNext(current)\n }, transDur)\n }\n\n activate(current)\n scheduleNext(current)\n\n registerCleanup(root, () => {\n if (timeoutId) clearTimeout(timeoutId)\n })\n}\n\n// ── Public API ────────────────────────────────────────────────────────────────\n\n/**\n * Wire all data-alive-* components within `root` (defaults to document.documentElement).\n * Safe to call multiple times — existing listeners are tracked and replaced on `destroy()`.\n */\nexport function init(root: Element = document.documentElement): void {\n // Accordion\n root.querySelectorAll('[data-alive-accordion]').forEach(el => wireAccordion(el, root))\n\n // Modal\n root.querySelectorAll('[data-alive-modal]').forEach(el => wireModal(el, root))\n\n // Drawer\n root.querySelectorAll('[data-alive-drawer]').forEach(el => wireDrawer(el, root))\n\n // Dropdown\n root.querySelectorAll('[data-alive-dropdown]').forEach(el => wireDropdown(el, root))\n\n // Tabs\n root.querySelectorAll('[data-alive-tabs]').forEach(el => wireTabs(el, root))\n\n // Scroll reveal\n root.querySelectorAll('[data-alive-scroll]').forEach(el => wireScroll(el, root))\n\n // Auto-stagger children\n root.querySelectorAll('[data-alive-stagger]').forEach(el => wireStagger(el))\n\n // 3D tilt\n root.querySelectorAll('[data-alive-tilt]').forEach(el => wireTilt(el, root))\n\n // Magnetic follow\n root.querySelectorAll('[data-alive-magnetic]').forEach(el => wireMagnetic(el, root))\n\n // Video scene sequencer\n root.querySelectorAll('[data-alive-sequence]').forEach(el => wireVideoSequence(el, root))\n}\n\n/**\n * Remove all event listeners registered by `init(root)`.\n */\nexport function destroy(root: Element = document.documentElement): void {\n const cleanups = cleanupRegistry.get(root) ?? []\n cleanups.forEach(fn => fn())\n cleanupRegistry.delete(root)\n}\n"],"mappings":"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","names":["cleanup"]}
|
package/dist/vite.js
CHANGED
|
@@ -2675,14 +2675,14 @@ video {
|
|
|
2675
2675
|
gap: 10px;
|
|
2676
2676
|
padding: 12px 18px;
|
|
2677
2677
|
border-radius: 14px;
|
|
2678
|
-
background: rgba(255,255,255,0.08);
|
|
2678
|
+
background: var(--alive-toast-bg, rgba(255,255,255,0.08));
|
|
2679
2679
|
backdrop-filter: blur(16px);
|
|
2680
2680
|
-webkit-backdrop-filter: blur(16px);
|
|
2681
|
-
border: 1px solid rgba(255,255,255,0.12);
|
|
2681
|
+
border: 1px solid var(--alive-toast-border, rgba(255,255,255,0.12));
|
|
2682
2682
|
box-shadow: 0 8px 32px rgba(0,0,0,0.24), 0 1px 0 rgba(255,255,255,0.06) inset;
|
|
2683
2683
|
font-size: 0.875rem;
|
|
2684
2684
|
font-weight: 500;
|
|
2685
|
-
color: #fff;
|
|
2685
|
+
color: var(--alive-toast-color, #fff);
|
|
2686
2686
|
animation: alive-toast-loop 5s cubic-bezier(0.22, 1, 0.36, 1) infinite both;
|
|
2687
2687
|
}
|
|
2688
2688
|
.alive-toast-icon {
|
|
@@ -2694,7 +2694,8 @@ video {
|
|
|
2694
2694
|
justify-content: center;
|
|
2695
2695
|
flex-shrink: 0;
|
|
2696
2696
|
font-size: 14px;
|
|
2697
|
-
background: rgba(255,255,255,0.1);
|
|
2697
|
+
background: var(--alive-toast-icon-bg, rgba(255,255,255,0.1));
|
|
2698
|
+
color: var(--alive-toast-icon-color, currentColor);
|
|
2698
2699
|
}
|
|
2699
2700
|
.alive-toast-title { font-weight: 600; font-size: 0.875rem; }
|
|
2700
2701
|
.alive-toast-body { font-size: 0.8125rem; opacity: 0.65; margin-top: 1px; }
|
|
@@ -2728,7 +2729,7 @@ video {
|
|
|
2728
2729
|
.alive-typewriter {
|
|
2729
2730
|
display: inline-block;
|
|
2730
2731
|
white-space: nowrap;
|
|
2731
|
-
border-right: 2px solid currentColor;
|
|
2732
|
+
border-right: 2px solid var(--alive-typewriter-cursor, currentColor);
|
|
2732
2733
|
animation:
|
|
2733
2734
|
alive-type-in 2s steps(40, end) both,
|
|
2734
2735
|
alive-blink 0.8s step-end infinite;
|
|
@@ -2927,7 +2928,7 @@ video {
|
|
|
2927
2928
|
position: absolute;
|
|
2928
2929
|
inset: -24px;
|
|
2929
2930
|
border-radius: inherit;
|
|
2930
|
-
background: radial-gradient(ellipse at center, rgba(99,102,241,0.25) 0%, rgba(99,102,241,0.08) 50%, transparent 70%);
|
|
2931
|
+
background: radial-gradient(ellipse at center, var(--alive-spotlight-color, rgba(99,102,241,0.25)) 0%, var(--alive-spotlight-color-mid, rgba(99,102,241,0.08)) 50%, transparent 70%);
|
|
2931
2932
|
animation: alive-spotlight-in 0.6s cubic-bezier(0.22, 1, 0.36, 1) both;
|
|
2932
2933
|
pointer-events: none;
|
|
2933
2934
|
z-index: -1;
|
|
@@ -2937,8 +2938,8 @@ video {
|
|
|
2937
2938
|
position: absolute;
|
|
2938
2939
|
inset: -4px;
|
|
2939
2940
|
border-radius: inherit;
|
|
2940
|
-
border: 1px solid rgba(99,102,241,0.4);
|
|
2941
|
-
box-shadow: 0 0 24px rgba(99,102,241,0.3), 0 0 48px rgba(99,102,241,0.15);
|
|
2941
|
+
border: 1px solid var(--alive-spotlight-ring-color, rgba(99,102,241,0.4));
|
|
2942
|
+
box-shadow: 0 0 24px var(--alive-spotlight-glow, rgba(99,102,241,0.3)), 0 0 48px var(--alive-spotlight-glow-far, rgba(99,102,241,0.15));
|
|
2942
2943
|
animation: alive-spotlight-in 0.6s cubic-bezier(0.22, 1, 0.36, 1) both;
|
|
2943
2944
|
pointer-events: none;
|
|
2944
2945
|
}
|
|
@@ -2964,6 +2965,9 @@ video {
|
|
|
2964
2965
|
font-size: 0.75rem;
|
|
2965
2966
|
font-weight: 600;
|
|
2966
2967
|
letter-spacing: 0.02em;
|
|
2968
|
+
background: var(--alive-badge-bg, transparent);
|
|
2969
|
+
color: var(--alive-badge-color, inherit);
|
|
2970
|
+
border: 1px solid var(--alive-badge-border, transparent);
|
|
2967
2971
|
animation: alive-badge-in 0.4s cubic-bezier(0.22, 1, 0.36, 1) both;
|
|
2968
2972
|
}
|
|
2969
2973
|
.alive-badge-pulse .alive-badge-dot {
|
|
@@ -2972,6 +2976,7 @@ video {
|
|
|
2972
2976
|
height: 8px;
|
|
2973
2977
|
border-radius: 50%;
|
|
2974
2978
|
flex-shrink: 0;
|
|
2979
|
+
background: var(--alive-badge-dot, currentColor);
|
|
2975
2980
|
}
|
|
2976
2981
|
.alive-badge-pulse .alive-badge-dot::before {
|
|
2977
2982
|
content: '';
|
|
@@ -3188,8 +3193,8 @@ video {
|
|
|
3188
3193
|
gap: 8px;
|
|
3189
3194
|
padding: 20px 24px;
|
|
3190
3195
|
border-radius: 14px;
|
|
3191
|
-
background: rgba(255,255,255,0.04);
|
|
3192
|
-
border: 1px solid rgba(255,255,255,0.08);
|
|
3196
|
+
background: var(--alive-metric-bg, rgba(255,255,255,0.04));
|
|
3197
|
+
border: 1px solid var(--alive-metric-border, rgba(255,255,255,0.08));
|
|
3193
3198
|
animation: alive-metric-in 0.5s cubic-bezier(0.22, 1, 0.36, 1) both;
|
|
3194
3199
|
min-width: 160px;
|
|
3195
3200
|
}
|
|
@@ -3198,14 +3203,14 @@ video {
|
|
|
3198
3203
|
font-weight: 500;
|
|
3199
3204
|
text-transform: uppercase;
|
|
3200
3205
|
letter-spacing: 0.07em;
|
|
3201
|
-
color: rgba(255,255,255,0.4);
|
|
3206
|
+
color: var(--alive-metric-label-color, rgba(255,255,255,0.4));
|
|
3202
3207
|
}
|
|
3203
3208
|
.alive-metric-card-value {
|
|
3204
3209
|
font-size: 2.25rem;
|
|
3205
3210
|
font-weight: 800;
|
|
3206
3211
|
letter-spacing: -0.04em;
|
|
3207
3212
|
line-height: 1;
|
|
3208
|
-
color: #fff;
|
|
3213
|
+
color: var(--alive-metric-value-color, #fff);
|
|
3209
3214
|
}
|
|
3210
3215
|
.alive-metric-card-change {
|
|
3211
3216
|
display: inline-flex;
|
|
@@ -3229,7 +3234,7 @@ video {
|
|
|
3229
3234
|
.alive-metric-card-bar-fill {
|
|
3230
3235
|
height: 100%;
|
|
3231
3236
|
border-radius: 2px;
|
|
3232
|
-
background: linear-gradient(90deg, #6366f1, #8b5cf6, #6366f1);
|
|
3237
|
+
background: linear-gradient(90deg, var(--alive-metric-accent, #6366f1), var(--alive-metric-accent-2, #8b5cf6), var(--alive-metric-accent, #6366f1));
|
|
3233
3238
|
background-size: 200% auto;
|
|
3234
3239
|
transform-origin: left;
|
|
3235
3240
|
animation:
|
|
@@ -4563,6 +4568,32 @@ video {
|
|
|
4563
4568
|
.alive-meteor:nth-child(2) { top: 25%; left: 30%; animation-delay: 0.8s; animation-duration: 1.8s; width: 40px; }
|
|
4564
4569
|
.alive-meteor:nth-child(3) { top: 5%; left: 60%; animation-delay: 1.5s; animation-duration: 2.5s; }
|
|
4565
4570
|
.alive-meteor:nth-child(4) { top: 40%; left: 75%; animation-delay: 0.4s; animation-duration: 1.6s; width: 80px; }
|
|
4571
|
+
|
|
4572
|
+
/* \u2500\u2500 Scene Sequencer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
4573
|
+
Pair with [data-alive-sequence] + [data-alive-scene] attributes.
|
|
4574
|
+
The runtime (./runtime) drives is-active and transition classes.
|
|
4575
|
+
See: data-alive-duration, data-alive-transition, data-alive-loop.
|
|
4576
|
+
\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
4577
|
+
[data-alive-sequence] {
|
|
4578
|
+
position: relative;
|
|
4579
|
+
overflow: hidden;
|
|
4580
|
+
}
|
|
4581
|
+
[data-alive-scene] {
|
|
4582
|
+
position: absolute;
|
|
4583
|
+
inset: 0;
|
|
4584
|
+
opacity: 0;
|
|
4585
|
+
pointer-events: none;
|
|
4586
|
+
}
|
|
4587
|
+
[data-alive-scene].is-active {
|
|
4588
|
+
opacity: 1;
|
|
4589
|
+
pointer-events: auto;
|
|
4590
|
+
z-index: 1;
|
|
4591
|
+
}
|
|
4592
|
+
/* Outgoing scene (has a -out class) must stay visible during the transition */
|
|
4593
|
+
[data-alive-scene][class*="-out"] {
|
|
4594
|
+
opacity: 1;
|
|
4595
|
+
z-index: 2;
|
|
4596
|
+
}
|
|
4566
4597
|
`;
|
|
4567
4598
|
}
|
|
4568
4599
|
var init_base = __esm({
|