@alivecss/aliveui 1.0.3 → 1.0.5
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 +109 -0
- package/dist/index.js +109 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +109 -0
- package/dist/index.mjs.map +1 -1
- package/dist/runtime.js +61 -0
- package/dist/runtime.js.map +1 -1
- package/dist/runtime.mjs +61 -0
- package/dist/runtime.mjs.map +1 -1
- package/dist/vite.js +109 -0
- package/dist/vite.js.map +1 -1
- package/dist/vite.mjs +109 -0
- package/dist/vite.mjs.map +1 -1
- package/package.json +1 -1
package/dist/runtime.js
CHANGED
|
@@ -211,12 +211,73 @@ function activateTab(container, panelId) {
|
|
|
211
211
|
activePanel?.classList.add("is-active");
|
|
212
212
|
activePanel?.setAttribute("aria-hidden", "false");
|
|
213
213
|
}
|
|
214
|
+
function wireScroll(el, root) {
|
|
215
|
+
const obs = new IntersectionObserver(
|
|
216
|
+
(entries) => {
|
|
217
|
+
entries.forEach((entry) => {
|
|
218
|
+
if (entry.isIntersecting) {
|
|
219
|
+
entry.target.classList.add("is-visible");
|
|
220
|
+
obs.unobserve(entry.target);
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
},
|
|
224
|
+
{ threshold: 0.1, rootMargin: "0px 0px -40px 0px" }
|
|
225
|
+
);
|
|
226
|
+
obs.observe(el);
|
|
227
|
+
registerCleanup(root, () => obs.disconnect());
|
|
228
|
+
}
|
|
229
|
+
function wireStagger(container) {
|
|
230
|
+
const children = [...container.children];
|
|
231
|
+
children.forEach((child, i) => {
|
|
232
|
+
child.style.setProperty("--alive-index", String(i));
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
function wireTilt(el, root) {
|
|
236
|
+
const htmlEl = el;
|
|
237
|
+
const STRENGTH = 8;
|
|
238
|
+
const moveCleanup = addListener(htmlEl, "mousemove", (e) => {
|
|
239
|
+
const rect = htmlEl.getBoundingClientRect();
|
|
240
|
+
const x = (e.clientX - rect.left) / rect.width - 0.5;
|
|
241
|
+
const y = (e.clientY - rect.top) / rect.height - 0.5;
|
|
242
|
+
htmlEl.style.transform = `perspective(800px) rotateY(${x * STRENGTH}deg) rotateX(${-y * STRENGTH}deg) scale(1.01)`;
|
|
243
|
+
htmlEl.style.transition = "transform 0.1s ease-out";
|
|
244
|
+
});
|
|
245
|
+
const leaveCleanup = addListener(htmlEl, "mouseleave", () => {
|
|
246
|
+
htmlEl.style.transform = "";
|
|
247
|
+
htmlEl.style.transition = "transform 0.4s cubic-bezier(0.16, 1, 0.3, 1)";
|
|
248
|
+
});
|
|
249
|
+
registerCleanup(root, moveCleanup);
|
|
250
|
+
registerCleanup(root, leaveCleanup);
|
|
251
|
+
}
|
|
252
|
+
function wireMagnetic(el, root) {
|
|
253
|
+
const htmlEl = el;
|
|
254
|
+
const PULL = 0.35;
|
|
255
|
+
const moveCleanup = addListener(htmlEl, "mousemove", (e) => {
|
|
256
|
+
const rect = htmlEl.getBoundingClientRect();
|
|
257
|
+
const cx = rect.left + rect.width / 2;
|
|
258
|
+
const cy = rect.top + rect.height / 2;
|
|
259
|
+
const dx = (e.clientX - cx) * PULL;
|
|
260
|
+
const dy = (e.clientY - cy) * PULL;
|
|
261
|
+
htmlEl.style.transform = `translate(${dx}px, ${dy}px)`;
|
|
262
|
+
htmlEl.style.transition = "transform 0.2s cubic-bezier(0.16, 1, 0.3, 1)";
|
|
263
|
+
});
|
|
264
|
+
const leaveCleanup = addListener(htmlEl, "mouseleave", () => {
|
|
265
|
+
htmlEl.style.transform = "";
|
|
266
|
+
htmlEl.style.transition = "transform 0.5s cubic-bezier(0.16, 1, 0.3, 1)";
|
|
267
|
+
});
|
|
268
|
+
registerCleanup(root, moveCleanup);
|
|
269
|
+
registerCleanup(root, leaveCleanup);
|
|
270
|
+
}
|
|
214
271
|
function init(root = document.documentElement) {
|
|
215
272
|
root.querySelectorAll("[data-alive-accordion]").forEach((el) => wireAccordion(el, root));
|
|
216
273
|
root.querySelectorAll("[data-alive-modal]").forEach((el) => wireModal(el, root));
|
|
217
274
|
root.querySelectorAll("[data-alive-drawer]").forEach((el) => wireDrawer(el, root));
|
|
218
275
|
root.querySelectorAll("[data-alive-dropdown]").forEach((el) => wireDropdown(el, root));
|
|
219
276
|
root.querySelectorAll("[data-alive-tabs]").forEach((el) => wireTabs(el, root));
|
|
277
|
+
root.querySelectorAll("[data-alive-scroll]").forEach((el) => wireScroll(el, root));
|
|
278
|
+
root.querySelectorAll("[data-alive-stagger]").forEach((el) => wireStagger(el));
|
|
279
|
+
root.querySelectorAll("[data-alive-tilt]").forEach((el) => wireTilt(el, root));
|
|
280
|
+
root.querySelectorAll("[data-alive-magnetic]").forEach((el) => wireMagnetic(el, root));
|
|
220
281
|
}
|
|
221
282
|
function destroy(root = document.documentElement) {
|
|
222
283
|
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// ── 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\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// ── 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"]}
|
package/dist/runtime.mjs
CHANGED
|
@@ -181,12 +181,73 @@ function activateTab(container, panelId) {
|
|
|
181
181
|
activePanel?.classList.add("is-active");
|
|
182
182
|
activePanel?.setAttribute("aria-hidden", "false");
|
|
183
183
|
}
|
|
184
|
+
function wireScroll(el, root) {
|
|
185
|
+
const obs = new IntersectionObserver(
|
|
186
|
+
(entries) => {
|
|
187
|
+
entries.forEach((entry) => {
|
|
188
|
+
if (entry.isIntersecting) {
|
|
189
|
+
entry.target.classList.add("is-visible");
|
|
190
|
+
obs.unobserve(entry.target);
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
},
|
|
194
|
+
{ threshold: 0.1, rootMargin: "0px 0px -40px 0px" }
|
|
195
|
+
);
|
|
196
|
+
obs.observe(el);
|
|
197
|
+
registerCleanup(root, () => obs.disconnect());
|
|
198
|
+
}
|
|
199
|
+
function wireStagger(container) {
|
|
200
|
+
const children = [...container.children];
|
|
201
|
+
children.forEach((child, i) => {
|
|
202
|
+
child.style.setProperty("--alive-index", String(i));
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
function wireTilt(el, root) {
|
|
206
|
+
const htmlEl = el;
|
|
207
|
+
const STRENGTH = 8;
|
|
208
|
+
const moveCleanup = addListener(htmlEl, "mousemove", (e) => {
|
|
209
|
+
const rect = htmlEl.getBoundingClientRect();
|
|
210
|
+
const x = (e.clientX - rect.left) / rect.width - 0.5;
|
|
211
|
+
const y = (e.clientY - rect.top) / rect.height - 0.5;
|
|
212
|
+
htmlEl.style.transform = `perspective(800px) rotateY(${x * STRENGTH}deg) rotateX(${-y * STRENGTH}deg) scale(1.01)`;
|
|
213
|
+
htmlEl.style.transition = "transform 0.1s ease-out";
|
|
214
|
+
});
|
|
215
|
+
const leaveCleanup = addListener(htmlEl, "mouseleave", () => {
|
|
216
|
+
htmlEl.style.transform = "";
|
|
217
|
+
htmlEl.style.transition = "transform 0.4s cubic-bezier(0.16, 1, 0.3, 1)";
|
|
218
|
+
});
|
|
219
|
+
registerCleanup(root, moveCleanup);
|
|
220
|
+
registerCleanup(root, leaveCleanup);
|
|
221
|
+
}
|
|
222
|
+
function wireMagnetic(el, root) {
|
|
223
|
+
const htmlEl = el;
|
|
224
|
+
const PULL = 0.35;
|
|
225
|
+
const moveCleanup = addListener(htmlEl, "mousemove", (e) => {
|
|
226
|
+
const rect = htmlEl.getBoundingClientRect();
|
|
227
|
+
const cx = rect.left + rect.width / 2;
|
|
228
|
+
const cy = rect.top + rect.height / 2;
|
|
229
|
+
const dx = (e.clientX - cx) * PULL;
|
|
230
|
+
const dy = (e.clientY - cy) * PULL;
|
|
231
|
+
htmlEl.style.transform = `translate(${dx}px, ${dy}px)`;
|
|
232
|
+
htmlEl.style.transition = "transform 0.2s cubic-bezier(0.16, 1, 0.3, 1)";
|
|
233
|
+
});
|
|
234
|
+
const leaveCleanup = addListener(htmlEl, "mouseleave", () => {
|
|
235
|
+
htmlEl.style.transform = "";
|
|
236
|
+
htmlEl.style.transition = "transform 0.5s cubic-bezier(0.16, 1, 0.3, 1)";
|
|
237
|
+
});
|
|
238
|
+
registerCleanup(root, moveCleanup);
|
|
239
|
+
registerCleanup(root, leaveCleanup);
|
|
240
|
+
}
|
|
184
241
|
function init(root = document.documentElement) {
|
|
185
242
|
root.querySelectorAll("[data-alive-accordion]").forEach((el) => wireAccordion(el, root));
|
|
186
243
|
root.querySelectorAll("[data-alive-modal]").forEach((el) => wireModal(el, root));
|
|
187
244
|
root.querySelectorAll("[data-alive-drawer]").forEach((el) => wireDrawer(el, root));
|
|
188
245
|
root.querySelectorAll("[data-alive-dropdown]").forEach((el) => wireDropdown(el, root));
|
|
189
246
|
root.querySelectorAll("[data-alive-tabs]").forEach((el) => wireTabs(el, root));
|
|
247
|
+
root.querySelectorAll("[data-alive-scroll]").forEach((el) => wireScroll(el, root));
|
|
248
|
+
root.querySelectorAll("[data-alive-stagger]").forEach((el) => wireStagger(el));
|
|
249
|
+
root.querySelectorAll("[data-alive-tilt]").forEach((el) => wireTilt(el, root));
|
|
250
|
+
root.querySelectorAll("[data-alive-magnetic]").forEach((el) => wireMagnetic(el, root));
|
|
190
251
|
}
|
|
191
252
|
function destroy(root = document.documentElement) {
|
|
192
253
|
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// ── 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\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;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;AAC7E;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// ── 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"]}
|
package/dist/vite.js
CHANGED
|
@@ -610,6 +610,9 @@ function generateBase(_config) {
|
|
|
610
610
|
::before,
|
|
611
611
|
::after {
|
|
612
612
|
box-sizing: border-box;
|
|
613
|
+
border-width: 0;
|
|
614
|
+
border-style: solid;
|
|
615
|
+
border-color: currentColor;
|
|
613
616
|
}
|
|
614
617
|
|
|
615
618
|
html {
|
|
@@ -629,6 +632,39 @@ body {
|
|
|
629
632
|
-moz-osx-font-smoothing: grayscale;
|
|
630
633
|
}
|
|
631
634
|
|
|
635
|
+
blockquote,
|
|
636
|
+
dl,
|
|
637
|
+
dd,
|
|
638
|
+
h1,
|
|
639
|
+
h2,
|
|
640
|
+
h3,
|
|
641
|
+
h4,
|
|
642
|
+
h5,
|
|
643
|
+
h6,
|
|
644
|
+
hr,
|
|
645
|
+
figure,
|
|
646
|
+
p,
|
|
647
|
+
pre {
|
|
648
|
+
margin: 0;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
fieldset {
|
|
652
|
+
margin: 0;
|
|
653
|
+
padding: 0;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
legend {
|
|
657
|
+
padding: 0;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
ol,
|
|
661
|
+
ul,
|
|
662
|
+
menu {
|
|
663
|
+
list-style: none;
|
|
664
|
+
margin: 0;
|
|
665
|
+
padding: 0;
|
|
666
|
+
}
|
|
667
|
+
|
|
632
668
|
button,
|
|
633
669
|
input,
|
|
634
670
|
optgroup,
|
|
@@ -638,9 +674,24 @@ textarea {
|
|
|
638
674
|
font-size: 100%;
|
|
639
675
|
font-weight: inherit;
|
|
640
676
|
line-height: inherit;
|
|
677
|
+
letter-spacing: inherit;
|
|
641
678
|
color: inherit;
|
|
642
679
|
margin: 0;
|
|
643
680
|
padding: 0;
|
|
681
|
+
background-color: transparent;
|
|
682
|
+
background-image: none;
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
button,
|
|
686
|
+
[type='button'],
|
|
687
|
+
[type='reset'],
|
|
688
|
+
[type='submit'] {
|
|
689
|
+
-webkit-appearance: button;
|
|
690
|
+
cursor: pointer;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
:disabled {
|
|
694
|
+
cursor: default;
|
|
644
695
|
}
|
|
645
696
|
|
|
646
697
|
button,
|
|
@@ -648,6 +699,28 @@ select {
|
|
|
648
699
|
text-transform: none;
|
|
649
700
|
}
|
|
650
701
|
|
|
702
|
+
img,
|
|
703
|
+
svg,
|
|
704
|
+
video,
|
|
705
|
+
canvas,
|
|
706
|
+
audio,
|
|
707
|
+
iframe,
|
|
708
|
+
embed,
|
|
709
|
+
object {
|
|
710
|
+
display: block;
|
|
711
|
+
vertical-align: middle;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
img,
|
|
715
|
+
video {
|
|
716
|
+
max-width: 100%;
|
|
717
|
+
height: auto;
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
[hidden] {
|
|
721
|
+
display: none;
|
|
722
|
+
}
|
|
723
|
+
|
|
651
724
|
/* \u2500\u2500 Design tokens \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 */
|
|
652
725
|
:root {
|
|
653
726
|
/* Motion durations */
|
|
@@ -845,6 +918,30 @@ select {
|
|
|
845
918
|
.alive-loop-ping { animation: alive-ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; }
|
|
846
919
|
.alive-loop-bounce { animation: alive-bounce 1s infinite; }
|
|
847
920
|
|
|
921
|
+
/* \u2500\u2500 Scroll-reveal (data-alive-scroll) \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 */
|
|
922
|
+
|
|
923
|
+
[data-alive-scroll] {
|
|
924
|
+
opacity: 0;
|
|
925
|
+
transform: translateY(8px);
|
|
926
|
+
}
|
|
927
|
+
[data-alive-scroll].is-visible {
|
|
928
|
+
animation: alive-fade-up var(--alive-duration-slow) var(--alive-ease-emphasized) both;
|
|
929
|
+
}
|
|
930
|
+
[data-alive-scroll="fade"] {
|
|
931
|
+
opacity: 0;
|
|
932
|
+
transform: none;
|
|
933
|
+
}
|
|
934
|
+
[data-alive-scroll="fade"].is-visible {
|
|
935
|
+
animation: alive-fade-in var(--alive-duration-normal) var(--alive-ease-standard) both;
|
|
936
|
+
}
|
|
937
|
+
[data-alive-scroll="scale"] {
|
|
938
|
+
opacity: 0;
|
|
939
|
+
transform: scale(0.94);
|
|
940
|
+
}
|
|
941
|
+
[data-alive-scroll="scale"].is-visible {
|
|
942
|
+
animation: alive-scale-in var(--alive-duration-slow) var(--alive-ease-emphasized) both;
|
|
943
|
+
}
|
|
944
|
+
|
|
848
945
|
/* Reduced motion \u2014 respect system preference */
|
|
849
946
|
@media (prefers-reduced-motion: reduce) {
|
|
850
947
|
.alive-enter,
|
|
@@ -867,6 +964,18 @@ select {
|
|
|
867
964
|
transform: none;
|
|
868
965
|
}
|
|
869
966
|
|
|
967
|
+
[data-alive-scroll],
|
|
968
|
+
[data-alive-scroll="fade"],
|
|
969
|
+
[data-alive-scroll="scale"] {
|
|
970
|
+
opacity: 1;
|
|
971
|
+
transform: none;
|
|
972
|
+
}
|
|
973
|
+
[data-alive-scroll].is-visible,
|
|
974
|
+
[data-alive-scroll="fade"].is-visible,
|
|
975
|
+
[data-alive-scroll="scale"].is-visible {
|
|
976
|
+
animation: none;
|
|
977
|
+
}
|
|
978
|
+
|
|
870
979
|
/* depth system \u2014 disable hover lift and active press */
|
|
871
980
|
.d2,
|
|
872
981
|
.d2:hover,
|