@elurjs/core 3.5.0
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/LICENSE +21 -0
- package/README.md +157 -0
- package/dist/lib/async.cjs +16 -0
- package/dist/lib/async.js +123 -0
- package/dist/lib/component.cjs +2 -0
- package/dist/lib/component.js +66 -0
- package/dist/lib/context.cjs +2 -0
- package/dist/lib/context.js +52 -0
- package/dist/lib/devtools.cjs +59 -0
- package/dist/lib/devtools.js +419 -0
- package/dist/lib/elur/async.cjs +16 -0
- package/dist/lib/elur/async.cjs.map +1 -0
- package/dist/lib/elur/async.d.cts +32 -0
- package/dist/lib/elur/async.d.ts +32 -0
- package/dist/lib/elur/async.js +123 -0
- package/dist/lib/elur/async.js.map +1 -0
- package/dist/lib/elur/component.cjs +2 -0
- package/dist/lib/elur/component.cjs.map +1 -0
- package/dist/lib/elur/component.d.cts +17 -0
- package/dist/lib/elur/component.d.ts +17 -0
- package/dist/lib/elur/component.js +66 -0
- package/dist/lib/elur/component.js.map +1 -0
- package/dist/lib/elur/context.cjs +2 -0
- package/dist/lib/elur/context.cjs.map +1 -0
- package/dist/lib/elur/context.d.cts +29 -0
- package/dist/lib/elur/context.d.ts +29 -0
- package/dist/lib/elur/context.js +52 -0
- package/dist/lib/elur/context.js.map +1 -0
- package/dist/lib/elur/devtools.cjs +59 -0
- package/dist/lib/elur/devtools.cjs.map +1 -0
- package/dist/lib/elur/devtools.d.cts +24 -0
- package/dist/lib/elur/devtools.d.ts +24 -0
- package/dist/lib/elur/devtools.js +419 -0
- package/dist/lib/elur/devtools.js.map +1 -0
- package/dist/lib/elur/form.cjs +2 -0
- package/dist/lib/elur/form.cjs.map +1 -0
- package/dist/lib/elur/form.d.cts +283 -0
- package/dist/lib/elur/form.d.ts +283 -0
- package/dist/lib/elur/form.js +315 -0
- package/dist/lib/elur/form.js.map +1 -0
- package/dist/lib/elur/hydrate/index.cjs +2 -0
- package/dist/lib/elur/hydrate/index.cjs.map +1 -0
- package/dist/lib/elur/hydrate/index.d.cts +13 -0
- package/dist/lib/elur/hydrate/index.d.ts +13 -0
- package/dist/lib/elur/hydrate/index.js +410 -0
- package/dist/lib/elur/hydrate/index.js.map +1 -0
- package/dist/lib/elur/index.d.cts +19 -0
- package/dist/lib/elur/index.d.ts +19 -0
- package/dist/lib/elur/lifecycle.cjs +2 -0
- package/dist/lib/elur/lifecycle.cjs.map +1 -0
- package/dist/lib/elur/lifecycle.d.cts +45 -0
- package/dist/lib/elur/lifecycle.d.ts +45 -0
- package/dist/lib/elur/lifecycle.js +39 -0
- package/dist/lib/elur/lifecycle.js.map +1 -0
- package/dist/lib/elur/plugins.cjs +2 -0
- package/dist/lib/elur/plugins.cjs.map +1 -0
- package/dist/lib/elur/plugins.d.cts +48 -0
- package/dist/lib/elur/plugins.d.ts +48 -0
- package/dist/lib/elur/plugins.js +59 -0
- package/dist/lib/elur/plugins.js.map +1 -0
- package/dist/lib/elur/reactivity.cjs +2 -0
- package/dist/lib/elur/reactivity.cjs.map +1 -0
- package/dist/lib/elur/reactivity.d.cts +60 -0
- package/dist/lib/elur/reactivity.d.ts +60 -0
- package/dist/lib/elur/reactivity.js +188 -0
- package/dist/lib/elur/reactivity.js.map +1 -0
- package/dist/lib/elur/router.cjs +12 -0
- package/dist/lib/elur/router.cjs.map +1 -0
- package/dist/lib/elur/router.d.cts +137 -0
- package/dist/lib/elur/router.d.ts +137 -0
- package/dist/lib/elur/router.js +513 -0
- package/dist/lib/elur/router.js.map +1 -0
- package/dist/lib/elur/server/index.cjs +2 -0
- package/dist/lib/elur/server/index.cjs.map +1 -0
- package/dist/lib/elur/server/index.d.cts +44 -0
- package/dist/lib/elur/server/index.d.ts +44 -0
- package/dist/lib/elur/server/index.js +307 -0
- package/dist/lib/elur/server/index.js.map +1 -0
- package/dist/lib/elur/store.cjs +2 -0
- package/dist/lib/elur/store.cjs.map +1 -0
- package/dist/lib/elur/store.d.cts +137 -0
- package/dist/lib/elur/store.d.ts +137 -0
- package/dist/lib/elur/store.js +143 -0
- package/dist/lib/elur/store.js.map +1 -0
- package/dist/lib/elur/template/bindings.cjs +2 -0
- package/dist/lib/elur/template/bindings.cjs.map +1 -0
- package/dist/lib/elur/template/bindings.d.cts +40 -0
- package/dist/lib/elur/template/bindings.d.ts +40 -0
- package/dist/lib/elur/template/bindings.js +214 -0
- package/dist/lib/elur/template/bindings.js.map +1 -0
- package/dist/lib/elur/template/dom-write.cjs +2 -0
- package/dist/lib/elur/template/dom-write.cjs.map +1 -0
- package/dist/lib/elur/template/dom-write.d.cts +5 -0
- package/dist/lib/elur/template/dom-write.d.ts +5 -0
- package/dist/lib/elur/template/dom-write.js +16 -0
- package/dist/lib/elur/template/dom-write.js.map +1 -0
- package/dist/lib/elur/template/error-boundary.cjs +2 -0
- package/dist/lib/elur/template/error-boundary.cjs.map +1 -0
- package/dist/lib/elur/template/error-boundary.d.cts +7 -0
- package/dist/lib/elur/template/error-boundary.d.ts +7 -0
- package/dist/lib/elur/template/error-boundary.js +90 -0
- package/dist/lib/elur/template/error-boundary.js.map +1 -0
- package/dist/lib/elur/template/html.cjs +2 -0
- package/dist/lib/elur/template/html.cjs.map +1 -0
- package/dist/lib/elur/template/html.d.cts +8 -0
- package/dist/lib/elur/template/html.d.ts +8 -0
- package/dist/lib/elur/template/html.js +104 -0
- package/dist/lib/elur/template/html.js.map +1 -0
- package/dist/lib/elur/template/index.cjs +1 -0
- package/dist/lib/elur/template/index.d.cts +15 -0
- package/dist/lib/elur/template/index.d.ts +15 -0
- package/dist/lib/elur/template/index.js +13 -0
- package/dist/lib/elur/template/keyed-diff.cjs +2 -0
- package/dist/lib/elur/template/keyed-diff.cjs.map +1 -0
- package/dist/lib/elur/template/keyed-diff.d.cts +32 -0
- package/dist/lib/elur/template/keyed-diff.d.ts +32 -0
- package/dist/lib/elur/template/keyed-diff.js +100 -0
- package/dist/lib/elur/template/keyed-diff.js.map +1 -0
- package/dist/lib/elur/template/keyed.cjs +2 -0
- package/dist/lib/elur/template/keyed.cjs.map +1 -0
- package/dist/lib/elur/template/keyed.d.cts +27 -0
- package/dist/lib/elur/template/keyed.d.ts +27 -0
- package/dist/lib/elur/template/keyed.js +52 -0
- package/dist/lib/elur/template/keyed.js.map +1 -0
- package/dist/lib/elur/template/mount-helpers.cjs +2 -0
- package/dist/lib/elur/template/mount-helpers.cjs.map +1 -0
- package/dist/lib/elur/template/mount-helpers.d.cts +29 -0
- package/dist/lib/elur/template/mount-helpers.d.ts +29 -0
- package/dist/lib/elur/template/mount-helpers.js +132 -0
- package/dist/lib/elur/template/mount-helpers.js.map +1 -0
- package/dist/lib/elur/template/node-binding.cjs +2 -0
- package/dist/lib/elur/template/node-binding.cjs.map +1 -0
- package/dist/lib/elur/template/node-binding.d.cts +6 -0
- package/dist/lib/elur/template/node-binding.d.ts +6 -0
- package/dist/lib/elur/template/node-binding.js +95 -0
- package/dist/lib/elur/template/node-binding.js.map +1 -0
- package/dist/lib/elur/template/portal.cjs +2 -0
- package/dist/lib/elur/template/portal.cjs.map +1 -0
- package/dist/lib/elur/template/portal.d.cts +19 -0
- package/dist/lib/elur/template/portal.d.ts +19 -0
- package/dist/lib/elur/template/portal.js +49 -0
- package/dist/lib/elur/template/portal.js.map +1 -0
- package/dist/lib/elur/template/raw.cjs +2 -0
- package/dist/lib/elur/template/raw.cjs.map +1 -0
- package/dist/lib/elur/template/raw.d.cts +9 -0
- package/dist/lib/elur/template/raw.d.ts +9 -0
- package/dist/lib/elur/template/raw.js +29 -0
- package/dist/lib/elur/template/raw.js.map +1 -0
- package/dist/lib/elur/template/sanitize.cjs +2 -0
- package/dist/lib/elur/template/sanitize.cjs.map +1 -0
- package/dist/lib/elur/template/sanitize.d.cts +16 -0
- package/dist/lib/elur/template/sanitize.d.ts +16 -0
- package/dist/lib/elur/template/sanitize.js +29 -0
- package/dist/lib/elur/template/sanitize.js.map +1 -0
- package/dist/lib/elur/template/transitions.cjs +2 -0
- package/dist/lib/elur/template/transitions.cjs.map +1 -0
- package/dist/lib/elur/template/transitions.d.cts +43 -0
- package/dist/lib/elur/template/transitions.d.ts +43 -0
- package/dist/lib/elur/template/transitions.js +96 -0
- package/dist/lib/elur/template/transitions.js.map +1 -0
- package/dist/lib/elur/template/types.cjs +2 -0
- package/dist/lib/elur/template/types.cjs.map +1 -0
- package/dist/lib/elur/template/types.d.cts +114 -0
- package/dist/lib/elur/template/types.d.ts +114 -0
- package/dist/lib/elur/template/types.js +23 -0
- package/dist/lib/elur/template/types.js.map +1 -0
- package/dist/lib/elur.cjs +1 -0
- package/dist/lib/elur.js +18 -0
- package/dist/lib/form.cjs +2 -0
- package/dist/lib/form.js +315 -0
- package/dist/lib/hydrate.cjs +2 -0
- package/dist/lib/hydrate.js +410 -0
- package/dist/lib/index.cjs +1 -0
- package/dist/lib/index.d.cts +2 -0
- package/dist/lib/index.d.ts +2 -0
- package/dist/lib/index.js +18 -0
- package/dist/lib/lifecycle.cjs +2 -0
- package/dist/lib/lifecycle.js +39 -0
- package/dist/lib/plugins.cjs +2 -0
- package/dist/lib/plugins.js +59 -0
- package/dist/lib/router.cjs +12 -0
- package/dist/lib/router.js +513 -0
- package/dist/lib/server.cjs +2 -0
- package/dist/lib/server.js +307 -0
- package/dist/lib/signals.cjs +2 -0
- package/dist/lib/signals.js +188 -0
- package/dist/lib/store.cjs +2 -0
- package/dist/lib/store.js +143 -0
- package/dist/lib/template.cjs +1 -0
- package/dist/lib/template.js +13 -0
- package/package.json +216 -0
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require(`../../signals.cjs`),t=require(`./types.cjs`),n=require(`../../lifecycle.cjs`),r=require(`./mount-helpers.cjs`);function i(e){let t=e.name??`elur`;return{enterFrom:e.enterFrom??`${t}-enter-from`,enterActive:e.enterActive??`${t}-enter-active`,enterTo:e.enterTo??`${t}-enter-to`,leaveFrom:e.leaveFrom??`${t}-leave-from`,leaveActive:e.leaveActive??`${t}-leave-active`,leaveTo:e.leaveTo??`${t}-leave-to`}}function a(e){return Math.max(0,...e.split(`,`).map(e=>parseFloat(e.trim())||0))}function o(e,t=0){return new Promise(n=>{let r=getComputedStyle(e),i=Math.max(a(r.transitionDuration||`0`),a(r.animationDuration||`0`))*1e3,o=i>0?i+100:t;if(o<=0){n();return}let s,c=t=>{t.target===e&&(clearTimeout(s),e.removeEventListener(`transitionend`,c),e.removeEventListener(`animationend`,c),n())};e.addEventListener(`transitionend`,c),e.addEventListener(`animationend`,c),s=setTimeout(()=>{e.removeEventListener(`transitionend`,c),e.removeEventListener(`animationend`,c),n()},o)})}function s(a,s={}){let c=i(s);return{__isElurTemplate:!0,mount(e){let t=typeof e==`string`?document.querySelector(e)??document.body:e;return{unmount:this._render(t,null)}},_render(i,l){let u=document.createComment(t.COMMENT.TRANSITION);i.insertBefore(u,l);let d=null,f=null,p=0,m=!0,h=()=>{let e=u.nextSibling;for(;e&&e!==l;){if(e.nodeType===Node.ELEMENT_NODE)return e;e=e.nextSibling}return null};function g(e){return n.isElurComponent(e)?r._mountComponentSilent(e,i,l):e._render(i,l)}let _=(e,t=!1)=>{p++,f&&=(f(),null),d=g(e);let n=h();if(n&&(!m||s.appear)&&!t){let e=p;(async()=>{s.onBeforeEnter?.(n),n.classList.add(c.enterFrom,c.enterActive),n.getBoundingClientRect(),await new Promise(e=>requestAnimationFrame(()=>e())),p===e&&(n.classList.remove(c.enterFrom),n.classList.add(c.enterTo),await o(n,s.duration),p===e&&(n.classList.remove(c.enterActive,c.enterTo),s.onAfterEnter?.(n)))})().catch(()=>{})}m=!1},v=()=>{let e=d;d=null;let t=h();if(!t){e?.();return}let n=++p;f=e??null,(async()=>{s.onBeforeLeave?.(t),t.classList.add(c.leaveFrom,c.leaveActive),t.getBoundingClientRect(),await new Promise(e=>requestAnimationFrame(()=>e())),p===n&&(t.classList.remove(c.leaveFrom),t.classList.add(c.leaveTo),await o(t,s.duration),p===n&&(t.classList.remove(c.leaveActive,c.leaveTo),s.onAfterLeave?.(t),f?.(),f=null))})().catch(()=>{})},y=null;if(typeof a==`function`&&!n.isElurComponent(a)){let t=a,n=null;y=e.effect(()=>{let e=t(),r=n===null,i=e===null;r&&!i?_(e):!r&&i?v():!r&&!i&&(p++,f?.(),f=null,d?.(),d=null,_(e,!0)),n=e}),m=!1}else _(a);return()=>{p++,y?.(),d?.(),f?.(),d=null,f=null,u.remove()}}}}exports.transition=s;
|
|
2
|
+
//# sourceMappingURL=transitions.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transitions.cjs","names":[],"sources":["../../../../src/elur/template/transitions.ts"],"sourcesContent":["import { effect } from \"../reactivity.js\";\nimport { isElurComponent } from \"../lifecycle.js\";\nimport type { ElurComponent } from \"../lifecycle.js\";\nimport type { ElurTemplate, ElurMountHandle, TransitionContent } from \"./types.js\";\nimport { COMMENT } from \"./types.js\";\nimport { _mountComponentSilent } from \"./mount-helpers.js\";\n\n// =============================================================================\n// --- TransitionOptions ---\n// =============================================================================\n\n/**\n * Options for `transition()`. All class-name overrides are optional — by\n * default they are derived from `name` (default `\"elur\"`).\n *\n * | phase | from class | active class | to class |\n * |--------------|-------------------|---------------------|-----------------|\n * | enter | `{n}-enter-from` | `{n}-enter-active` | `{n}-enter-to` |\n * | leave | `{n}-leave-from` | `{n}-leave-active` | `{n}-leave-to` |\n */\nexport interface TransitionOptions {\n /**\n * Prefix for all generated CSS classes. Default `\"elur\"`.\n * e.g. `name: \"fade\"` generates `.fade-enter-from`, `.fade-leave-to`, …\n */\n name?: string;\n enterFrom?: string;\n enterActive?: string;\n enterTo?: string;\n leaveFrom?: string;\n leaveActive?: string;\n leaveTo?: string;\n /**\n * When `true` the enter transition also plays on the very first render\n * (similar to Vue's `appear`). Default `false`.\n */\n appear?: boolean;\n /**\n * Fallback duration in **milliseconds** used when no `transition-duration`\n * or `animation-duration` is found on the element via `getComputedStyle`.\n */\n duration?: number;\n onBeforeEnter?: (el: Element) => void;\n onAfterEnter?: (el: Element) => void;\n onBeforeLeave?: (el: Element) => void;\n onAfterLeave?: (el: Element) => void;\n}\n\n// =============================================================================\n// --- Internal transition helpers ---\n// =============================================================================\n\nfunction _resolveTransitionClasses(opts: TransitionOptions) {\n const n = opts.name ?? \"elur\";\n return {\n enterFrom: opts.enterFrom ?? `${n}-enter-from`,\n enterActive: opts.enterActive ?? `${n}-enter-active`,\n enterTo: opts.enterTo ?? `${n}-enter-to`,\n leaveFrom: opts.leaveFrom ?? `${n}-leave-from`,\n leaveActive: opts.leaveActive ?? `${n}-leave-active`,\n leaveTo: opts.leaveTo ?? `${n}-leave-to`,\n };\n}\n\nfunction _cssMaxDuration(cssValue: string): number {\n return Math.max(0, ...cssValue.split(\",\").map((s) => parseFloat(s.trim()) || 0));\n}\n\nfunction _waitTransitionEnd(el: Element, fallbackMs = 0): Promise<void> {\n return new Promise((resolve) => {\n const st = getComputedStyle(el);\n const ms =\n Math.max(\n _cssMaxDuration(st.transitionDuration || \"0\"),\n _cssMaxDuration(st.animationDuration || \"0\"),\n ) * 1000;\n const wait = ms > 0 ? ms + 100 : fallbackMs;\n\n if (wait <= 0) { resolve(); return; }\n\n let timerId: ReturnType<typeof setTimeout>;\n const done = (e: Event) => {\n if (e.target !== el) return;\n clearTimeout(timerId);\n el.removeEventListener(\"transitionend\", done);\n el.removeEventListener(\"animationend\", done);\n resolve();\n };\n el.addEventListener(\"transitionend\", done);\n el.addEventListener(\"animationend\", done);\n timerId = setTimeout(() => {\n el.removeEventListener(\"transitionend\", done);\n el.removeEventListener(\"animationend\", done);\n resolve();\n }, wait);\n });\n}\n\n// =============================================================================\n// --- transition() ---\n// =============================================================================\n\n/**\n * Wraps content with CSS class-based enter/leave transitions.\n * Static content plays enter on mount (only with `appear: true`).\n * Reactive `() => Template | null` auto-animates enter/leave on toggle.\n */\nexport function transition(\n content: TransitionContent,\n options: TransitionOptions = {},\n): ElurTemplate {\n const cls = _resolveTransitionClasses(options);\n\n return {\n __isElurTemplate: true as const,\n\n mount(container: Element | string): ElurMountHandle {\n const el =\n typeof container === \"string\"\n ? (document.querySelector(container) ?? document.body)\n : container;\n const cleanup = this._render(el, null);\n return { unmount: cleanup };\n },\n\n _render(parent: Node, before: Node | null): () => void {\n const marker = document.createComment(COMMENT.TRANSITION);\n parent.insertBefore(marker, before);\n\n let contentCleanup: (() => void) | null = null;\n let leaveCleanup: (() => void) | null = null;\n let leaveGen = 0;\n let isFirstRender = true;\n\n /** Find first Element node between `marker` and `before`. */\n const getEl = (): Element | null => {\n let node: Node | null = marker.nextSibling;\n while (node && node !== before) {\n if (node.nodeType === Node.ELEMENT_NODE) return node as Element;\n node = node.nextSibling;\n }\n return null;\n };\n\n function mountContent(tpl: ElurTemplate | ElurComponent): () => void {\n if (isElurComponent(tpl)) {\n return _mountComponentSilent(tpl as ElurComponent, parent, before);\n }\n return (tpl as ElurTemplate)._render(parent, before);\n }\n\n /** Mount content and play enter animation (does NOT block). */\n const doEnter = (tpl: ElurTemplate | ElurComponent, skipAnim = false): void => {\n leaveGen++;\n if (leaveCleanup) {\n leaveCleanup();\n leaveCleanup = null;\n }\n\n contentCleanup = mountContent(tpl);\n\n const el = getEl();\n const shouldAnimate = el && (!isFirstRender || options.appear) && !skipAnim;\n if (shouldAnimate) {\n const gen = leaveGen;\n const doIt = async () => {\n options.onBeforeEnter?.(el);\n el.classList.add(cls.enterFrom, cls.enterActive);\n void el.getBoundingClientRect();\n await new Promise<void>((r) => requestAnimationFrame(() => r()));\n if (leaveGen !== gen) return;\n el.classList.remove(cls.enterFrom);\n el.classList.add(cls.enterTo);\n await _waitTransitionEnd(el, options.duration);\n if (leaveGen !== gen) return;\n el.classList.remove(cls.enterActive, cls.enterTo);\n options.onAfterEnter?.(el);\n };\n doIt().catch(() => { /* ignore */ });\n }\n isFirstRender = false;\n };\n\n /** Remove current content after playing leave animation (does NOT block). */\n const doLeave = (): void => {\n const savedCleanup = contentCleanup;\n contentCleanup = null;\n const el = getEl();\n\n if (!el) { savedCleanup?.(); return; }\n\n const gen = ++leaveGen;\n leaveCleanup = savedCleanup ?? null;\n\n const doIt = async () => {\n options.onBeforeLeave?.(el);\n el.classList.add(cls.leaveFrom, cls.leaveActive);\n void el.getBoundingClientRect();\n await new Promise<void>((r) => requestAnimationFrame(() => r()));\n if (leaveGen !== gen) return;\n el.classList.remove(cls.leaveFrom);\n el.classList.add(cls.leaveTo);\n await _waitTransitionEnd(el, options.duration);\n if (leaveGen !== gen) return;\n el.classList.remove(cls.leaveActive, cls.leaveTo);\n options.onAfterLeave?.(el);\n leaveCleanup?.();\n leaveCleanup = null;\n };\n doIt().catch(() => { /* ignore */ });\n };\n\n let disposeWatcher: (() => void) | null = null;\n\n if (typeof content === \"function\" && !isElurComponent(content as unknown)) {\n const getter = content as () => ElurTemplate | ElurComponent | null;\n let prevVal: ElurTemplate | ElurComponent | null = null;\n\n disposeWatcher = effect(() => {\n const val = getter();\n const wasNull = prevVal === null;\n const isNull = val === null;\n\n if (wasNull && !isNull) {\n doEnter(val!);\n } else if (!wasNull && isNull) {\n doLeave();\n } else if (!wasNull && !isNull) {\n leaveGen++;\n leaveCleanup?.();\n leaveCleanup = null;\n contentCleanup?.();\n contentCleanup = null;\n doEnter(val!, true);\n }\n prevVal = val;\n });\n isFirstRender = false;\n } else {\n doEnter(content as ElurTemplate | ElurComponent);\n }\n\n return () => {\n leaveGen++;\n disposeWatcher?.();\n contentCleanup?.();\n leaveCleanup?.();\n contentCleanup = null;\n leaveCleanup = null;\n marker.remove();\n };\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { ElurTemplate, TransitionContent } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Options for `transition()`. All class-name overrides are optional — by
|
|
4
|
+
* default they are derived from `name` (default `"elur"`).
|
|
5
|
+
*
|
|
6
|
+
* | phase | from class | active class | to class |
|
|
7
|
+
* |--------------|-------------------|---------------------|-----------------|
|
|
8
|
+
* | enter | `{n}-enter-from` | `{n}-enter-active` | `{n}-enter-to` |
|
|
9
|
+
* | leave | `{n}-leave-from` | `{n}-leave-active` | `{n}-leave-to` |
|
|
10
|
+
*/
|
|
11
|
+
export interface TransitionOptions {
|
|
12
|
+
/**
|
|
13
|
+
* Prefix for all generated CSS classes. Default `"elur"`.
|
|
14
|
+
* e.g. `name: "fade"` generates `.fade-enter-from`, `.fade-leave-to`, …
|
|
15
|
+
*/
|
|
16
|
+
name?: string;
|
|
17
|
+
enterFrom?: string;
|
|
18
|
+
enterActive?: string;
|
|
19
|
+
enterTo?: string;
|
|
20
|
+
leaveFrom?: string;
|
|
21
|
+
leaveActive?: string;
|
|
22
|
+
leaveTo?: string;
|
|
23
|
+
/**
|
|
24
|
+
* When `true` the enter transition also plays on the very first render
|
|
25
|
+
* (similar to Vue's `appear`). Default `false`.
|
|
26
|
+
*/
|
|
27
|
+
appear?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Fallback duration in **milliseconds** used when no `transition-duration`
|
|
30
|
+
* or `animation-duration` is found on the element via `getComputedStyle`.
|
|
31
|
+
*/
|
|
32
|
+
duration?: number;
|
|
33
|
+
onBeforeEnter?: (el: Element) => void;
|
|
34
|
+
onAfterEnter?: (el: Element) => void;
|
|
35
|
+
onBeforeLeave?: (el: Element) => void;
|
|
36
|
+
onAfterLeave?: (el: Element) => void;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Wraps content with CSS class-based enter/leave transitions.
|
|
40
|
+
* Static content plays enter on mount (only with `appear: true`).
|
|
41
|
+
* Reactive `() => Template | null` auto-animates enter/leave on toggle.
|
|
42
|
+
*/
|
|
43
|
+
export declare function transition(content: TransitionContent, options?: TransitionOptions): ElurTemplate;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { ElurTemplate, TransitionContent } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Options for `transition()`. All class-name overrides are optional — by
|
|
4
|
+
* default they are derived from `name` (default `"elur"`).
|
|
5
|
+
*
|
|
6
|
+
* | phase | from class | active class | to class |
|
|
7
|
+
* |--------------|-------------------|---------------------|-----------------|
|
|
8
|
+
* | enter | `{n}-enter-from` | `{n}-enter-active` | `{n}-enter-to` |
|
|
9
|
+
* | leave | `{n}-leave-from` | `{n}-leave-active` | `{n}-leave-to` |
|
|
10
|
+
*/
|
|
11
|
+
export interface TransitionOptions {
|
|
12
|
+
/**
|
|
13
|
+
* Prefix for all generated CSS classes. Default `"elur"`.
|
|
14
|
+
* e.g. `name: "fade"` generates `.fade-enter-from`, `.fade-leave-to`, …
|
|
15
|
+
*/
|
|
16
|
+
name?: string;
|
|
17
|
+
enterFrom?: string;
|
|
18
|
+
enterActive?: string;
|
|
19
|
+
enterTo?: string;
|
|
20
|
+
leaveFrom?: string;
|
|
21
|
+
leaveActive?: string;
|
|
22
|
+
leaveTo?: string;
|
|
23
|
+
/**
|
|
24
|
+
* When `true` the enter transition also plays on the very first render
|
|
25
|
+
* (similar to Vue's `appear`). Default `false`.
|
|
26
|
+
*/
|
|
27
|
+
appear?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Fallback duration in **milliseconds** used when no `transition-duration`
|
|
30
|
+
* or `animation-duration` is found on the element via `getComputedStyle`.
|
|
31
|
+
*/
|
|
32
|
+
duration?: number;
|
|
33
|
+
onBeforeEnter?: (el: Element) => void;
|
|
34
|
+
onAfterEnter?: (el: Element) => void;
|
|
35
|
+
onBeforeLeave?: (el: Element) => void;
|
|
36
|
+
onAfterLeave?: (el: Element) => void;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Wraps content with CSS class-based enter/leave transitions.
|
|
40
|
+
* Static content plays enter on mount (only with `appear: true`).
|
|
41
|
+
* Reactive `() => Template | null` auto-animates enter/leave on toggle.
|
|
42
|
+
*/
|
|
43
|
+
export declare function transition(content: TransitionContent, options?: TransitionOptions): ElurTemplate;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { effect as e } from "../../signals.js";
|
|
2
|
+
import { COMMENT as t } from "./types.js";
|
|
3
|
+
import { isElurComponent as n } from "../../lifecycle.js";
|
|
4
|
+
import { _mountComponentSilent as r } from "./mount-helpers.js";
|
|
5
|
+
//#region src/elur/template/transitions.ts
|
|
6
|
+
function i(e) {
|
|
7
|
+
let t = e.name ?? "elur";
|
|
8
|
+
return {
|
|
9
|
+
enterFrom: e.enterFrom ?? `${t}-enter-from`,
|
|
10
|
+
enterActive: e.enterActive ?? `${t}-enter-active`,
|
|
11
|
+
enterTo: e.enterTo ?? `${t}-enter-to`,
|
|
12
|
+
leaveFrom: e.leaveFrom ?? `${t}-leave-from`,
|
|
13
|
+
leaveActive: e.leaveActive ?? `${t}-leave-active`,
|
|
14
|
+
leaveTo: e.leaveTo ?? `${t}-leave-to`
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function a(e) {
|
|
18
|
+
return Math.max(0, ...e.split(",").map((e) => parseFloat(e.trim()) || 0));
|
|
19
|
+
}
|
|
20
|
+
function o(e, t = 0) {
|
|
21
|
+
return new Promise((n) => {
|
|
22
|
+
let r = getComputedStyle(e), i = Math.max(a(r.transitionDuration || "0"), a(r.animationDuration || "0")) * 1e3, o = i > 0 ? i + 100 : t;
|
|
23
|
+
if (o <= 0) {
|
|
24
|
+
n();
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
let s, c = (t) => {
|
|
28
|
+
t.target === e && (clearTimeout(s), e.removeEventListener("transitionend", c), e.removeEventListener("animationend", c), n());
|
|
29
|
+
};
|
|
30
|
+
e.addEventListener("transitionend", c), e.addEventListener("animationend", c), s = setTimeout(() => {
|
|
31
|
+
e.removeEventListener("transitionend", c), e.removeEventListener("animationend", c), n();
|
|
32
|
+
}, o);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
function s(a, s = {}) {
|
|
36
|
+
let c = i(s);
|
|
37
|
+
return {
|
|
38
|
+
__isElurTemplate: !0,
|
|
39
|
+
mount(e) {
|
|
40
|
+
let t = typeof e == "string" ? document.querySelector(e) ?? document.body : e;
|
|
41
|
+
return { unmount: this._render(t, null) };
|
|
42
|
+
},
|
|
43
|
+
_render(i, l) {
|
|
44
|
+
let u = document.createComment(t.TRANSITION);
|
|
45
|
+
i.insertBefore(u, l);
|
|
46
|
+
let d = null, f = null, p = 0, m = !0, h = () => {
|
|
47
|
+
let e = u.nextSibling;
|
|
48
|
+
for (; e && e !== l;) {
|
|
49
|
+
if (e.nodeType === Node.ELEMENT_NODE) return e;
|
|
50
|
+
e = e.nextSibling;
|
|
51
|
+
}
|
|
52
|
+
return null;
|
|
53
|
+
};
|
|
54
|
+
function g(e) {
|
|
55
|
+
return n(e) ? r(e, i, l) : e._render(i, l);
|
|
56
|
+
}
|
|
57
|
+
let _ = (e, t = !1) => {
|
|
58
|
+
p++, f &&= (f(), null), d = g(e);
|
|
59
|
+
let n = h();
|
|
60
|
+
if (n && (!m || s.appear) && !t) {
|
|
61
|
+
let e = p;
|
|
62
|
+
(async () => {
|
|
63
|
+
s.onBeforeEnter?.(n), n.classList.add(c.enterFrom, c.enterActive), n.getBoundingClientRect(), await new Promise((e) => requestAnimationFrame(() => e())), p === e && (n.classList.remove(c.enterFrom), n.classList.add(c.enterTo), await o(n, s.duration), p === e && (n.classList.remove(c.enterActive, c.enterTo), s.onAfterEnter?.(n)));
|
|
64
|
+
})().catch(() => {});
|
|
65
|
+
}
|
|
66
|
+
m = !1;
|
|
67
|
+
}, v = () => {
|
|
68
|
+
let e = d;
|
|
69
|
+
d = null;
|
|
70
|
+
let t = h();
|
|
71
|
+
if (!t) {
|
|
72
|
+
e?.();
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
let n = ++p;
|
|
76
|
+
f = e ?? null, (async () => {
|
|
77
|
+
s.onBeforeLeave?.(t), t.classList.add(c.leaveFrom, c.leaveActive), t.getBoundingClientRect(), await new Promise((e) => requestAnimationFrame(() => e())), p === n && (t.classList.remove(c.leaveFrom), t.classList.add(c.leaveTo), await o(t, s.duration), p === n && (t.classList.remove(c.leaveActive, c.leaveTo), s.onAfterLeave?.(t), f?.(), f = null));
|
|
78
|
+
})().catch(() => {});
|
|
79
|
+
}, y = null;
|
|
80
|
+
if (typeof a == "function" && !n(a)) {
|
|
81
|
+
let t = a, n = null;
|
|
82
|
+
y = e(() => {
|
|
83
|
+
let e = t(), r = n === null, i = e === null;
|
|
84
|
+
r && !i ? _(e) : !r && i ? v() : !r && !i && (p++, f?.(), f = null, d?.(), d = null, _(e, !0)), n = e;
|
|
85
|
+
}), m = !1;
|
|
86
|
+
} else _(a);
|
|
87
|
+
return () => {
|
|
88
|
+
p++, y?.(), d?.(), f?.(), d = null, f = null, u.remove();
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
//#endregion
|
|
94
|
+
export { s as transition };
|
|
95
|
+
|
|
96
|
+
//# sourceMappingURL=transitions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transitions.js","names":[],"sources":["../../../../src/elur/template/transitions.ts"],"sourcesContent":["import { effect } from \"../reactivity.js\";\nimport { isElurComponent } from \"../lifecycle.js\";\nimport type { ElurComponent } from \"../lifecycle.js\";\nimport type { ElurTemplate, ElurMountHandle, TransitionContent } from \"./types.js\";\nimport { COMMENT } from \"./types.js\";\nimport { _mountComponentSilent } from \"./mount-helpers.js\";\n\n// =============================================================================\n// --- TransitionOptions ---\n// =============================================================================\n\n/**\n * Options for `transition()`. All class-name overrides are optional — by\n * default they are derived from `name` (default `\"elur\"`).\n *\n * | phase | from class | active class | to class |\n * |--------------|-------------------|---------------------|-----------------|\n * | enter | `{n}-enter-from` | `{n}-enter-active` | `{n}-enter-to` |\n * | leave | `{n}-leave-from` | `{n}-leave-active` | `{n}-leave-to` |\n */\nexport interface TransitionOptions {\n /**\n * Prefix for all generated CSS classes. Default `\"elur\"`.\n * e.g. `name: \"fade\"` generates `.fade-enter-from`, `.fade-leave-to`, …\n */\n name?: string;\n enterFrom?: string;\n enterActive?: string;\n enterTo?: string;\n leaveFrom?: string;\n leaveActive?: string;\n leaveTo?: string;\n /**\n * When `true` the enter transition also plays on the very first render\n * (similar to Vue's `appear`). Default `false`.\n */\n appear?: boolean;\n /**\n * Fallback duration in **milliseconds** used when no `transition-duration`\n * or `animation-duration` is found on the element via `getComputedStyle`.\n */\n duration?: number;\n onBeforeEnter?: (el: Element) => void;\n onAfterEnter?: (el: Element) => void;\n onBeforeLeave?: (el: Element) => void;\n onAfterLeave?: (el: Element) => void;\n}\n\n// =============================================================================\n// --- Internal transition helpers ---\n// =============================================================================\n\nfunction _resolveTransitionClasses(opts: TransitionOptions) {\n const n = opts.name ?? \"elur\";\n return {\n enterFrom: opts.enterFrom ?? `${n}-enter-from`,\n enterActive: opts.enterActive ?? `${n}-enter-active`,\n enterTo: opts.enterTo ?? `${n}-enter-to`,\n leaveFrom: opts.leaveFrom ?? `${n}-leave-from`,\n leaveActive: opts.leaveActive ?? `${n}-leave-active`,\n leaveTo: opts.leaveTo ?? `${n}-leave-to`,\n };\n}\n\nfunction _cssMaxDuration(cssValue: string): number {\n return Math.max(0, ...cssValue.split(\",\").map((s) => parseFloat(s.trim()) || 0));\n}\n\nfunction _waitTransitionEnd(el: Element, fallbackMs = 0): Promise<void> {\n return new Promise((resolve) => {\n const st = getComputedStyle(el);\n const ms =\n Math.max(\n _cssMaxDuration(st.transitionDuration || \"0\"),\n _cssMaxDuration(st.animationDuration || \"0\"),\n ) * 1000;\n const wait = ms > 0 ? ms + 100 : fallbackMs;\n\n if (wait <= 0) { resolve(); return; }\n\n let timerId: ReturnType<typeof setTimeout>;\n const done = (e: Event) => {\n if (e.target !== el) return;\n clearTimeout(timerId);\n el.removeEventListener(\"transitionend\", done);\n el.removeEventListener(\"animationend\", done);\n resolve();\n };\n el.addEventListener(\"transitionend\", done);\n el.addEventListener(\"animationend\", done);\n timerId = setTimeout(() => {\n el.removeEventListener(\"transitionend\", done);\n el.removeEventListener(\"animationend\", done);\n resolve();\n }, wait);\n });\n}\n\n// =============================================================================\n// --- transition() ---\n// =============================================================================\n\n/**\n * Wraps content with CSS class-based enter/leave transitions.\n * Static content plays enter on mount (only with `appear: true`).\n * Reactive `() => Template | null` auto-animates enter/leave on toggle.\n */\nexport function transition(\n content: TransitionContent,\n options: TransitionOptions = {},\n): ElurTemplate {\n const cls = _resolveTransitionClasses(options);\n\n return {\n __isElurTemplate: true as const,\n\n mount(container: Element | string): ElurMountHandle {\n const el =\n typeof container === \"string\"\n ? (document.querySelector(container) ?? document.body)\n : container;\n const cleanup = this._render(el, null);\n return { unmount: cleanup };\n },\n\n _render(parent: Node, before: Node | null): () => void {\n const marker = document.createComment(COMMENT.TRANSITION);\n parent.insertBefore(marker, before);\n\n let contentCleanup: (() => void) | null = null;\n let leaveCleanup: (() => void) | null = null;\n let leaveGen = 0;\n let isFirstRender = true;\n\n /** Find first Element node between `marker` and `before`. */\n const getEl = (): Element | null => {\n let node: Node | null = marker.nextSibling;\n while (node && node !== before) {\n if (node.nodeType === Node.ELEMENT_NODE) return node as Element;\n node = node.nextSibling;\n }\n return null;\n };\n\n function mountContent(tpl: ElurTemplate | ElurComponent): () => void {\n if (isElurComponent(tpl)) {\n return _mountComponentSilent(tpl as ElurComponent, parent, before);\n }\n return (tpl as ElurTemplate)._render(parent, before);\n }\n\n /** Mount content and play enter animation (does NOT block). */\n const doEnter = (tpl: ElurTemplate | ElurComponent, skipAnim = false): void => {\n leaveGen++;\n if (leaveCleanup) {\n leaveCleanup();\n leaveCleanup = null;\n }\n\n contentCleanup = mountContent(tpl);\n\n const el = getEl();\n const shouldAnimate = el && (!isFirstRender || options.appear) && !skipAnim;\n if (shouldAnimate) {\n const gen = leaveGen;\n const doIt = async () => {\n options.onBeforeEnter?.(el);\n el.classList.add(cls.enterFrom, cls.enterActive);\n void el.getBoundingClientRect();\n await new Promise<void>((r) => requestAnimationFrame(() => r()));\n if (leaveGen !== gen) return;\n el.classList.remove(cls.enterFrom);\n el.classList.add(cls.enterTo);\n await _waitTransitionEnd(el, options.duration);\n if (leaveGen !== gen) return;\n el.classList.remove(cls.enterActive, cls.enterTo);\n options.onAfterEnter?.(el);\n };\n doIt().catch(() => { /* ignore */ });\n }\n isFirstRender = false;\n };\n\n /** Remove current content after playing leave animation (does NOT block). */\n const doLeave = (): void => {\n const savedCleanup = contentCleanup;\n contentCleanup = null;\n const el = getEl();\n\n if (!el) { savedCleanup?.(); return; }\n\n const gen = ++leaveGen;\n leaveCleanup = savedCleanup ?? null;\n\n const doIt = async () => {\n options.onBeforeLeave?.(el);\n el.classList.add(cls.leaveFrom, cls.leaveActive);\n void el.getBoundingClientRect();\n await new Promise<void>((r) => requestAnimationFrame(() => r()));\n if (leaveGen !== gen) return;\n el.classList.remove(cls.leaveFrom);\n el.classList.add(cls.leaveTo);\n await _waitTransitionEnd(el, options.duration);\n if (leaveGen !== gen) return;\n el.classList.remove(cls.leaveActive, cls.leaveTo);\n options.onAfterLeave?.(el);\n leaveCleanup?.();\n leaveCleanup = null;\n };\n doIt().catch(() => { /* ignore */ });\n };\n\n let disposeWatcher: (() => void) | null = null;\n\n if (typeof content === \"function\" && !isElurComponent(content as unknown)) {\n const getter = content as () => ElurTemplate | ElurComponent | null;\n let prevVal: ElurTemplate | ElurComponent | null = null;\n\n disposeWatcher = effect(() => {\n const val = getter();\n const wasNull = prevVal === null;\n const isNull = val === null;\n\n if (wasNull && !isNull) {\n doEnter(val!);\n } else if (!wasNull && isNull) {\n doLeave();\n } else if (!wasNull && !isNull) {\n leaveGen++;\n leaveCleanup?.();\n leaveCleanup = null;\n contentCleanup?.();\n contentCleanup = null;\n doEnter(val!, true);\n }\n prevVal = val;\n });\n isFirstRender = false;\n } else {\n doEnter(content as ElurTemplate | ElurComponent);\n }\n\n return () => {\n leaveGen++;\n disposeWatcher?.();\n contentCleanup?.();\n leaveCleanup?.();\n contentCleanup = null;\n leaveCleanup = null;\n marker.remove();\n };\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var e=Symbol.for(`elur/template-descriptor`),t=Symbol.for(`elur/render-protocol`),n={partialAttributeInterpolation:!1};function r(){return{el:null}}var i={SCOPE:`elur-scope`,ERROR_BOUNDARY:`elur-eb`,TRANSITION:`elur-t`,KEYED_START:`elur-ks`,KEYED_END:`elur-ke`,KEYED_ZONE:`elur-kz`};function a(e){return typeof e==`object`&&!!e&&e.__isElurTemplate===!0}function o(e){return typeof e==`object`&&!!e&&e.__isKeyedList===!0}exports.COMMENT=i,exports.ELUR_RENDER_PROTOCOL=t,exports.ELUR_TEMPLATE_DESCRIPTOR=e,exports.isElurTemplate=a,exports.isKeyedList=o,exports.ref=r,exports.templateFeatures=n;
|
|
2
|
+
//# sourceMappingURL=types.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.cjs","names":[],"sources":["../../../../src/elur/template/types.ts"],"sourcesContent":["// =============================================================================\n// --- Public types ---\n// =============================================================================\n\nexport type TemplateBindingContext =\n | { type: \"node\" }\n | { type: \"event\"; eventName: string; modifiers: string[]; hadOpenQuote: boolean }\n | { type: \"attr\"; attrName: string; hadOpenQuote: boolean; url?: boolean; executable?: boolean };\n\nexport interface TemplateDescriptor {\n readonly version: 1;\n readonly strings: readonly string[];\n readonly values: readonly unknown[];\n readonly contexts: readonly TemplateBindingContext[];\n}\n\nexport interface ServerRenderProtocolContext {\n readonly markers: boolean;\n readonly signal?: AbortSignal;\n readonly context?: unknown;\n render(value: unknown, options?: { markers?: boolean }): Promise<string>;\n}\n\n/** Context passed to a custom value's `mountDom` protocol during client-side mount. */\nexport interface DomProtocolContext {\n readonly parent: Node;\n readonly before: Node | null;\n readonly context?: unknown;\n}\n\n/** Context passed to a custom value's `hydrateDom` protocol during hydration. */\nexport interface HydrationProtocolContext {\n readonly parent: Node;\n readonly bounds: { start: Comment; end: Comment } | null;\n readonly context?: unknown;\n /** Remounts a value inside the current bounds (used as fallback). */\n render(value: unknown): unknown;\n}\n\nexport interface ElurRenderProtocol {\n renderServer?(context: ServerRenderProtocolContext): string | Promise<string>;\n mountDom?(context: DomProtocolContext): (() => void) | void;\n hydrateDom?(context: HydrationProtocolContext): (() => void) | void;\n}\n\nexport const ELUR_TEMPLATE_DESCRIPTOR = Symbol.for(\"elur/template-descriptor\");\nexport const ELUR_RENDER_PROTOCOL = Symbol.for(\"elur/render-protocol\");\n\n/**\n * Runtime feature capabilities, for tooling to detect support without\n * inferring it from version strings.\n *\n * NOTE: Partial attribute interpolation is now handled at compile time by\n * @elurjs/vite-plugin-elur. The core runtime does not support it natively.\n * Use the Vite plugin for partial interpolation support.\n */\nexport const templateFeatures = {\n /** Partial attribute interpolation (`class=\"btn ${size}\"`) is supported. */\n partialAttributeInterpolation: false,\n} as const;\n\nexport interface ElurTemplate {\n readonly __isElurTemplate: true;\n readonly [ELUR_TEMPLATE_DESCRIPTOR]?: TemplateDescriptor;\n readonly [ELUR_RENDER_PROTOCOL]?: ElurRenderProtocol;\n /** Mounts the template into a container element (public / root API). */\n mount(container: Element | string): ElurMountHandle;\n /** @internal Renders before `before` node (or appends to `parent`). Returns cleanup. */\n _render(parent: Node, before: Node | null): () => void;\n}\n\nexport interface ElurMountHandle {\n unmount(): void;\n}\n\n/** Direct reference to a DOM element, assigned on mount and cleared on unmount. */\nexport interface ElurRef<T extends Element = Element> {\n el: T | null;\n}\n\n/** Creates an empty `ElurRef`. Use as `ref` attribute value in templates. */\nexport function ref<T extends Element = Element>(): ElurRef<T> {\n return { el: null };\n}\n\n/** Keyed list result for efficient DOM diffing via `repeat()`. */\nexport interface KeyedList<T = unknown> {\n readonly __isKeyedList: true;\n readonly items: T[];\n readonly keyFn: (item: T, index: number) => string | number;\n readonly renderFn: (item: T, index: number) => ElurTemplate | import(\"../lifecycle.js\").ElurComponent;\n}\n\nexport interface KEntry {\n start: Comment;\n end: Comment;\n cleanup: () => void;\n}\n\n/** Opaque token for a named portal target. */\nexport interface PortalOutlet {\n readonly __isPortalOutlet: true;\n /** @internal */\n _container: Element | null;\n}\n\n/** Fallback: a static template/component, or a factory receiving the error. */\nexport type ErrorFallback =\n | ElurTemplate\n | import(\"../lifecycle.js\").ElurComponent\n | ((err: unknown) => ElurTemplate | import(\"../lifecycle.js\").ElurComponent);\n\n/** Content that can be wrapped with `transition()`. */\nexport type TransitionContent =\n | ElurTemplate\n | import(\"../lifecycle.js\").ElurComponent\n | (() => ElurTemplate | import(\"../lifecycle.js\").ElurComponent | null);\n\nexport const COMMENT = {\n SCOPE: \"elur-scope\",\n ERROR_BOUNDARY: \"elur-eb\",\n TRANSITION: \"elur-t\",\n KEYED_START: \"elur-ks\",\n KEYED_END: \"elur-ke\",\n KEYED_ZONE: \"elur-kz\",\n} as const;\n\n// =============================================================================\n// --- DOM inspection helpers ---\n// =============================================================================\n\nexport function isElurTemplate(v: unknown): v is ElurTemplate {\n return (\n v != null &&\n typeof v === \"object\" &&\n (v as Record<string, unknown>).__isElurTemplate === true\n );\n}\n\nexport function isKeyedList(v: unknown): v is KeyedList {\n return (\n v != null &&\n typeof v === \"object\" &&\n (v as Record<string, unknown>).__isKeyedList === true\n );\n}\n"],"mappings":"AA6CA,IAAa,EAA2B,OAAO,IAAI,2BAA2B,CACjE,EAAuB,OAAO,IAAI,uBAAuB,CAUzD,EAAmB,CAE5B,8BAA+B,GAClC,CAsBD,SAAgB,GAA+C,CAC3D,MAAO,CAAE,GAAI,KAAM,CAoCvB,IAAa,EAAU,CACnB,MAAO,aACP,eAAgB,UAChB,WAAY,SACZ,YAAa,UACb,UAAW,UACX,WAAY,UACf,CAMD,SAAgB,EAAe,EAA+B,CAC1D,OAEI,OAAO,GAAM,YADb,GAEC,EAA8B,mBAAqB,GAI5D,SAAgB,EAAY,EAA4B,CACpD,OAEI,OAAO,GAAM,YADb,GAEC,EAA8B,gBAAkB"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
export type TemplateBindingContext = {
|
|
2
|
+
type: "node";
|
|
3
|
+
} | {
|
|
4
|
+
type: "event";
|
|
5
|
+
eventName: string;
|
|
6
|
+
modifiers: string[];
|
|
7
|
+
hadOpenQuote: boolean;
|
|
8
|
+
} | {
|
|
9
|
+
type: "attr";
|
|
10
|
+
attrName: string;
|
|
11
|
+
hadOpenQuote: boolean;
|
|
12
|
+
url?: boolean;
|
|
13
|
+
executable?: boolean;
|
|
14
|
+
};
|
|
15
|
+
export interface TemplateDescriptor {
|
|
16
|
+
readonly version: 1;
|
|
17
|
+
readonly strings: readonly string[];
|
|
18
|
+
readonly values: readonly unknown[];
|
|
19
|
+
readonly contexts: readonly TemplateBindingContext[];
|
|
20
|
+
}
|
|
21
|
+
export interface ServerRenderProtocolContext {
|
|
22
|
+
readonly markers: boolean;
|
|
23
|
+
readonly signal?: AbortSignal;
|
|
24
|
+
readonly context?: unknown;
|
|
25
|
+
render(value: unknown, options?: {
|
|
26
|
+
markers?: boolean;
|
|
27
|
+
}): Promise<string>;
|
|
28
|
+
}
|
|
29
|
+
/** Context passed to a custom value's `mountDom` protocol during client-side mount. */
|
|
30
|
+
export interface DomProtocolContext {
|
|
31
|
+
readonly parent: Node;
|
|
32
|
+
readonly before: Node | null;
|
|
33
|
+
readonly context?: unknown;
|
|
34
|
+
}
|
|
35
|
+
/** Context passed to a custom value's `hydrateDom` protocol during hydration. */
|
|
36
|
+
export interface HydrationProtocolContext {
|
|
37
|
+
readonly parent: Node;
|
|
38
|
+
readonly bounds: {
|
|
39
|
+
start: Comment;
|
|
40
|
+
end: Comment;
|
|
41
|
+
} | null;
|
|
42
|
+
readonly context?: unknown;
|
|
43
|
+
/** Remounts a value inside the current bounds (used as fallback). */
|
|
44
|
+
render(value: unknown): unknown;
|
|
45
|
+
}
|
|
46
|
+
export interface ElurRenderProtocol {
|
|
47
|
+
renderServer?(context: ServerRenderProtocolContext): string | Promise<string>;
|
|
48
|
+
mountDom?(context: DomProtocolContext): (() => void) | void;
|
|
49
|
+
hydrateDom?(context: HydrationProtocolContext): (() => void) | void;
|
|
50
|
+
}
|
|
51
|
+
export declare const ELUR_TEMPLATE_DESCRIPTOR: unique symbol;
|
|
52
|
+
export declare const ELUR_RENDER_PROTOCOL: unique symbol;
|
|
53
|
+
/**
|
|
54
|
+
* Runtime feature capabilities, for tooling to detect support without
|
|
55
|
+
* inferring it from version strings.
|
|
56
|
+
*
|
|
57
|
+
* NOTE: Partial attribute interpolation is now handled at compile time by
|
|
58
|
+
* @elurjs/vite-plugin-elur. The core runtime does not support it natively.
|
|
59
|
+
* Use the Vite plugin for partial interpolation support.
|
|
60
|
+
*/
|
|
61
|
+
export declare const templateFeatures: {
|
|
62
|
+
/** Partial attribute interpolation (`class="btn ${size}"`) is supported. */
|
|
63
|
+
readonly partialAttributeInterpolation: false;
|
|
64
|
+
};
|
|
65
|
+
export interface ElurTemplate {
|
|
66
|
+
readonly __isElurTemplate: true;
|
|
67
|
+
readonly [ELUR_TEMPLATE_DESCRIPTOR]?: TemplateDescriptor;
|
|
68
|
+
readonly [ELUR_RENDER_PROTOCOL]?: ElurRenderProtocol;
|
|
69
|
+
/** Mounts the template into a container element (public / root API). */
|
|
70
|
+
mount(container: Element | string): ElurMountHandle;
|
|
71
|
+
/** @internal Renders before `before` node (or appends to `parent`). Returns cleanup. */
|
|
72
|
+
_render(parent: Node, before: Node | null): () => void;
|
|
73
|
+
}
|
|
74
|
+
export interface ElurMountHandle {
|
|
75
|
+
unmount(): void;
|
|
76
|
+
}
|
|
77
|
+
/** Direct reference to a DOM element, assigned on mount and cleared on unmount. */
|
|
78
|
+
export interface ElurRef<T extends Element = Element> {
|
|
79
|
+
el: T | null;
|
|
80
|
+
}
|
|
81
|
+
/** Creates an empty `ElurRef`. Use as `ref` attribute value in templates. */
|
|
82
|
+
export declare function ref<T extends Element = Element>(): ElurRef<T>;
|
|
83
|
+
/** Keyed list result for efficient DOM diffing via `repeat()`. */
|
|
84
|
+
export interface KeyedList<T = unknown> {
|
|
85
|
+
readonly __isKeyedList: true;
|
|
86
|
+
readonly items: T[];
|
|
87
|
+
readonly keyFn: (item: T, index: number) => string | number;
|
|
88
|
+
readonly renderFn: (item: T, index: number) => ElurTemplate | import("../lifecycle.js").ElurComponent;
|
|
89
|
+
}
|
|
90
|
+
export interface KEntry {
|
|
91
|
+
start: Comment;
|
|
92
|
+
end: Comment;
|
|
93
|
+
cleanup: () => void;
|
|
94
|
+
}
|
|
95
|
+
/** Opaque token for a named portal target. */
|
|
96
|
+
export interface PortalOutlet {
|
|
97
|
+
readonly __isPortalOutlet: true;
|
|
98
|
+
/** @internal */
|
|
99
|
+
_container: Element | null;
|
|
100
|
+
}
|
|
101
|
+
/** Fallback: a static template/component, or a factory receiving the error. */
|
|
102
|
+
export type ErrorFallback = ElurTemplate | import("../lifecycle.js").ElurComponent | ((err: unknown) => ElurTemplate | import("../lifecycle.js").ElurComponent);
|
|
103
|
+
/** Content that can be wrapped with `transition()`. */
|
|
104
|
+
export type TransitionContent = ElurTemplate | import("../lifecycle.js").ElurComponent | (() => ElurTemplate | import("../lifecycle.js").ElurComponent | null);
|
|
105
|
+
export declare const COMMENT: {
|
|
106
|
+
readonly SCOPE: "elur-scope";
|
|
107
|
+
readonly ERROR_BOUNDARY: "elur-eb";
|
|
108
|
+
readonly TRANSITION: "elur-t";
|
|
109
|
+
readonly KEYED_START: "elur-ks";
|
|
110
|
+
readonly KEYED_END: "elur-ke";
|
|
111
|
+
readonly KEYED_ZONE: "elur-kz";
|
|
112
|
+
};
|
|
113
|
+
export declare function isElurTemplate(v: unknown): v is ElurTemplate;
|
|
114
|
+
export declare function isKeyedList(v: unknown): v is KeyedList;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
export type TemplateBindingContext = {
|
|
2
|
+
type: "node";
|
|
3
|
+
} | {
|
|
4
|
+
type: "event";
|
|
5
|
+
eventName: string;
|
|
6
|
+
modifiers: string[];
|
|
7
|
+
hadOpenQuote: boolean;
|
|
8
|
+
} | {
|
|
9
|
+
type: "attr";
|
|
10
|
+
attrName: string;
|
|
11
|
+
hadOpenQuote: boolean;
|
|
12
|
+
url?: boolean;
|
|
13
|
+
executable?: boolean;
|
|
14
|
+
};
|
|
15
|
+
export interface TemplateDescriptor {
|
|
16
|
+
readonly version: 1;
|
|
17
|
+
readonly strings: readonly string[];
|
|
18
|
+
readonly values: readonly unknown[];
|
|
19
|
+
readonly contexts: readonly TemplateBindingContext[];
|
|
20
|
+
}
|
|
21
|
+
export interface ServerRenderProtocolContext {
|
|
22
|
+
readonly markers: boolean;
|
|
23
|
+
readonly signal?: AbortSignal;
|
|
24
|
+
readonly context?: unknown;
|
|
25
|
+
render(value: unknown, options?: {
|
|
26
|
+
markers?: boolean;
|
|
27
|
+
}): Promise<string>;
|
|
28
|
+
}
|
|
29
|
+
/** Context passed to a custom value's `mountDom` protocol during client-side mount. */
|
|
30
|
+
export interface DomProtocolContext {
|
|
31
|
+
readonly parent: Node;
|
|
32
|
+
readonly before: Node | null;
|
|
33
|
+
readonly context?: unknown;
|
|
34
|
+
}
|
|
35
|
+
/** Context passed to a custom value's `hydrateDom` protocol during hydration. */
|
|
36
|
+
export interface HydrationProtocolContext {
|
|
37
|
+
readonly parent: Node;
|
|
38
|
+
readonly bounds: {
|
|
39
|
+
start: Comment;
|
|
40
|
+
end: Comment;
|
|
41
|
+
} | null;
|
|
42
|
+
readonly context?: unknown;
|
|
43
|
+
/** Remounts a value inside the current bounds (used as fallback). */
|
|
44
|
+
render(value: unknown): unknown;
|
|
45
|
+
}
|
|
46
|
+
export interface ElurRenderProtocol {
|
|
47
|
+
renderServer?(context: ServerRenderProtocolContext): string | Promise<string>;
|
|
48
|
+
mountDom?(context: DomProtocolContext): (() => void) | void;
|
|
49
|
+
hydrateDom?(context: HydrationProtocolContext): (() => void) | void;
|
|
50
|
+
}
|
|
51
|
+
export declare const ELUR_TEMPLATE_DESCRIPTOR: unique symbol;
|
|
52
|
+
export declare const ELUR_RENDER_PROTOCOL: unique symbol;
|
|
53
|
+
/**
|
|
54
|
+
* Runtime feature capabilities, for tooling to detect support without
|
|
55
|
+
* inferring it from version strings.
|
|
56
|
+
*
|
|
57
|
+
* NOTE: Partial attribute interpolation is now handled at compile time by
|
|
58
|
+
* @elurjs/vite-plugin-elur. The core runtime does not support it natively.
|
|
59
|
+
* Use the Vite plugin for partial interpolation support.
|
|
60
|
+
*/
|
|
61
|
+
export declare const templateFeatures: {
|
|
62
|
+
/** Partial attribute interpolation (`class="btn ${size}"`) is supported. */
|
|
63
|
+
readonly partialAttributeInterpolation: false;
|
|
64
|
+
};
|
|
65
|
+
export interface ElurTemplate {
|
|
66
|
+
readonly __isElurTemplate: true;
|
|
67
|
+
readonly [ELUR_TEMPLATE_DESCRIPTOR]?: TemplateDescriptor;
|
|
68
|
+
readonly [ELUR_RENDER_PROTOCOL]?: ElurRenderProtocol;
|
|
69
|
+
/** Mounts the template into a container element (public / root API). */
|
|
70
|
+
mount(container: Element | string): ElurMountHandle;
|
|
71
|
+
/** @internal Renders before `before` node (or appends to `parent`). Returns cleanup. */
|
|
72
|
+
_render(parent: Node, before: Node | null): () => void;
|
|
73
|
+
}
|
|
74
|
+
export interface ElurMountHandle {
|
|
75
|
+
unmount(): void;
|
|
76
|
+
}
|
|
77
|
+
/** Direct reference to a DOM element, assigned on mount and cleared on unmount. */
|
|
78
|
+
export interface ElurRef<T extends Element = Element> {
|
|
79
|
+
el: T | null;
|
|
80
|
+
}
|
|
81
|
+
/** Creates an empty `ElurRef`. Use as `ref` attribute value in templates. */
|
|
82
|
+
export declare function ref<T extends Element = Element>(): ElurRef<T>;
|
|
83
|
+
/** Keyed list result for efficient DOM diffing via `repeat()`. */
|
|
84
|
+
export interface KeyedList<T = unknown> {
|
|
85
|
+
readonly __isKeyedList: true;
|
|
86
|
+
readonly items: T[];
|
|
87
|
+
readonly keyFn: (item: T, index: number) => string | number;
|
|
88
|
+
readonly renderFn: (item: T, index: number) => ElurTemplate | import("../lifecycle.js").ElurComponent;
|
|
89
|
+
}
|
|
90
|
+
export interface KEntry {
|
|
91
|
+
start: Comment;
|
|
92
|
+
end: Comment;
|
|
93
|
+
cleanup: () => void;
|
|
94
|
+
}
|
|
95
|
+
/** Opaque token for a named portal target. */
|
|
96
|
+
export interface PortalOutlet {
|
|
97
|
+
readonly __isPortalOutlet: true;
|
|
98
|
+
/** @internal */
|
|
99
|
+
_container: Element | null;
|
|
100
|
+
}
|
|
101
|
+
/** Fallback: a static template/component, or a factory receiving the error. */
|
|
102
|
+
export type ErrorFallback = ElurTemplate | import("../lifecycle.js").ElurComponent | ((err: unknown) => ElurTemplate | import("../lifecycle.js").ElurComponent);
|
|
103
|
+
/** Content that can be wrapped with `transition()`. */
|
|
104
|
+
export type TransitionContent = ElurTemplate | import("../lifecycle.js").ElurComponent | (() => ElurTemplate | import("../lifecycle.js").ElurComponent | null);
|
|
105
|
+
export declare const COMMENT: {
|
|
106
|
+
readonly SCOPE: "elur-scope";
|
|
107
|
+
readonly ERROR_BOUNDARY: "elur-eb";
|
|
108
|
+
readonly TRANSITION: "elur-t";
|
|
109
|
+
readonly KEYED_START: "elur-ks";
|
|
110
|
+
readonly KEYED_END: "elur-ke";
|
|
111
|
+
readonly KEYED_ZONE: "elur-kz";
|
|
112
|
+
};
|
|
113
|
+
export declare function isElurTemplate(v: unknown): v is ElurTemplate;
|
|
114
|
+
export declare function isKeyedList(v: unknown): v is KeyedList;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//#region src/elur/template/types.ts
|
|
2
|
+
var e = Symbol.for("elur/template-descriptor"), t = Symbol.for("elur/render-protocol"), n = { partialAttributeInterpolation: !1 };
|
|
3
|
+
function r() {
|
|
4
|
+
return { el: null };
|
|
5
|
+
}
|
|
6
|
+
var i = {
|
|
7
|
+
SCOPE: "elur-scope",
|
|
8
|
+
ERROR_BOUNDARY: "elur-eb",
|
|
9
|
+
TRANSITION: "elur-t",
|
|
10
|
+
KEYED_START: "elur-ks",
|
|
11
|
+
KEYED_END: "elur-ke",
|
|
12
|
+
KEYED_ZONE: "elur-kz"
|
|
13
|
+
};
|
|
14
|
+
function a(e) {
|
|
15
|
+
return typeof e == "object" && !!e && e.__isElurTemplate === !0;
|
|
16
|
+
}
|
|
17
|
+
function o(e) {
|
|
18
|
+
return typeof e == "object" && !!e && e.__isKeyedList === !0;
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
export { i as COMMENT, t as ELUR_RENDER_PROTOCOL, e as ELUR_TEMPLATE_DESCRIPTOR, a as isElurTemplate, o as isKeyedList, r as ref, n as templateFeatures };
|
|
22
|
+
|
|
23
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","names":[],"sources":["../../../../src/elur/template/types.ts"],"sourcesContent":["// =============================================================================\n// --- Public types ---\n// =============================================================================\n\nexport type TemplateBindingContext =\n | { type: \"node\" }\n | { type: \"event\"; eventName: string; modifiers: string[]; hadOpenQuote: boolean }\n | { type: \"attr\"; attrName: string; hadOpenQuote: boolean; url?: boolean; executable?: boolean };\n\nexport interface TemplateDescriptor {\n readonly version: 1;\n readonly strings: readonly string[];\n readonly values: readonly unknown[];\n readonly contexts: readonly TemplateBindingContext[];\n}\n\nexport interface ServerRenderProtocolContext {\n readonly markers: boolean;\n readonly signal?: AbortSignal;\n readonly context?: unknown;\n render(value: unknown, options?: { markers?: boolean }): Promise<string>;\n}\n\n/** Context passed to a custom value's `mountDom` protocol during client-side mount. */\nexport interface DomProtocolContext {\n readonly parent: Node;\n readonly before: Node | null;\n readonly context?: unknown;\n}\n\n/** Context passed to a custom value's `hydrateDom` protocol during hydration. */\nexport interface HydrationProtocolContext {\n readonly parent: Node;\n readonly bounds: { start: Comment; end: Comment } | null;\n readonly context?: unknown;\n /** Remounts a value inside the current bounds (used as fallback). */\n render(value: unknown): unknown;\n}\n\nexport interface ElurRenderProtocol {\n renderServer?(context: ServerRenderProtocolContext): string | Promise<string>;\n mountDom?(context: DomProtocolContext): (() => void) | void;\n hydrateDom?(context: HydrationProtocolContext): (() => void) | void;\n}\n\nexport const ELUR_TEMPLATE_DESCRIPTOR = Symbol.for(\"elur/template-descriptor\");\nexport const ELUR_RENDER_PROTOCOL = Symbol.for(\"elur/render-protocol\");\n\n/**\n * Runtime feature capabilities, for tooling to detect support without\n * inferring it from version strings.\n *\n * NOTE: Partial attribute interpolation is now handled at compile time by\n * @elurjs/vite-plugin-elur. The core runtime does not support it natively.\n * Use the Vite plugin for partial interpolation support.\n */\nexport const templateFeatures = {\n /** Partial attribute interpolation (`class=\"btn ${size}\"`) is supported. */\n partialAttributeInterpolation: false,\n} as const;\n\nexport interface ElurTemplate {\n readonly __isElurTemplate: true;\n readonly [ELUR_TEMPLATE_DESCRIPTOR]?: TemplateDescriptor;\n readonly [ELUR_RENDER_PROTOCOL]?: ElurRenderProtocol;\n /** Mounts the template into a container element (public / root API). */\n mount(container: Element | string): ElurMountHandle;\n /** @internal Renders before `before` node (or appends to `parent`). Returns cleanup. */\n _render(parent: Node, before: Node | null): () => void;\n}\n\nexport interface ElurMountHandle {\n unmount(): void;\n}\n\n/** Direct reference to a DOM element, assigned on mount and cleared on unmount. */\nexport interface ElurRef<T extends Element = Element> {\n el: T | null;\n}\n\n/** Creates an empty `ElurRef`. Use as `ref` attribute value in templates. */\nexport function ref<T extends Element = Element>(): ElurRef<T> {\n return { el: null };\n}\n\n/** Keyed list result for efficient DOM diffing via `repeat()`. */\nexport interface KeyedList<T = unknown> {\n readonly __isKeyedList: true;\n readonly items: T[];\n readonly keyFn: (item: T, index: number) => string | number;\n readonly renderFn: (item: T, index: number) => ElurTemplate | import(\"../lifecycle.js\").ElurComponent;\n}\n\nexport interface KEntry {\n start: Comment;\n end: Comment;\n cleanup: () => void;\n}\n\n/** Opaque token for a named portal target. */\nexport interface PortalOutlet {\n readonly __isPortalOutlet: true;\n /** @internal */\n _container: Element | null;\n}\n\n/** Fallback: a static template/component, or a factory receiving the error. */\nexport type ErrorFallback =\n | ElurTemplate\n | import(\"../lifecycle.js\").ElurComponent\n | ((err: unknown) => ElurTemplate | import(\"../lifecycle.js\").ElurComponent);\n\n/** Content that can be wrapped with `transition()`. */\nexport type TransitionContent =\n | ElurTemplate\n | import(\"../lifecycle.js\").ElurComponent\n | (() => ElurTemplate | import(\"../lifecycle.js\").ElurComponent | null);\n\nexport const COMMENT = {\n SCOPE: \"elur-scope\",\n ERROR_BOUNDARY: \"elur-eb\",\n TRANSITION: \"elur-t\",\n KEYED_START: \"elur-ks\",\n KEYED_END: \"elur-ke\",\n KEYED_ZONE: \"elur-kz\",\n} as const;\n\n// =============================================================================\n// --- DOM inspection helpers ---\n// =============================================================================\n\nexport function isElurTemplate(v: unknown): v is ElurTemplate {\n return (\n v != null &&\n typeof v === \"object\" &&\n (v as Record<string, unknown>).__isElurTemplate === true\n );\n}\n\nexport function isKeyedList(v: unknown): v is KeyedList {\n return (\n v != null &&\n typeof v === \"object\" &&\n (v as Record<string, unknown>).__isKeyedList === true\n );\n}\n"],"mappings":";AA6CA,IAAa,IAA2B,OAAO,IAAI,2BAA2B,EACjE,IAAuB,OAAO,IAAI,uBAAuB,EAUzD,IAAmB,EAE5B,+BAA+B,IAClC;AAsBD,SAAgB,IAA+C;AAC3D,QAAO,EAAE,IAAI,MAAM;;AAoCvB,IAAa,IAAU;CACnB,OAAO;CACP,gBAAgB;CAChB,YAAY;CACZ,aAAa;CACb,WAAW;CACX,YAAY;CACf;AAMD,SAAgB,EAAe,GAA+B;AAC1D,QAEI,OAAO,KAAM,cADb,KAEC,EAA8B,qBAAqB;;AAI5D,SAAgB,EAAY,GAA4B;AACpD,QAEI,OAAO,KAAM,cADb,KAEC,EAA8B,kBAAkB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./signals.cjs`),t=require(`./elur/template/types.cjs`),n=require(`./lifecycle.cjs`),r=require(`./context.cjs`),i=require(`./elur/template/keyed.cjs`),a=require(`./elur/template/bindings.cjs`),o=require(`./elur/template/html.cjs`),s=require(`./elur/template/raw.cjs`),c=require(`./elur/template/transitions.cjs`),l=require(`./elur/template/portal.cjs`),u=require(`./elur/template/error-boundary.cjs`),d=require(`./router.cjs`),f=require(`./component.cjs`),p=require(`./store.cjs`),m=require(`./plugins.cjs`),h=require(`./async.cjs`),g=require(`./form.cjs`);exports.ELUR_RENDER_PROTOCOL=t.ELUR_RENDER_PROTOCOL,exports.ELUR_TEMPLATE_DESCRIPTOR=t.ELUR_TEMPLATE_DESCRIPTOR,exports.ElurComponent=n.ElurComponent,exports.Link=d.Link,exports.RouterKey=d.RouterKey,exports.RouterView=d.RouterView,exports.Signal=e.Signal,exports._hasActiveRouter=d._hasActiveRouter,exports.batch=e.batch,exports.bridgePlugin=m.bridgePlugin,exports.computed=e.computed,exports.createErrorBoundary=u.createErrorBoundary,exports.createForm=g.createForm,exports.createInjectionKey=r.createInjectionKey,exports.createPortalOutlet=l.createPortalOutlet,exports.createRouter=d.createRouter,exports.createStore=p.createStore,exports.createValidator=g.createValidator,exports.effect=e.effect,exports.elurField=g.elurField,exports.elurFieldArray=g.elurFieldArray,exports.elurRouter=d.elurRouter,exports.email=g.email,exports.extendValidators=g.extendValidators,exports.guardPlugin=m.guardPlugin,exports.html=o.html,exports.inject=r.inject,exports.injectOutlet=l.injectOutlet,exports.lazy=h.lazy,exports.loggerPlugin=m.loggerPlugin,exports.max=g.max,exports.maxLength=g.maxLength,exports.min=g.min,exports.minLength=g.minLength,exports.mount=f.mount,exports.nextTick=e.nextTick,exports.pattern=g.pattern,exports.persistPlugin=m.persistPlugin,exports.portal=l.portal,exports.portalOutlet=l.portalOutlet,exports.provide=r.provide,exports.provideOutlet=l.provideOutlet,exports.raw=s.raw,exports.ref=t.ref,exports.repeat=i.repeat,exports.required=g.required,exports.showWhen=a.showWhen,exports.signal=e.signal,exports.suspend=h.suspend,exports.templateFeatures=t.templateFeatures,exports.transition=c.transition,exports.untrack=e.untrack,exports.validators=g.validators,exports.watch=e.watch;
|
package/dist/lib/elur.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Signal as e, batch as t, computed as n, effect as r, nextTick as i, signal as a, untrack as o, watch as s } from "./signals.js";
|
|
2
|
+
import { ELUR_RENDER_PROTOCOL as c, ELUR_TEMPLATE_DESCRIPTOR as l, ref as u, templateFeatures as d } from "./elur/template/types.js";
|
|
3
|
+
import { ElurComponent as f } from "./lifecycle.js";
|
|
4
|
+
import { createInjectionKey as p, inject as m, provide as h } from "./context.js";
|
|
5
|
+
import { repeat as g } from "./elur/template/keyed.js";
|
|
6
|
+
import { showWhen as _ } from "./elur/template/bindings.js";
|
|
7
|
+
import { html as v } from "./elur/template/html.js";
|
|
8
|
+
import { raw as y } from "./elur/template/raw.js";
|
|
9
|
+
import { transition as b } from "./elur/template/transitions.js";
|
|
10
|
+
import { createPortalOutlet as x, injectOutlet as S, portal as C, portalOutlet as w, provideOutlet as T } from "./elur/template/portal.js";
|
|
11
|
+
import { createErrorBoundary as E } from "./elur/template/error-boundary.js";
|
|
12
|
+
import { Link as D, RouterKey as O, RouterView as k, _hasActiveRouter as A, createRouter as j, elurRouter as M } from "./router.js";
|
|
13
|
+
import { mount as N } from "./component.js";
|
|
14
|
+
import { createStore as P } from "./store.js";
|
|
15
|
+
import { bridgePlugin as F, guardPlugin as I, loggerPlugin as L, persistPlugin as R } from "./plugins.js";
|
|
16
|
+
import { lazy as z, suspend as B } from "./async.js";
|
|
17
|
+
import { createForm as V, createValidator as H, elurField as U, elurFieldArray as W, email as G, extendValidators as K, max as q, maxLength as J, min as Y, minLength as X, pattern as Z, required as Q, validators as $ } from "./form.js";
|
|
18
|
+
export { c as ELUR_RENDER_PROTOCOL, l as ELUR_TEMPLATE_DESCRIPTOR, f as ElurComponent, D as Link, O as RouterKey, k as RouterView, e as Signal, A as _hasActiveRouter, t as batch, F as bridgePlugin, n as computed, E as createErrorBoundary, V as createForm, p as createInjectionKey, x as createPortalOutlet, j as createRouter, P as createStore, H as createValidator, r as effect, U as elurField, W as elurFieldArray, M as elurRouter, G as email, K as extendValidators, I as guardPlugin, v as html, m as inject, S as injectOutlet, z as lazy, L as loggerPlugin, q as max, J as maxLength, Y as min, X as minLength, N as mount, i as nextTick, Z as pattern, R as persistPlugin, C as portal, w as portalOutlet, h as provide, T as provideOutlet, y as raw, u as ref, g as repeat, Q as required, _ as showWhen, a as signal, B as suspend, d as templateFeatures, b as transition, o as untrack, $ as validators, s as watch };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./signals.cjs`);function t(e=`Required`){return t=>t==null||t===``||Array.isArray(t)&&t.length===0?e:null}function n(e,t){return n=>typeof n==`string`&&n.length<e?t??`Minimum ${e} characters`:null}function r(e,t){return n=>typeof n==`string`&&n.length>e?t??`Maximum ${e} characters`:null}function i(e,t=`Invalid format`){return n=>typeof n==`string`&&!e.test(n)?t:null}function a(e=`Invalid email`){return i(/^[^\s@]+@[^\s@]+\.[^\s@]+$/,e)}function o(e,t){return n=>typeof n==`number`&&n<e?t??`Minimum value is ${e}`:null}function s(e,t){return n=>typeof n==`number`&&n>e?t??`Maximum value is ${e}`:null}function c(e){return e}var l={required:t,minLength:n,maxLength:r,email:a,pattern:i,min:o,max:s};function u(e,t){return{...e,...t}}function d(t,n=[],r=`blur`,i){let a=e.signal(t),o=e.signal(!1),s=e.signal(!1),c=e.signal(null),l=e.signal(!1),u=t,d=!0,f=e.effect(()=>{if(a.value,d){d=!1;return}c.peek()!==null&&(c.value=null)}),p=e.computed(()=>{if(c.value)return c.value;let e=i?.();for(let t of n){let n=t(a.value,e);if(n)return n}return null}),m=e.computed(()=>(r===`input`?s.value||o.value:r===`submit`?l.value:o.value)?p.value:null);function h(e){return e.type===`checkbox`||e.type===`radio`}function g(e){if(!e||!(`value`in e))return t;let n=e,r=n.value;return typeof t==`boolean`?n.checked===!0?!0:h(n)?!1:r===`true`||r===`1`?!0:r===`false`||r===`0`||r===``?!1:t:typeof t==`number`?r===``?NaN:Number(r):r}let _=e=>{a.value=g(e.target),s.value=!0},v=()=>{o.value=!0};function y(){e.batch(()=>{a.value=u,o.value=!1,s.value=!1,c.value=null,l.value=!1})}function b(t,n={}){let{shouldTouch:r=!1,shouldDirty:i=!0,shouldValidate:c=!0}=n;e.batch(()=>{a.value=t,i&&(s.value=!0),r&&(o.value=!0),c&&(l.value=!0)})}function x(e){c.value=e,e&&(o.value=!0)}function S(){o.value=!0,l.value=!0}function C(e){u=e}function w(){f(),m.dispose(),p.dispose()}return{value:a,error:m,rawError:p,touched:o,dirty:s,onInput:_,onBlur:v,reset:y,setValue:b,_setExternalError:x,_forceVisible:S,_setInitialValue:C,_dispose:w}}function f(t,n={},r=`blur`){function i(e){let t={};for(let i in e){let a=n[i]??[];t[i]=d(e[i],a,r)}return t}let a=e.signal(t.map(i)),o=t,s=e.computed(()=>a.value.length);function c(e){a.value=[...a.value,i(e)]}function l(e){let t=a.value;if(!(e<0||e>=t.length)){for(let n in t[e])t[e][n]._dispose();a.value=t.filter((t,n)=>n!==e)}}function u(e,t){let n=[...a.value];if(e<0||e>=n.length||t<0||t>=n.length||e===t)return;let[r]=n.splice(e,1);n.splice(t,0,r),a.value=n}function f(e,t){let n=[...a.value];if(!(e<0||e>=n.length)){for(let t in n[e])n[e][t]._dispose();n[e]=i(t),a.value=n}}function p(e){for(let e of a.value)for(let t in e)e[t]._dispose();a.value=e.map(i)}function m(e){let t=[...a.value];for(let n=0;n<e.length;n++){let r=e[n];if(n>=t.length){t.push(i(r));continue}let a=t[n];for(let[e,t]of Object.entries(r))a[e]&&a[e].setValue(t,{shouldDirty:!1,shouldTouch:!1,shouldValidate:!1})}a.value=t}function h(e){e&&(o=e);for(let e of a.value)for(let t in e)e[t]._dispose();a.value=o.map(i)}function g(){for(let e of a.value)for(let t in e)e[t]._dispose();s.dispose()}return{fields:a,append:c,remove:l,move:u,replace:f,length:s,setValues:p,patchValues:m,reset:h,_dispose:g}}function p(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function m(e,t=``,n=[]){for(let[r,i]of Object.entries(e)){let e=t?`${t}.${r}`:r;if(p(i)&&Object.keys(i).length>0){m(i,e,n);continue}n.push([e,i])}return n}function h(e,t,n){let r=t.split(`.`),i=e;for(let e=0;e<r.length-1;e++){let t=r[e],n=i[t];p(n)||(i[t]={}),i=i[t]}i[r[r.length-1]]=n}function g(t,n={}){let r=n.validateOn??`blur`,i={},a=n.validators;function o(){let e={};for(let t in i)h(e,t,i[t].value.value);return e}for(let[e,n]of m(t))i[e]=d(n,a?.[e]??[],r,o);let s=e.signal(!1),c=e.signal(0),l=e.computed(()=>o()),u=e.computed(()=>{let e={};for(let t in i){let n=i[t].error.value;n&&(e[t]=n)}return e}),f=e.computed(()=>{for(let e in i)if(i[e].rawError.value)return!1;return!0}),p=e.computed(()=>{for(let e in i)if(i[e].error.value)return!1;return!0}),g=e.computed(()=>{for(let e in i)if(i[e].dirty.value)return!0;return!1}),_=e.computed(()=>{for(let e in i)if(i[e].touched.value)return!0;return!1});function v(e){for(let t in e)i[t]?._setExternalError(e[t]??null)}function y(e,t,n={}){let r=i[e];r&&r.setValue(t,n)}function b(t,n={}){let{keepDirty:r=!1,keepTouched:a=!1,keepErrors:o=!0}=n;e.batch(()=>{for(let[e,n]of m(t)){let t=i[e];t&&(t.setValue(n,{shouldDirty:!r,shouldTouch:!1,shouldValidate:!o}),a||(t.touched.value=!1))}})}function x(e){if(e)for(let[t,n]of m(e)){let e=i[t];e&&e._setInitialValue(n)}for(let e in i)i[e].reset();s.value=!1,c.value=0}function S(){l.dispose(),u.dispose(),f.dispose(),p.dispose(),g.dispose(),_.dispose();for(let e in i)i[e]._dispose()}function C(e){return t=>{t.preventDefault(),c.value++;for(let e in i)i[e]._forceVisible();let r=l.value;if(n.validate){let e=n.validate(r);if(e){let t={},n=!1;for(let r in e){let i=e[r],a=Array.isArray(i)?i[0]??null:i??null;a&&(t[r]=a,n=!0)}if(n){v(t);return}}}for(let e in i)if(i[e].rawError.value)return;let a=e(r);a instanceof Promise&&(s.value=!0,a.finally(()=>{s.value=!1}).catch(()=>{}))}}return{fields:i,values:l,errors:u,canSubmit:f,valid:p,dirty:g,touched:_,isSubmitting:s,submitCount:c,handleSubmit:C,reset:x,setValue:y,setValues:b,setErrors:v,dispose:S}}exports.createForm=g,exports.createValidator=c,exports.elurField=d,exports.elurFieldArray=f,exports.email=a,exports.extendValidators=u,exports.max=s,exports.maxLength=r,exports.min=o,exports.minLength=n,exports.pattern=i,exports.required=t,exports.validators=l;
|
|
2
|
+
//# sourceMappingURL=form.cjs.map
|