@alivecss/aliveui 1.0.0 → 1.0.2
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/README.md +7 -7
- package/dist/cli.js +89 -26
- package/dist/index.js +100 -28
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +100 -28
- package/dist/index.mjs.map +1 -1
- package/dist/runtime.d.mts +1 -1
- package/dist/runtime.d.ts +1 -1
- package/dist/runtime.js.map +1 -1
- package/dist/runtime.mjs.map +1 -1
- package/dist/vite.d.mts +1 -1
- package/dist/vite.d.ts +1 -1
- package/dist/vite.js +101 -28
- package/dist/vite.js.map +1 -1
- package/dist/vite.mjs +101 -28
- package/dist/vite.mjs.map +1 -1
- package/package.json +1 -1
package/dist/runtime.d.mts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* dropdown, and tabs components — zero dependencies, ~2 KB.
|
|
6
6
|
*
|
|
7
7
|
* Usage:
|
|
8
|
-
* import { init } from '@
|
|
8
|
+
* import { init } from '@alivecss/aliveui/runtime'
|
|
9
9
|
* init() // wire everything in document
|
|
10
10
|
* init(myRootElement) // wire a subtree
|
|
11
11
|
*/
|
package/dist/runtime.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* dropdown, and tabs components — zero dependencies, ~2 KB.
|
|
6
6
|
*
|
|
7
7
|
* Usage:
|
|
8
|
-
* import { init } from '@
|
|
8
|
+
* import { init } from '@alivecss/aliveui/runtime'
|
|
9
9
|
* init() // wire everything in document
|
|
10
10
|
* init(myRootElement) // wire a subtree
|
|
11
11
|
*/
|
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 '@pratikshadake/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":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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// ── 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":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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"]}
|
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 '@pratikshadake/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// ── 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"]}
|
package/dist/vite.d.mts
CHANGED
|
@@ -31,7 +31,7 @@ type DeepPartial<T> = {
|
|
|
31
31
|
* `@aliveui` directives in your CSS are processed automatically.
|
|
32
32
|
*
|
|
33
33
|
* Usage in vite.config.ts:
|
|
34
|
-
* import { aliveUIVite } from '@
|
|
34
|
+
* import { aliveUIVite } from '@alivecss/aliveui/vite'
|
|
35
35
|
*
|
|
36
36
|
* export default defineConfig({
|
|
37
37
|
* plugins: [aliveUIVite({ content: ['./src/**\/*.{ts,tsx,html}'] })],
|
package/dist/vite.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ type DeepPartial<T> = {
|
|
|
31
31
|
* `@aliveui` directives in your CSS are processed automatically.
|
|
32
32
|
*
|
|
33
33
|
* Usage in vite.config.ts:
|
|
34
|
-
* import { aliveUIVite } from '@
|
|
34
|
+
* import { aliveUIVite } from '@alivecss/aliveui/vite'
|
|
35
35
|
*
|
|
36
36
|
* export default defineConfig({
|
|
37
37
|
* plugins: [aliveUIVite({ content: ['./src/**\/*.{ts,tsx,html}'] })],
|
package/dist/vite.js
CHANGED
|
@@ -612,6 +612,42 @@ function generateBase(_config) {
|
|
|
612
612
|
box-sizing: border-box;
|
|
613
613
|
}
|
|
614
614
|
|
|
615
|
+
html {
|
|
616
|
+
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
|
|
617
|
+
"Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif,
|
|
618
|
+
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
|
619
|
+
line-height: 1.5;
|
|
620
|
+
-webkit-text-size-adjust: 100%;
|
|
621
|
+
-moz-tab-size: 4;
|
|
622
|
+
tab-size: 4;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
body {
|
|
626
|
+
margin: 0;
|
|
627
|
+
line-height: inherit;
|
|
628
|
+
-webkit-font-smoothing: antialiased;
|
|
629
|
+
-moz-osx-font-smoothing: grayscale;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
button,
|
|
633
|
+
input,
|
|
634
|
+
optgroup,
|
|
635
|
+
select,
|
|
636
|
+
textarea {
|
|
637
|
+
font-family: inherit;
|
|
638
|
+
font-size: 100%;
|
|
639
|
+
font-weight: inherit;
|
|
640
|
+
line-height: inherit;
|
|
641
|
+
color: inherit;
|
|
642
|
+
margin: 0;
|
|
643
|
+
padding: 0;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
button,
|
|
647
|
+
select {
|
|
648
|
+
text-transform: none;
|
|
649
|
+
}
|
|
650
|
+
|
|
615
651
|
/* \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 */
|
|
616
652
|
:root {
|
|
617
653
|
/* Motion durations */
|
|
@@ -2725,9 +2761,23 @@ var init_typography = __esm({
|
|
|
2725
2761
|
});
|
|
2726
2762
|
|
|
2727
2763
|
// src/generator/layout.ts
|
|
2728
|
-
function
|
|
2764
|
+
function has2(obj, key) {
|
|
2765
|
+
return typeof obj[key] === "string";
|
|
2766
|
+
}
|
|
2767
|
+
function generateLayout(classes, config) {
|
|
2768
|
+
const { spacing } = config.theme;
|
|
2729
2769
|
const rules = [];
|
|
2730
2770
|
for (const cls of classes) {
|
|
2771
|
+
const spaceYMatch = cls.match(/^space-y-(.+)$/);
|
|
2772
|
+
if (spaceYMatch && has2(spacing, spaceYMatch[1])) {
|
|
2773
|
+
rules.push(`.${escapeSelector(cls)} > * + * { margin-top: ${spacing[spaceYMatch[1]]}; }`);
|
|
2774
|
+
continue;
|
|
2775
|
+
}
|
|
2776
|
+
const spaceXMatch = cls.match(/^space-x-(.+)$/);
|
|
2777
|
+
if (spaceXMatch && has2(spacing, spaceXMatch[1])) {
|
|
2778
|
+
rules.push(`.${escapeSelector(cls)} > * + * { margin-left: ${spacing[spaceXMatch[1]]}; }`);
|
|
2779
|
+
continue;
|
|
2780
|
+
}
|
|
2731
2781
|
const generated = matchLayout(cls);
|
|
2732
2782
|
if (generated) rules.push(generated);
|
|
2733
2783
|
}
|
|
@@ -2770,6 +2820,10 @@ function matchLayout(cls) {
|
|
|
2770
2820
|
if (cls === "flex-grow-0") return `.${cls} { flex-grow: 0; }`;
|
|
2771
2821
|
if (cls === "flex-shrink") return `.${cls} { flex-shrink: 1; }`;
|
|
2772
2822
|
if (cls === "flex-shrink-0") return `.${cls} { flex-shrink: 0; }`;
|
|
2823
|
+
if (cls === "grow") return `.${cls} { flex-grow: 1; }`;
|
|
2824
|
+
if (cls === "grow-0") return `.${cls} { flex-grow: 0; }`;
|
|
2825
|
+
if (cls === "shrink") return `.${cls} { flex-shrink: 1; }`;
|
|
2826
|
+
if (cls === "shrink-0") return `.${cls} { flex-shrink: 0; }`;
|
|
2773
2827
|
if (cls === "items-start") return `.${cls} { align-items: flex-start; }`;
|
|
2774
2828
|
if (cls === "items-end") return `.${cls} { align-items: flex-end; }`;
|
|
2775
2829
|
if (cls === "items-center") return `.${cls} { align-items: center; }`;
|
|
@@ -2947,11 +3001,12 @@ function matchLayout(cls) {
|
|
|
2947
3001
|
var init_layout = __esm({
|
|
2948
3002
|
"src/generator/layout.ts"() {
|
|
2949
3003
|
"use strict";
|
|
3004
|
+
init_utils();
|
|
2950
3005
|
}
|
|
2951
3006
|
});
|
|
2952
3007
|
|
|
2953
3008
|
// src/generator/sizing.ts
|
|
2954
|
-
function
|
|
3009
|
+
function has3(obj, key) {
|
|
2955
3010
|
return typeof obj[key] === "string";
|
|
2956
3011
|
}
|
|
2957
3012
|
function generateSizing(classes, config) {
|
|
@@ -3002,8 +3057,8 @@ function matchSizing(cls, spacing) {
|
|
|
3002
3057
|
if (key === "min") return `.${cls} { width: min-content; }`;
|
|
3003
3058
|
if (key === "max") return `.${cls} { width: max-content; }`;
|
|
3004
3059
|
if (key === "fit") return `.${cls} { width: fit-content; }`;
|
|
3005
|
-
if (
|
|
3006
|
-
if (
|
|
3060
|
+
if (has3(fractions, key)) return `.${cls} { width: ${fractions[key]}; }`;
|
|
3061
|
+
if (has3(spacing, key)) return `.${cls} { width: ${spacing[key]}; }`;
|
|
3007
3062
|
}
|
|
3008
3063
|
const minWMatch = cls.match(/^min-w-(.+)$/);
|
|
3009
3064
|
if (minWMatch) {
|
|
@@ -3013,7 +3068,7 @@ function matchSizing(cls, spacing) {
|
|
|
3013
3068
|
if (key === "min") return `.${cls} { min-width: min-content; }`;
|
|
3014
3069
|
if (key === "max") return `.${cls} { min-width: max-content; }`;
|
|
3015
3070
|
if (key === "fit") return `.${cls} { min-width: fit-content; }`;
|
|
3016
|
-
if (
|
|
3071
|
+
if (has3(spacing, key)) return `.${cls} { min-width: ${spacing[key]}; }`;
|
|
3017
3072
|
}
|
|
3018
3073
|
const maxWMap = {
|
|
3019
3074
|
none: "none",
|
|
@@ -3040,7 +3095,7 @@ function matchSizing(cls, spacing) {
|
|
|
3040
3095
|
"screen-2xl": "1536px"
|
|
3041
3096
|
};
|
|
3042
3097
|
const maxWMatch = cls.match(/^max-w-(.+)$/);
|
|
3043
|
-
if (maxWMatch &&
|
|
3098
|
+
if (maxWMatch && has3(maxWMap, maxWMatch[1])) {
|
|
3044
3099
|
return `.${cls} { max-width: ${maxWMap[maxWMatch[1]]}; }`;
|
|
3045
3100
|
}
|
|
3046
3101
|
const hMatch = cls.match(/^h-(.+)$/);
|
|
@@ -3054,8 +3109,8 @@ function matchSizing(cls, spacing) {
|
|
|
3054
3109
|
if (key === "min") return `.${cls} { height: min-content; }`;
|
|
3055
3110
|
if (key === "max") return `.${cls} { height: max-content; }`;
|
|
3056
3111
|
if (key === "fit") return `.${cls} { height: fit-content; }`;
|
|
3057
|
-
if (
|
|
3058
|
-
if (
|
|
3112
|
+
if (has3(fractions, key)) return `.${cls} { height: ${fractions[key]}; }`;
|
|
3113
|
+
if (has3(spacing, key)) return `.${cls} { height: ${spacing[key]}; }`;
|
|
3059
3114
|
}
|
|
3060
3115
|
const minHMatch = cls.match(/^min-h-(.+)$/);
|
|
3061
3116
|
if (minHMatch) {
|
|
@@ -3066,7 +3121,7 @@ function matchSizing(cls, spacing) {
|
|
|
3066
3121
|
if (key === "svh") return `.${cls} { min-height: 100svh; }`;
|
|
3067
3122
|
if (key === "dvh") return `.${cls} { min-height: 100dvh; }`;
|
|
3068
3123
|
if (key === "fit") return `.${cls} { min-height: fit-content; }`;
|
|
3069
|
-
if (
|
|
3124
|
+
if (has3(spacing, key)) return `.${cls} { min-height: ${spacing[key]}; }`;
|
|
3070
3125
|
}
|
|
3071
3126
|
const maxHMatch = cls.match(/^max-h-(.+)$/);
|
|
3072
3127
|
if (maxHMatch) {
|
|
@@ -3077,7 +3132,16 @@ function matchSizing(cls, spacing) {
|
|
|
3077
3132
|
if (key === "svh") return `.${cls} { max-height: 100svh; }`;
|
|
3078
3133
|
if (key === "dvh") return `.${cls} { max-height: 100dvh; }`;
|
|
3079
3134
|
if (key === "fit") return `.${cls} { max-height: fit-content; }`;
|
|
3080
|
-
if (
|
|
3135
|
+
if (has3(spacing, key)) return `.${cls} { max-height: ${spacing[key]}; }`;
|
|
3136
|
+
}
|
|
3137
|
+
const basisMatch = cls.match(/^basis-(.+)$/);
|
|
3138
|
+
if (basisMatch) {
|
|
3139
|
+
const key = basisMatch[1];
|
|
3140
|
+
if (key === "auto") return `.${cls} { flex-basis: auto; }`;
|
|
3141
|
+
if (key === "full") return `.${cls} { flex-basis: 100%; }`;
|
|
3142
|
+
if (key === "0") return `.${cls} { flex-basis: 0px; }`;
|
|
3143
|
+
if (has3(fractions, key)) return `.${cls} { flex-basis: ${fractions[key]}; }`;
|
|
3144
|
+
if (has3(spacing, key)) return `.${cls} { flex-basis: ${spacing[key]}; }`;
|
|
3081
3145
|
}
|
|
3082
3146
|
return null;
|
|
3083
3147
|
}
|
|
@@ -3088,7 +3152,7 @@ var init_sizing = __esm({
|
|
|
3088
3152
|
});
|
|
3089
3153
|
|
|
3090
3154
|
// src/generator/effects.ts
|
|
3091
|
-
function
|
|
3155
|
+
function has4(obj, key) {
|
|
3092
3156
|
return typeof obj[key] === "string";
|
|
3093
3157
|
}
|
|
3094
3158
|
function generateEffects(classes, config) {
|
|
@@ -3102,7 +3166,7 @@ function generateEffects(classes, config) {
|
|
|
3102
3166
|
}
|
|
3103
3167
|
function matchEffects(cls, opacity, zIndex, boxShadow, borderRadius) {
|
|
3104
3168
|
const opacityMatch = cls.match(/^opacity-(.+)$/);
|
|
3105
|
-
if (opacityMatch &&
|
|
3169
|
+
if (opacityMatch && has4(opacity, opacityMatch[1])) {
|
|
3106
3170
|
return `.${cls} {
|
|
3107
3171
|
opacity: ${opacity[opacityMatch[1]]};
|
|
3108
3172
|
transition-property: opacity;
|
|
@@ -3111,47 +3175,47 @@ function matchEffects(cls, opacity, zIndex, boxShadow, borderRadius) {
|
|
|
3111
3175
|
}`;
|
|
3112
3176
|
}
|
|
3113
3177
|
const zMatch = cls.match(/^z-(.+)$/);
|
|
3114
|
-
if (zMatch &&
|
|
3178
|
+
if (zMatch && has4(zIndex, zMatch[1])) {
|
|
3115
3179
|
return `.${cls} { z-index: ${zIndex[zMatch[1]]}; }`;
|
|
3116
3180
|
}
|
|
3117
3181
|
const shadowMatch = cls.match(/^shadow(?:-(.+))?$/);
|
|
3118
3182
|
if (shadowMatch) {
|
|
3119
3183
|
const key = shadowMatch[1] ?? "DEFAULT";
|
|
3120
|
-
if (
|
|
3184
|
+
if (has4(boxShadow, key)) {
|
|
3121
3185
|
return `.${cls} { box-shadow: ${boxShadow[key]}; }`;
|
|
3122
3186
|
}
|
|
3123
|
-
if (!shadowMatch[1] &&
|
|
3187
|
+
if (!shadowMatch[1] && has4(boxShadow, "DEFAULT")) {
|
|
3124
3188
|
return `.${cls} { box-shadow: ${boxShadow["DEFAULT"]}; }`;
|
|
3125
3189
|
}
|
|
3126
3190
|
}
|
|
3127
3191
|
const roundedMatch = cls.match(/^rounded(?:-(.+))?$/);
|
|
3128
3192
|
if (roundedMatch) {
|
|
3129
3193
|
const key = roundedMatch[1] ?? "DEFAULT";
|
|
3130
|
-
if (
|
|
3131
|
-
if (!roundedMatch[1] &&
|
|
3194
|
+
if (has4(borderRadius, key)) return `.${cls} { border-radius: ${borderRadius[key]}; }`;
|
|
3195
|
+
if (!roundedMatch[1] && has4(borderRadius, "DEFAULT")) return `.${cls} { border-radius: ${borderRadius["DEFAULT"]}; }`;
|
|
3132
3196
|
}
|
|
3133
3197
|
const roundedTMatch = cls.match(/^rounded-t(?:-(.+))?$/);
|
|
3134
3198
|
if (roundedTMatch) {
|
|
3135
3199
|
const rkey = roundedTMatch[1] ?? "DEFAULT";
|
|
3136
|
-
const val =
|
|
3200
|
+
const val = has4(borderRadius, rkey) ? borderRadius[rkey] : has4(borderRadius, "DEFAULT") ? borderRadius["DEFAULT"] : null;
|
|
3137
3201
|
if (val) return `.${cls} { border-top-left-radius: ${val}; border-top-right-radius: ${val}; }`;
|
|
3138
3202
|
}
|
|
3139
3203
|
const roundedBMatch = cls.match(/^rounded-b(?:-(.+))?$/);
|
|
3140
3204
|
if (roundedBMatch) {
|
|
3141
3205
|
const rkey = roundedBMatch[1] ?? "DEFAULT";
|
|
3142
|
-
const val =
|
|
3206
|
+
const val = has4(borderRadius, rkey) ? borderRadius[rkey] : has4(borderRadius, "DEFAULT") ? borderRadius["DEFAULT"] : null;
|
|
3143
3207
|
if (val) return `.${cls} { border-bottom-left-radius: ${val}; border-bottom-right-radius: ${val}; }`;
|
|
3144
3208
|
}
|
|
3145
3209
|
const roundedLMatch = cls.match(/^rounded-l(?:-(.+))?$/);
|
|
3146
3210
|
if (roundedLMatch) {
|
|
3147
3211
|
const rkey = roundedLMatch[1] ?? "DEFAULT";
|
|
3148
|
-
const val =
|
|
3212
|
+
const val = has4(borderRadius, rkey) ? borderRadius[rkey] : has4(borderRadius, "DEFAULT") ? borderRadius["DEFAULT"] : null;
|
|
3149
3213
|
if (val) return `.${cls} { border-top-left-radius: ${val}; border-bottom-left-radius: ${val}; }`;
|
|
3150
3214
|
}
|
|
3151
3215
|
const roundedRMatch = cls.match(/^rounded-r(?:-(.+))?$/);
|
|
3152
3216
|
if (roundedRMatch) {
|
|
3153
3217
|
const rkey = roundedRMatch[1] ?? "DEFAULT";
|
|
3154
|
-
const val =
|
|
3218
|
+
const val = has4(borderRadius, rkey) ? borderRadius[rkey] : has4(borderRadius, "DEFAULT") ? borderRadius["DEFAULT"] : null;
|
|
3155
3219
|
if (val) return `.${cls} { border-top-right-radius: ${val}; border-bottom-right-radius: ${val}; }`;
|
|
3156
3220
|
}
|
|
3157
3221
|
if (cls === "border") return `.${cls} { border-width: 1px; border-style: solid; }`;
|
|
@@ -3205,15 +3269,15 @@ function matchEffects(cls, opacity, zIndex, boxShadow, borderRadius) {
|
|
|
3205
3269
|
"150": "1.5"
|
|
3206
3270
|
};
|
|
3207
3271
|
const scaleMatch = cls.match(/^scale-(\d+)$/);
|
|
3208
|
-
if (scaleMatch &&
|
|
3272
|
+
if (scaleMatch && has4(scaleMap, scaleMatch[1])) {
|
|
3209
3273
|
return `.${cls} { transform: scale(${scaleMap[scaleMatch[1]]}); }`;
|
|
3210
3274
|
}
|
|
3211
3275
|
const scaleXMatch = cls.match(/^scale-x-(\d+)$/);
|
|
3212
|
-
if (scaleXMatch &&
|
|
3276
|
+
if (scaleXMatch && has4(scaleMap, scaleXMatch[1])) {
|
|
3213
3277
|
return `.${cls} { transform: scaleX(${scaleMap[scaleXMatch[1]]}); }`;
|
|
3214
3278
|
}
|
|
3215
3279
|
const scaleYMatch = cls.match(/^scale-y-(\d+)$/);
|
|
3216
|
-
if (scaleYMatch &&
|
|
3280
|
+
if (scaleYMatch && has4(scaleMap, scaleYMatch[1])) {
|
|
3217
3281
|
return `.${cls} { transform: scaleY(${scaleMap[scaleYMatch[1]]}); }`;
|
|
3218
3282
|
}
|
|
3219
3283
|
const rotateMatch = cls.match(/^-?rotate-(\d+)$/);
|
|
@@ -3256,7 +3320,7 @@ function matchEffects(cls, opacity, zIndex, boxShadow, borderRadius) {
|
|
|
3256
3320
|
"3xl": "64px"
|
|
3257
3321
|
};
|
|
3258
3322
|
const key = blurMatch[1] ?? "DEFAULT";
|
|
3259
|
-
if (
|
|
3323
|
+
if (has4(blurMap, key)) return `.${cls} { filter: blur(${blurMap[key]}); }`;
|
|
3260
3324
|
}
|
|
3261
3325
|
const backdropBlurMatch = cls.match(/^backdrop-blur(?:-(.+))?$/);
|
|
3262
3326
|
if (backdropBlurMatch) {
|
|
@@ -3271,7 +3335,7 @@ function matchEffects(cls, opacity, zIndex, boxShadow, borderRadius) {
|
|
|
3271
3335
|
"3xl": "64px"
|
|
3272
3336
|
};
|
|
3273
3337
|
const key = backdropBlurMatch[1] ?? "DEFAULT";
|
|
3274
|
-
if (
|
|
3338
|
+
if (has4(blurMap, key)) return `.${cls} { backdrop-filter: blur(${blurMap[key]}); }`;
|
|
3275
3339
|
}
|
|
3276
3340
|
const arbOpacityMatch = cls.match(/^opacity-\[(.+)\]$/);
|
|
3277
3341
|
if (arbOpacityMatch) {
|
|
@@ -3813,14 +3877,23 @@ var init_src = __esm({
|
|
|
3813
3877
|
postcssPlugin: "aliveui",
|
|
3814
3878
|
async Once(root, { result, postcss }) {
|
|
3815
3879
|
const classes = await scanContent(config);
|
|
3880
|
+
const hasAliveDirective = root.some((node) => node.type === "atrule" && node.name === "aliveui");
|
|
3881
|
+
if (hasAliveDirective) {
|
|
3882
|
+
const layerDecl = postcss.atRule({ name: "layer", params: "aliveui.base, aliveui.utilities" });
|
|
3883
|
+
root.prepend(layerDecl);
|
|
3884
|
+
}
|
|
3816
3885
|
root.walkAtRules("aliveui", (atRule) => {
|
|
3817
3886
|
const param = atRule.params.trim();
|
|
3818
3887
|
if (param === "base") {
|
|
3819
|
-
const css =
|
|
3888
|
+
const css = `@layer aliveui.base {
|
|
3889
|
+
${generateBase(config)}
|
|
3890
|
+
}`;
|
|
3820
3891
|
const parsed = postcss.parse(css, { from: atRule.source?.input.file });
|
|
3821
3892
|
atRule.replaceWith(parsed.nodes);
|
|
3822
3893
|
} else if (param === "utilities") {
|
|
3823
|
-
const css =
|
|
3894
|
+
const css = `@layer aliveui.utilities {
|
|
3895
|
+
${generateUtilities(classes, config)}
|
|
3896
|
+
}`;
|
|
3824
3897
|
const parsed = postcss.parse(css, { from: atRule.source?.input.file });
|
|
3825
3898
|
atRule.replaceWith(parsed.nodes);
|
|
3826
3899
|
} else {
|