@jasonshimmy/custom-elements-runtime 2.7.0 → 2.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/custom-elements-runtime.cjs.js +1 -1
- package/dist/custom-elements-runtime.directive-enhancements.cjs.js +1 -1
- package/dist/custom-elements-runtime.directive-enhancements.cjs.js.map +1 -1
- package/dist/custom-elements-runtime.directive-enhancements.es.js +88 -80
- package/dist/custom-elements-runtime.directive-enhancements.es.js.map +1 -1
- package/dist/custom-elements-runtime.directives.cjs.js +1 -1
- package/dist/custom-elements-runtime.directives.cjs.js.map +1 -1
- package/dist/custom-elements-runtime.directives.es.js +53 -23
- package/dist/custom-elements-runtime.directives.es.js.map +1 -1
- package/dist/custom-elements-runtime.es.js +2 -2
- package/dist/custom-elements-runtime.router.cjs.js +1 -1
- package/dist/custom-elements-runtime.router.es.js +1 -1
- package/dist/directives.d.ts +15 -2
- package/dist/{template-compiler-D0LrTkNv.js → template-compiler-CVBKYu3j.js} +541 -540
- package/dist/{template-compiler-D0LrTkNv.js.map → template-compiler-CVBKYu3j.js.map} +1 -1
- package/dist/template-compiler-G8h2OJbA.cjs +23 -0
- package/dist/{template-compiler-C-jyYSkk.cjs.map → template-compiler-G8h2OJbA.cjs.map} +1 -1
- package/package.json +1 -1
- package/dist/template-compiler-C-jyYSkk.cjs +0 -23
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("./template-compiler-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("./template-compiler-G8h2OJbA.cjs"),c=require("./namespace-helpers-Ctd_h7j2.cjs"),O=require("./transitions-f4KfN29T.cjs"),d=require("./logger-CSALKaYm.cjs"),x=100,k=3e4;function A(e,t,o){return o==="jitCacheHitRate"?e<t*.5?"critical":e<t?"warning":"healthy":e>t*2?"critical":e>t?"warning":"healthy"}function D(e){const t=[];return e.memoryUsage?.status!=="healthy"&&t.push("Consider reducing component complexity or implementing better memory cleanup"),e.averageRenderTime?.status!=="healthy"&&t.push("Optimize component render functions - consider lazy loading or virtualization"),e.jitCacheHitRate?.status!=="healthy"&&t.push("JIT CSS cache performance is poor - review CSS patterns for optimization"),e.componentErrorRate?.status!=="healthy"&&t.push("High component error rate detected - review error handling and component logic"),e.activeReactiveStates?.status!=="healthy"&&t.push("High number of reactive states - consider state consolidation or cleanup"),e.memoryLeakIndicator?.status!=="healthy"&&t.push("Potential memory leak detected - review component cleanup and event listener management"),t}function v(){const e=new Map,t=new Set;let o=null;function r(s,i,a){e.set(s,{name:s,value:i,threshold:a,status:"healthy",lastUpdated:Date.now(),history:[]})}function l(){r("activeComponents",0,1e3),r("componentCreateRate",0,50),r("componentErrorRate",0,.1),r("memoryUsage",0,50*1024*1024),r("memoryGrowthRate",0,1024*1024),r("averageRenderTime",0,16),r("slowRenderCount",0,10),r("jitCacheHitRate",100,80),r("activeReactiveStates",0,5e3),r("dependencyUpdates",0,100),r("memoryLeakIndicator",0,.1)}function m(s,i){const a=e.get(s);a&&(a.value=i,a.lastUpdated=Date.now(),a.history.push(i),a.history.length>x&&a.history.shift(),a.status=A(i,a.threshold,s))}function u(){const s={};let i="healthy";for(const[a,h]of e)s[a]={...h},h.status==="critical"?i="critical":h.status==="warning"&&i==="healthy"&&(i="warning");return{overall:i,metrics:s,timestamp:Date.now(),recommendations:D(s)}}function f(){if("memory"in performance&&performance.memory){const s=performance.memory;m("memoryUsage",s.usedJSHeapSize);const i=e.get("memoryUsage");if(i&&i.history.length>1){const a=i.history[i.history.length-2],h=i.history[i.history.length-1];m("memoryGrowthRate",Math.max(0,h-a))}}}function w(s){for(const i of t)try{i(s)}catch(a){d.devError("Error in health monitor listener:",a)}}function _(){f();const s=u();w(s),s.overall==="critical"?d.devError("🚨 Runtime Health: Critical issues detected",s.recommendations):s.overall==="warning"&&d.devWarn("⚠️ Runtime Health: Performance warnings",s.recommendations)}function M(){typeof window>"u"||(o=setInterval(_,k))}function R(){o!==null&&(clearInterval(o),o=null)}function H(s){t.add(s)}function L(s){t.delete(s)}function b(s){const i=e.get(s);return i?[...i.history]:[]}function T(){for(const s of e.values())s.history=[]}return l(),M(),{updateMetric:m,getHealthReport:u,addListener:H,removeListener:L,stop:R,getMetricHistory:b,clearHistory:T}}let p=null;function g(){return p||(p=v()),p}function I(e,t){g().updateMetric(e,t)}function U(){return g().getHealthReport()}function C(){typeof window>"u"||typeof customElements>"u"||customElements.get("cer-keep-alive")||customElements.define("cer-keep-alive",K())}function K(){return class extends HTMLElement{_cache=new Map;_slot=null;_slotListener=null;connectedCallback(){this.shadowRoot||this.attachShadow({mode:"open"}),this.shadowRoot.querySelector("slot")||(this.shadowRoot.innerHTML="<slot></slot>"),this._slot=this.shadowRoot.querySelector("slot"),this._slot&&(this._slotListener=()=>this._handleSlotChange(),this._slot.addEventListener("slotchange",this._slotListener),this._handleSlotChange())}disconnectedCallback(){this._slot&&this._slotListener&&this._slot.removeEventListener("slotchange",this._slotListener),this._slotListener=null}clearCache(t){t?this._cache.delete(t):this._cache.clear()}_handleSlotChange(){if(!this._slot)return;const t=this._slot.assignedElements({flatten:!0});for(const o of t){const r=this._buildCacheKey(o);if(!this._cache.has(r))this._cache.set(r,o);else{const l=this._cache.get(r);if(l!==o)try{o.parentNode?.replaceChild(l,o)}catch{this._cache.set(r,o)}}}}_buildCacheKey(t){const o=t.tagName.toLowerCase(),r=t.getAttribute("id");return r?`${o}:${r}`:o}}}function S(){customElements.get("cer-suspense")||n.component("cer-suspense",()=>{const{pending:e}=n.useProps({pending:!1});return e?n.html`<slot name="fallback"><span>Loading…</span></slot>`:n.html`<slot></slot>`})}function E(){customElements.get("cer-error-boundary")||n.component("cer-error-boundary",()=>{const e=c.ref(!1),t=c.ref("");return n.useOnError(o=>{e.value=!0,t.value=o.message}),n.useExpose({_cerHandleChildError:o=>{e.peek()||(e.value=!0,t.value=o instanceof Error?o.message:String(o))},reset:()=>{e.value=!1,t.value=""}}),e.value?n.html`<slot name="fallback"
|
|
2
2
|
><div role="alert">
|
|
3
3
|
<strong>Something went wrong.</strong>
|
|
4
4
|
${t.value?n.html`<p>${t.value}</p>`:n.html``}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("./custom-elements-runtime.directives.cjs.js");function g(n,e){return i.when(!n,e)}function m(n,e){const r=!n||n.length===0;return i.when(r,e)}function k(n,e){const r=!!(n&&n.length>0);return i.when(r,e)}function y(n,e,r){const o=[];return n.forEach((t,c)=>{e(t,c)&&o.push({item:t,originalIndex:c})}),o.map(({item:t,originalIndex:c},h)=>{const l=typeof t=="object"&&t!=null?t?.key??t?.id??`filtered-${c}`:`filtered-${c}`;return i.anchorBlock(r(t,c,h),`each-where-${l}`)})}function x(n,e){const r=i.nextDirectiveIndex(),o=n?.length??0;return o===0&&e.empty?i.anchorBlock(e.empty,`switch-length-${r}-empty`):o===1&&e.one?i.anchorBlock(e.one(n[0]),`switch-length-${r}-one`):e.exactly?.[o]?i.anchorBlock(e.exactly[o](n),`switch-length-${r}-${o}`):o>1&&e.many?i.anchorBlock(e.many(n),`switch-length-${r}-many`):i.anchorBlock([],`switch-length-${r}-fallback`)}function $(n,e,r){const o=new Map;return n.forEach(t=>{const c=e(t);o.has(c)||o.set(c,[]),o.get(c).push(t)}),Array.from(o.entries()).map(([t,c],h)=>i.anchorBlock(r(t,c,h),`each-group-${t}`))}function B(n,e,r,o){const t=r*e,c=Math.min(t+e,n.length);return n.slice(t,c).map((l,p)=>{const u=t+p,w=typeof l=="object"&&l!=null?l?.key??l?.id??`page-${u}`:`page-${u}`;return i.anchorBlock(o(l,u,p),`each-page-${w}`)})}function v(n,e){const r=i.nextDirectiveIndex();return n.loading&&e.loading?i.anchorBlock(e.loading,`promise-${r}-loading`):n.error&&e.error?i.anchorBlock(e.error(n.error),`promise-${r}-error`):n.data!==void 0&&e.success?i.anchorBlock(e.success(n.data),`promise-${r}-success`):e.idle?i.anchorBlock(e.idle,`promise-${r}-idle`):i.anchorBlock([],`promise-${r}-fallback`)}function s(n,e){const r=typeof window<"u"&&window.matchMedia?.(n)?.matches;return i.when(!!r,e)}const a={sm:"(min-width:640px)",md:"(min-width:768px)",lg:"(min-width:1024px)",xl:"(min-width:1280px)","2xl":"(min-width:1536px)",dark:"(prefers-color-scheme: dark)"},d=["sm","md","lg","xl","2xl"],f={sm:n=>s(a.sm,n),md:n=>s(a.md,n),lg:n=>s(a.lg,n),xl:n=>s(a.xl,n),"2xl":n=>s(a["2xl"],n),dark:n=>s(a.dark,n),light:n=>s("(prefers-color-scheme: light)",n),touch:n=>s("(hover: none) and (pointer: coarse)",n),mouse:n=>s("(hover: hover) and (pointer: fine)",n),reducedMotion:n=>s("(prefers-reduced-motion: reduce)",n),highContrast:n=>s("(prefers-contrast: high)",n),portrait:n=>s("(orientation: portrait)",n),landscape:n=>s("(orientation: landscape)",n)};function b(n,e){const r=[];n.includes("dark")?r.push(a.dark):n.includes("light")&&r.push("(prefers-color-scheme: light)");const o=n.filter(h=>d.includes(h)),t=o[o.length-1];t&&t in a&&r.push(a[t]);const c=r.length>0?r.join(" and "):"all";return s(c,e)}function O(n){const e=[],r=i.nextDirectiveIndex();return n.base&&e.push(i.anchorBlock(n.base,`responsive-${r}-base`)),d.forEach(o=>{const t=n[o];t&&e.push(f[o](t))}),e}function E(n){const e=[];let r=null;return{case(o,t){const c=typeof o=="function"?o:h=>h===o;return e.push({condition:c,content:t}),this},when(o,t){return e.push({condition:o,content:t}),this},otherwise(o){return r=o,this},done(){const o=i.nextDirectiveIndex();for(let t=0;t<e.length;t++){const{condition:c,content:h}=e[t];if(c(n))return i.anchorBlock(h,`switch-on-${o}-case-${t}`)}return i.anchorBlock(r||[],`switch-on-${o}-otherwise`)}}}exports.eachGroup=$;exports.eachPage=B;exports.eachWhere=y;exports.mediaVariants=a;exports.responsive=f;exports.responsiveOrder=d;exports.responsiveSwitch=O;exports.switchOn=E;exports.switchOnLength=x;exports.switchOnPromise=v;exports.unless=g;exports.whenEmpty=m;exports.whenMedia=s;exports.whenNotEmpty=k;exports.whenVariants=b;
|
|
2
2
|
//# sourceMappingURL=custom-elements-runtime.directive-enhancements.cjs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"custom-elements-runtime.directive-enhancements.cjs.js","sources":["../src/lib/directive-enhancements.ts"],"sourcesContent":["// Enhanced collection directives for better developer experience\n\nimport type { VNode } from './runtime/types';\nimport { when, anchorBlock } from './directives';\n\n/**\n * Conditional rendering with negated condition (opposite of when)\n * @param cond - Boolean condition to negate\n * @param children - Content to render when condition is false\n */\nexport function unless(cond: boolean, children: VNode | VNode[]): VNode {\n return when(!cond, children);\n}\n\n/**\n * Render content only if array/collection is empty\n * @param collection - Array or collection to check\n * @param children - Content to render when empty\n */\nexport function whenEmpty<T>(\n collection: T[] | null | undefined,\n children: VNode | VNode[],\n): VNode {\n const isEmpty = !collection || collection.length === 0;\n return when(isEmpty, children);\n}\n\n/**\n * Render content only if array/collection has items\n * @param collection - Array or collection to check\n * @param children - Content to render when not empty\n */\nexport function whenNotEmpty<T>(\n collection: T[] | null | undefined,\n children: VNode | VNode[],\n): VNode {\n const hasItems = Boolean(collection && collection.length > 0);\n return when(hasItems, children);\n}\n\n/**\n * Enhanced each with filtering capability\n * @param list - Array to iterate over\n * @param predicate - Filter function (optional)\n * @param render - Render function for each item\n */\nexport function eachWhere<T>(\n list: T[],\n predicate: (item: T, index: number) => boolean,\n render: (item: T, index: number, filteredIndex: number) => VNode | VNode[],\n): VNode[] {\n const filtered: Array<{ item: T; originalIndex: number }> = [];\n\n list.forEach((item, index) => {\n if (predicate(item, index)) {\n filtered.push({ item, originalIndex: index });\n }\n });\n\n return filtered.map(({ item, originalIndex }, filteredIndex) => {\n const itemKey =\n typeof item === 'object' && item != null\n ? ((item as Record<string, unknown>)?.key ??\n (item as Record<string, unknown>)?.id ??\n `filtered-${originalIndex}`)\n : `filtered-${originalIndex}`;\n\n return anchorBlock(\n render(item, originalIndex, filteredIndex),\n `each-where-${itemKey}`,\n );\n });\n}\n\n/**\n * Render different content based on array length\n * @param list - Array to check\n * @param cases - Object with length-based cases\n */\nexport function switchOnLength<T>(\n list: T[],\n cases: {\n empty?: VNode | VNode[];\n one?: (item: T) => VNode | VNode[];\n many?: (items: T[]) => VNode | VNode[];\n exactly?: { [count: number]: (items: T[]) => VNode | VNode[] };\n },\n): VNode {\n const length = list?.length ?? 0;\n\n if (length === 0 && cases.empty) {\n return anchorBlock(cases.empty, 'switch-length-empty');\n }\n\n if (length === 1 && cases.one) {\n return anchorBlock(cases.one(list[0]), 'switch-length-one');\n }\n\n if (cases.exactly?.[length]) {\n return anchorBlock(cases.exactly[length](list), `switch-length-${length}`);\n }\n\n if (length > 1 && cases.many) {\n return anchorBlock(cases.many(list), 'switch-length-many');\n }\n\n return anchorBlock([], 'switch-length-fallback');\n}\n\n/**\n * Group array items and render each group\n * @param list - Array to group\n * @param groupBy - Function to determine group key\n * @param renderGroup - Function to render each group\n */\nexport function eachGroup<T, K extends string | number>(\n list: T[],\n groupBy: (item: T) => K,\n renderGroup: (groupKey: K, items: T[], groupIndex: number) => VNode | VNode[],\n): VNode[] {\n const groups = new Map<K, T[]>();\n\n list.forEach((item) => {\n const key = groupBy(item);\n if (!groups.has(key)) {\n groups.set(key, []);\n }\n groups.get(key)!.push(item);\n });\n\n return Array.from(groups.entries()).map(([groupKey, items], groupIndex) => {\n return anchorBlock(\n renderGroup(groupKey, items, groupIndex),\n `each-group-${groupKey}`,\n );\n });\n}\n\n/**\n * Render with pagination/chunking\n * @param list - Array to chunk\n * @param pageSize - Items per page/chunk\n * @param currentPage - Current page (0-based)\n * @param render - Render function for visible items\n */\nexport function eachPage<T>(\n list: T[],\n pageSize: number,\n currentPage: number,\n render: (item: T, index: number, pageIndex: number) => VNode | VNode[],\n): VNode[] {\n const startIndex = currentPage * pageSize;\n const endIndex = Math.min(startIndex + pageSize, list.length);\n const pageItems = list.slice(startIndex, endIndex);\n\n return pageItems.map((item, pageIndex) => {\n const globalIndex = startIndex + pageIndex;\n const itemKey =\n typeof item === 'object' && item != null\n ? ((item as Record<string, unknown>)?.key ??\n (item as Record<string, unknown>)?.id ??\n `page-${globalIndex}`)\n : `page-${globalIndex}`;\n\n return anchorBlock(\n render(item, globalIndex, pageIndex),\n `each-page-${itemKey}`,\n );\n });\n}\n\n/* --- Async & Loading State Directives --- */\n\n/**\n * Render content based on Promise state\n * @param promiseState - Object with loading, data, error states\n * @param cases - Render functions for each state\n */\nexport function switchOnPromise<T, E = Error>(\n promiseState: {\n loading?: boolean;\n data?: T;\n error?: E;\n },\n cases: {\n loading?: VNode | VNode[];\n success?: (data: T) => VNode | VNode[];\n error?: (error: E) => VNode | VNode[];\n idle?: VNode | VNode[];\n },\n): VNode {\n if (promiseState.loading && cases.loading) {\n return anchorBlock(cases.loading, 'promise-loading');\n }\n\n if (promiseState.error && cases.error) {\n return anchorBlock(cases.error(promiseState.error), 'promise-error');\n }\n\n if (promiseState.data !== undefined && cases.success) {\n return anchorBlock(cases.success(promiseState.data), 'promise-success');\n }\n\n if (cases.idle) {\n return anchorBlock(cases.idle, 'promise-idle');\n }\n\n return anchorBlock([], 'promise-fallback');\n}\n\n/* --- Utility Directives --- */\n\n/**\n * Render content based on screen size/media query\n * @param mediaQuery - CSS media query string\n * @param children - Content to render when media query matches\n */\nexport function whenMedia(\n mediaQuery: string,\n children: VNode | VNode[],\n): VNode {\n const matches =\n typeof window !== 'undefined' && window.matchMedia?.(mediaQuery)?.matches;\n return when(Boolean(matches), children);\n}\n\n/* --- Responsive & Media Query Directives (aligned with style.ts) --- */\n\n/**\n * Media variants matching those in style.ts\n */\nexport const mediaVariants = {\n // Responsive breakpoints (matching style.ts)\n sm: '(min-width:640px)',\n md: '(min-width:768px)',\n lg: '(min-width:1024px)',\n xl: '(min-width:1280px)',\n '2xl': '(min-width:1536px)',\n\n // Dark mode (matching style.ts)\n dark: '(prefers-color-scheme: dark)',\n} as const;\n\n/**\n * Responsive order matching style.ts\n */\nexport const responsiveOrder = ['sm', 'md', 'lg', 'xl', '2xl'] as const;\n\n/**\n * Individual responsive directives matching the style.ts breakpoint system\n */\nexport const responsive = {\n // Breakpoint-based rendering (matching style.ts exactly)\n sm: (children: VNode | VNode[]) => whenMedia(mediaVariants.sm, children),\n md: (children: VNode | VNode[]) => whenMedia(mediaVariants.md, children),\n lg: (children: VNode | VNode[]) => whenMedia(mediaVariants.lg, children),\n xl: (children: VNode | VNode[]) => whenMedia(mediaVariants.xl, children),\n '2xl': (children: VNode | VNode[]) =>\n whenMedia(mediaVariants['2xl'], children),\n\n // Dark mode (matching style.ts)\n dark: (children: VNode | VNode[]) => whenMedia(mediaVariants.dark, children),\n light: (children: VNode | VNode[]) =>\n whenMedia('(prefers-color-scheme: light)', children),\n\n // Accessibility and interaction preferences\n touch: (children: VNode | VNode[]) =>\n whenMedia('(hover: none) and (pointer: coarse)', children),\n mouse: (children: VNode | VNode[]) =>\n whenMedia('(hover: hover) and (pointer: fine)', children),\n reducedMotion: (children: VNode | VNode[]) =>\n whenMedia('(prefers-reduced-motion: reduce)', children),\n highContrast: (children: VNode | VNode[]) =>\n whenMedia('(prefers-contrast: high)', children),\n\n // Orientation\n portrait: (children: VNode | VNode[]) =>\n whenMedia('(orientation: portrait)', children),\n landscape: (children: VNode | VNode[]) =>\n whenMedia('(orientation: landscape)', children),\n} as const;\n\n/**\n * Advanced responsive directive that matches the style.ts multi-variant processing\n * Allows chaining responsive and dark mode conditions like in CSS classes\n * @param variants - Array of variant keys (e.g., ['dark', 'lg'])\n * @param children - Content to render when all variants match\n */\nexport function whenVariants(\n variants: Array<keyof typeof mediaVariants | 'light'>,\n children: VNode | VNode[],\n): VNode {\n const conditions: string[] = [];\n\n // Process dark/light mode\n if (variants.includes('dark')) {\n conditions.push(mediaVariants.dark);\n } else if (variants.includes('light')) {\n conditions.push('(prefers-color-scheme: light)');\n }\n\n // Process responsive variants (take the last one, matching style.ts behavior)\n const responsiveVariants = variants.filter((v) =>\n responsiveOrder.includes(v as (typeof responsiveOrder)[number]),\n );\n const lastResponsive = responsiveVariants[responsiveVariants.length - 1];\n if (lastResponsive && lastResponsive in mediaVariants) {\n conditions.push(\n mediaVariants[lastResponsive as keyof typeof mediaVariants],\n );\n }\n\n const mediaQuery = conditions.length > 0 ? conditions.join(' and ') : 'all';\n return whenMedia(mediaQuery, children);\n}\n\n/**\n * Responsive switch directive - render different content for different breakpoints\n * Mirrors the responsive behavior from the style system\n * @param content - Object with breakpoint keys and corresponding content\n */\nexport function responsiveSwitch(content: {\n base?: VNode | VNode[];\n sm?: VNode | VNode[];\n md?: VNode | VNode[];\n lg?: VNode | VNode[];\n xl?: VNode | VNode[];\n '2xl'?: VNode | VNode[];\n}): VNode[] {\n const results: VNode[] = [];\n\n // Handle light mode variants\n if (content.base) {\n // Base content (no media query)\n results.push(anchorBlock(content.base, 'responsive-base'));\n }\n\n // Add responsive variants in order\n responsiveOrder.forEach((breakpoint) => {\n const breakpointContent = content[breakpoint];\n if (breakpointContent) {\n results.push(responsive[breakpoint](breakpointContent));\n }\n });\n\n return results;\n}\n\n/* --- Enhanced Match Directive --- */\n\n/**\n * Enhanced match directive with more fluent API\n * @param value - Value to match against\n */\nexport function switchOn<T>(value: T) {\n const branches: Array<{\n condition: (val: T) => boolean;\n content: VNode | VNode[];\n }> = [];\n let otherwiseContent: VNode | VNode[] | null = null;\n\n return {\n case(matcher: T | ((val: T) => boolean), content: VNode | VNode[]) {\n const condition =\n typeof matcher === 'function'\n ? (matcher as (val: T) => boolean)\n : (val: T) => val === matcher;\n\n branches.push({ condition, content });\n return this;\n },\n\n when(predicate: (val: T) => boolean, content: VNode | VNode[]) {\n branches.push({ condition: predicate, content });\n return this;\n },\n\n otherwise(content: VNode | VNode[]) {\n otherwiseContent = content;\n return this;\n },\n\n done() {\n for (let i = 0; i < branches.length; i++) {\n const { condition, content } = branches[i];\n if (condition(value)) {\n return anchorBlock(content, `switch-case-${i}`);\n }\n }\n return anchorBlock(otherwiseContent || [], 'switch-otherwise');\n },\n };\n}\n"],"names":["unless","cond","children","when","whenEmpty","collection","isEmpty","whenNotEmpty","hasItems","eachWhere","list","predicate","render","filtered","item","index","originalIndex","filteredIndex","itemKey","anchorBlock","switchOnLength","cases","length","eachGroup","groupBy","renderGroup","groups","key","groupKey","items","groupIndex","eachPage","pageSize","currentPage","startIndex","endIndex","pageIndex","globalIndex","switchOnPromise","promiseState","whenMedia","mediaQuery","matches","mediaVariants","responsiveOrder","responsive","whenVariants","variants","conditions","responsiveVariants","v","lastResponsive","responsiveSwitch","content","results","breakpoint","breakpointContent","switchOn","value","branches","otherwiseContent","matcher","condition","val","i"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"custom-elements-runtime.directive-enhancements.cjs.js","sources":["../src/lib/directive-enhancements.ts"],"sourcesContent":["// Enhanced collection directives for better developer experience\n\nimport type { VNode } from './runtime/types';\nimport { when, anchorBlock, nextDirectiveIndex } from './directives';\n\n/**\n * Conditional rendering with negated condition (opposite of when)\n * @param cond - Boolean condition to negate\n * @param children - Content to render when condition is false\n */\nexport function unless(cond: boolean, children: VNode | VNode[]): VNode {\n return when(!cond, children);\n}\n\n/**\n * Render content only if array/collection is empty\n * @param collection - Array or collection to check\n * @param children - Content to render when empty\n */\nexport function whenEmpty<T>(\n collection: T[] | null | undefined,\n children: VNode | VNode[],\n): VNode {\n const isEmpty = !collection || collection.length === 0;\n return when(isEmpty, children);\n}\n\n/**\n * Render content only if array/collection has items\n * @param collection - Array or collection to check\n * @param children - Content to render when not empty\n */\nexport function whenNotEmpty<T>(\n collection: T[] | null | undefined,\n children: VNode | VNode[],\n): VNode {\n const hasItems = Boolean(collection && collection.length > 0);\n return when(hasItems, children);\n}\n\n/**\n * Enhanced each with filtering capability\n * @param list - Array to iterate over\n * @param predicate - Filter function (optional)\n * @param render - Render function for each item\n */\nexport function eachWhere<T>(\n list: T[],\n predicate: (item: T, index: number) => boolean,\n render: (item: T, index: number, filteredIndex: number) => VNode | VNode[],\n): VNode[] {\n const filtered: Array<{ item: T; originalIndex: number }> = [];\n\n list.forEach((item, index) => {\n if (predicate(item, index)) {\n filtered.push({ item, originalIndex: index });\n }\n });\n\n return filtered.map(({ item, originalIndex }, filteredIndex) => {\n const itemKey =\n typeof item === 'object' && item != null\n ? ((item as Record<string, unknown>)?.key ??\n (item as Record<string, unknown>)?.id ??\n `filtered-${originalIndex}`)\n : `filtered-${originalIndex}`;\n\n return anchorBlock(\n render(item, originalIndex, filteredIndex),\n `each-where-${itemKey}`,\n );\n });\n}\n\n/**\n * Render different content based on array length\n * @param list - Array to check\n * @param cases - Object with length-based cases\n */\nexport function switchOnLength<T>(\n list: T[],\n cases: {\n empty?: VNode | VNode[];\n one?: (item: T) => VNode | VNode[];\n many?: (items: T[]) => VNode | VNode[];\n exactly?: { [count: number]: (items: T[]) => VNode | VNode[] };\n },\n): VNode {\n const si = nextDirectiveIndex();\n const length = list?.length ?? 0;\n\n if (length === 0 && cases.empty) {\n return anchorBlock(cases.empty, `switch-length-${si}-empty`);\n }\n\n if (length === 1 && cases.one) {\n return anchorBlock(cases.one(list[0]), `switch-length-${si}-one`);\n }\n\n if (cases.exactly?.[length]) {\n return anchorBlock(\n cases.exactly[length](list),\n `switch-length-${si}-${length}`,\n );\n }\n\n if (length > 1 && cases.many) {\n return anchorBlock(cases.many(list), `switch-length-${si}-many`);\n }\n\n return anchorBlock([], `switch-length-${si}-fallback`);\n}\n\n/**\n * Group array items and render each group\n * @param list - Array to group\n * @param groupBy - Function to determine group key\n * @param renderGroup - Function to render each group\n */\nexport function eachGroup<T, K extends string | number>(\n list: T[],\n groupBy: (item: T) => K,\n renderGroup: (groupKey: K, items: T[], groupIndex: number) => VNode | VNode[],\n): VNode[] {\n const groups = new Map<K, T[]>();\n\n list.forEach((item) => {\n const key = groupBy(item);\n if (!groups.has(key)) {\n groups.set(key, []);\n }\n groups.get(key)!.push(item);\n });\n\n return Array.from(groups.entries()).map(([groupKey, items], groupIndex) => {\n return anchorBlock(\n renderGroup(groupKey, items, groupIndex),\n `each-group-${groupKey}`,\n );\n });\n}\n\n/**\n * Render with pagination/chunking\n * @param list - Array to chunk\n * @param pageSize - Items per page/chunk\n * @param currentPage - Current page (0-based)\n * @param render - Render function for visible items\n */\nexport function eachPage<T>(\n list: T[],\n pageSize: number,\n currentPage: number,\n render: (item: T, index: number, pageIndex: number) => VNode | VNode[],\n): VNode[] {\n const startIndex = currentPage * pageSize;\n const endIndex = Math.min(startIndex + pageSize, list.length);\n const pageItems = list.slice(startIndex, endIndex);\n\n return pageItems.map((item, pageIndex) => {\n const globalIndex = startIndex + pageIndex;\n const itemKey =\n typeof item === 'object' && item != null\n ? ((item as Record<string, unknown>)?.key ??\n (item as Record<string, unknown>)?.id ??\n `page-${globalIndex}`)\n : `page-${globalIndex}`;\n\n return anchorBlock(\n render(item, globalIndex, pageIndex),\n `each-page-${itemKey}`,\n );\n });\n}\n\n/* --- Async & Loading State Directives --- */\n\n/**\n * Render content based on Promise state\n * @param promiseState - Object with loading, data, error states\n * @param cases - Render functions for each state\n */\nexport function switchOnPromise<T, E = Error>(\n promiseState: {\n loading?: boolean;\n data?: T;\n error?: E;\n },\n cases: {\n loading?: VNode | VNode[];\n success?: (data: T) => VNode | VNode[];\n error?: (error: E) => VNode | VNode[];\n idle?: VNode | VNode[];\n },\n): VNode {\n const si = nextDirectiveIndex();\n\n if (promiseState.loading && cases.loading) {\n return anchorBlock(cases.loading, `promise-${si}-loading`);\n }\n\n if (promiseState.error && cases.error) {\n return anchorBlock(cases.error(promiseState.error), `promise-${si}-error`);\n }\n\n if (promiseState.data !== undefined && cases.success) {\n return anchorBlock(\n cases.success(promiseState.data),\n `promise-${si}-success`,\n );\n }\n\n if (cases.idle) {\n return anchorBlock(cases.idle, `promise-${si}-idle`);\n }\n\n return anchorBlock([], `promise-${si}-fallback`);\n}\n\n/* --- Utility Directives --- */\n\n/**\n * Render content based on screen size/media query\n * @param mediaQuery - CSS media query string\n * @param children - Content to render when media query matches\n */\nexport function whenMedia(\n mediaQuery: string,\n children: VNode | VNode[],\n): VNode {\n const matches =\n typeof window !== 'undefined' && window.matchMedia?.(mediaQuery)?.matches;\n return when(Boolean(matches), children);\n}\n\n/* --- Responsive & Media Query Directives (aligned with style.ts) --- */\n\n/**\n * Media variants matching those in style.ts\n */\nexport const mediaVariants = {\n // Responsive breakpoints (matching style.ts)\n sm: '(min-width:640px)',\n md: '(min-width:768px)',\n lg: '(min-width:1024px)',\n xl: '(min-width:1280px)',\n '2xl': '(min-width:1536px)',\n\n // Dark mode (matching style.ts)\n dark: '(prefers-color-scheme: dark)',\n} as const;\n\n/**\n * Responsive order matching style.ts\n */\nexport const responsiveOrder = ['sm', 'md', 'lg', 'xl', '2xl'] as const;\n\n/**\n * Individual responsive directives matching the style.ts breakpoint system\n */\nexport const responsive = {\n // Breakpoint-based rendering (matching style.ts exactly)\n sm: (children: VNode | VNode[]) => whenMedia(mediaVariants.sm, children),\n md: (children: VNode | VNode[]) => whenMedia(mediaVariants.md, children),\n lg: (children: VNode | VNode[]) => whenMedia(mediaVariants.lg, children),\n xl: (children: VNode | VNode[]) => whenMedia(mediaVariants.xl, children),\n '2xl': (children: VNode | VNode[]) =>\n whenMedia(mediaVariants['2xl'], children),\n\n // Dark mode (matching style.ts)\n dark: (children: VNode | VNode[]) => whenMedia(mediaVariants.dark, children),\n light: (children: VNode | VNode[]) =>\n whenMedia('(prefers-color-scheme: light)', children),\n\n // Accessibility and interaction preferences\n touch: (children: VNode | VNode[]) =>\n whenMedia('(hover: none) and (pointer: coarse)', children),\n mouse: (children: VNode | VNode[]) =>\n whenMedia('(hover: hover) and (pointer: fine)', children),\n reducedMotion: (children: VNode | VNode[]) =>\n whenMedia('(prefers-reduced-motion: reduce)', children),\n highContrast: (children: VNode | VNode[]) =>\n whenMedia('(prefers-contrast: high)', children),\n\n // Orientation\n portrait: (children: VNode | VNode[]) =>\n whenMedia('(orientation: portrait)', children),\n landscape: (children: VNode | VNode[]) =>\n whenMedia('(orientation: landscape)', children),\n} as const;\n\n/**\n * Advanced responsive directive that matches the style.ts multi-variant processing\n * Allows chaining responsive and dark mode conditions like in CSS classes\n * @param variants - Array of variant keys (e.g., ['dark', 'lg'])\n * @param children - Content to render when all variants match\n */\nexport function whenVariants(\n variants: Array<keyof typeof mediaVariants | 'light'>,\n children: VNode | VNode[],\n): VNode {\n const conditions: string[] = [];\n\n // Process dark/light mode\n if (variants.includes('dark')) {\n conditions.push(mediaVariants.dark);\n } else if (variants.includes('light')) {\n conditions.push('(prefers-color-scheme: light)');\n }\n\n // Process responsive variants (take the last one, matching style.ts behavior)\n const responsiveVariants = variants.filter((v) =>\n responsiveOrder.includes(v as (typeof responsiveOrder)[number]),\n );\n const lastResponsive = responsiveVariants[responsiveVariants.length - 1];\n if (lastResponsive && lastResponsive in mediaVariants) {\n conditions.push(\n mediaVariants[lastResponsive as keyof typeof mediaVariants],\n );\n }\n\n const mediaQuery = conditions.length > 0 ? conditions.join(' and ') : 'all';\n return whenMedia(mediaQuery, children);\n}\n\n/**\n * Responsive switch directive - render different content for different breakpoints\n * Mirrors the responsive behavior from the style system\n * @param content - Object with breakpoint keys and corresponding content\n */\nexport function responsiveSwitch(content: {\n base?: VNode | VNode[];\n sm?: VNode | VNode[];\n md?: VNode | VNode[];\n lg?: VNode | VNode[];\n xl?: VNode | VNode[];\n '2xl'?: VNode | VNode[];\n}): VNode[] {\n const results: VNode[] = [];\n\n const si = nextDirectiveIndex();\n\n // Handle light mode variants\n if (content.base) {\n // Base content (no media query)\n results.push(anchorBlock(content.base, `responsive-${si}-base`));\n }\n\n // Add responsive variants in order\n responsiveOrder.forEach((breakpoint) => {\n const breakpointContent = content[breakpoint];\n if (breakpointContent) {\n results.push(responsive[breakpoint](breakpointContent));\n }\n });\n\n return results;\n}\n\n/* --- Enhanced Match Directive --- */\n\n/**\n * Enhanced match directive with more fluent API\n * @param value - Value to match against\n */\nexport function switchOn<T>(value: T) {\n const branches: Array<{\n condition: (val: T) => boolean;\n content: VNode | VNode[];\n }> = [];\n let otherwiseContent: VNode | VNode[] | null = null;\n\n return {\n case(matcher: T | ((val: T) => boolean), content: VNode | VNode[]) {\n const condition =\n typeof matcher === 'function'\n ? (matcher as (val: T) => boolean)\n : (val: T) => val === matcher;\n\n branches.push({ condition, content });\n return this;\n },\n\n when(predicate: (val: T) => boolean, content: VNode | VNode[]) {\n branches.push({ condition: predicate, content });\n return this;\n },\n\n otherwise(content: VNode | VNode[]) {\n otherwiseContent = content;\n return this;\n },\n\n done() {\n const si = nextDirectiveIndex();\n for (let i = 0; i < branches.length; i++) {\n const { condition, content } = branches[i];\n if (condition(value)) {\n return anchorBlock(content, `switch-on-${si}-case-${i}`);\n }\n }\n return anchorBlock(otherwiseContent || [], `switch-on-${si}-otherwise`);\n },\n };\n}\n"],"names":["unless","cond","children","when","whenEmpty","collection","isEmpty","whenNotEmpty","hasItems","eachWhere","list","predicate","render","filtered","item","index","originalIndex","filteredIndex","itemKey","anchorBlock","switchOnLength","cases","si","nextDirectiveIndex","length","eachGroup","groupBy","renderGroup","groups","key","groupKey","items","groupIndex","eachPage","pageSize","currentPage","startIndex","endIndex","pageIndex","globalIndex","switchOnPromise","promiseState","whenMedia","mediaQuery","matches","mediaVariants","responsiveOrder","responsive","whenVariants","variants","conditions","responsiveVariants","v","lastResponsive","responsiveSwitch","content","results","breakpoint","breakpointContent","switchOn","value","branches","otherwiseContent","matcher","condition","val","i"],"mappings":"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"}
|
|
@@ -1,59 +1,66 @@
|
|
|
1
|
-
import { anchorBlock as s,
|
|
1
|
+
import { anchorBlock as s, nextDirectiveIndex as a, when as d } from "./custom-elements-runtime.directives.es.js";
|
|
2
2
|
function y(n, e) {
|
|
3
|
-
return
|
|
3
|
+
return d(!n, e);
|
|
4
4
|
}
|
|
5
5
|
function x(n, e) {
|
|
6
6
|
const t = !n || n.length === 0;
|
|
7
|
-
return
|
|
7
|
+
return d(t, e);
|
|
8
8
|
}
|
|
9
9
|
function k(n, e) {
|
|
10
10
|
const t = !!(n && n.length > 0);
|
|
11
|
-
return
|
|
11
|
+
return d(t, e);
|
|
12
12
|
}
|
|
13
13
|
function b(n, e, t) {
|
|
14
|
-
const
|
|
15
|
-
return n.forEach((
|
|
16
|
-
e(
|
|
17
|
-
}),
|
|
18
|
-
const l = typeof
|
|
14
|
+
const o = [];
|
|
15
|
+
return n.forEach((r, i) => {
|
|
16
|
+
e(r, i) && o.push({ item: r, originalIndex: i });
|
|
17
|
+
}), o.map(({ item: r, originalIndex: i }, h) => {
|
|
18
|
+
const l = typeof r == "object" && r != null ? r?.key ?? r?.id ?? `filtered-${i}` : `filtered-${i}`;
|
|
19
19
|
return s(
|
|
20
|
-
t(
|
|
20
|
+
t(r, i, h),
|
|
21
21
|
`each-where-${l}`
|
|
22
22
|
);
|
|
23
23
|
});
|
|
24
24
|
}
|
|
25
|
-
function
|
|
26
|
-
const t = n?.length ?? 0;
|
|
27
|
-
return
|
|
25
|
+
function v(n, e) {
|
|
26
|
+
const t = a(), o = n?.length ?? 0;
|
|
27
|
+
return o === 0 && e.empty ? s(e.empty, `switch-length-${t}-empty`) : o === 1 && e.one ? s(e.one(n[0]), `switch-length-${t}-one`) : e.exactly?.[o] ? s(
|
|
28
|
+
e.exactly[o](n),
|
|
29
|
+
`switch-length-${t}-${o}`
|
|
30
|
+
) : o > 1 && e.many ? s(e.many(n), `switch-length-${t}-many`) : s([], `switch-length-${t}-fallback`);
|
|
28
31
|
}
|
|
29
|
-
function
|
|
30
|
-
const
|
|
31
|
-
return n.forEach((
|
|
32
|
-
const i = e(
|
|
33
|
-
|
|
34
|
-
}), Array.from(
|
|
35
|
-
t(
|
|
36
|
-
`each-group-${
|
|
32
|
+
function E(n, e, t) {
|
|
33
|
+
const o = /* @__PURE__ */ new Map();
|
|
34
|
+
return n.forEach((r) => {
|
|
35
|
+
const i = e(r);
|
|
36
|
+
o.has(i) || o.set(i, []), o.get(i).push(r);
|
|
37
|
+
}), Array.from(o.entries()).map(([r, i], h) => s(
|
|
38
|
+
t(r, i, h),
|
|
39
|
+
`each-group-${r}`
|
|
37
40
|
));
|
|
38
41
|
}
|
|
39
|
-
function
|
|
40
|
-
const
|
|
41
|
-
return n.slice(
|
|
42
|
-
const
|
|
42
|
+
function I(n, e, t, o) {
|
|
43
|
+
const r = t * e, i = Math.min(r + e, n.length);
|
|
44
|
+
return n.slice(r, i).map((l, f) => {
|
|
45
|
+
const p = r + f, m = typeof l == "object" && l != null ? l?.key ?? l?.id ?? `page-${p}` : `page-${p}`;
|
|
43
46
|
return s(
|
|
44
|
-
|
|
45
|
-
`each-page-${
|
|
47
|
+
o(l, p, f),
|
|
48
|
+
`each-page-${m}`
|
|
46
49
|
);
|
|
47
50
|
});
|
|
48
51
|
}
|
|
49
52
|
function M(n, e) {
|
|
50
|
-
|
|
53
|
+
const t = a();
|
|
54
|
+
return n.loading && e.loading ? s(e.loading, `promise-${t}-loading`) : n.error && e.error ? s(e.error(n.error), `promise-${t}-error`) : n.data !== void 0 && e.success ? s(
|
|
55
|
+
e.success(n.data),
|
|
56
|
+
`promise-${t}-success`
|
|
57
|
+
) : e.idle ? s(e.idle, `promise-${t}-idle`) : s([], `promise-${t}-fallback`);
|
|
51
58
|
}
|
|
52
|
-
function
|
|
59
|
+
function c(n, e) {
|
|
53
60
|
const t = typeof window < "u" && window.matchMedia?.(n)?.matches;
|
|
54
|
-
return
|
|
61
|
+
return d(!!t, e);
|
|
55
62
|
}
|
|
56
|
-
const
|
|
63
|
+
const u = {
|
|
57
64
|
// Responsive breakpoints (matching style.ts)
|
|
58
65
|
sm: "(min-width:640px)",
|
|
59
66
|
md: "(min-width:768px)",
|
|
@@ -62,83 +69,84 @@ const c = {
|
|
|
62
69
|
"2xl": "(min-width:1536px)",
|
|
63
70
|
// Dark mode (matching style.ts)
|
|
64
71
|
dark: "(prefers-color-scheme: dark)"
|
|
65
|
-
},
|
|
72
|
+
}, g = ["sm", "md", "lg", "xl", "2xl"], w = {
|
|
66
73
|
// Breakpoint-based rendering (matching style.ts exactly)
|
|
67
|
-
sm: (n) =>
|
|
68
|
-
md: (n) =>
|
|
69
|
-
lg: (n) =>
|
|
70
|
-
xl: (n) =>
|
|
71
|
-
"2xl": (n) =>
|
|
74
|
+
sm: (n) => c(u.sm, n),
|
|
75
|
+
md: (n) => c(u.md, n),
|
|
76
|
+
lg: (n) => c(u.lg, n),
|
|
77
|
+
xl: (n) => c(u.xl, n),
|
|
78
|
+
"2xl": (n) => c(u["2xl"], n),
|
|
72
79
|
// Dark mode (matching style.ts)
|
|
73
|
-
dark: (n) =>
|
|
74
|
-
light: (n) =>
|
|
80
|
+
dark: (n) => c(u.dark, n),
|
|
81
|
+
light: (n) => c("(prefers-color-scheme: light)", n),
|
|
75
82
|
// Accessibility and interaction preferences
|
|
76
|
-
touch: (n) =>
|
|
77
|
-
mouse: (n) =>
|
|
78
|
-
reducedMotion: (n) =>
|
|
79
|
-
highContrast: (n) =>
|
|
83
|
+
touch: (n) => c("(hover: none) and (pointer: coarse)", n),
|
|
84
|
+
mouse: (n) => c("(hover: hover) and (pointer: fine)", n),
|
|
85
|
+
reducedMotion: (n) => c("(prefers-reduced-motion: reduce)", n),
|
|
86
|
+
highContrast: (n) => c("(prefers-contrast: high)", n),
|
|
80
87
|
// Orientation
|
|
81
|
-
portrait: (n) =>
|
|
82
|
-
landscape: (n) =>
|
|
88
|
+
portrait: (n) => c("(orientation: portrait)", n),
|
|
89
|
+
landscape: (n) => c("(orientation: landscape)", n)
|
|
83
90
|
};
|
|
84
|
-
function
|
|
91
|
+
function O(n, e) {
|
|
85
92
|
const t = [];
|
|
86
|
-
n.includes("dark") ? t.push(
|
|
87
|
-
const
|
|
88
|
-
(
|
|
89
|
-
),
|
|
90
|
-
|
|
91
|
-
|
|
93
|
+
n.includes("dark") ? t.push(u.dark) : n.includes("light") && t.push("(prefers-color-scheme: light)");
|
|
94
|
+
const o = n.filter(
|
|
95
|
+
(h) => g.includes(h)
|
|
96
|
+
), r = o[o.length - 1];
|
|
97
|
+
r && r in u && t.push(
|
|
98
|
+
u[r]
|
|
92
99
|
);
|
|
93
100
|
const i = t.length > 0 ? t.join(" and ") : "all";
|
|
94
|
-
return
|
|
101
|
+
return c(i, e);
|
|
95
102
|
}
|
|
96
|
-
function
|
|
97
|
-
const e = [];
|
|
98
|
-
return n.base && e.push(s(n.base,
|
|
99
|
-
const r = n[
|
|
100
|
-
r && e.push(
|
|
103
|
+
function j(n) {
|
|
104
|
+
const e = [], t = a();
|
|
105
|
+
return n.base && e.push(s(n.base, `responsive-${t}-base`)), g.forEach((o) => {
|
|
106
|
+
const r = n[o];
|
|
107
|
+
r && e.push(w[o](r));
|
|
101
108
|
}), e;
|
|
102
109
|
}
|
|
103
|
-
function
|
|
110
|
+
function B(n) {
|
|
104
111
|
const e = [];
|
|
105
112
|
let t = null;
|
|
106
113
|
return {
|
|
107
|
-
case(
|
|
108
|
-
const i = typeof
|
|
109
|
-
return e.push({ condition: i, content:
|
|
114
|
+
case(o, r) {
|
|
115
|
+
const i = typeof o == "function" ? o : (h) => h === o;
|
|
116
|
+
return e.push({ condition: i, content: r }), this;
|
|
110
117
|
},
|
|
111
|
-
when(
|
|
112
|
-
return e.push({ condition:
|
|
118
|
+
when(o, r) {
|
|
119
|
+
return e.push({ condition: o, content: r }), this;
|
|
113
120
|
},
|
|
114
|
-
otherwise(
|
|
115
|
-
return t =
|
|
121
|
+
otherwise(o) {
|
|
122
|
+
return t = o, this;
|
|
116
123
|
},
|
|
117
124
|
done() {
|
|
125
|
+
const o = a();
|
|
118
126
|
for (let r = 0; r < e.length; r++) {
|
|
119
|
-
const { condition:
|
|
120
|
-
if (
|
|
121
|
-
return s(
|
|
127
|
+
const { condition: i, content: h } = e[r];
|
|
128
|
+
if (i(n))
|
|
129
|
+
return s(h, `switch-on-${o}-case-${r}`);
|
|
122
130
|
}
|
|
123
|
-
return s(t || [],
|
|
131
|
+
return s(t || [], `switch-on-${o}-otherwise`);
|
|
124
132
|
}
|
|
125
133
|
};
|
|
126
134
|
}
|
|
127
135
|
export {
|
|
128
|
-
|
|
129
|
-
|
|
136
|
+
E as eachGroup,
|
|
137
|
+
I as eachPage,
|
|
130
138
|
b as eachWhere,
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
139
|
+
u as mediaVariants,
|
|
140
|
+
w as responsive,
|
|
141
|
+
g as responsiveOrder,
|
|
142
|
+
j as responsiveSwitch,
|
|
143
|
+
B as switchOn,
|
|
144
|
+
v as switchOnLength,
|
|
137
145
|
M as switchOnPromise,
|
|
138
146
|
y as unless,
|
|
139
147
|
x as whenEmpty,
|
|
140
|
-
|
|
148
|
+
c as whenMedia,
|
|
141
149
|
k as whenNotEmpty,
|
|
142
|
-
|
|
150
|
+
O as whenVariants
|
|
143
151
|
};
|
|
144
152
|
//# sourceMappingURL=custom-elements-runtime.directive-enhancements.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"custom-elements-runtime.directive-enhancements.es.js","sources":["../src/lib/directive-enhancements.ts"],"sourcesContent":["// Enhanced collection directives for better developer experience\n\nimport type { VNode } from './runtime/types';\nimport { when, anchorBlock } from './directives';\n\n/**\n * Conditional rendering with negated condition (opposite of when)\n * @param cond - Boolean condition to negate\n * @param children - Content to render when condition is false\n */\nexport function unless(cond: boolean, children: VNode | VNode[]): VNode {\n return when(!cond, children);\n}\n\n/**\n * Render content only if array/collection is empty\n * @param collection - Array or collection to check\n * @param children - Content to render when empty\n */\nexport function whenEmpty<T>(\n collection: T[] | null | undefined,\n children: VNode | VNode[],\n): VNode {\n const isEmpty = !collection || collection.length === 0;\n return when(isEmpty, children);\n}\n\n/**\n * Render content only if array/collection has items\n * @param collection - Array or collection to check\n * @param children - Content to render when not empty\n */\nexport function whenNotEmpty<T>(\n collection: T[] | null | undefined,\n children: VNode | VNode[],\n): VNode {\n const hasItems = Boolean(collection && collection.length > 0);\n return when(hasItems, children);\n}\n\n/**\n * Enhanced each with filtering capability\n * @param list - Array to iterate over\n * @param predicate - Filter function (optional)\n * @param render - Render function for each item\n */\nexport function eachWhere<T>(\n list: T[],\n predicate: (item: T, index: number) => boolean,\n render: (item: T, index: number, filteredIndex: number) => VNode | VNode[],\n): VNode[] {\n const filtered: Array<{ item: T; originalIndex: number }> = [];\n\n list.forEach((item, index) => {\n if (predicate(item, index)) {\n filtered.push({ item, originalIndex: index });\n }\n });\n\n return filtered.map(({ item, originalIndex }, filteredIndex) => {\n const itemKey =\n typeof item === 'object' && item != null\n ? ((item as Record<string, unknown>)?.key ??\n (item as Record<string, unknown>)?.id ??\n `filtered-${originalIndex}`)\n : `filtered-${originalIndex}`;\n\n return anchorBlock(\n render(item, originalIndex, filteredIndex),\n `each-where-${itemKey}`,\n );\n });\n}\n\n/**\n * Render different content based on array length\n * @param list - Array to check\n * @param cases - Object with length-based cases\n */\nexport function switchOnLength<T>(\n list: T[],\n cases: {\n empty?: VNode | VNode[];\n one?: (item: T) => VNode | VNode[];\n many?: (items: T[]) => VNode | VNode[];\n exactly?: { [count: number]: (items: T[]) => VNode | VNode[] };\n },\n): VNode {\n const length = list?.length ?? 0;\n\n if (length === 0 && cases.empty) {\n return anchorBlock(cases.empty, 'switch-length-empty');\n }\n\n if (length === 1 && cases.one) {\n return anchorBlock(cases.one(list[0]), 'switch-length-one');\n }\n\n if (cases.exactly?.[length]) {\n return anchorBlock(cases.exactly[length](list), `switch-length-${length}`);\n }\n\n if (length > 1 && cases.many) {\n return anchorBlock(cases.many(list), 'switch-length-many');\n }\n\n return anchorBlock([], 'switch-length-fallback');\n}\n\n/**\n * Group array items and render each group\n * @param list - Array to group\n * @param groupBy - Function to determine group key\n * @param renderGroup - Function to render each group\n */\nexport function eachGroup<T, K extends string | number>(\n list: T[],\n groupBy: (item: T) => K,\n renderGroup: (groupKey: K, items: T[], groupIndex: number) => VNode | VNode[],\n): VNode[] {\n const groups = new Map<K, T[]>();\n\n list.forEach((item) => {\n const key = groupBy(item);\n if (!groups.has(key)) {\n groups.set(key, []);\n }\n groups.get(key)!.push(item);\n });\n\n return Array.from(groups.entries()).map(([groupKey, items], groupIndex) => {\n return anchorBlock(\n renderGroup(groupKey, items, groupIndex),\n `each-group-${groupKey}`,\n );\n });\n}\n\n/**\n * Render with pagination/chunking\n * @param list - Array to chunk\n * @param pageSize - Items per page/chunk\n * @param currentPage - Current page (0-based)\n * @param render - Render function for visible items\n */\nexport function eachPage<T>(\n list: T[],\n pageSize: number,\n currentPage: number,\n render: (item: T, index: number, pageIndex: number) => VNode | VNode[],\n): VNode[] {\n const startIndex = currentPage * pageSize;\n const endIndex = Math.min(startIndex + pageSize, list.length);\n const pageItems = list.slice(startIndex, endIndex);\n\n return pageItems.map((item, pageIndex) => {\n const globalIndex = startIndex + pageIndex;\n const itemKey =\n typeof item === 'object' && item != null\n ? ((item as Record<string, unknown>)?.key ??\n (item as Record<string, unknown>)?.id ??\n `page-${globalIndex}`)\n : `page-${globalIndex}`;\n\n return anchorBlock(\n render(item, globalIndex, pageIndex),\n `each-page-${itemKey}`,\n );\n });\n}\n\n/* --- Async & Loading State Directives --- */\n\n/**\n * Render content based on Promise state\n * @param promiseState - Object with loading, data, error states\n * @param cases - Render functions for each state\n */\nexport function switchOnPromise<T, E = Error>(\n promiseState: {\n loading?: boolean;\n data?: T;\n error?: E;\n },\n cases: {\n loading?: VNode | VNode[];\n success?: (data: T) => VNode | VNode[];\n error?: (error: E) => VNode | VNode[];\n idle?: VNode | VNode[];\n },\n): VNode {\n if (promiseState.loading && cases.loading) {\n return anchorBlock(cases.loading, 'promise-loading');\n }\n\n if (promiseState.error && cases.error) {\n return anchorBlock(cases.error(promiseState.error), 'promise-error');\n }\n\n if (promiseState.data !== undefined && cases.success) {\n return anchorBlock(cases.success(promiseState.data), 'promise-success');\n }\n\n if (cases.idle) {\n return anchorBlock(cases.idle, 'promise-idle');\n }\n\n return anchorBlock([], 'promise-fallback');\n}\n\n/* --- Utility Directives --- */\n\n/**\n * Render content based on screen size/media query\n * @param mediaQuery - CSS media query string\n * @param children - Content to render when media query matches\n */\nexport function whenMedia(\n mediaQuery: string,\n children: VNode | VNode[],\n): VNode {\n const matches =\n typeof window !== 'undefined' && window.matchMedia?.(mediaQuery)?.matches;\n return when(Boolean(matches), children);\n}\n\n/* --- Responsive & Media Query Directives (aligned with style.ts) --- */\n\n/**\n * Media variants matching those in style.ts\n */\nexport const mediaVariants = {\n // Responsive breakpoints (matching style.ts)\n sm: '(min-width:640px)',\n md: '(min-width:768px)',\n lg: '(min-width:1024px)',\n xl: '(min-width:1280px)',\n '2xl': '(min-width:1536px)',\n\n // Dark mode (matching style.ts)\n dark: '(prefers-color-scheme: dark)',\n} as const;\n\n/**\n * Responsive order matching style.ts\n */\nexport const responsiveOrder = ['sm', 'md', 'lg', 'xl', '2xl'] as const;\n\n/**\n * Individual responsive directives matching the style.ts breakpoint system\n */\nexport const responsive = {\n // Breakpoint-based rendering (matching style.ts exactly)\n sm: (children: VNode | VNode[]) => whenMedia(mediaVariants.sm, children),\n md: (children: VNode | VNode[]) => whenMedia(mediaVariants.md, children),\n lg: (children: VNode | VNode[]) => whenMedia(mediaVariants.lg, children),\n xl: (children: VNode | VNode[]) => whenMedia(mediaVariants.xl, children),\n '2xl': (children: VNode | VNode[]) =>\n whenMedia(mediaVariants['2xl'], children),\n\n // Dark mode (matching style.ts)\n dark: (children: VNode | VNode[]) => whenMedia(mediaVariants.dark, children),\n light: (children: VNode | VNode[]) =>\n whenMedia('(prefers-color-scheme: light)', children),\n\n // Accessibility and interaction preferences\n touch: (children: VNode | VNode[]) =>\n whenMedia('(hover: none) and (pointer: coarse)', children),\n mouse: (children: VNode | VNode[]) =>\n whenMedia('(hover: hover) and (pointer: fine)', children),\n reducedMotion: (children: VNode | VNode[]) =>\n whenMedia('(prefers-reduced-motion: reduce)', children),\n highContrast: (children: VNode | VNode[]) =>\n whenMedia('(prefers-contrast: high)', children),\n\n // Orientation\n portrait: (children: VNode | VNode[]) =>\n whenMedia('(orientation: portrait)', children),\n landscape: (children: VNode | VNode[]) =>\n whenMedia('(orientation: landscape)', children),\n} as const;\n\n/**\n * Advanced responsive directive that matches the style.ts multi-variant processing\n * Allows chaining responsive and dark mode conditions like in CSS classes\n * @param variants - Array of variant keys (e.g., ['dark', 'lg'])\n * @param children - Content to render when all variants match\n */\nexport function whenVariants(\n variants: Array<keyof typeof mediaVariants | 'light'>,\n children: VNode | VNode[],\n): VNode {\n const conditions: string[] = [];\n\n // Process dark/light mode\n if (variants.includes('dark')) {\n conditions.push(mediaVariants.dark);\n } else if (variants.includes('light')) {\n conditions.push('(prefers-color-scheme: light)');\n }\n\n // Process responsive variants (take the last one, matching style.ts behavior)\n const responsiveVariants = variants.filter((v) =>\n responsiveOrder.includes(v as (typeof responsiveOrder)[number]),\n );\n const lastResponsive = responsiveVariants[responsiveVariants.length - 1];\n if (lastResponsive && lastResponsive in mediaVariants) {\n conditions.push(\n mediaVariants[lastResponsive as keyof typeof mediaVariants],\n );\n }\n\n const mediaQuery = conditions.length > 0 ? conditions.join(' and ') : 'all';\n return whenMedia(mediaQuery, children);\n}\n\n/**\n * Responsive switch directive - render different content for different breakpoints\n * Mirrors the responsive behavior from the style system\n * @param content - Object with breakpoint keys and corresponding content\n */\nexport function responsiveSwitch(content: {\n base?: VNode | VNode[];\n sm?: VNode | VNode[];\n md?: VNode | VNode[];\n lg?: VNode | VNode[];\n xl?: VNode | VNode[];\n '2xl'?: VNode | VNode[];\n}): VNode[] {\n const results: VNode[] = [];\n\n // Handle light mode variants\n if (content.base) {\n // Base content (no media query)\n results.push(anchorBlock(content.base, 'responsive-base'));\n }\n\n // Add responsive variants in order\n responsiveOrder.forEach((breakpoint) => {\n const breakpointContent = content[breakpoint];\n if (breakpointContent) {\n results.push(responsive[breakpoint](breakpointContent));\n }\n });\n\n return results;\n}\n\n/* --- Enhanced Match Directive --- */\n\n/**\n * Enhanced match directive with more fluent API\n * @param value - Value to match against\n */\nexport function switchOn<T>(value: T) {\n const branches: Array<{\n condition: (val: T) => boolean;\n content: VNode | VNode[];\n }> = [];\n let otherwiseContent: VNode | VNode[] | null = null;\n\n return {\n case(matcher: T | ((val: T) => boolean), content: VNode | VNode[]) {\n const condition =\n typeof matcher === 'function'\n ? (matcher as (val: T) => boolean)\n : (val: T) => val === matcher;\n\n branches.push({ condition, content });\n return this;\n },\n\n when(predicate: (val: T) => boolean, content: VNode | VNode[]) {\n branches.push({ condition: predicate, content });\n return this;\n },\n\n otherwise(content: VNode | VNode[]) {\n otherwiseContent = content;\n return this;\n },\n\n done() {\n for (let i = 0; i < branches.length; i++) {\n const { condition, content } = branches[i];\n if (condition(value)) {\n return anchorBlock(content, `switch-case-${i}`);\n }\n }\n return anchorBlock(otherwiseContent || [], 'switch-otherwise');\n },\n };\n}\n"],"names":["unless","cond","children","when","whenEmpty","collection","isEmpty","whenNotEmpty","hasItems","eachWhere","list","predicate","render","filtered","item","index","originalIndex","filteredIndex","itemKey","anchorBlock","switchOnLength","cases","length","eachGroup","groupBy","renderGroup","groups","key","groupKey","items","groupIndex","eachPage","pageSize","currentPage","startIndex","endIndex","pageIndex","globalIndex","switchOnPromise","promiseState","whenMedia","mediaQuery","matches","mediaVariants","responsiveOrder","responsive","whenVariants","variants","conditions","responsiveVariants","v","lastResponsive","responsiveSwitch","content","results","breakpoint","breakpointContent","switchOn","value","branches","otherwiseContent","matcher","condition","val","i"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"custom-elements-runtime.directive-enhancements.es.js","sources":["../src/lib/directive-enhancements.ts"],"sourcesContent":["// Enhanced collection directives for better developer experience\n\nimport type { VNode } from './runtime/types';\nimport { when, anchorBlock, nextDirectiveIndex } from './directives';\n\n/**\n * Conditional rendering with negated condition (opposite of when)\n * @param cond - Boolean condition to negate\n * @param children - Content to render when condition is false\n */\nexport function unless(cond: boolean, children: VNode | VNode[]): VNode {\n return when(!cond, children);\n}\n\n/**\n * Render content only if array/collection is empty\n * @param collection - Array or collection to check\n * @param children - Content to render when empty\n */\nexport function whenEmpty<T>(\n collection: T[] | null | undefined,\n children: VNode | VNode[],\n): VNode {\n const isEmpty = !collection || collection.length === 0;\n return when(isEmpty, children);\n}\n\n/**\n * Render content only if array/collection has items\n * @param collection - Array or collection to check\n * @param children - Content to render when not empty\n */\nexport function whenNotEmpty<T>(\n collection: T[] | null | undefined,\n children: VNode | VNode[],\n): VNode {\n const hasItems = Boolean(collection && collection.length > 0);\n return when(hasItems, children);\n}\n\n/**\n * Enhanced each with filtering capability\n * @param list - Array to iterate over\n * @param predicate - Filter function (optional)\n * @param render - Render function for each item\n */\nexport function eachWhere<T>(\n list: T[],\n predicate: (item: T, index: number) => boolean,\n render: (item: T, index: number, filteredIndex: number) => VNode | VNode[],\n): VNode[] {\n const filtered: Array<{ item: T; originalIndex: number }> = [];\n\n list.forEach((item, index) => {\n if (predicate(item, index)) {\n filtered.push({ item, originalIndex: index });\n }\n });\n\n return filtered.map(({ item, originalIndex }, filteredIndex) => {\n const itemKey =\n typeof item === 'object' && item != null\n ? ((item as Record<string, unknown>)?.key ??\n (item as Record<string, unknown>)?.id ??\n `filtered-${originalIndex}`)\n : `filtered-${originalIndex}`;\n\n return anchorBlock(\n render(item, originalIndex, filteredIndex),\n `each-where-${itemKey}`,\n );\n });\n}\n\n/**\n * Render different content based on array length\n * @param list - Array to check\n * @param cases - Object with length-based cases\n */\nexport function switchOnLength<T>(\n list: T[],\n cases: {\n empty?: VNode | VNode[];\n one?: (item: T) => VNode | VNode[];\n many?: (items: T[]) => VNode | VNode[];\n exactly?: { [count: number]: (items: T[]) => VNode | VNode[] };\n },\n): VNode {\n const si = nextDirectiveIndex();\n const length = list?.length ?? 0;\n\n if (length === 0 && cases.empty) {\n return anchorBlock(cases.empty, `switch-length-${si}-empty`);\n }\n\n if (length === 1 && cases.one) {\n return anchorBlock(cases.one(list[0]), `switch-length-${si}-one`);\n }\n\n if (cases.exactly?.[length]) {\n return anchorBlock(\n cases.exactly[length](list),\n `switch-length-${si}-${length}`,\n );\n }\n\n if (length > 1 && cases.many) {\n return anchorBlock(cases.many(list), `switch-length-${si}-many`);\n }\n\n return anchorBlock([], `switch-length-${si}-fallback`);\n}\n\n/**\n * Group array items and render each group\n * @param list - Array to group\n * @param groupBy - Function to determine group key\n * @param renderGroup - Function to render each group\n */\nexport function eachGroup<T, K extends string | number>(\n list: T[],\n groupBy: (item: T) => K,\n renderGroup: (groupKey: K, items: T[], groupIndex: number) => VNode | VNode[],\n): VNode[] {\n const groups = new Map<K, T[]>();\n\n list.forEach((item) => {\n const key = groupBy(item);\n if (!groups.has(key)) {\n groups.set(key, []);\n }\n groups.get(key)!.push(item);\n });\n\n return Array.from(groups.entries()).map(([groupKey, items], groupIndex) => {\n return anchorBlock(\n renderGroup(groupKey, items, groupIndex),\n `each-group-${groupKey}`,\n );\n });\n}\n\n/**\n * Render with pagination/chunking\n * @param list - Array to chunk\n * @param pageSize - Items per page/chunk\n * @param currentPage - Current page (0-based)\n * @param render - Render function for visible items\n */\nexport function eachPage<T>(\n list: T[],\n pageSize: number,\n currentPage: number,\n render: (item: T, index: number, pageIndex: number) => VNode | VNode[],\n): VNode[] {\n const startIndex = currentPage * pageSize;\n const endIndex = Math.min(startIndex + pageSize, list.length);\n const pageItems = list.slice(startIndex, endIndex);\n\n return pageItems.map((item, pageIndex) => {\n const globalIndex = startIndex + pageIndex;\n const itemKey =\n typeof item === 'object' && item != null\n ? ((item as Record<string, unknown>)?.key ??\n (item as Record<string, unknown>)?.id ??\n `page-${globalIndex}`)\n : `page-${globalIndex}`;\n\n return anchorBlock(\n render(item, globalIndex, pageIndex),\n `each-page-${itemKey}`,\n );\n });\n}\n\n/* --- Async & Loading State Directives --- */\n\n/**\n * Render content based on Promise state\n * @param promiseState - Object with loading, data, error states\n * @param cases - Render functions for each state\n */\nexport function switchOnPromise<T, E = Error>(\n promiseState: {\n loading?: boolean;\n data?: T;\n error?: E;\n },\n cases: {\n loading?: VNode | VNode[];\n success?: (data: T) => VNode | VNode[];\n error?: (error: E) => VNode | VNode[];\n idle?: VNode | VNode[];\n },\n): VNode {\n const si = nextDirectiveIndex();\n\n if (promiseState.loading && cases.loading) {\n return anchorBlock(cases.loading, `promise-${si}-loading`);\n }\n\n if (promiseState.error && cases.error) {\n return anchorBlock(cases.error(promiseState.error), `promise-${si}-error`);\n }\n\n if (promiseState.data !== undefined && cases.success) {\n return anchorBlock(\n cases.success(promiseState.data),\n `promise-${si}-success`,\n );\n }\n\n if (cases.idle) {\n return anchorBlock(cases.idle, `promise-${si}-idle`);\n }\n\n return anchorBlock([], `promise-${si}-fallback`);\n}\n\n/* --- Utility Directives --- */\n\n/**\n * Render content based on screen size/media query\n * @param mediaQuery - CSS media query string\n * @param children - Content to render when media query matches\n */\nexport function whenMedia(\n mediaQuery: string,\n children: VNode | VNode[],\n): VNode {\n const matches =\n typeof window !== 'undefined' && window.matchMedia?.(mediaQuery)?.matches;\n return when(Boolean(matches), children);\n}\n\n/* --- Responsive & Media Query Directives (aligned with style.ts) --- */\n\n/**\n * Media variants matching those in style.ts\n */\nexport const mediaVariants = {\n // Responsive breakpoints (matching style.ts)\n sm: '(min-width:640px)',\n md: '(min-width:768px)',\n lg: '(min-width:1024px)',\n xl: '(min-width:1280px)',\n '2xl': '(min-width:1536px)',\n\n // Dark mode (matching style.ts)\n dark: '(prefers-color-scheme: dark)',\n} as const;\n\n/**\n * Responsive order matching style.ts\n */\nexport const responsiveOrder = ['sm', 'md', 'lg', 'xl', '2xl'] as const;\n\n/**\n * Individual responsive directives matching the style.ts breakpoint system\n */\nexport const responsive = {\n // Breakpoint-based rendering (matching style.ts exactly)\n sm: (children: VNode | VNode[]) => whenMedia(mediaVariants.sm, children),\n md: (children: VNode | VNode[]) => whenMedia(mediaVariants.md, children),\n lg: (children: VNode | VNode[]) => whenMedia(mediaVariants.lg, children),\n xl: (children: VNode | VNode[]) => whenMedia(mediaVariants.xl, children),\n '2xl': (children: VNode | VNode[]) =>\n whenMedia(mediaVariants['2xl'], children),\n\n // Dark mode (matching style.ts)\n dark: (children: VNode | VNode[]) => whenMedia(mediaVariants.dark, children),\n light: (children: VNode | VNode[]) =>\n whenMedia('(prefers-color-scheme: light)', children),\n\n // Accessibility and interaction preferences\n touch: (children: VNode | VNode[]) =>\n whenMedia('(hover: none) and (pointer: coarse)', children),\n mouse: (children: VNode | VNode[]) =>\n whenMedia('(hover: hover) and (pointer: fine)', children),\n reducedMotion: (children: VNode | VNode[]) =>\n whenMedia('(prefers-reduced-motion: reduce)', children),\n highContrast: (children: VNode | VNode[]) =>\n whenMedia('(prefers-contrast: high)', children),\n\n // Orientation\n portrait: (children: VNode | VNode[]) =>\n whenMedia('(orientation: portrait)', children),\n landscape: (children: VNode | VNode[]) =>\n whenMedia('(orientation: landscape)', children),\n} as const;\n\n/**\n * Advanced responsive directive that matches the style.ts multi-variant processing\n * Allows chaining responsive and dark mode conditions like in CSS classes\n * @param variants - Array of variant keys (e.g., ['dark', 'lg'])\n * @param children - Content to render when all variants match\n */\nexport function whenVariants(\n variants: Array<keyof typeof mediaVariants | 'light'>,\n children: VNode | VNode[],\n): VNode {\n const conditions: string[] = [];\n\n // Process dark/light mode\n if (variants.includes('dark')) {\n conditions.push(mediaVariants.dark);\n } else if (variants.includes('light')) {\n conditions.push('(prefers-color-scheme: light)');\n }\n\n // Process responsive variants (take the last one, matching style.ts behavior)\n const responsiveVariants = variants.filter((v) =>\n responsiveOrder.includes(v as (typeof responsiveOrder)[number]),\n );\n const lastResponsive = responsiveVariants[responsiveVariants.length - 1];\n if (lastResponsive && lastResponsive in mediaVariants) {\n conditions.push(\n mediaVariants[lastResponsive as keyof typeof mediaVariants],\n );\n }\n\n const mediaQuery = conditions.length > 0 ? conditions.join(' and ') : 'all';\n return whenMedia(mediaQuery, children);\n}\n\n/**\n * Responsive switch directive - render different content for different breakpoints\n * Mirrors the responsive behavior from the style system\n * @param content - Object with breakpoint keys and corresponding content\n */\nexport function responsiveSwitch(content: {\n base?: VNode | VNode[];\n sm?: VNode | VNode[];\n md?: VNode | VNode[];\n lg?: VNode | VNode[];\n xl?: VNode | VNode[];\n '2xl'?: VNode | VNode[];\n}): VNode[] {\n const results: VNode[] = [];\n\n const si = nextDirectiveIndex();\n\n // Handle light mode variants\n if (content.base) {\n // Base content (no media query)\n results.push(anchorBlock(content.base, `responsive-${si}-base`));\n }\n\n // Add responsive variants in order\n responsiveOrder.forEach((breakpoint) => {\n const breakpointContent = content[breakpoint];\n if (breakpointContent) {\n results.push(responsive[breakpoint](breakpointContent));\n }\n });\n\n return results;\n}\n\n/* --- Enhanced Match Directive --- */\n\n/**\n * Enhanced match directive with more fluent API\n * @param value - Value to match against\n */\nexport function switchOn<T>(value: T) {\n const branches: Array<{\n condition: (val: T) => boolean;\n content: VNode | VNode[];\n }> = [];\n let otherwiseContent: VNode | VNode[] | null = null;\n\n return {\n case(matcher: T | ((val: T) => boolean), content: VNode | VNode[]) {\n const condition =\n typeof matcher === 'function'\n ? (matcher as (val: T) => boolean)\n : (val: T) => val === matcher;\n\n branches.push({ condition, content });\n return this;\n },\n\n when(predicate: (val: T) => boolean, content: VNode | VNode[]) {\n branches.push({ condition: predicate, content });\n return this;\n },\n\n otherwise(content: VNode | VNode[]) {\n otherwiseContent = content;\n return this;\n },\n\n done() {\n const si = nextDirectiveIndex();\n for (let i = 0; i < branches.length; i++) {\n const { condition, content } = branches[i];\n if (condition(value)) {\n return anchorBlock(content, `switch-on-${si}-case-${i}`);\n }\n }\n return anchorBlock(otherwiseContent || [], `switch-on-${si}-otherwise`);\n },\n };\n}\n"],"names":["unless","cond","children","when","whenEmpty","collection","isEmpty","whenNotEmpty","hasItems","eachWhere","list","predicate","render","filtered","item","index","originalIndex","filteredIndex","itemKey","anchorBlock","switchOnLength","cases","si","nextDirectiveIndex","length","eachGroup","groupBy","renderGroup","groups","key","groupKey","items","groupIndex","eachPage","pageSize","currentPage","startIndex","endIndex","pageIndex","globalIndex","switchOnPromise","promiseState","whenMedia","mediaQuery","matches","mediaVariants","responsiveOrder","responsive","whenVariants","variants","conditions","responsiveVariants","v","lastResponsive","responsiveSwitch","content","results","breakpoint","breakpointContent","switchOn","value","branches","otherwiseContent","matcher","condition","val","i"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});let u="",i=0;const h=[];function y(){u="",i=0,h.length=0}function d(){return i++}function a(n){const t=i++;return n!==void 0?n:u?`${u}.${t}`:`when-block-${t}`}function f(n){h.push([u,i]),u=n,i=0}function l(){const n=h[h.length-1];n&&(h.length--,[u,i]=n)}function $(n,t,e){const r=a(e);if(typeof t!="function")return o(n?t:[],r);if(!n)return o([],r);f(r);const c=t();return l(),o(c,r)}function g(n,t){return n.map((e,r)=>{const c=typeof e=="object"?e?.key??e?.id??`idx-${r}`:String(e);return o(t(e,r),`each-${c}`)})}function x(){const n=[];return{when(t,e){return n.push([t,e]),this},otherwise(t){return n.push([!0,t]),this},done(){const t=`match-${a()}`;for(let e=0;e<n.length;e++){const[r,c]=n[e];if(r){const s=`${t}-branch-${e}`;if(typeof c=="function"){f(s);const p=c();return l(),[o(p,s)]}return[o(c,s)]}}return[o([],`${t}-empty`)]}}}function o(n,t){const e=n?Array.isArray(n)?n.filter(r=>r!=null):[n].filter(r=>r!=null):[];return{tag:"#anchor",key:t,children:e}}exports.anchorBlock=o;exports.each=g;exports.match=x;exports.nextDirectiveIndex=d;exports.resetWhenCounter=y;exports.when=$;
|
|
2
2
|
//# sourceMappingURL=custom-elements-runtime.directives.cjs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"custom-elements-runtime.directives.cjs.js","sources":["../src/lib/directives.ts"],"sourcesContent":["import type { VNode } from './runtime/types';\n\n/* --- When --- */\nexport function when(cond: boolean
|
|
1
|
+
{"version":3,"file":"custom-elements-runtime.directives.cjs.js","sources":["../src/lib/directives.ts"],"sourcesContent":["import type { VNode } from './runtime/types';\n\n// ── Per-render directive scope tracking ─────────────────────────────────────\n//\n// A FLAT counter (index++) breaks when a when() factory itself contains more\n// when() calls: those inner calls consume counter slots, causing SUBSEQUENT\n// SIBLING when() calls to get a different index depending on whether the factory\n// ran. For example:\n//\n// when(A, () => { when(B); when(C); }) // ← factory may or may not run\n// when(D) // ← index shifts when factory runs\n//\n// The fix: each when() call claims its own slot (stable regardless of whether\n// the factory runs), then ENTERS a new child scope for the factory. Inner\n// when() calls consume indices in that child scope, never bleeding into the\n// sibling counter of the outer scope.\n//\n// Key format: root sibling 0 → \"when-block-0\"\n// child of \"when-block-0\" at pos 1 → \"when-block-0.1\"\n// grandchild → \"when-block-0.1.0\" etc.\n\n/** Current scope's parent prefix (empty string = root scope). */\nlet _scopeParent = '';\n/** Next sibling index inside the current scope. */\nlet _scopeIndex = 0;\n/** Stack of [parentPrefix, siblingIndex] for nested scopes. */\nconst _scopeStack: Array<readonly [string, number]> = [];\n\n/**\n * Reset all scope state at the start of each component render pass.\n * Called automatically by the component renderer — not needed in user code.\n * @internal\n */\nexport function resetWhenCounter(): void {\n _scopeParent = '';\n _scopeIndex = 0;\n _scopeStack.length = 0;\n}\n\n/**\n * Claim the next directive call index within the current scope.\n * Used by directive-enhancements.ts for non-when() directives (switchOnLength,\n * switchOnPromise, etc.) that need a stable unique number per call site.\n * @internal\n */\nexport function nextDirectiveIndex(): number {\n return _scopeIndex++;\n}\n\n/** Claim the next slot in the current scope and return its anchor key. */\nfunction claimKey(explicitKey?: string): string {\n const idx = _scopeIndex++;\n if (explicitKey !== undefined) return explicitKey;\n return _scopeParent ? `${_scopeParent}.${idx}` : `when-block-${idx}`;\n}\n\n/** Push a new child scope keyed under `anchorKey`. */\nfunction enterScope(anchorKey: string): void {\n _scopeStack.push([_scopeParent, _scopeIndex] as const);\n _scopeParent = anchorKey;\n _scopeIndex = 0;\n}\n\n/** Pop back to the parent scope. */\nfunction exitScope(): void {\n const top = _scopeStack[_scopeStack.length - 1];\n if (top) {\n _scopeStack.length--;\n [_scopeParent, _scopeIndex] = top;\n }\n}\n\n/* --- When --- */\nexport function when(\n cond: boolean,\n children: VNode | VNode[],\n key?: string,\n): VNode;\nexport function when(\n cond: boolean,\n factory: () => VNode | VNode[],\n key?: string,\n): VNode;\nexport function when(\n cond: boolean,\n childrenOrFactory: VNode | VNode[] | (() => VNode | VNode[]),\n key?: string,\n): VNode {\n // Claim this call's position BEFORE potentially entering a child scope.\n // This guarantees sibling when() calls always get the same index regardless\n // of whether a factory executes and how many when() calls it contains.\n const anchorKey = claimKey(key);\n\n if (typeof childrenOrFactory !== 'function') {\n return anchorBlock(cond ? childrenOrFactory : [], anchorKey);\n }\n\n if (!cond) {\n return anchorBlock([], anchorKey);\n }\n\n // Run the factory in a child scope so its inner when() calls don't\n // affect the sibling counter of the outer scope.\n enterScope(anchorKey);\n const children = childrenOrFactory();\n exitScope();\n return anchorBlock(children, anchorKey);\n}\n\n/* --- Each --- */\nexport function each<\n T extends string | number | boolean | { id?: string | number; key?: string },\n>(list: T[], render: (item: T, index: number) => VNode | VNode[]): VNode[] {\n return list.map((item, i) => {\n // For primitives, use value as key; for objects, prefer key/id\n const itemKey =\n typeof item === 'object'\n ? ((item as Record<string, unknown>)?.key ??\n (item as Record<string, unknown>)?.id ??\n `idx-${i}`)\n : String(item);\n return anchorBlock(render(item, i), `each-${itemKey}`);\n });\n}\n\n/* --- match --- */\ntype Branch = [\n condition: unknown,\n content: VNode | VNode[] | (() => VNode | VNode[]),\n];\n\nexport function match() {\n const branches: Branch[] = [];\n return {\n when(cond: unknown, content: VNode | VNode[] | (() => VNode | VNode[])) {\n branches.push([cond, content]);\n return this;\n },\n otherwise(content: VNode | VNode[]) {\n branches.push([true, content]);\n return this;\n },\n done() {\n const matchKey = `match-${claimKey()}`;\n for (let idx = 0; idx < branches.length; idx++) {\n const [cond, content] = branches[idx];\n if (cond) {\n const branchKey = `${matchKey}-branch-${idx}`;\n if (typeof content === 'function') {\n enterScope(branchKey);\n const payload = (content as () => VNode | VNode[])();\n exitScope();\n return [anchorBlock(payload, branchKey)];\n }\n return [anchorBlock(content, branchKey)];\n }\n }\n return [anchorBlock([], `${matchKey}-empty`)];\n },\n };\n}\n\n/**\n * Create a stable anchor block with consistent boundaries.\n * Always has start/end boundaries.\n */\nexport function anchorBlock(\n children: VNode | VNode[] | null | undefined,\n anchorKey: string,\n): VNode {\n // Normalize children to array, filtering out only null/undefined values.\n // Preserve meaningful falsy values such as 0, false, and empty string.\n const childArray = !children\n ? []\n : Array.isArray(children)\n ? children.filter((c) => c !== null && c !== undefined)\n : [children].filter((c) => c !== null && c !== undefined);\n\n return {\n tag: '#anchor',\n key: anchorKey,\n children: childArray,\n };\n}\n"],"names":["_scopeParent","_scopeIndex","_scopeStack","resetWhenCounter","nextDirectiveIndex","claimKey","explicitKey","idx","enterScope","anchorKey","exitScope","top","when","cond","childrenOrFactory","key","anchorBlock","children","each","list","render","item","i","itemKey","match","branches","content","matchKey","branchKey","payload","childArray","c"],"mappings":"gFAsBA,IAAIA,EAAe,GAEfC,EAAc,EAElB,MAAMC,EAAgD,CAAA,EAO/C,SAASC,GAAyB,CACvCH,EAAe,GACfC,EAAc,EACdC,EAAY,OAAS,CACvB,CAQO,SAASE,GAA6B,CAC3C,OAAOH,GACT,CAGA,SAASI,EAASC,EAA8B,CAC9C,MAAMC,EAAMN,IACZ,OAAIK,IAAgB,OAAkBA,EAC/BN,EAAe,GAAGA,CAAY,IAAIO,CAAG,GAAK,cAAcA,CAAG,EACpE,CAGA,SAASC,EAAWC,EAAyB,CAC3CP,EAAY,KAAK,CAACF,EAAcC,CAAW,CAAU,EACrDD,EAAeS,EACfR,EAAc,CAChB,CAGA,SAASS,GAAkB,CACzB,MAAMC,EAAMT,EAAYA,EAAY,OAAS,CAAC,EAC1CS,IACFT,EAAY,SACZ,CAACF,EAAcC,CAAW,EAAIU,EAElC,CAaO,SAASC,EACdC,EACAC,EACAC,EACO,CAIP,MAAMN,EAAYJ,EAASU,CAAG,EAE9B,GAAI,OAAOD,GAAsB,WAC/B,OAAOE,EAAYH,EAAOC,EAAoB,CAAA,EAAIL,CAAS,EAG7D,GAAI,CAACI,EACH,OAAOG,EAAY,CAAA,EAAIP,CAAS,EAKlCD,EAAWC,CAAS,EACpB,MAAMQ,EAAWH,EAAA,EACjB,OAAAJ,EAAA,EACOM,EAAYC,EAAUR,CAAS,CACxC,CAGO,SAASS,EAEdC,EAAWC,EAA8D,CACzE,OAAOD,EAAK,IAAI,CAACE,EAAMC,IAAM,CAE3B,MAAMC,EACJ,OAAOF,GAAS,SACVA,GAAkC,KACnCA,GAAkC,IACnC,OAAOC,CAAC,GACR,OAAOD,CAAI,EACjB,OAAOL,EAAYI,EAAOC,EAAMC,CAAC,EAAG,QAAQC,CAAO,EAAE,CACvD,CAAC,CACH,CAQO,SAASC,GAAQ,CACtB,MAAMC,EAAqB,CAAA,EAC3B,MAAO,CACL,KAAKZ,EAAea,EAAoD,CACtE,OAAAD,EAAS,KAAK,CAACZ,EAAMa,CAAO,CAAC,EACtB,IACT,EACA,UAAUA,EAA0B,CAClC,OAAAD,EAAS,KAAK,CAAC,GAAMC,CAAO,CAAC,EACtB,IACT,EACA,MAAO,CACL,MAAMC,EAAW,SAAStB,EAAA,CAAU,GACpC,QAASE,EAAM,EAAGA,EAAMkB,EAAS,OAAQlB,IAAO,CAC9C,KAAM,CAACM,EAAMa,CAAO,EAAID,EAASlB,CAAG,EACpC,GAAIM,EAAM,CACR,MAAMe,EAAY,GAAGD,CAAQ,WAAWpB,CAAG,GAC3C,GAAI,OAAOmB,GAAY,WAAY,CACjClB,EAAWoB,CAAS,EACpB,MAAMC,EAAWH,EAAA,EACjB,OAAAhB,EAAA,EACO,CAACM,EAAYa,EAASD,CAAS,CAAC,CACzC,CACA,MAAO,CAACZ,EAAYU,EAASE,CAAS,CAAC,CACzC,CACF,CACA,MAAO,CAACZ,EAAY,CAAA,EAAI,GAAGW,CAAQ,QAAQ,CAAC,CAC9C,CAAA,CAEJ,CAMO,SAASX,EACdC,EACAR,EACO,CAGP,MAAMqB,EAAcb,EAEhB,MAAM,QAAQA,CAAQ,EACpBA,EAAS,OAAQc,GAAMA,GAAM,IAAuB,EACpD,CAACd,CAAQ,EAAE,OAAQc,GAAMA,GAAM,IAAuB,EAHxD,CAAA,EAKJ,MAAO,CACL,IAAK,UACL,IAAKtB,EACL,SAAUqB,CAAA,CAEd"}
|