lightview 2.1.0 → 2.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build-bundles.mjs +2 -6
- package/build.js +236 -46
- package/components/data-display/avatar.js +25 -1
- package/components/data-display/chart.js +22 -5
- package/components/data-display/countdown.js +3 -2
- package/components/data-input/checkbox.js +23 -1
- package/components/data-input/input.js +24 -1
- package/components/data-input/radio.js +37 -2
- package/components/data-input/select.js +24 -1
- package/components/data-input/toggle.js +21 -1
- package/components/navigation/breadcrumbs.js +42 -2
- package/docs/assets/js/examplify.js +1 -1
- package/docs/cdom-nav.html +32 -6
- package/docs/cdom.html +610 -180
- package/docs/components/avatar.html +24 -54
- package/docs/components/badge.html +14 -14
- package/docs/components/breadcrumbs.html +95 -29
- package/docs/components/chart-area.html +3 -3
- package/docs/components/chart-bar.html +4 -181
- package/docs/components/chart-column.html +4 -189
- package/docs/components/chart-line.html +3 -3
- package/docs/components/chart-pie.html +112 -166
- package/docs/components/chart.html +11 -13
- package/docs/components/checkbox.html +48 -28
- package/docs/components/collapse.html +6 -6
- package/docs/components/countdown.html +12 -12
- package/docs/components/dropdown.html +1 -1
- package/docs/components/file-input.html +4 -4
- package/docs/components/footer.html +11 -11
- package/docs/components/input.html +45 -29
- package/docs/components/join.html +4 -4
- package/docs/components/kbd.html +3 -3
- package/docs/components/loading.html +41 -53
- package/docs/components/pagination.html +4 -4
- package/docs/components/progress.html +6 -4
- package/docs/components/radio.html +42 -31
- package/docs/components/select.html +48 -59
- package/docs/components/toggle.html +44 -25
- package/docs/getting-started/index.html +4 -4
- package/jprx/LICENSE +21 -0
- package/jprx/README.md +130 -0
- package/{cdom → jprx}/helpers/array.js +9 -4
- package/{cdom → jprx}/helpers/state.js +6 -3
- package/jprx/index.js +69 -0
- package/jprx/package.json +24 -0
- package/jprx/parser.js +1517 -0
- package/lightview-all.js +3785 -1
- package/lightview-cdom.js +2128 -1
- package/lightview-router.js +179 -208
- package/lightview-x.js +1435 -1
- package/lightview.js +613 -1
- package/package.json +5 -2
- package/src/lightview-cdom.js +201 -49
- package/src/lightview-router.js +210 -0
- package/src/lightview-x.js +104 -55
- package/src/lightview.js +12 -1
- package/{watch.js → start-dev.js} +2 -1
- package/tests/cdom/parser.test.js +83 -12
- package/wrangler.toml +0 -3
- package/cdom/parser.js +0 -602
- package/test-text-tag.js +0 -6
- /package/{cdom → jprx}/helpers/compare.js +0 -0
- /package/{cdom → jprx}/helpers/conditional.js +0 -0
- /package/{cdom → jprx}/helpers/datetime.js +0 -0
- /package/{cdom → jprx}/helpers/format.js +0 -0
- /package/{cdom → jprx}/helpers/logic.js +0 -0
- /package/{cdom → jprx}/helpers/lookup.js +0 -0
- /package/{cdom → jprx}/helpers/math.js +0 -0
- /package/{cdom → jprx}/helpers/network.js +0 -0
- /package/{cdom → jprx}/helpers/stats.js +0 -0
- /package/{cdom → jprx}/helpers/string.js +0 -0
package/lightview-cdom.js
CHANGED
|
@@ -1 +1,2128 @@
|
|
|
1
|
-
var LightviewCDOM=function(e){"use strict";const t=new Map,r=new Map,n=(e,n,i={})=>{t.set(e,n),i&&r.set(e,i)},i=()=>globalThis.Lightview||null,s=()=>{var e;return(null==(e=i())?void 0:e.registry)||null};class o{constructor(e,t){this.parent=e,this.key=t,this.isBindingTarget=!0}get value(){return this.parent[this.key]}set value(e){this.parent[this.key]=e}get __parent__(){return this.parent}}const a=e=>e&&"function"==typeof e&&"value"in e?e.value:!e||"object"!=typeof e||globalThis.Node&&e instanceof globalThis.Node||!("value"in e)?e:e.value,l=(e,t)=>{let r=e;for(const n of t){if(!n)continue;if(r=a(r),null==r)return;r=r[n.startsWith("[")?n.slice(1,-1):n]}return a(r)},u=(e,t)=>{let r=e;for(let n=0;n<t.length;n++){const e=t[n];if(!e)continue;const i=e.startsWith("[")?e.slice(1,-1):e,s=a(r);if(null==s)return;if(n===t.length-1)return new o(s,i);r=s[i]}return r},c=(e,t)=>{if("string"!=typeof e)return e;const r=s();if("."===e)return a(t);if(e.startsWith("$/")){const[t,...n]=e.slice(2).split("/"),i=null==r?void 0:r.get(t);if(!i)return;return l(i,n)}if(e.startsWith("./"))return l(t,e.slice(2).split("/"));if(e.startsWith("../"))return l(null==t?void 0:t.__parent__,e.slice(3).split("/"));if(e.includes("/")||e.includes("."))return l(t,e.split(/[\/.]/));const n=a(t);return n&&"object"==typeof n&&(e in n||void 0!==n[e])?l(n,[e]):e},f=(e,t)=>{if("string"!=typeof e)return e;const r=s();if("."===e)return t;if(e.startsWith("$/")){const t=e.slice(2).split(/[\/.]/),n=t.shift(),i=null==r?void 0:r.get(n);if(!i)return;return u(i,t)}if(e.startsWith("./"))return u(t,e.slice(2).split(/[\/.]/));if(e.startsWith("../"))return u(null==t?void 0:t.__parent__,e.slice(3).split(/[\/.]/));if(e.includes("/")||e.includes("."))return u(t,e.split(/[\/.]/));const n=a(t);return n&&"object"==typeof n&&/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(e)?new o(n,e):e};class h{constructor(e){this.fn=e,this.isLazy=!0}resolve(e){return this.fn(e)}}const p=(e,t,r=!1)=>{if(e.startsWith("'")&&e.endsWith("'")||e.startsWith('"')&&e.endsWith('"'))return{value:e.slice(1,-1),isLiteral:!0};if(""!==e&&!isNaN(Number(e)))return{value:Number(e),isLiteral:!0};if("true"===e)return{value:!0,isLiteral:!0};if("false"===e)return{value:!1,isLiteral:!0};if("null"===e)return{value:null,isLiteral:!0};if("_"===e||e.startsWith("_/")||e.startsWith("_."))return{value:new h(t=>{if("_"===e)return t;const r=(e.startsWith("_."),e.slice(2));return c(r,t)}),isLazy:!0};if("$event"===e||e.startsWith("$event/")||e.startsWith("$event."))return{value:new h(t=>{if("$event"===e)return t;const r=(e.startsWith("$event."),e.slice(7));return c(r,t)}),isLazy:!0};if(e.includes("(")){let n=e;e.startsWith("/")?n="$"+e:!r||e.startsWith("$")||e.startsWith("./")||(n=`$/${e}`);const i=g(n,t);return i instanceof h?{value:i,isLazy:!0}:{value:i,isSignal:!1}}const n=e.endsWith("..."),i=n?e.slice(0,-3):e;let s;if(s=i.startsWith("/")?"$"+i:i.startsWith("$")||i.startsWith("./")||i.startsWith("../")?i:r?`$/${i}`:`./${i}`,n){const e=s.split("/"),r=e.pop(),n=e.join("/"),i=n?c(n,t):t,o=a(i);if(Array.isArray(o)){return{value:o.map(e=>{const t=a(e);return t&&t[r]}),isExplosion:!0}}if(o&&"object"==typeof o){const e=o[r];return{value:a(e),isExplosion:!0}}return{value:void 0,isExplosion:!0}}return{value:f(s,t),isExplosion:!1}},g=(e,n)=>{var i;if("string"!=typeof e)return e;const s=e.indexOf("(");if(-1!==s&&e.endsWith(")")){const o=e.slice(0,s).trim(),l=e.slice(s+1,-1),u=o.split("/");let c=u.pop().replace(/^\$/,"");""===c&&(u.length>0||"/"===o)&&(c="/");const g=u.join("/"),d=e.startsWith("$/")||e.startsWith("$");let y=n;g&&"$"!==g&&(y=f(g,n));const v=t.get(c);if(!v)return null==(i=globalThis.console)||i.warn(`LightviewCDOM: Helper "${c}" not found.`),e;const m=r.get(c)||{},b=[];let w="",A=0,_=null;for(let e=0;e<l.length;e++){const t=l[e];if(t===_)_=null;else if(_||"'"!==t&&'"'!==t)if(_||"("!==t)if(_||")"!==t){if(!_&&","===t&&0===A){b.push(w.trim()),w="";continue}}else A--;else A++;else _=t;w+=t}w&&b.push(w.trim());const N=[];let W=!1;for(let e=0;e<b.length;e++){const t=b[e],r=p(t,y,d&&("$"===g||!g));r.isLazy&&(W=!0);const n=!(m.pathAware&&0===e);let i=n?a(r.value):r.value;r.isExplosion&&Array.isArray(i)?N.push(...i.map(e=>n?a(e):e)):N.push(i)}if(W)return new h(e=>{const t=N.map((t,r)=>{const n=!(m.pathAware&&0===r),i=t instanceof h?t.resolve(e):t;return n?a(i):i});return v(...t)});const M=v(...N);return a(M)}return a(c(e,n))},d=(e,t)=>{const r=i();return r&&"string"==typeof e?r.computed(()=>g(e,t)):e},y=(...e)=>e.reduce((e,t)=>Number(e)+Number(t),0),v=(e,t)=>Number(e)-Number(t),m=(...e)=>e.reduce((e,t)=>Number(e)*Number(t),1),b=(e,t)=>Number(e)/Number(t),w=(e,t=0)=>Number(Math.round(e+"e"+t)+"e-"+t),A=e=>Math.ceil(e),_=e=>Math.floor(e),N=e=>Math.abs(e),W=(e,t)=>e%t,M=(e,t)=>Math.pow(e,t),S=e=>Math.sqrt(e),j=(e,t,r)=>e?t:r,L=(...e)=>e.every(Boolean),$=(...e)=>e.some(Boolean),E=e=>!e,D=(e,t)=>e===t,x=(e,t)=>e!==t,O=(...e)=>{const t=e[e.length-1];return e.slice(0,-1).join(t)},T=(...e)=>e.join(""),C=e=>String(e).toUpperCase(),k=e=>String(e).toLowerCase(),I=e=>String(e).trim(),z=e=>String(e).length,P=(e,t,r)=>String(e).replace(t,r),R=(e,t)=>String(e).split(t),B=e=>{const t=String(e);return t.charAt(0).toUpperCase()+t.slice(1)},q=e=>String(e).toLowerCase().split(" ").map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" "),J=(e,t)=>String(e).includes(t),F=(e,t)=>String(e).startsWith(t),H=(e,t)=>String(e).endsWith(t),U=(e,t)=>null!=e?e:t,G=(...e)=>e.length,V=(e,t)=>Array.isArray(e)?"function"==typeof t&&t.isLazy?e.filter(e=>t.resolve(e)):e.filter(e=>!!e):[],Z=(e,t)=>Array.isArray(e)?"string"==typeof t?e.map(e=>e&&"object"==typeof e?e[t]:e):t&&t.isLazy?e.map(e=>t.resolve(e)):e:[],K=(e,t)=>{if(Array.isArray(e))return t&&t.isLazy?e.find(e=>t.resolve(e)):e.find(e=>!!e)},Y=e=>Array.isArray(e)?[...new Set(e)]:[],Q=(e,t="asc")=>{if(!Array.isArray(e))return[];const r=[...e];return r.sort((e,r)=>e<r?"asc"===t?-1:1:e>r?"asc"===t?1:-1:0),r},X=e=>Array.isArray(e)?[...e].reverse():[],ee=e=>Array.isArray(e)?e[0]:void 0,te=e=>Array.isArray(e)?e[e.length-1]:void 0,re=(e,t,r)=>Array.isArray(e)?e.slice(t,r):[],ne=e=>Array.isArray(e)?e.flat(1/0):[],ie=(e,t=",")=>Array.isArray(e)?e.join(String(t)):"",se=e=>Array.isArray(e)?e.length:e?String(e).length:0,oe=(e,t)=>e>t,ae=(e,t)=>e<t,le=(e,t)=>e>=t,ue=(e,t)=>e<=t,ce=(e,t)=>e!==t,fe=(e,t,r)=>e>=t&&e<=r,he=(e,t)=>Array.isArray(e)&&e.includes(t),pe=(e,t)=>{if(!Array.isArray(e))return 0;return(t&&t.isLazy?e.filter(e=>t.resolve(e)):e).reduce((e,t)=>e+(Number(t)||0),0)},ge=(e,t)=>Array.isArray(e)?t&&t.isLazy?e.filter(e=>t.resolve(e)).length:e.filter(e=>!!e).length:0,de=(e,t)=>{if(!Array.isArray(e))return 0;const r=t&&t.isLazy?e.filter(e=>t.resolve(e)):e;return 0===r.length?0:r.reduce((e,t)=>e+(Number(t)||0),0)/r.length},ye=()=>(new Date).getTime(),ve=()=>{const e=new Date;return e.setHours(0,0,0,0),e.getTime()},me=e=>new Date(e).getTime(),be=(e,t)=>{const r=new Date(e);if(isNaN(r.getTime()))return"";const n={year:"numeric",month:"2-digit",day:"2-digit"};return"long"===t&&(n.month="long"),r.toLocaleDateString(void 0,n)},we=e=>new Date(e).getFullYear(),Ae=e=>new Date(e).getMonth()+1,_e=e=>new Date(e).getDate(),Ne=e=>new Date(e).getDay(),We=(e,t)=>{const r=new Date(e);return r.setDate(r.getDate()+Number(t)),r.getTime()},Me=(e,t,r="days")=>{const n=Math.abs(new Date(e)-new Date(t));return"seconds"===r?n/1e3:"minutes"===r?n/6e4:"hours"===r?n/36e5:n/864e5},Se=(e,t=2)=>Number(e).toFixed(t),je=(e,t="$",r=2)=>t+Number(e).toFixed(r).replace(/\B(?=(\d{3})+(?!\d))/g,","),Le=(e,t=0)=>(100*Number(e)).toFixed(t)+"%",$e=e=>String(e).replace(/\B(?=(\d{3})+(?!\d))/g,","),Ee=(e,t,r)=>{if(!Array.isArray(t))return;const n=t.indexOf(e);return-1!==n&&Array.isArray(r)?r[n]:void 0},De=(e,t,r)=>{if(!Array.isArray(t))return;const n=t.find(t=>Array.isArray(t)&&t[0]===e);return n?n[r-1]:void 0},xe=(e,t)=>Array.isArray(e)?e[t]:void 0,Oe=(e,t)=>Array.isArray(t)?t.indexOf(e):-1,Te=(...e)=>e.reduce((e,t)=>e+(Number(t)||0),0),Ce=(...e)=>0===e.length?0:Te(...e)/e.length,ke=(...e)=>Math.min(...e),Ie=(...e)=>Math.max(...e),ze=(...e)=>{if(0===e.length)return 0;const t=[...e].sort((e,t)=>e-t),r=Math.floor(t.length/2);return t.length%2!=0?t[r]:(t[r-1]+t[r])/2},Pe=(...e)=>{if(0===e.length)return 0;const t=Ce(...e),r=e.map(e=>Math.pow(e-t,2));return Math.sqrt(Ce(...r))},Re=(...e)=>{if(0===e.length)return 0;const t=Ce(...e),r=e.map(e=>Math.pow(e-t,2));return Ce(...r)},Be=(e,t)=>(e&&"object"==typeof e&&"value"in e||e&&"function"==typeof e&&"value"in e?e.value=t:e&&"object"==typeof e&&t&&"object"==typeof t&&Object.assign(e,t),t),qe=(e,t=1)=>{const r=e&&"object"==typeof e&&"value"in e?e.value:0,n=Number(r)+Number(t);return Be(e,n)},Je=(e,t=1)=>{const r=e&&"object"==typeof e&&"value"in e?e.value:0,n=Number(r)-Number(t);return Be(e,n)},Fe=e=>{const t=!(!e||"object"!=typeof e||!("value"in e))&&e.value;return Be(e,!t)},He=(e,t)=>{const r=e&&"object"==typeof e&&"value"in e?e.value:[];if(Array.isArray(r)){const n=[...r,t];return Be(e,n)}return r},Ue=e=>{const t=e&&"object"==typeof e&&"value"in e?e.value:[];if(Array.isArray(t)&&t.length>0){const r=t.slice(0,-1);Be(e,r)}return t},Ge=(e,t)=>{const r={...e&&"object"==typeof e&&"value"in e?e.value:{},...t};return Be(e,r)},Ve=e=>{const t=e&&"object"==typeof e&&"value"in e?e.value:null;return Array.isArray(t)?Be(e,[]):Be(e,"object"==typeof t&&null!==t?{}:null)},Ze=(e,t={})=>{const r={...t},n={...r.headers};let i=r.body;return void 0!==i&&(null!==i&&"object"==typeof i?(i=JSON.stringify(i),n["Content-Type"]||(n["Content-Type"]="application/json")):(i=String(i),n["Content-Type"]||(n["Content-Type"]="text/plain"))),r.body=i,r.headers=n,globalThis.fetch(e,r)},Ke=globalThis.__LIGHTVIEW_INTERNALS__||(globalThis.__LIGHTVIEW_INTERNALS__={currentEffect:null,registry:new Map,dependencyMap:new WeakMap}),Ye=(e,t)=>{let r="string"==typeof t?t:null==t?void 0:t.name;const n=null==t?void 0:t.storage;if(r&&n)try{const t=n.getItem(r);null!==t&&(e=JSON.parse(t))}catch(a){}let i=e;const s=new Set,o=(...e)=>{if(0===e.length)return o.value;o.value=e[0]};if(Object.defineProperty(o,"value",{get:()=>(Ke.currentEffect&&(s.add(Ke.currentEffect),Ke.currentEffect.dependencies.add(s)),i),set(e){if(i!==e){if(i=e,r&&n)try{n.setItem(r,JSON.stringify(i))}catch(a){}[...s].forEach(e=>e())}}}),r)if(Ke.registry.has(r)){if(Ke.registry.get(r)!==o)throw new Error(`Lightview: A signal or state with the name "${r}" is already registered.`)}else Ke.registry.set(r,o);return o};Ye.get=(e,t)=>Ke.registry.has(e)||void 0===t?Ke.registry.get(e):Ye(t,e);const Qe=e=>{const t=()=>{if(t.active&&!t.running){t.dependencies.forEach(e=>e.delete(t)),t.dependencies.clear(),t.running=!0,Ke.currentEffect=t;try{e()}finally{Ke.currentEffect=null,t.running=!1}}};return t.active=!0,t.running=!1,t.dependencies=new Set,t.stop=()=>{t.dependencies.forEach(e=>e.delete(t)),t.dependencies.clear(),t.active=!1},t(),t},Xe=()=>Ke.registry,et=new WeakMap,tt=new WeakMap,rt=new WeakMap,nt=(e,t)=>Object.getOwnPropertyNames(e).filter(r=>"function"==typeof e[r]&&t(r)),it=nt(Date.prototype,e=>/^(to|get|valueOf)/.test(e)),st=nt(Date.prototype,e=>/^set/.test(e)),ot=["map","forEach","filter","find","findIndex","some","every","reduce","reduceRight","includes","indexOf","lastIndexOf","join","slice","concat","flat","flatMap","at","entries","keys","values"],at=["push","pop","shift","unshift","splice","sort","reverse","fill","copyWithin"],lt=["map","forEach","filter","find","findIndex","some","every","flatMap"],ut=(e,t,r)=>{let n=e.get(t);return n||(n=r(),e.set(t,n)),n},ct=(e,t,r,n)=>{if("__parent__"===t)return rt.get(r);n.has(t)||n.set(t,Ye(Reflect.get(e,t,r)));const i=n.get(t).value;if("object"==typeof i&&null!==i){const e=pt(i);return rt.set(e,r),e}return i},ft=(e,t,r,n,i)=>{i.has(t)||i.set(t,Ye(Reflect.get(e,t,n)));const s=Reflect.set(e,t,r,n),o=i.get(t);return s&&o&&(o.value=r),s},ht=(e,t,r=[])=>{const n=ut(tt,e,()=>new Map);if(!n.has(t)){const r="function"==typeof e[t]?e[t].call(e):e[t];n.set(t,Ye(r))}const i=e instanceof Date,s=Array.isArray(e),o=i?it:s?ot:r,a=i?st:s?at:[];return new Proxy(e,{get(e,r,i){if("__parent__"===r)return rt.get(i);const l=e[r];if("function"==typeof l){const u=o.includes(r),c=a.includes(r);return function(...o){if(u){const e=n.get(t);e&&e.value}const a="function"==typeof e[t]?e[t].call(e):e[t];if(s&<.includes(r)&&"function"==typeof o[0]){const e=o[0];o[0]=function(t,r,n){const s="object"==typeof t&&null!==t?pt(t):t;return s&&"object"==typeof s&&rt.set(s,i),e.call(this,s,r,n)}}const f=l.apply(e,o),h="function"==typeof e[t]?e[t].call(e):e[t];if(a!==h||c){const e=n.get(t);e&&e.value!==h&&(e.value=h)}return f}}if(r===t){const s=n.get(t);return s?s.value:Reflect.get(e,r,i)}if(s&&!isNaN(parseInt(r))){const e=n.get(t);e&&e.value}return ct(e,r,i,n)},set(e,r,i,s){if(r===t){const o=Reflect.set(e,r,i,s);if(o){const e=n.get(t);e&&(e.value=i)}return o}return ft(e,r,i,s,n)}})},pt=(e,t)=>{if("object"!=typeof e||null===e)return e;const r="string"==typeof t?t:null==t?void 0:t.name,n=null==t?void 0:t.storage;if(r&&n)try{const t=n.getItem(r);if(t){const r=JSON.parse(t);Array.isArray(e)&&Array.isArray(r)?(e.length=0,e.push(...r)):Object.assign(e,r)}}catch(s){}let i=et.get(e);if(!i){const t=Array.isArray(e),r=e instanceof Date,n=t||r;if(!n&&(e instanceof RegExp||e instanceof Map||e instanceof Set||e instanceof WeakMap||e instanceof WeakSet))return e;i=n?ht(e,t?"length":r?"getTime":null):new Proxy(e,{get:(e,t,r)=>"__parent__"===t?rt.get(r):ct(e,t,r,ut(tt,e,()=>new Map)),set:(e,t,r,n)=>ft(e,t,r,n,ut(tt,e,()=>new Map))}),et.set(e,i)}if(r&&n&&Qe(()=>{try{n.setItem(r,JSON.stringify(i))}catch(s){}}),r){const e=Xe();if(e.has(r)){if(e.get(r)!==i)throw new Error(`Lightview: A signal or state with the name "${r}" is already registered.`)}else e.set(r,i)}return i};var gt;pt.get=(e,t)=>{const r=Xe();return r.has(e)||void 0===t?r.get(e):pt(t,e)},(gt=n)("+",y),gt("add",y),gt("-",v),gt("sub",v),gt("*",m),gt("mul",m),gt("/",b),gt("div",b),gt("round",w),gt("ceil",A),gt("floor",_),gt("abs",N),gt("mod",W),gt("pow",M),gt("sqrt",S),(e=>{e("if",j),e("and",L),e("&&",L),e("or",$),e("||",$),e("not",E),e("!",E),e("eq",D),e("==",D),e("===",D),e("neq",x)})(n),(e=>{e("join",O),e("concat",T),e("upper",C),e("lower",k),e("trim",I),e("len",z),e("replace",P),e("split",R),e("capitalize",B),e("titleCase",q),e("contains",J),e("startsWith",F),e("endsWith",H),e("default",U)})(n),(e=>{e("count",G),e("filter",V),e("map",Z),e("find",K),e("unique",Y),e("sort",Q),e("reverse",X),e("first",ee),e("last",te),e("slice",re),e("flatten",ne),e("join",ie),e("len",se),e("length",se)})(n),(e=>{e("gt",oe),e(">",oe),e("lt",ae),e("<",ae),e("gte",le),e(">=",le),e("lte",ue),e("<=",ue),e("neq",ce),e("!=",ce),e("between",fe),e("in",he)})(n),(e=>{e("sumIf",pe),e("countIf",ge),e("avgIf",de)})(n),(e=>{e("now",ye),e("today",ve),e("date",me),e("formatDate",be),e("year",we),e("month",Ae),e("day",_e),e("weekday",Ne),e("addDays",We),e("dateDiff",Me)})(n),(e=>{e("number",Se),e("currency",je),e("percent",Le),e("thousands",$e)})(n),(e=>{e("lookup",Ee),e("vlookup",De),e("index",xe),e("match",Oe)})(n),(e=>{e("sum",Te),e("avg",Ce),e("min",ke),e("max",Ie),e("median",ze),e("stdev",Pe),e("var",Re)})(n),(e=>{const t={pathAware:!0};e("set",Be,t),e("increment",qe,t),e("++",qe,t),e("decrement",Je,t),e("--",Je,t),e("toggle",Fe,t),e("!!",Fe,t),e("push",He,t),e("pop",Ue,t),e("assign",Ge,t),e("clear",Ve,t)})((e,t)=>n(e,t,{pathAware:!0})),(e=>{e("fetch",Ze)})(n);const dt=new WeakMap,yt=(e,t=null)=>{const r=[];let n=e;const i=globalThis.ShadowRoot;for(;n;){const e=dt.get(n);e&&r.unshift(e),n=n.parentElement||(i&&n.parentNode instanceof i?n.parentNode.host:null)}const s=Xe();return new Proxy({},{get(e,n,i){var o;if("$event"===n||"event"===n)return t;if("__parent__"===n)return;for(let t=r.length-1;t>=0;t--){const e=r[t];if(n in e)return e[n]}if(s&&s.has(n))return s.get(n);const a=null==(o=globalThis.Lightview)?void 0:o.state;return a&&n in a?a[n]:void 0},set(e,t,n,i){var s;for(let a=r.length-1;a>=0;a--){const e=r[a];if(t in e)return e[t]=n,!0}if(r.length>0)return r[r.length-1][t]=n,!0;const o=null==(s=globalThis.Lightview)?void 0:s.state;return!!o&&(o[t]=n,!0)},has(e,n){var i;if("$event"===n||"event"===n)return!!t;for(const t of r)if(n in t)return!0;const s=null==(i=globalThis.Lightview)?void 0:i.state;return!(!s||!(n in s))},ownKeys(e){var n;const i=new Set;t&&(i.add("$event"),i.add("event"));for(const t of r)for(const e in t)i.add(e);const s=null==(n=globalThis.Lightview)?void 0:n.state;if(s)for(const t in s)i.add(t);return Array.from(i)},getOwnPropertyDescriptor:(e,t)=>({enumerable:!0,configurable:!0})})},vt=e=>{var t;const r=e.getAttribute("cdom-state");if(r&&!dt.has(e))try{const t=JSON.parse(r),n=pt(t);dt.set(e,n)}catch(n){null==(t=globalThis.console)||t.error("LightviewCDOM: Failed to parse cdom-state",n)}},mt=e=>{const t=e.getAttribute("cdom-bind");if(!t)return;const r=e.type||"",n=e.tagName.toLowerCase();let i="value",s="input";"checkbox"===r||"radio"===r?(i="checked",s="change"):"select"===n&&(s="change");const o=yt(e);let l=f(t,o);if(l&&l.isBindingTarget&&void 0===l.value){const r=e[i];void 0!==r&&""!==r&&(Be(o,{[l.key]:r}),l=f(t,o))}Qe(()=>{const t=a(l);e[i]!==t&&(e[i]=void 0===t?"":t)}),e.addEventListener(s,()=>{const r=e[i];l&&l.isBindingTarget?l.value=r:Be(o,{[t]:r})})},bt=e=>{Array.from(e.attributes).forEach(t=>{if(t.name.startsWith("cdom-on:")){const r=t.name.slice(8),n=t.value;e.addEventListener(r,t=>{const r=yt(e,t),i=g(n,r);i&&"object"==typeof i&&i.isLazy&&"function"==typeof i.resolve&&i.resolve(t)})}})},wt=(e=document.body)=>{const t=e=>{1===e.nodeType&&(e.hasAttribute("cdom-state")&&vt(e),e.hasAttribute("cdom-bind")&&mt(e),bt(e));let r=e.firstChild;for(;r;)t(r),r=r.nextSibling};t(e)},At=(e,t=null)=>{if(!e)return e;if("string"==typeof e&&e.startsWith("$"))return d(e,t);if(Array.isArray(e))return e.map(e=>At(e,t));if(e instanceof String)return e.toString();if("object"==typeof e&&null!==e){t&&!("__parent__"in e)&&Object.defineProperty(e,"__parent__",{value:t,enumerable:!1,writable:!0,configurable:!0});for(const t in e)e[t]=At(e[t],e);return e}return e},_t={registerHelper:n,parseExpression:d,resolvePath:c,resolvePathAsContext:f,resolveExpression:g,parseCDOMC:e=>{let t=0;const r=e.length,n=()=>{for(;t<r;){const n=e[t];if(!/\s/.test(n)){if("/"===n){const n=e[t+1];if("/"===n){for(t+=2;t<r&&"\n"!==e[t]&&"\r"!==e[t];)t++;continue}if("*"===n){for(t+=2;t<r;){if("*"===e[t]&&"/"===e[t+1]){t+=2;break}t++}continue}}break}t++}},i=()=>{const n=e[t++];let i="";for(;t<r;){const r=e[t++];if(r===n)return new String(i);if("\\"===r){const r=e[t++];i+="n"===r?"\n":"t"===r?"\t":'"'===r?'"':"'"===r?"'":"\\"===r?"\\":r}else i+=r}throw new Error("Unterminated string")},s=()=>{const n=t;let i=0;for(;t<r;){const r=e[t];if(i>0)")"===r?i--:"("===r&&i++,t++;else{if(/[\s:,{}\[\]"'`()]/.test(r)){if("("===r){i++,t++;continue}break}t++}}const s=e.slice(n,t);return"true"===s||"false"!==s&&("null"===s?null:""===s.trim()||isNaN(Number(s))?s:Number(s))},o=()=>{if(n(),t>=r)return;const o=e[t];return"{"===o?a():"["===o?l():'"'===o||"'"===o?i():s()},a=()=>{t++;const a={};if(n(),t<r&&"}"===e[t])return t++,a;for(;t<r;){let r;if(n(),r='"'===e[t]||"'"===e[t]?i():s(),n(),":"!==e[t])throw new Error(`Expected ':' at position ${t}, found '${e[t]}'`);t++;const l=o();if(a[String(r)]=l,n(),"}"===e[t])return t++,a;if(","!==e[t])throw new Error(`Expected '}' or ',' at position ${t}, found '${e[t]}'`);if(t++,n(),"}"===e[t])return t++,a}},l=()=>{t++;const i=[];if(n(),t<r&&"]"===e[t])return t++,i;for(;t<r;){const r=o();if(i.push(r),n(),"]"===e[t])return t++,i;if(","!==e[t])throw new Error(`Expected ']' or ',' at position ${t}, found '${e[t]}'`);if(t++,n(),"]"===e[t])return t++,i}};n();return o()},unwrapSignal:a,getContext:yt,handleCDOMState:vt,handleCDOMBind:mt,handleCDOMOn:bt,activate:wt,hydrate:At,version:"1.0.0"};return"undefined"!=typeof window&&(globalThis.LightviewCDOM=_t),e.activate=wt,e.default=_t,e.getContext=yt,e.handleCDOMBind=mt,e.handleCDOMOn=bt,e.handleCDOMState=vt,e.hydrate=At,Object.defineProperties(e,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}}),e}({});
|
|
1
|
+
var LightviewCDOM = function(exports) {
|
|
2
|
+
"use strict";
|
|
3
|
+
const helpers = /* @__PURE__ */ new Map();
|
|
4
|
+
const helperOptions = /* @__PURE__ */ new Map();
|
|
5
|
+
const operators = {
|
|
6
|
+
prefix: /* @__PURE__ */ new Map(),
|
|
7
|
+
// e.g., '++' -> { helper: 'increment', precedence: 70 }
|
|
8
|
+
postfix: /* @__PURE__ */ new Map(),
|
|
9
|
+
// e.g., '++' -> { helper: 'increment', precedence: 70 }
|
|
10
|
+
infix: /* @__PURE__ */ new Map()
|
|
11
|
+
// e.g., '+' -> { helper: 'add', precedence: 50 }
|
|
12
|
+
};
|
|
13
|
+
const DEFAULT_PRECEDENCE = {
|
|
14
|
+
prefix: 80,
|
|
15
|
+
postfix: 80,
|
|
16
|
+
infix: 50
|
|
17
|
+
};
|
|
18
|
+
const registerHelper = (name, fn, options = {}) => {
|
|
19
|
+
helpers.set(name, fn);
|
|
20
|
+
if (options) helperOptions.set(name, options);
|
|
21
|
+
};
|
|
22
|
+
const registerOperator = (helperName, symbol, position, precedence) => {
|
|
23
|
+
var _a;
|
|
24
|
+
if (!["prefix", "postfix", "infix"].includes(position)) {
|
|
25
|
+
throw new Error(`Invalid operator position: ${position}. Must be 'prefix', 'postfix', or 'infix'.`);
|
|
26
|
+
}
|
|
27
|
+
if (!helpers.has(helperName)) {
|
|
28
|
+
(_a = globalThis.console) == null ? void 0 : _a.warn(`LightviewCDOM: Operator "${symbol}" registered for helper "${helperName}" which is not yet registered.`);
|
|
29
|
+
}
|
|
30
|
+
const prec = precedence ?? DEFAULT_PRECEDENCE[position];
|
|
31
|
+
operators[position].set(symbol, { helper: helperName, precedence: prec });
|
|
32
|
+
};
|
|
33
|
+
const getLV = () => globalThis.Lightview || null;
|
|
34
|
+
const getRegistry$1 = () => {
|
|
35
|
+
var _a;
|
|
36
|
+
return ((_a = getLV()) == null ? void 0 : _a.registry) || null;
|
|
37
|
+
};
|
|
38
|
+
class BindingTarget {
|
|
39
|
+
constructor(parent, key) {
|
|
40
|
+
this.parent = parent;
|
|
41
|
+
this.key = key;
|
|
42
|
+
this.isBindingTarget = true;
|
|
43
|
+
}
|
|
44
|
+
get value() {
|
|
45
|
+
return this.parent[this.key];
|
|
46
|
+
}
|
|
47
|
+
set value(v) {
|
|
48
|
+
this.parent[this.key] = v;
|
|
49
|
+
}
|
|
50
|
+
get __parent__() {
|
|
51
|
+
return this.parent;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const unwrapSignal = (val) => {
|
|
55
|
+
if (val && typeof val === "function" && "value" in val) {
|
|
56
|
+
return val.value;
|
|
57
|
+
}
|
|
58
|
+
if (val && typeof val === "object" && !(globalThis.Node && val instanceof globalThis.Node) && "value" in val) {
|
|
59
|
+
return val.value;
|
|
60
|
+
}
|
|
61
|
+
return val;
|
|
62
|
+
};
|
|
63
|
+
const traverse = (root, segments) => {
|
|
64
|
+
let current = root;
|
|
65
|
+
for (const segment of segments) {
|
|
66
|
+
if (!segment) continue;
|
|
67
|
+
current = unwrapSignal(current);
|
|
68
|
+
if (current == null) return void 0;
|
|
69
|
+
const key = segment.startsWith("[") ? segment.slice(1, -1) : segment;
|
|
70
|
+
current = current[key];
|
|
71
|
+
}
|
|
72
|
+
return unwrapSignal(current);
|
|
73
|
+
};
|
|
74
|
+
const traverseAsContext = (root, segments) => {
|
|
75
|
+
let current = root;
|
|
76
|
+
for (let i = 0; i < segments.length; i++) {
|
|
77
|
+
const segment = segments[i];
|
|
78
|
+
if (!segment) continue;
|
|
79
|
+
const key = segment.startsWith("[") ? segment.slice(1, -1) : segment;
|
|
80
|
+
const unwrapped = unwrapSignal(current);
|
|
81
|
+
if (unwrapped == null) return void 0;
|
|
82
|
+
if (i === segments.length - 1) {
|
|
83
|
+
return new BindingTarget(unwrapped, key);
|
|
84
|
+
}
|
|
85
|
+
current = unwrapped[key];
|
|
86
|
+
}
|
|
87
|
+
return current;
|
|
88
|
+
};
|
|
89
|
+
const resolvePath = (path, context) => {
|
|
90
|
+
if (typeof path !== "string") return path;
|
|
91
|
+
const registry = getRegistry$1();
|
|
92
|
+
if (path === ".") return unwrapSignal(context);
|
|
93
|
+
if (path.startsWith("$/")) {
|
|
94
|
+
const [rootName, ...rest] = path.slice(2).split("/");
|
|
95
|
+
let cur = context;
|
|
96
|
+
while (cur) {
|
|
97
|
+
const localState = cur.__state__;
|
|
98
|
+
if (localState && rootName in localState) {
|
|
99
|
+
return traverse(localState[rootName], rest);
|
|
100
|
+
}
|
|
101
|
+
cur = cur.__parent__;
|
|
102
|
+
}
|
|
103
|
+
const rootSignal = registry == null ? void 0 : registry.get(rootName);
|
|
104
|
+
if (!rootSignal) return void 0;
|
|
105
|
+
return traverse(rootSignal, rest);
|
|
106
|
+
}
|
|
107
|
+
if (path.startsWith("./")) {
|
|
108
|
+
return traverse(context, path.slice(2).split("/"));
|
|
109
|
+
}
|
|
110
|
+
if (path.startsWith("../")) {
|
|
111
|
+
return traverse(context == null ? void 0 : context.__parent__, path.slice(3).split("/"));
|
|
112
|
+
}
|
|
113
|
+
if (path.includes("/") || path.includes(".")) {
|
|
114
|
+
return traverse(context, path.split(/[\/.]/));
|
|
115
|
+
}
|
|
116
|
+
const unwrappedContext = unwrapSignal(context);
|
|
117
|
+
if (unwrappedContext && typeof unwrappedContext === "object") {
|
|
118
|
+
if (path in unwrappedContext || unwrappedContext[path] !== void 0) {
|
|
119
|
+
return traverse(unwrappedContext, [path]);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return path;
|
|
123
|
+
};
|
|
124
|
+
const resolvePathAsContext = (path, context) => {
|
|
125
|
+
if (typeof path !== "string") return path;
|
|
126
|
+
const registry = getRegistry$1();
|
|
127
|
+
if (path === ".") return context;
|
|
128
|
+
if (path.startsWith("$/")) {
|
|
129
|
+
const segments = path.slice(2).split(/[/.]/);
|
|
130
|
+
const rootName = segments.shift();
|
|
131
|
+
let cur = context;
|
|
132
|
+
while (cur) {
|
|
133
|
+
const localState = cur.__state__;
|
|
134
|
+
if (localState && rootName in localState) {
|
|
135
|
+
return traverseAsContext(localState[rootName], segments);
|
|
136
|
+
}
|
|
137
|
+
cur = cur.__parent__;
|
|
138
|
+
}
|
|
139
|
+
const rootSignal = registry == null ? void 0 : registry.get(rootName);
|
|
140
|
+
if (!rootSignal) return void 0;
|
|
141
|
+
return traverseAsContext(rootSignal, segments);
|
|
142
|
+
}
|
|
143
|
+
if (path.startsWith("./")) {
|
|
144
|
+
return traverseAsContext(context, path.slice(2).split(/[\/.]/));
|
|
145
|
+
}
|
|
146
|
+
if (path.startsWith("../")) {
|
|
147
|
+
return traverseAsContext(context == null ? void 0 : context.__parent__, path.slice(3).split(/[\/.]/));
|
|
148
|
+
}
|
|
149
|
+
if (path.includes("/") || path.includes(".")) {
|
|
150
|
+
return traverseAsContext(context, path.split(/[\/.]/));
|
|
151
|
+
}
|
|
152
|
+
const unwrappedContext = unwrapSignal(context);
|
|
153
|
+
if (unwrappedContext && typeof unwrappedContext === "object") {
|
|
154
|
+
if (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(path)) {
|
|
155
|
+
return new BindingTarget(unwrappedContext, path);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return path;
|
|
159
|
+
};
|
|
160
|
+
class LazyValue {
|
|
161
|
+
constructor(fn) {
|
|
162
|
+
this.fn = fn;
|
|
163
|
+
this.isLazy = true;
|
|
164
|
+
}
|
|
165
|
+
resolve(context) {
|
|
166
|
+
return this.fn(context);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
const resolveArgument = (arg, context, globalMode = false) => {
|
|
170
|
+
if (arg.startsWith("'") && arg.endsWith("'") || arg.startsWith('"') && arg.endsWith('"')) {
|
|
171
|
+
return { value: arg.slice(1, -1), isLiteral: true };
|
|
172
|
+
}
|
|
173
|
+
if (arg !== "" && !isNaN(Number(arg))) {
|
|
174
|
+
return { value: Number(arg), isLiteral: true };
|
|
175
|
+
}
|
|
176
|
+
if (arg === "true") return { value: true, isLiteral: true };
|
|
177
|
+
if (arg === "false") return { value: false, isLiteral: true };
|
|
178
|
+
if (arg === "null") return { value: null, isLiteral: true };
|
|
179
|
+
if (arg === "_" || arg.startsWith("_/") || arg.startsWith("_.")) {
|
|
180
|
+
return {
|
|
181
|
+
value: new LazyValue((item) => {
|
|
182
|
+
if (arg === "_") return item;
|
|
183
|
+
const path = arg.startsWith("_.") ? arg.slice(2) : arg.slice(2);
|
|
184
|
+
return resolvePath(path, item);
|
|
185
|
+
}),
|
|
186
|
+
isLazy: true
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
if (arg === "$event" || arg.startsWith("$event/") || arg.startsWith("$event.")) {
|
|
190
|
+
return {
|
|
191
|
+
value: new LazyValue((event) => {
|
|
192
|
+
if (arg === "$event") return event;
|
|
193
|
+
const path = arg.startsWith("$event.") ? arg.slice(7) : arg.slice(7);
|
|
194
|
+
return resolvePath(path, event);
|
|
195
|
+
}),
|
|
196
|
+
isLazy: true
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
if (arg.startsWith("{") || arg.startsWith("[")) {
|
|
200
|
+
try {
|
|
201
|
+
const data = parseJPRX(arg);
|
|
202
|
+
const resolveTemplate = (node, context2) => {
|
|
203
|
+
if (typeof node === "string") {
|
|
204
|
+
if (node.startsWith("$")) {
|
|
205
|
+
const res = resolveExpression(node, context2);
|
|
206
|
+
const final = res instanceof LazyValue ? res.resolve(context2) : res;
|
|
207
|
+
return unwrapSignal(final);
|
|
208
|
+
}
|
|
209
|
+
if (node === "_" || node.startsWith("_/") || node.startsWith("_.")) {
|
|
210
|
+
const path = node.startsWith("_.") || node.startsWith("_/") ? node.slice(2) : node.slice(2);
|
|
211
|
+
const res = node === "_" ? context2 : resolvePath(path, context2);
|
|
212
|
+
return unwrapSignal(res);
|
|
213
|
+
}
|
|
214
|
+
if (node.startsWith("../")) return unwrapSignal(resolvePath(node, context2));
|
|
215
|
+
}
|
|
216
|
+
if (Array.isArray(node)) return node.map((n) => resolveTemplate(n, context2));
|
|
217
|
+
if (node && typeof node === "object") {
|
|
218
|
+
const res = {};
|
|
219
|
+
for (const k in node) res[k] = resolveTemplate(node[k], context2);
|
|
220
|
+
return res;
|
|
221
|
+
}
|
|
222
|
+
return node;
|
|
223
|
+
};
|
|
224
|
+
const hasReactive = (obj) => {
|
|
225
|
+
if (typeof obj === "string") {
|
|
226
|
+
return obj.startsWith("$") || obj.startsWith("_") || obj.startsWith("../");
|
|
227
|
+
}
|
|
228
|
+
if (Array.isArray(obj)) return obj.some(hasReactive);
|
|
229
|
+
if (obj && typeof obj === "object") return Object.values(obj).some(hasReactive);
|
|
230
|
+
return false;
|
|
231
|
+
};
|
|
232
|
+
if (hasReactive(data)) {
|
|
233
|
+
return {
|
|
234
|
+
value: new LazyValue((context2) => resolveTemplate(data, context2)),
|
|
235
|
+
isLazy: true
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
return { value: data, isLiteral: true };
|
|
239
|
+
} catch (e) {
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
if (arg.includes("(")) {
|
|
243
|
+
let nestedExpr = arg;
|
|
244
|
+
if (arg.startsWith("/")) {
|
|
245
|
+
nestedExpr = "$" + arg;
|
|
246
|
+
} else if (globalMode && !arg.startsWith("$") && !arg.startsWith("./")) {
|
|
247
|
+
nestedExpr = `$/${arg}`;
|
|
248
|
+
}
|
|
249
|
+
const val = resolveExpression(nestedExpr, context);
|
|
250
|
+
if (val instanceof LazyValue) {
|
|
251
|
+
return { value: val, isLazy: true };
|
|
252
|
+
}
|
|
253
|
+
return { value: val, isSignal: false };
|
|
254
|
+
}
|
|
255
|
+
let normalizedPath;
|
|
256
|
+
if (arg.startsWith("/")) {
|
|
257
|
+
normalizedPath = "$" + arg;
|
|
258
|
+
} else if (arg.startsWith("$") || arg.startsWith("./") || arg.startsWith("../")) {
|
|
259
|
+
normalizedPath = arg;
|
|
260
|
+
} else if (globalMode) {
|
|
261
|
+
normalizedPath = `$/${arg}`;
|
|
262
|
+
} else {
|
|
263
|
+
normalizedPath = `./${arg}`;
|
|
264
|
+
}
|
|
265
|
+
const explosionIdx = arg.indexOf("...");
|
|
266
|
+
if (explosionIdx !== -1) {
|
|
267
|
+
const normExplosionIdx = normalizedPath.indexOf("...");
|
|
268
|
+
const pathPart = normalizedPath.slice(0, normExplosionIdx);
|
|
269
|
+
const propName = arg.slice(explosionIdx + 3);
|
|
270
|
+
const parent = resolvePath(pathPart, context);
|
|
271
|
+
const unwrappedParent = unwrapSignal(parent);
|
|
272
|
+
if (Array.isArray(unwrappedParent)) {
|
|
273
|
+
const values = unwrappedParent.map((item) => {
|
|
274
|
+
const unwrappedItem = unwrapSignal(item);
|
|
275
|
+
if (!propName) return unwrappedItem;
|
|
276
|
+
return unwrappedItem && typeof unwrappedItem === "object" ? unwrapSignal(unwrappedItem[propName]) : void 0;
|
|
277
|
+
});
|
|
278
|
+
return { value: values, isExplosion: true };
|
|
279
|
+
} else if (unwrappedParent && typeof unwrappedParent === "object") {
|
|
280
|
+
if (!propName) return { value: unwrappedParent, isExplosion: true };
|
|
281
|
+
const val = unwrappedParent[propName];
|
|
282
|
+
return { value: unwrapSignal(val), isExplosion: true };
|
|
283
|
+
}
|
|
284
|
+
return { value: void 0, isExplosion: true };
|
|
285
|
+
}
|
|
286
|
+
const value = resolvePathAsContext(normalizedPath, context);
|
|
287
|
+
return { value, isExplosion: false };
|
|
288
|
+
};
|
|
289
|
+
const TokenType = {
|
|
290
|
+
PATH: "PATH",
|
|
291
|
+
// $/user/age, ./name, ../parent
|
|
292
|
+
LITERAL: "LITERAL",
|
|
293
|
+
// 123, "hello", true, false, null
|
|
294
|
+
OPERATOR: "OPERATOR",
|
|
295
|
+
// +, -, *, /, ++, --, etc.
|
|
296
|
+
LPAREN: "LPAREN",
|
|
297
|
+
// (
|
|
298
|
+
RPAREN: "RPAREN",
|
|
299
|
+
// )
|
|
300
|
+
COMMA: "COMMA",
|
|
301
|
+
// ,
|
|
302
|
+
EXPLOSION: "EXPLOSION",
|
|
303
|
+
// ... suffix
|
|
304
|
+
PLACEHOLDER: "PLACEHOLDER",
|
|
305
|
+
// _, _/path
|
|
306
|
+
EVENT: "EVENT",
|
|
307
|
+
// $event, $event.target
|
|
308
|
+
EOF: "EOF"
|
|
309
|
+
};
|
|
310
|
+
const getOperatorSymbols = () => {
|
|
311
|
+
const allOps = /* @__PURE__ */ new Set([
|
|
312
|
+
...operators.prefix.keys(),
|
|
313
|
+
...operators.postfix.keys(),
|
|
314
|
+
...operators.infix.keys()
|
|
315
|
+
]);
|
|
316
|
+
return [...allOps].sort((a, b) => b.length - a.length);
|
|
317
|
+
};
|
|
318
|
+
const tokenize = (expr) => {
|
|
319
|
+
const tokens = [];
|
|
320
|
+
let i = 0;
|
|
321
|
+
const len2 = expr.length;
|
|
322
|
+
const opSymbols = getOperatorSymbols();
|
|
323
|
+
while (i < len2) {
|
|
324
|
+
if (/\s/.test(expr[i])) {
|
|
325
|
+
i++;
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
if (expr[i] === "$" && i + 1 < len2) {
|
|
329
|
+
let isOpAfter = false;
|
|
330
|
+
for (const op of opSymbols) {
|
|
331
|
+
if (expr.slice(i + 1, i + 1 + op.length) === op) {
|
|
332
|
+
isOpAfter = true;
|
|
333
|
+
break;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
if (isOpAfter) {
|
|
337
|
+
i++;
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
if (expr[i] === "(") {
|
|
342
|
+
tokens.push({ type: TokenType.LPAREN, value: "(" });
|
|
343
|
+
i++;
|
|
344
|
+
continue;
|
|
345
|
+
}
|
|
346
|
+
if (expr[i] === ")") {
|
|
347
|
+
tokens.push({ type: TokenType.RPAREN, value: ")" });
|
|
348
|
+
i++;
|
|
349
|
+
continue;
|
|
350
|
+
}
|
|
351
|
+
if (expr[i] === ",") {
|
|
352
|
+
tokens.push({ type: TokenType.COMMA, value: "," });
|
|
353
|
+
i++;
|
|
354
|
+
continue;
|
|
355
|
+
}
|
|
356
|
+
let matchedOp = null;
|
|
357
|
+
for (const op of opSymbols) {
|
|
358
|
+
if (expr.slice(i, i + op.length) === op) {
|
|
359
|
+
const before = i > 0 ? expr[i - 1] : " ";
|
|
360
|
+
const after = i + op.length < len2 ? expr[i + op.length] : " ";
|
|
361
|
+
const isInfix = operators.infix.has(op);
|
|
362
|
+
const isPrefix = operators.prefix.has(op);
|
|
363
|
+
const isPostfix = operators.postfix.has(op);
|
|
364
|
+
if (isInfix && !isPrefix && !isPostfix) {
|
|
365
|
+
if (/\s/.test(before) && /\s/.test(after)) {
|
|
366
|
+
matchedOp = op;
|
|
367
|
+
break;
|
|
368
|
+
}
|
|
369
|
+
continue;
|
|
370
|
+
}
|
|
371
|
+
const validBefore = /[\s)]/.test(before) || i === 0 || tokens.length === 0 || tokens[tokens.length - 1].type === TokenType.LPAREN || tokens[tokens.length - 1].type === TokenType.COMMA || tokens[tokens.length - 1].type === TokenType.OPERATOR;
|
|
372
|
+
const validAfter = /[\s($./'"0-9_]/.test(after) || i + op.length >= len2 || opSymbols.some((o) => expr.slice(i + op.length).startsWith(o));
|
|
373
|
+
if (validBefore || validAfter) {
|
|
374
|
+
matchedOp = op;
|
|
375
|
+
break;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
if (matchedOp) {
|
|
380
|
+
tokens.push({ type: TokenType.OPERATOR, value: matchedOp });
|
|
381
|
+
i += matchedOp.length;
|
|
382
|
+
continue;
|
|
383
|
+
}
|
|
384
|
+
if (expr[i] === '"' || expr[i] === "'") {
|
|
385
|
+
const quote = expr[i];
|
|
386
|
+
let str = "";
|
|
387
|
+
i++;
|
|
388
|
+
while (i < len2 && expr[i] !== quote) {
|
|
389
|
+
if (expr[i] === "\\" && i + 1 < len2) {
|
|
390
|
+
i++;
|
|
391
|
+
if (expr[i] === "n") str += "\n";
|
|
392
|
+
else if (expr[i] === "t") str += " ";
|
|
393
|
+
else str += expr[i];
|
|
394
|
+
} else {
|
|
395
|
+
str += expr[i];
|
|
396
|
+
}
|
|
397
|
+
i++;
|
|
398
|
+
}
|
|
399
|
+
i++;
|
|
400
|
+
tokens.push({ type: TokenType.LITERAL, value: str });
|
|
401
|
+
continue;
|
|
402
|
+
}
|
|
403
|
+
if (/\d/.test(expr[i]) || expr[i] === "-" && /\d/.test(expr[i + 1]) && (tokens.length === 0 || tokens[tokens.length - 1].type === TokenType.OPERATOR || tokens[tokens.length - 1].type === TokenType.LPAREN || tokens[tokens.length - 1].type === TokenType.COMMA)) {
|
|
404
|
+
let num = "";
|
|
405
|
+
if (expr[i] === "-") {
|
|
406
|
+
num = "-";
|
|
407
|
+
i++;
|
|
408
|
+
}
|
|
409
|
+
while (i < len2 && /[\d.]/.test(expr[i])) {
|
|
410
|
+
num += expr[i];
|
|
411
|
+
i++;
|
|
412
|
+
}
|
|
413
|
+
tokens.push({ type: TokenType.LITERAL, value: parseFloat(num) });
|
|
414
|
+
continue;
|
|
415
|
+
}
|
|
416
|
+
if (expr[i] === "_" && (i + 1 >= len2 || !/[a-zA-Z0-9]/.test(expr[i + 1]) || expr[i + 1] === "/" || expr[i + 1] === ".")) {
|
|
417
|
+
let placeholder = "_";
|
|
418
|
+
i++;
|
|
419
|
+
if (i < len2 && (expr[i] === "/" || expr[i] === ".")) {
|
|
420
|
+
while (i < len2 && !/[\s,)(]/.test(expr[i])) {
|
|
421
|
+
placeholder += expr[i];
|
|
422
|
+
i++;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
tokens.push({ type: TokenType.PLACEHOLDER, value: placeholder });
|
|
426
|
+
continue;
|
|
427
|
+
}
|
|
428
|
+
if (expr.slice(i, i + 6) === "$event") {
|
|
429
|
+
let eventPath = "$event";
|
|
430
|
+
i += 6;
|
|
431
|
+
while (i < len2 && /[a-zA-Z0-9_./]/.test(expr[i])) {
|
|
432
|
+
eventPath += expr[i];
|
|
433
|
+
i++;
|
|
434
|
+
}
|
|
435
|
+
tokens.push({ type: TokenType.EVENT, value: eventPath });
|
|
436
|
+
continue;
|
|
437
|
+
}
|
|
438
|
+
if (expr[i] === "$" || expr[i] === "." || expr[i] === "/") {
|
|
439
|
+
let path = "";
|
|
440
|
+
while (i < len2) {
|
|
441
|
+
let isOp = false;
|
|
442
|
+
for (const op of opSymbols) {
|
|
443
|
+
if (expr.slice(i, i + op.length) === op) {
|
|
444
|
+
const isInfix = operators.infix.has(op);
|
|
445
|
+
const isPrefix = operators.prefix.has(op);
|
|
446
|
+
const isPostfix = operators.postfix.has(op);
|
|
447
|
+
if (isInfix && !isPrefix && !isPostfix) {
|
|
448
|
+
const after = i + op.length < len2 ? expr[i + op.length] : " ";
|
|
449
|
+
if (/\s/.test(expr[i - 1]) && /\s/.test(after)) {
|
|
450
|
+
isOp = true;
|
|
451
|
+
break;
|
|
452
|
+
}
|
|
453
|
+
continue;
|
|
454
|
+
}
|
|
455
|
+
if (path.length > 0 && path[path.length - 1] !== "/") {
|
|
456
|
+
isOp = true;
|
|
457
|
+
break;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
if (isOp) break;
|
|
462
|
+
if (/[\s,()]/.test(expr[i])) break;
|
|
463
|
+
if (expr.slice(i, i + 3) === "...") {
|
|
464
|
+
break;
|
|
465
|
+
}
|
|
466
|
+
path += expr[i];
|
|
467
|
+
i++;
|
|
468
|
+
}
|
|
469
|
+
if (expr.slice(i, i + 3) === "...") {
|
|
470
|
+
tokens.push({ type: TokenType.PATH, value: path });
|
|
471
|
+
tokens.push({ type: TokenType.EXPLOSION, value: "..." });
|
|
472
|
+
i += 3;
|
|
473
|
+
} else {
|
|
474
|
+
tokens.push({ type: TokenType.PATH, value: path });
|
|
475
|
+
}
|
|
476
|
+
continue;
|
|
477
|
+
}
|
|
478
|
+
if (/[a-zA-Z]/.test(expr[i])) {
|
|
479
|
+
let ident = "";
|
|
480
|
+
while (i < len2 && /[a-zA-Z0-9_]/.test(expr[i])) {
|
|
481
|
+
ident += expr[i];
|
|
482
|
+
i++;
|
|
483
|
+
}
|
|
484
|
+
if (ident === "true") tokens.push({ type: TokenType.LITERAL, value: true });
|
|
485
|
+
else if (ident === "false") tokens.push({ type: TokenType.LITERAL, value: false });
|
|
486
|
+
else if (ident === "null") tokens.push({ type: TokenType.LITERAL, value: null });
|
|
487
|
+
else tokens.push({ type: TokenType.PATH, value: ident });
|
|
488
|
+
continue;
|
|
489
|
+
}
|
|
490
|
+
i++;
|
|
491
|
+
}
|
|
492
|
+
tokens.push({ type: TokenType.EOF, value: null });
|
|
493
|
+
return tokens;
|
|
494
|
+
};
|
|
495
|
+
const hasOperatorSyntax = (expr) => {
|
|
496
|
+
if (!expr || typeof expr !== "string") return false;
|
|
497
|
+
if (expr.includes("(")) return false;
|
|
498
|
+
if (/^\$(\+\+|--|!!)\/?/.test(expr)) {
|
|
499
|
+
return true;
|
|
500
|
+
}
|
|
501
|
+
if (/(\+\+|--)$/.test(expr)) {
|
|
502
|
+
return true;
|
|
503
|
+
}
|
|
504
|
+
if (/\s+([+\-*/]|>|<|>=|<=|!=)\s+/.test(expr)) {
|
|
505
|
+
return true;
|
|
506
|
+
}
|
|
507
|
+
return false;
|
|
508
|
+
};
|
|
509
|
+
class PrattParser {
|
|
510
|
+
constructor(tokens, context, isGlobalMode = false) {
|
|
511
|
+
this.tokens = tokens;
|
|
512
|
+
this.pos = 0;
|
|
513
|
+
this.context = context;
|
|
514
|
+
this.isGlobalMode = isGlobalMode;
|
|
515
|
+
}
|
|
516
|
+
peek() {
|
|
517
|
+
return this.tokens[this.pos] || { type: TokenType.EOF, value: null };
|
|
518
|
+
}
|
|
519
|
+
consume() {
|
|
520
|
+
return this.tokens[this.pos++];
|
|
521
|
+
}
|
|
522
|
+
expect(type) {
|
|
523
|
+
const tok = this.consume();
|
|
524
|
+
if (tok.type !== type) {
|
|
525
|
+
throw new Error(`JPRX: Expected ${type} but got ${tok.type}`);
|
|
526
|
+
}
|
|
527
|
+
return tok;
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* Get binding power (precedence) for an infix or postfix operator.
|
|
531
|
+
*/
|
|
532
|
+
getInfixPrecedence(op) {
|
|
533
|
+
const infixInfo = operators.infix.get(op);
|
|
534
|
+
if (infixInfo) return infixInfo.precedence;
|
|
535
|
+
const postfixInfo = operators.postfix.get(op);
|
|
536
|
+
if (postfixInfo) return postfixInfo.precedence;
|
|
537
|
+
return 0;
|
|
538
|
+
}
|
|
539
|
+
/**
|
|
540
|
+
* Parse an expression with given minimum precedence.
|
|
541
|
+
*/
|
|
542
|
+
parseExpression(minPrecedence = 0) {
|
|
543
|
+
let left = this.parsePrefix();
|
|
544
|
+
let tok = this.peek();
|
|
545
|
+
while (tok.type === TokenType.OPERATOR) {
|
|
546
|
+
const prec = this.getInfixPrecedence(tok.value);
|
|
547
|
+
if (prec < minPrecedence) break;
|
|
548
|
+
if (operators.postfix.has(tok.value) && !operators.infix.has(tok.value)) {
|
|
549
|
+
this.consume();
|
|
550
|
+
left = { type: "Postfix", operator: tok.value, operand: left };
|
|
551
|
+
tok = this.peek();
|
|
552
|
+
continue;
|
|
553
|
+
}
|
|
554
|
+
if (operators.infix.has(tok.value)) {
|
|
555
|
+
this.consume();
|
|
556
|
+
const right = this.parseExpression(prec + 1);
|
|
557
|
+
left = { type: "Infix", operator: tok.value, left, right };
|
|
558
|
+
tok = this.peek();
|
|
559
|
+
continue;
|
|
560
|
+
}
|
|
561
|
+
this.consume();
|
|
562
|
+
const nextTok = this.peek();
|
|
563
|
+
if (nextTok.type === TokenType.PATH || nextTok.type === TokenType.LITERAL || nextTok.type === TokenType.LPAREN || nextTok.type === TokenType.PLACEHOLDER || nextTok.type === TokenType.EVENT || nextTok.type === TokenType.OPERATOR && operators.prefix.has(nextTok.value)) {
|
|
564
|
+
const right = this.parseExpression(prec + 1);
|
|
565
|
+
left = { type: "Infix", operator: tok.value, left, right };
|
|
566
|
+
} else {
|
|
567
|
+
left = { type: "Postfix", operator: tok.value, operand: left };
|
|
568
|
+
}
|
|
569
|
+
tok = this.peek();
|
|
570
|
+
}
|
|
571
|
+
return left;
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* Parse a prefix expression (literals, paths, prefix operators, groups).
|
|
575
|
+
*/
|
|
576
|
+
parsePrefix() {
|
|
577
|
+
const tok = this.peek();
|
|
578
|
+
if (tok.type === TokenType.OPERATOR && operators.prefix.has(tok.value)) {
|
|
579
|
+
this.consume();
|
|
580
|
+
const prefixInfo = operators.prefix.get(tok.value);
|
|
581
|
+
const operand = this.parseExpression(prefixInfo.precedence);
|
|
582
|
+
return { type: "Prefix", operator: tok.value, operand };
|
|
583
|
+
}
|
|
584
|
+
if (tok.type === TokenType.LPAREN) {
|
|
585
|
+
this.consume();
|
|
586
|
+
const inner = this.parseExpression(0);
|
|
587
|
+
this.expect(TokenType.RPAREN);
|
|
588
|
+
return inner;
|
|
589
|
+
}
|
|
590
|
+
if (tok.type === TokenType.LITERAL) {
|
|
591
|
+
this.consume();
|
|
592
|
+
return { type: "Literal", value: tok.value };
|
|
593
|
+
}
|
|
594
|
+
if (tok.type === TokenType.PLACEHOLDER) {
|
|
595
|
+
this.consume();
|
|
596
|
+
return { type: "Placeholder", value: tok.value };
|
|
597
|
+
}
|
|
598
|
+
if (tok.type === TokenType.EVENT) {
|
|
599
|
+
this.consume();
|
|
600
|
+
return { type: "Event", value: tok.value };
|
|
601
|
+
}
|
|
602
|
+
if (tok.type === TokenType.PATH) {
|
|
603
|
+
this.consume();
|
|
604
|
+
const nextTok = this.peek();
|
|
605
|
+
if (nextTok.type === TokenType.EXPLOSION) {
|
|
606
|
+
this.consume();
|
|
607
|
+
return { type: "Explosion", path: tok.value };
|
|
608
|
+
}
|
|
609
|
+
return { type: "Path", value: tok.value };
|
|
610
|
+
}
|
|
611
|
+
if (tok.type === TokenType.EOF) {
|
|
612
|
+
return { type: "Literal", value: void 0 };
|
|
613
|
+
}
|
|
614
|
+
throw new Error(`JPRX: Unexpected token ${tok.type}: ${tok.value}`);
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
const evaluateAST = (ast, context, forMutation = false) => {
|
|
618
|
+
if (!ast) return void 0;
|
|
619
|
+
switch (ast.type) {
|
|
620
|
+
case "Literal":
|
|
621
|
+
return ast.value;
|
|
622
|
+
case "Path": {
|
|
623
|
+
const resolved = forMutation ? resolvePathAsContext(ast.value, context) : resolvePath(ast.value, context);
|
|
624
|
+
return forMutation ? resolved : unwrapSignal(resolved);
|
|
625
|
+
}
|
|
626
|
+
case "Placeholder": {
|
|
627
|
+
return new LazyValue((item) => {
|
|
628
|
+
if (ast.value === "_") return item;
|
|
629
|
+
const path = ast.value.startsWith("_.") ? ast.value.slice(2) : ast.value.slice(2);
|
|
630
|
+
return resolvePath(path, item);
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
case "Event": {
|
|
634
|
+
return new LazyValue((event) => {
|
|
635
|
+
if (ast.value === "$event") return event;
|
|
636
|
+
const path = ast.value.startsWith("$event.") ? ast.value.slice(7) : ast.value.slice(7);
|
|
637
|
+
return resolvePath(path, event);
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
case "Explosion": {
|
|
641
|
+
const result = resolveArgument(ast.path + "...", context, false);
|
|
642
|
+
return result.value;
|
|
643
|
+
}
|
|
644
|
+
case "Prefix": {
|
|
645
|
+
const opInfo = operators.prefix.get(ast.operator);
|
|
646
|
+
if (!opInfo) {
|
|
647
|
+
throw new Error(`JPRX: Unknown prefix operator: ${ast.operator}`);
|
|
648
|
+
}
|
|
649
|
+
const helper = helpers.get(opInfo.helper);
|
|
650
|
+
if (!helper) {
|
|
651
|
+
throw new Error(`JPRX: Helper "${opInfo.helper}" for operator "${ast.operator}" not found.`);
|
|
652
|
+
}
|
|
653
|
+
const opts = helperOptions.get(opInfo.helper) || {};
|
|
654
|
+
const operand = evaluateAST(ast.operand, context, opts.pathAware);
|
|
655
|
+
return helper(operand);
|
|
656
|
+
}
|
|
657
|
+
case "Postfix": {
|
|
658
|
+
const opInfo = operators.postfix.get(ast.operator);
|
|
659
|
+
if (!opInfo) {
|
|
660
|
+
throw new Error(`JPRX: Unknown postfix operator: ${ast.operator}`);
|
|
661
|
+
}
|
|
662
|
+
const helper = helpers.get(opInfo.helper);
|
|
663
|
+
if (!helper) {
|
|
664
|
+
throw new Error(`JPRX: Helper "${opInfo.helper}" for operator "${ast.operator}" not found.`);
|
|
665
|
+
}
|
|
666
|
+
const opts = helperOptions.get(opInfo.helper) || {};
|
|
667
|
+
const operand = evaluateAST(ast.operand, context, opts.pathAware);
|
|
668
|
+
return helper(operand);
|
|
669
|
+
}
|
|
670
|
+
case "Infix": {
|
|
671
|
+
const opInfo = operators.infix.get(ast.operator);
|
|
672
|
+
if (!opInfo) {
|
|
673
|
+
throw new Error(`JPRX: Unknown infix operator: ${ast.operator}`);
|
|
674
|
+
}
|
|
675
|
+
const helper = helpers.get(opInfo.helper);
|
|
676
|
+
if (!helper) {
|
|
677
|
+
throw new Error(`JPRX: Helper "${opInfo.helper}" for operator "${ast.operator}" not found.`);
|
|
678
|
+
}
|
|
679
|
+
const opts = helperOptions.get(opInfo.helper) || {};
|
|
680
|
+
const left = evaluateAST(ast.left, context, opts.pathAware);
|
|
681
|
+
const right = evaluateAST(ast.right, context, false);
|
|
682
|
+
return helper(unwrapSignal(left), unwrapSignal(right));
|
|
683
|
+
}
|
|
684
|
+
default:
|
|
685
|
+
throw new Error(`JPRX: Unknown AST node type: ${ast.type}`);
|
|
686
|
+
}
|
|
687
|
+
};
|
|
688
|
+
const parseWithPratt = (expr, context) => {
|
|
689
|
+
const tokens = tokenize(expr);
|
|
690
|
+
const parser = new PrattParser(tokens, context);
|
|
691
|
+
const ast = parser.parseExpression(0);
|
|
692
|
+
return evaluateAST(ast, context);
|
|
693
|
+
};
|
|
694
|
+
const resolveExpression = (expr, context) => {
|
|
695
|
+
var _a, _b;
|
|
696
|
+
if (typeof expr !== "string") return expr;
|
|
697
|
+
if (hasOperatorSyntax(expr)) {
|
|
698
|
+
try {
|
|
699
|
+
return parseWithPratt(expr, context);
|
|
700
|
+
} catch (e) {
|
|
701
|
+
(_a = globalThis.console) == null ? void 0 : _a.warn("JPRX: Pratt parser failed, falling back to legacy:", e.message);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
const funcStart = expr.indexOf("(");
|
|
705
|
+
if (funcStart !== -1 && expr.endsWith(")")) {
|
|
706
|
+
const fullPath = expr.slice(0, funcStart).trim();
|
|
707
|
+
const argsStr = expr.slice(funcStart + 1, -1);
|
|
708
|
+
const segments = fullPath.split("/");
|
|
709
|
+
let funcName = segments.pop().replace(/^\$/, "");
|
|
710
|
+
if (funcName === "" && (segments.length > 0 || fullPath === "/")) {
|
|
711
|
+
funcName = "/";
|
|
712
|
+
}
|
|
713
|
+
const navPath = segments.join("/");
|
|
714
|
+
const isGlobalExpr = expr.startsWith("$/") || expr.startsWith("$");
|
|
715
|
+
let baseContext = context;
|
|
716
|
+
if (navPath && navPath !== "$") {
|
|
717
|
+
baseContext = resolvePathAsContext(navPath, context);
|
|
718
|
+
}
|
|
719
|
+
const helper = helpers.get(funcName);
|
|
720
|
+
if (!helper) {
|
|
721
|
+
(_b = globalThis.console) == null ? void 0 : _b.warn(`LightviewCDOM: Helper "${funcName}" not found.`);
|
|
722
|
+
return expr;
|
|
723
|
+
}
|
|
724
|
+
const options = helperOptions.get(funcName) || {};
|
|
725
|
+
const argsList = [];
|
|
726
|
+
let current = "", parenDepth = 0, braceDepth = 0, bracketDepth = 0, quote = null;
|
|
727
|
+
for (let i = 0; i < argsStr.length; i++) {
|
|
728
|
+
const char = argsStr[i];
|
|
729
|
+
if (char === quote) quote = null;
|
|
730
|
+
else if (!quote && (char === "'" || char === '"')) quote = char;
|
|
731
|
+
else if (!quote && char === "(") parenDepth++;
|
|
732
|
+
else if (!quote && char === ")") parenDepth--;
|
|
733
|
+
else if (!quote && char === "{") braceDepth++;
|
|
734
|
+
else if (!quote && char === "}") braceDepth--;
|
|
735
|
+
else if (!quote && char === "[") bracketDepth++;
|
|
736
|
+
else if (!quote && char === "]") bracketDepth--;
|
|
737
|
+
else if (!quote && char === "," && parenDepth === 0 && braceDepth === 0 && bracketDepth === 0) {
|
|
738
|
+
argsList.push(current.trim());
|
|
739
|
+
current = "";
|
|
740
|
+
continue;
|
|
741
|
+
}
|
|
742
|
+
current += char;
|
|
743
|
+
}
|
|
744
|
+
if (current) argsList.push(current.trim());
|
|
745
|
+
const resolvedArgs = [];
|
|
746
|
+
let hasLazy = false;
|
|
747
|
+
for (let i = 0; i < argsList.length; i++) {
|
|
748
|
+
const arg = argsList[i];
|
|
749
|
+
const useGlobalMode = isGlobalExpr && (navPath === "$" || !navPath);
|
|
750
|
+
const res = resolveArgument(arg, baseContext, useGlobalMode);
|
|
751
|
+
if (res.isLazy) hasLazy = true;
|
|
752
|
+
const shouldUnwrap = !(options.pathAware && i === 0);
|
|
753
|
+
let val = res.value;
|
|
754
|
+
if (shouldUnwrap && !(val && val.isLazy)) {
|
|
755
|
+
val = unwrapSignal(val);
|
|
756
|
+
}
|
|
757
|
+
if (res.isExplosion && Array.isArray(val)) {
|
|
758
|
+
resolvedArgs.push(...val.map((v) => shouldUnwrap && !(v && v.isLazy) ? unwrapSignal(v) : v));
|
|
759
|
+
} else {
|
|
760
|
+
resolvedArgs.push(val);
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
if (hasLazy && !options.lazyAware) {
|
|
764
|
+
return new LazyValue((contextOverride) => {
|
|
765
|
+
const finalArgs = resolvedArgs.map((arg, i) => {
|
|
766
|
+
const shouldUnwrap = !(options.pathAware && i === 0);
|
|
767
|
+
const resolved = arg instanceof LazyValue ? arg.resolve(contextOverride) : arg;
|
|
768
|
+
return shouldUnwrap ? unwrapSignal(resolved) : resolved;
|
|
769
|
+
});
|
|
770
|
+
return helper(...finalArgs);
|
|
771
|
+
});
|
|
772
|
+
}
|
|
773
|
+
const result = helper(...resolvedArgs);
|
|
774
|
+
return unwrapSignal(result);
|
|
775
|
+
}
|
|
776
|
+
return unwrapSignal(resolvePath(expr, context));
|
|
777
|
+
};
|
|
778
|
+
const parseExpression = (expr, context) => {
|
|
779
|
+
const LV = getLV();
|
|
780
|
+
if (!LV || typeof expr !== "string") return expr;
|
|
781
|
+
return LV.computed(() => resolveExpression(expr, context));
|
|
782
|
+
};
|
|
783
|
+
const parseCDOMC = (input) => {
|
|
784
|
+
let i = 0;
|
|
785
|
+
const len2 = input.length;
|
|
786
|
+
const skipWhitespace = () => {
|
|
787
|
+
while (i < len2) {
|
|
788
|
+
const char = input[i];
|
|
789
|
+
if (/\s/.test(char)) {
|
|
790
|
+
i++;
|
|
791
|
+
continue;
|
|
792
|
+
}
|
|
793
|
+
if (char === "/") {
|
|
794
|
+
const next = input[i + 1];
|
|
795
|
+
if (next === "/") {
|
|
796
|
+
i += 2;
|
|
797
|
+
while (i < len2 && input[i] !== "\n" && input[i] !== "\r") i++;
|
|
798
|
+
continue;
|
|
799
|
+
} else if (next === "*") {
|
|
800
|
+
i += 2;
|
|
801
|
+
while (i < len2) {
|
|
802
|
+
if (input[i] === "*" && input[i + 1] === "/") {
|
|
803
|
+
i += 2;
|
|
804
|
+
break;
|
|
805
|
+
}
|
|
806
|
+
i++;
|
|
807
|
+
}
|
|
808
|
+
continue;
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
break;
|
|
812
|
+
}
|
|
813
|
+
};
|
|
814
|
+
const parseString = () => {
|
|
815
|
+
const quote = input[i++];
|
|
816
|
+
let res2 = "";
|
|
817
|
+
while (i < len2) {
|
|
818
|
+
const char = input[i++];
|
|
819
|
+
if (char === quote) return res2;
|
|
820
|
+
if (char === "\\") {
|
|
821
|
+
const next = input[i++];
|
|
822
|
+
if (next === "n") res2 += "\n";
|
|
823
|
+
else if (next === "t") res2 += " ";
|
|
824
|
+
else if (next === '"') res2 += '"';
|
|
825
|
+
else if (next === "'") res2 += "'";
|
|
826
|
+
else if (next === "\\") res2 += "\\";
|
|
827
|
+
else res2 += next;
|
|
828
|
+
} else {
|
|
829
|
+
res2 += char;
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
throw new Error("Unterminated string");
|
|
833
|
+
};
|
|
834
|
+
const parseWord = () => {
|
|
835
|
+
const start = i;
|
|
836
|
+
let pDepth = 0;
|
|
837
|
+
let bDepth = 0;
|
|
838
|
+
let brDepth = 0;
|
|
839
|
+
let quote = null;
|
|
840
|
+
while (i < len2) {
|
|
841
|
+
const char = input[i];
|
|
842
|
+
if (quote) {
|
|
843
|
+
if (char === quote) quote = null;
|
|
844
|
+
i++;
|
|
845
|
+
continue;
|
|
846
|
+
} else if (char === '"' || char === "'" || char === "`") {
|
|
847
|
+
quote = char;
|
|
848
|
+
i++;
|
|
849
|
+
continue;
|
|
850
|
+
}
|
|
851
|
+
if (char === "(") {
|
|
852
|
+
pDepth++;
|
|
853
|
+
i++;
|
|
854
|
+
continue;
|
|
855
|
+
}
|
|
856
|
+
if (char === "{") {
|
|
857
|
+
bDepth++;
|
|
858
|
+
i++;
|
|
859
|
+
continue;
|
|
860
|
+
}
|
|
861
|
+
if (char === "[") {
|
|
862
|
+
brDepth++;
|
|
863
|
+
i++;
|
|
864
|
+
continue;
|
|
865
|
+
}
|
|
866
|
+
if (char === ")") {
|
|
867
|
+
if (pDepth > 0) {
|
|
868
|
+
pDepth--;
|
|
869
|
+
i++;
|
|
870
|
+
continue;
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
if (char === "}") {
|
|
874
|
+
if (bDepth > 0) {
|
|
875
|
+
bDepth--;
|
|
876
|
+
i++;
|
|
877
|
+
continue;
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
if (char === "]") {
|
|
881
|
+
if (brDepth > 0) {
|
|
882
|
+
brDepth--;
|
|
883
|
+
i++;
|
|
884
|
+
continue;
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
if (pDepth === 0 && bDepth === 0 && brDepth === 0) {
|
|
888
|
+
if (/[\s:,{}\[\]"'`()]/.test(char)) {
|
|
889
|
+
break;
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
i++;
|
|
893
|
+
}
|
|
894
|
+
const word = input.slice(start, i);
|
|
895
|
+
if (word.startsWith("$")) {
|
|
896
|
+
return word;
|
|
897
|
+
}
|
|
898
|
+
if (word === "true") return true;
|
|
899
|
+
if (word === "false") return false;
|
|
900
|
+
if (word === "null") return null;
|
|
901
|
+
if (word.trim() !== "" && !isNaN(Number(word))) return Number(word);
|
|
902
|
+
return word;
|
|
903
|
+
};
|
|
904
|
+
const parseValue = () => {
|
|
905
|
+
skipWhitespace();
|
|
906
|
+
if (i >= len2) return void 0;
|
|
907
|
+
const char = input[i];
|
|
908
|
+
if (char === "{") return parseObject();
|
|
909
|
+
if (char === "[") return parseArray();
|
|
910
|
+
if (char === '"' || char === "'") return parseString();
|
|
911
|
+
return parseWord();
|
|
912
|
+
};
|
|
913
|
+
const parseObject = () => {
|
|
914
|
+
i++;
|
|
915
|
+
const obj = {};
|
|
916
|
+
skipWhitespace();
|
|
917
|
+
if (i < len2 && input[i] === "}") {
|
|
918
|
+
i++;
|
|
919
|
+
return obj;
|
|
920
|
+
}
|
|
921
|
+
while (i < len2) {
|
|
922
|
+
skipWhitespace();
|
|
923
|
+
let key;
|
|
924
|
+
if (input[i] === '"' || input[i] === "'") key = parseString();
|
|
925
|
+
else key = parseWord();
|
|
926
|
+
skipWhitespace();
|
|
927
|
+
if (input[i] !== ":") throw new Error(`Expected ':' at position ${i}, found '${input[i]}'`);
|
|
928
|
+
i++;
|
|
929
|
+
const value = parseValue();
|
|
930
|
+
obj[String(key)] = value;
|
|
931
|
+
skipWhitespace();
|
|
932
|
+
if (input[i] === "}") {
|
|
933
|
+
i++;
|
|
934
|
+
return obj;
|
|
935
|
+
}
|
|
936
|
+
if (input[i] === ",") {
|
|
937
|
+
i++;
|
|
938
|
+
skipWhitespace();
|
|
939
|
+
if (input[i] === "}") {
|
|
940
|
+
i++;
|
|
941
|
+
return obj;
|
|
942
|
+
}
|
|
943
|
+
continue;
|
|
944
|
+
}
|
|
945
|
+
throw new Error(`Expected '}' or ',' at position ${i}, found '${input[i]}'`);
|
|
946
|
+
}
|
|
947
|
+
};
|
|
948
|
+
const parseArray = () => {
|
|
949
|
+
i++;
|
|
950
|
+
const arr = [];
|
|
951
|
+
skipWhitespace();
|
|
952
|
+
if (i < len2 && input[i] === "]") {
|
|
953
|
+
i++;
|
|
954
|
+
return arr;
|
|
955
|
+
}
|
|
956
|
+
while (i < len2) {
|
|
957
|
+
const val = parseValue();
|
|
958
|
+
arr.push(val);
|
|
959
|
+
skipWhitespace();
|
|
960
|
+
if (input[i] === "]") {
|
|
961
|
+
i++;
|
|
962
|
+
return arr;
|
|
963
|
+
}
|
|
964
|
+
if (input[i] === ",") {
|
|
965
|
+
i++;
|
|
966
|
+
skipWhitespace();
|
|
967
|
+
if (input[i] === "]") {
|
|
968
|
+
i++;
|
|
969
|
+
return arr;
|
|
970
|
+
}
|
|
971
|
+
continue;
|
|
972
|
+
}
|
|
973
|
+
throw new Error(`Expected ']' or ',' at position ${i}, found '${input[i]}'`);
|
|
974
|
+
}
|
|
975
|
+
};
|
|
976
|
+
skipWhitespace();
|
|
977
|
+
const res = parseValue();
|
|
978
|
+
return res;
|
|
979
|
+
};
|
|
980
|
+
const parseJPRX = (input) => {
|
|
981
|
+
var _a, _b;
|
|
982
|
+
let result = "";
|
|
983
|
+
let i = 0;
|
|
984
|
+
const len2 = input.length;
|
|
985
|
+
while (i < len2) {
|
|
986
|
+
const char = input[i];
|
|
987
|
+
if (char === "/" && input[i + 1] === "/") {
|
|
988
|
+
while (i < len2 && input[i] !== "\n") i++;
|
|
989
|
+
continue;
|
|
990
|
+
}
|
|
991
|
+
if (char === "/" && input[i + 1] === "*") {
|
|
992
|
+
i += 2;
|
|
993
|
+
while (i < len2 && !(input[i] === "*" && input[i + 1] === "/")) i++;
|
|
994
|
+
i += 2;
|
|
995
|
+
continue;
|
|
996
|
+
}
|
|
997
|
+
if (char === '"' || char === "'") {
|
|
998
|
+
const quote = char;
|
|
999
|
+
result += '"';
|
|
1000
|
+
i++;
|
|
1001
|
+
while (i < len2 && input[i] !== quote) {
|
|
1002
|
+
const c = input[i];
|
|
1003
|
+
if (c === "\\") {
|
|
1004
|
+
result += "\\";
|
|
1005
|
+
i++;
|
|
1006
|
+
if (i < len2) {
|
|
1007
|
+
const next = input[i];
|
|
1008
|
+
if (next === '"') result += '\\"';
|
|
1009
|
+
else result += next;
|
|
1010
|
+
i++;
|
|
1011
|
+
}
|
|
1012
|
+
} else if (c === '"') {
|
|
1013
|
+
result += '\\"';
|
|
1014
|
+
i++;
|
|
1015
|
+
} else if (c === "\n") {
|
|
1016
|
+
result += "\\n";
|
|
1017
|
+
i++;
|
|
1018
|
+
} else if (c === "\r") {
|
|
1019
|
+
result += "\\r";
|
|
1020
|
+
i++;
|
|
1021
|
+
} else if (c === " ") {
|
|
1022
|
+
result += "\\t";
|
|
1023
|
+
i++;
|
|
1024
|
+
} else {
|
|
1025
|
+
result += c;
|
|
1026
|
+
i++;
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
result += '"';
|
|
1030
|
+
i++;
|
|
1031
|
+
continue;
|
|
1032
|
+
}
|
|
1033
|
+
if (char === "$") {
|
|
1034
|
+
let expr = "";
|
|
1035
|
+
let parenDepth = 0;
|
|
1036
|
+
let braceDepth = 0;
|
|
1037
|
+
let bracketDepth = 0;
|
|
1038
|
+
let inExprQuote = null;
|
|
1039
|
+
while (i < len2) {
|
|
1040
|
+
const c = input[i];
|
|
1041
|
+
if (inExprQuote) {
|
|
1042
|
+
if (c === inExprQuote && input[i - 1] !== "\\") inExprQuote = null;
|
|
1043
|
+
} else if (c === '"' || c === "'") {
|
|
1044
|
+
inExprQuote = c;
|
|
1045
|
+
} else {
|
|
1046
|
+
if (parenDepth === 0 && braceDepth === 0 && bracketDepth === 0) {
|
|
1047
|
+
if (/[\s,}\]:]/.test(c) && expr.length > 1) break;
|
|
1048
|
+
}
|
|
1049
|
+
if (c === "(") parenDepth++;
|
|
1050
|
+
else if (c === ")") parenDepth--;
|
|
1051
|
+
else if (c === "{") braceDepth++;
|
|
1052
|
+
else if (c === "}") braceDepth--;
|
|
1053
|
+
else if (c === "[") bracketDepth++;
|
|
1054
|
+
else if (c === "]") bracketDepth--;
|
|
1055
|
+
}
|
|
1056
|
+
expr += c;
|
|
1057
|
+
i++;
|
|
1058
|
+
}
|
|
1059
|
+
result += JSON.stringify(expr);
|
|
1060
|
+
continue;
|
|
1061
|
+
}
|
|
1062
|
+
if (/[a-zA-Z_./]/.test(char)) {
|
|
1063
|
+
let word = "";
|
|
1064
|
+
while (i < len2 && /[a-zA-Z0-9_$/.-]/.test(input[i])) {
|
|
1065
|
+
word += input[i];
|
|
1066
|
+
i++;
|
|
1067
|
+
}
|
|
1068
|
+
let j = i;
|
|
1069
|
+
while (j < len2 && /\s/.test(input[j])) j++;
|
|
1070
|
+
if (input[j] === ":") {
|
|
1071
|
+
result += `"${word}"`;
|
|
1072
|
+
} else {
|
|
1073
|
+
if (word === "true" || word === "false" || word === "null") {
|
|
1074
|
+
result += word;
|
|
1075
|
+
} else if (!isNaN(Number(word))) {
|
|
1076
|
+
result += word;
|
|
1077
|
+
} else {
|
|
1078
|
+
result += `"${word}"`;
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
continue;
|
|
1082
|
+
}
|
|
1083
|
+
if (/[\d]/.test(char) || char === "-" && /\d/.test(input[i + 1])) {
|
|
1084
|
+
let num = "";
|
|
1085
|
+
while (i < len2 && /[\d.\-eE]/.test(input[i])) {
|
|
1086
|
+
num += input[i];
|
|
1087
|
+
i++;
|
|
1088
|
+
}
|
|
1089
|
+
result += num;
|
|
1090
|
+
continue;
|
|
1091
|
+
}
|
|
1092
|
+
result += char;
|
|
1093
|
+
i++;
|
|
1094
|
+
}
|
|
1095
|
+
try {
|
|
1096
|
+
return JSON.parse(result);
|
|
1097
|
+
} catch (e) {
|
|
1098
|
+
(_a = globalThis.console) == null ? void 0 : _a.error("parseJPRX: JSON parse failed", e);
|
|
1099
|
+
(_b = globalThis.console) == null ? void 0 : _b.error("Transformed input:", result);
|
|
1100
|
+
throw e;
|
|
1101
|
+
}
|
|
1102
|
+
};
|
|
1103
|
+
const add = (...args) => args.reduce((a, b) => Number(a) + Number(b), 0);
|
|
1104
|
+
const subtract = (a, b) => Number(a) - Number(b);
|
|
1105
|
+
const multiply = (...args) => args.reduce((a, b) => Number(a) * Number(b), 1);
|
|
1106
|
+
const divide = (a, b) => Number(a) / Number(b);
|
|
1107
|
+
const round = (val, decimals = 0) => Number(Math.round(val + "e" + decimals) + "e-" + decimals);
|
|
1108
|
+
const ceil = (val) => Math.ceil(val);
|
|
1109
|
+
const floor = (val) => Math.floor(val);
|
|
1110
|
+
const abs = (val) => Math.abs(val);
|
|
1111
|
+
const mod = (a, b) => a % b;
|
|
1112
|
+
const pow = (a, b) => Math.pow(a, b);
|
|
1113
|
+
const sqrt = (val) => Math.sqrt(val);
|
|
1114
|
+
const registerMathHelpers = (register) => {
|
|
1115
|
+
register("+", add);
|
|
1116
|
+
register("add", add);
|
|
1117
|
+
register("-", subtract);
|
|
1118
|
+
register("sub", subtract);
|
|
1119
|
+
register("*", multiply);
|
|
1120
|
+
register("mul", multiply);
|
|
1121
|
+
register("/", divide);
|
|
1122
|
+
register("div", divide);
|
|
1123
|
+
register("round", round);
|
|
1124
|
+
register("ceil", ceil);
|
|
1125
|
+
register("floor", floor);
|
|
1126
|
+
register("abs", abs);
|
|
1127
|
+
register("mod", mod);
|
|
1128
|
+
register("pow", pow);
|
|
1129
|
+
register("sqrt", sqrt);
|
|
1130
|
+
};
|
|
1131
|
+
const ifHelper = (condition, thenVal, elseVal) => condition ? thenVal : elseVal;
|
|
1132
|
+
const andHelper = (...args) => args.every(Boolean);
|
|
1133
|
+
const orHelper = (...args) => args.some(Boolean);
|
|
1134
|
+
const notHelper = (val) => !val;
|
|
1135
|
+
const eqHelper = (a, b) => a === b;
|
|
1136
|
+
const neqHelper = (a, b) => a !== b;
|
|
1137
|
+
const registerLogicHelpers = (register) => {
|
|
1138
|
+
register("if", ifHelper);
|
|
1139
|
+
register("and", andHelper);
|
|
1140
|
+
register("&&", andHelper);
|
|
1141
|
+
register("or", orHelper);
|
|
1142
|
+
register("||", orHelper);
|
|
1143
|
+
register("not", notHelper);
|
|
1144
|
+
register("!", notHelper);
|
|
1145
|
+
register("eq", eqHelper);
|
|
1146
|
+
register("==", eqHelper);
|
|
1147
|
+
register("===", eqHelper);
|
|
1148
|
+
register("neq", neqHelper);
|
|
1149
|
+
};
|
|
1150
|
+
const join$1 = (...args) => {
|
|
1151
|
+
const separator = args[args.length - 1];
|
|
1152
|
+
const items = args.slice(0, -1);
|
|
1153
|
+
return items.join(separator);
|
|
1154
|
+
};
|
|
1155
|
+
const concat = (...args) => args.join("");
|
|
1156
|
+
const upper = (s) => String(s).toUpperCase();
|
|
1157
|
+
const lower = (s) => String(s).toLowerCase();
|
|
1158
|
+
const trim = (s) => String(s).trim();
|
|
1159
|
+
const len = (s) => String(s).length;
|
|
1160
|
+
const replace = (s, search, replacement) => String(s).replace(search, replacement);
|
|
1161
|
+
const split = (s, separator) => String(s).split(separator);
|
|
1162
|
+
const capitalize = (s) => {
|
|
1163
|
+
const str = String(s);
|
|
1164
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
1165
|
+
};
|
|
1166
|
+
const titleCase = (s) => {
|
|
1167
|
+
return String(s).toLowerCase().split(" ").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
1168
|
+
};
|
|
1169
|
+
const contains$1 = (s, search) => String(s).includes(search);
|
|
1170
|
+
const startsWith = (s, prefix) => String(s).startsWith(prefix);
|
|
1171
|
+
const endsWith = (s, suffix) => String(s).endsWith(suffix);
|
|
1172
|
+
const defaultHelper = (val, fallback) => val !== void 0 && val !== null ? val : fallback;
|
|
1173
|
+
const registerStringHelpers = (register) => {
|
|
1174
|
+
register("join", join$1);
|
|
1175
|
+
register("concat", concat);
|
|
1176
|
+
register("upper", upper);
|
|
1177
|
+
register("lower", lower);
|
|
1178
|
+
register("trim", trim);
|
|
1179
|
+
register("len", len);
|
|
1180
|
+
register("replace", replace);
|
|
1181
|
+
register("split", split);
|
|
1182
|
+
register("capitalize", capitalize);
|
|
1183
|
+
register("titleCase", titleCase);
|
|
1184
|
+
register("contains", contains$1);
|
|
1185
|
+
register("startsWith", startsWith);
|
|
1186
|
+
register("endsWith", endsWith);
|
|
1187
|
+
register("default", defaultHelper);
|
|
1188
|
+
};
|
|
1189
|
+
const count = (...args) => args.length;
|
|
1190
|
+
const filter = (arr, predicate) => {
|
|
1191
|
+
if (!Array.isArray(arr)) return [];
|
|
1192
|
+
if (typeof predicate === "function" && predicate.isLazy) {
|
|
1193
|
+
return arr.filter((item) => predicate.resolve(item));
|
|
1194
|
+
}
|
|
1195
|
+
return arr.filter((item) => !!item);
|
|
1196
|
+
};
|
|
1197
|
+
const map = (arr, transform) => {
|
|
1198
|
+
if (!Array.isArray(arr)) return [];
|
|
1199
|
+
if (typeof transform === "string") {
|
|
1200
|
+
return arr.map((item) => item && typeof item === "object" ? item[transform] : item);
|
|
1201
|
+
}
|
|
1202
|
+
if (transform && transform.isLazy && typeof transform.resolve === "function") {
|
|
1203
|
+
return arr.map((item) => transform.resolve(item));
|
|
1204
|
+
}
|
|
1205
|
+
if (typeof transform === "function") {
|
|
1206
|
+
return arr.map(transform);
|
|
1207
|
+
}
|
|
1208
|
+
return arr;
|
|
1209
|
+
};
|
|
1210
|
+
const find = (arr, predicate) => {
|
|
1211
|
+
if (!Array.isArray(arr)) return void 0;
|
|
1212
|
+
if (predicate && predicate.isLazy) {
|
|
1213
|
+
return arr.find((item) => predicate.resolve(item));
|
|
1214
|
+
}
|
|
1215
|
+
return arr.find((item) => !!item);
|
|
1216
|
+
};
|
|
1217
|
+
const unique = (arr) => Array.isArray(arr) ? [...new Set(arr)] : [];
|
|
1218
|
+
const sort = (arr, order = "asc") => {
|
|
1219
|
+
if (!Array.isArray(arr)) return [];
|
|
1220
|
+
const sorted = [...arr];
|
|
1221
|
+
sorted.sort((a, b) => {
|
|
1222
|
+
if (a < b) return order === "asc" ? -1 : 1;
|
|
1223
|
+
if (a > b) return order === "asc" ? 1 : -1;
|
|
1224
|
+
return 0;
|
|
1225
|
+
});
|
|
1226
|
+
return sorted;
|
|
1227
|
+
};
|
|
1228
|
+
const reverse = (arr) => Array.isArray(arr) ? [...arr].reverse() : [];
|
|
1229
|
+
const first = (arr) => Array.isArray(arr) ? arr[0] : void 0;
|
|
1230
|
+
const last = (arr) => Array.isArray(arr) ? arr[arr.length - 1] : void 0;
|
|
1231
|
+
const slice = (arr, start, end) => Array.isArray(arr) ? arr.slice(start, end) : [];
|
|
1232
|
+
const flatten = (arr) => Array.isArray(arr) ? arr.flat(Infinity) : [];
|
|
1233
|
+
const join = (arr, sep = ",") => Array.isArray(arr) ? arr.join(String(sep)) : "";
|
|
1234
|
+
const length = (arg) => Array.isArray(arg) ? arg.length : arg ? String(arg).length : 0;
|
|
1235
|
+
const registerArrayHelpers = (register) => {
|
|
1236
|
+
register("count", count);
|
|
1237
|
+
register("filter", filter, { lazyAware: true });
|
|
1238
|
+
register("map", map, { lazyAware: true });
|
|
1239
|
+
register("find", find, { lazyAware: true });
|
|
1240
|
+
register("unique", unique);
|
|
1241
|
+
register("sort", sort);
|
|
1242
|
+
register("reverse", reverse);
|
|
1243
|
+
register("first", first);
|
|
1244
|
+
register("last", last);
|
|
1245
|
+
register("slice", slice);
|
|
1246
|
+
register("flatten", flatten);
|
|
1247
|
+
register("join", join);
|
|
1248
|
+
register("len", length);
|
|
1249
|
+
register("length", length);
|
|
1250
|
+
};
|
|
1251
|
+
const gt = (a, b) => a > b;
|
|
1252
|
+
const lt = (a, b) => a < b;
|
|
1253
|
+
const gte = (a, b) => a >= b;
|
|
1254
|
+
const lte = (a, b) => a <= b;
|
|
1255
|
+
const neq = (a, b) => a !== b;
|
|
1256
|
+
const between = (val, min2, max2) => val >= min2 && val <= max2;
|
|
1257
|
+
const contains = (arr, val) => Array.isArray(arr) && arr.includes(val);
|
|
1258
|
+
const registerCompareHelpers = (register) => {
|
|
1259
|
+
register("gt", gt);
|
|
1260
|
+
register(">", gt);
|
|
1261
|
+
register("lt", lt);
|
|
1262
|
+
register("<", lt);
|
|
1263
|
+
register("gte", gte);
|
|
1264
|
+
register(">=", gte);
|
|
1265
|
+
register("lte", lte);
|
|
1266
|
+
register("<=", lte);
|
|
1267
|
+
register("neq", neq);
|
|
1268
|
+
register("!=", neq);
|
|
1269
|
+
register("between", between);
|
|
1270
|
+
register("in", contains);
|
|
1271
|
+
};
|
|
1272
|
+
const sumIf = (arr, predicate) => {
|
|
1273
|
+
if (!Array.isArray(arr)) return 0;
|
|
1274
|
+
const filtered = predicate && predicate.isLazy ? arr.filter((item) => predicate.resolve(item)) : arr;
|
|
1275
|
+
return filtered.reduce((a, b) => a + (Number(b) || 0), 0);
|
|
1276
|
+
};
|
|
1277
|
+
const countIf = (arr, predicate) => {
|
|
1278
|
+
if (!Array.isArray(arr)) return 0;
|
|
1279
|
+
if (predicate && predicate.isLazy) {
|
|
1280
|
+
return arr.filter((item) => predicate.resolve(item)).length;
|
|
1281
|
+
}
|
|
1282
|
+
return arr.filter((item) => !!item).length;
|
|
1283
|
+
};
|
|
1284
|
+
const avgIf = (arr, predicate) => {
|
|
1285
|
+
if (!Array.isArray(arr)) return 0;
|
|
1286
|
+
const filtered = predicate && predicate.isLazy ? arr.filter((item) => predicate.resolve(item)) : arr;
|
|
1287
|
+
if (filtered.length === 0) return 0;
|
|
1288
|
+
return filtered.reduce((a, b) => a + (Number(b) || 0), 0) / filtered.length;
|
|
1289
|
+
};
|
|
1290
|
+
const registerConditionalHelpers = (register) => {
|
|
1291
|
+
register("sumIf", sumIf);
|
|
1292
|
+
register("countIf", countIf);
|
|
1293
|
+
register("avgIf", avgIf);
|
|
1294
|
+
};
|
|
1295
|
+
const now = () => (/* @__PURE__ */ new Date()).getTime();
|
|
1296
|
+
const today = () => {
|
|
1297
|
+
const d = /* @__PURE__ */ new Date();
|
|
1298
|
+
d.setHours(0, 0, 0, 0);
|
|
1299
|
+
return d.getTime();
|
|
1300
|
+
};
|
|
1301
|
+
const date = (val) => new Date(val).getTime();
|
|
1302
|
+
const formatDate = (val, format) => {
|
|
1303
|
+
const d = new Date(val);
|
|
1304
|
+
if (isNaN(d.getTime())) return "";
|
|
1305
|
+
const options = { year: "numeric", month: "2-digit", day: "2-digit" };
|
|
1306
|
+
if (format === "long") options.month = "long";
|
|
1307
|
+
return d.toLocaleDateString(void 0, options);
|
|
1308
|
+
};
|
|
1309
|
+
const year = (val) => new Date(val).getFullYear();
|
|
1310
|
+
const month = (val) => new Date(val).getMonth() + 1;
|
|
1311
|
+
const day = (val) => new Date(val).getDate();
|
|
1312
|
+
const weekday = (val) => new Date(val).getDay();
|
|
1313
|
+
const addDays = (val, days) => {
|
|
1314
|
+
const d = new Date(val);
|
|
1315
|
+
d.setDate(d.getDate() + Number(days));
|
|
1316
|
+
return d.getTime();
|
|
1317
|
+
};
|
|
1318
|
+
const dateDiff = (d1, d2, unit = "days") => {
|
|
1319
|
+
const diff = Math.abs(new Date(d1) - new Date(d2));
|
|
1320
|
+
if (unit === "seconds") return diff / 1e3;
|
|
1321
|
+
if (unit === "minutes") return diff / (1e3 * 60);
|
|
1322
|
+
if (unit === "hours") return diff / (1e3 * 60 * 60);
|
|
1323
|
+
return diff / (1e3 * 60 * 60 * 24);
|
|
1324
|
+
};
|
|
1325
|
+
const registerDateTimeHelpers = (register) => {
|
|
1326
|
+
register("now", now);
|
|
1327
|
+
register("today", today);
|
|
1328
|
+
register("date", date);
|
|
1329
|
+
register("formatDate", formatDate);
|
|
1330
|
+
register("year", year);
|
|
1331
|
+
register("month", month);
|
|
1332
|
+
register("day", day);
|
|
1333
|
+
register("weekday", weekday);
|
|
1334
|
+
register("addDays", addDays);
|
|
1335
|
+
register("dateDiff", dateDiff);
|
|
1336
|
+
};
|
|
1337
|
+
const number = (val, decimals = 2) => Number(val).toFixed(decimals);
|
|
1338
|
+
const currency = (val, symbol = "$", decimals = 2) => {
|
|
1339
|
+
return symbol + Number(val).toFixed(decimals).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
1340
|
+
};
|
|
1341
|
+
const percent = (val, decimals = 0) => (Number(val) * 100).toFixed(decimals) + "%";
|
|
1342
|
+
const thousands = (val) => String(val).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
1343
|
+
const registerFormatHelpers = (register) => {
|
|
1344
|
+
register("number", number);
|
|
1345
|
+
register("currency", currency);
|
|
1346
|
+
register("percent", percent);
|
|
1347
|
+
register("thousands", thousands);
|
|
1348
|
+
};
|
|
1349
|
+
const lookup = (val, searchArr, resultArr) => {
|
|
1350
|
+
if (!Array.isArray(searchArr)) return void 0;
|
|
1351
|
+
const idx = searchArr.indexOf(val);
|
|
1352
|
+
return idx !== -1 && Array.isArray(resultArr) ? resultArr[idx] : void 0;
|
|
1353
|
+
};
|
|
1354
|
+
const vlookup = (val, table, colIdx) => {
|
|
1355
|
+
if (!Array.isArray(table)) return void 0;
|
|
1356
|
+
const row = table.find((r) => Array.isArray(r) && r[0] === val);
|
|
1357
|
+
return row ? row[colIdx - 1] : void 0;
|
|
1358
|
+
};
|
|
1359
|
+
const index = (arr, idx) => Array.isArray(arr) ? arr[idx] : void 0;
|
|
1360
|
+
const match = (val, arr) => Array.isArray(arr) ? arr.indexOf(val) : -1;
|
|
1361
|
+
const registerLookupHelpers = (register) => {
|
|
1362
|
+
register("lookup", lookup);
|
|
1363
|
+
register("vlookup", vlookup);
|
|
1364
|
+
register("index", index);
|
|
1365
|
+
register("match", match);
|
|
1366
|
+
};
|
|
1367
|
+
const sum = (...args) => args.reduce((a, b) => a + (Number(b) || 0), 0);
|
|
1368
|
+
const avg = (...args) => args.length === 0 ? 0 : sum(...args) / args.length;
|
|
1369
|
+
const min = (...args) => Math.min(...args);
|
|
1370
|
+
const max = (...args) => Math.max(...args);
|
|
1371
|
+
const median = (...args) => {
|
|
1372
|
+
if (args.length === 0) return 0;
|
|
1373
|
+
const sorted = [...args].sort((a, b) => a - b);
|
|
1374
|
+
const mid = Math.floor(sorted.length / 2);
|
|
1375
|
+
return sorted.length % 2 !== 0 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
|
|
1376
|
+
};
|
|
1377
|
+
const stdev = (...args) => {
|
|
1378
|
+
if (args.length === 0) return 0;
|
|
1379
|
+
const mean = avg(...args);
|
|
1380
|
+
const squareDiffs = args.map((value) => Math.pow(value - mean, 2));
|
|
1381
|
+
return Math.sqrt(avg(...squareDiffs));
|
|
1382
|
+
};
|
|
1383
|
+
const variance = (...args) => {
|
|
1384
|
+
if (args.length === 0) return 0;
|
|
1385
|
+
const mean = avg(...args);
|
|
1386
|
+
const squareDiffs = args.map((value) => Math.pow(value - mean, 2));
|
|
1387
|
+
return avg(...squareDiffs);
|
|
1388
|
+
};
|
|
1389
|
+
const registerStatsHelpers = (register) => {
|
|
1390
|
+
register("sum", sum);
|
|
1391
|
+
register("avg", avg);
|
|
1392
|
+
register("min", min);
|
|
1393
|
+
register("max", max);
|
|
1394
|
+
register("median", median);
|
|
1395
|
+
register("stdev", stdev);
|
|
1396
|
+
register("var", variance);
|
|
1397
|
+
};
|
|
1398
|
+
const set = (target, val) => {
|
|
1399
|
+
if (target && typeof target === "object" && "value" in target) {
|
|
1400
|
+
target.value = val;
|
|
1401
|
+
} else if (target && typeof target === "function" && "value" in target) {
|
|
1402
|
+
target.value = val;
|
|
1403
|
+
} else if (target && typeof target === "object" && val && typeof val === "object") {
|
|
1404
|
+
Object.assign(target, val);
|
|
1405
|
+
}
|
|
1406
|
+
return val;
|
|
1407
|
+
};
|
|
1408
|
+
const increment = (target, by = 1) => {
|
|
1409
|
+
const hasValue = target && (typeof target === "object" || typeof target === "function") && "value" in target;
|
|
1410
|
+
const current = hasValue ? target.value : 0;
|
|
1411
|
+
const next = Number(current) + Number(by);
|
|
1412
|
+
return set(target, next);
|
|
1413
|
+
};
|
|
1414
|
+
const decrement = (target, by = 1) => {
|
|
1415
|
+
const hasValue = target && (typeof target === "object" || typeof target === "function") && "value" in target;
|
|
1416
|
+
const current = hasValue ? target.value : 0;
|
|
1417
|
+
const next = Number(current) - Number(by);
|
|
1418
|
+
return set(target, next);
|
|
1419
|
+
};
|
|
1420
|
+
const toggle = (target) => {
|
|
1421
|
+
const hasValue = target && (typeof target === "object" || typeof target === "function") && "value" in target;
|
|
1422
|
+
const current = hasValue ? target.value : false;
|
|
1423
|
+
return set(target, !current);
|
|
1424
|
+
};
|
|
1425
|
+
const push = (target, item) => {
|
|
1426
|
+
const current = target && typeof target === "object" && "value" in target ? target.value : [];
|
|
1427
|
+
if (Array.isArray(current)) {
|
|
1428
|
+
const next = [...current, item];
|
|
1429
|
+
return set(target, next);
|
|
1430
|
+
}
|
|
1431
|
+
return current;
|
|
1432
|
+
};
|
|
1433
|
+
const pop = (target) => {
|
|
1434
|
+
const current = target && typeof target === "object" && "value" in target ? target.value : [];
|
|
1435
|
+
if (Array.isArray(current) && current.length > 0) {
|
|
1436
|
+
const next = current.slice(0, -1);
|
|
1437
|
+
set(target, next);
|
|
1438
|
+
}
|
|
1439
|
+
return current;
|
|
1440
|
+
};
|
|
1441
|
+
const assign = (target, obj) => {
|
|
1442
|
+
const current = target && typeof target === "object" && "value" in target ? target.value : {};
|
|
1443
|
+
const next = { ...current, ...obj };
|
|
1444
|
+
return set(target, next);
|
|
1445
|
+
};
|
|
1446
|
+
const clear = (target) => {
|
|
1447
|
+
const current = target && typeof target === "object" && "value" in target ? target.value : null;
|
|
1448
|
+
if (Array.isArray(current)) return set(target, []);
|
|
1449
|
+
if (typeof current === "object" && current !== null) return set(target, {});
|
|
1450
|
+
return set(target, null);
|
|
1451
|
+
};
|
|
1452
|
+
const registerStateHelpers = (register) => {
|
|
1453
|
+
const opts = { pathAware: true };
|
|
1454
|
+
register("set", set, opts);
|
|
1455
|
+
register("increment", increment, opts);
|
|
1456
|
+
register("++", increment, opts);
|
|
1457
|
+
register("decrement", decrement, opts);
|
|
1458
|
+
register("--", decrement, opts);
|
|
1459
|
+
register("toggle", toggle, opts);
|
|
1460
|
+
register("!!", toggle, opts);
|
|
1461
|
+
register("push", push, opts);
|
|
1462
|
+
register("pop", pop, opts);
|
|
1463
|
+
register("assign", assign, opts);
|
|
1464
|
+
register("clear", clear, opts);
|
|
1465
|
+
};
|
|
1466
|
+
const fetchHelper = (url, options = {}) => {
|
|
1467
|
+
const fetchOptions = { ...options };
|
|
1468
|
+
const headers = { ...fetchOptions.headers };
|
|
1469
|
+
let body = fetchOptions.body;
|
|
1470
|
+
if (body !== void 0) {
|
|
1471
|
+
if (body !== null && typeof body === "object") {
|
|
1472
|
+
body = JSON.stringify(body);
|
|
1473
|
+
if (!headers["Content-Type"]) {
|
|
1474
|
+
headers["Content-Type"] = "application/json";
|
|
1475
|
+
}
|
|
1476
|
+
} else {
|
|
1477
|
+
body = String(body);
|
|
1478
|
+
if (!headers["Content-Type"]) {
|
|
1479
|
+
headers["Content-Type"] = "text/plain";
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
fetchOptions.body = body;
|
|
1484
|
+
fetchOptions.headers = headers;
|
|
1485
|
+
return globalThis.fetch(url, fetchOptions);
|
|
1486
|
+
};
|
|
1487
|
+
const registerNetworkHelpers = (register) => {
|
|
1488
|
+
register("fetch", fetchHelper);
|
|
1489
|
+
};
|
|
1490
|
+
const _LV = globalThis.__LIGHTVIEW_INTERNALS__ || (globalThis.__LIGHTVIEW_INTERNALS__ = {
|
|
1491
|
+
currentEffect: null,
|
|
1492
|
+
registry: /* @__PURE__ */ new Map(),
|
|
1493
|
+
dependencyMap: /* @__PURE__ */ new WeakMap()
|
|
1494
|
+
// Tracking signals -> subscribers
|
|
1495
|
+
});
|
|
1496
|
+
const signal = (initialValue, optionsOrName) => {
|
|
1497
|
+
let name = typeof optionsOrName === "string" ? optionsOrName : optionsOrName == null ? void 0 : optionsOrName.name;
|
|
1498
|
+
const storage = optionsOrName == null ? void 0 : optionsOrName.storage;
|
|
1499
|
+
if (name && storage) {
|
|
1500
|
+
try {
|
|
1501
|
+
const stored = storage.getItem(name);
|
|
1502
|
+
if (stored !== null) {
|
|
1503
|
+
initialValue = JSON.parse(stored);
|
|
1504
|
+
}
|
|
1505
|
+
} catch (e) {
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
let value = initialValue;
|
|
1509
|
+
const subscribers = /* @__PURE__ */ new Set();
|
|
1510
|
+
const f = (...args) => {
|
|
1511
|
+
if (args.length === 0) return f.value;
|
|
1512
|
+
f.value = args[0];
|
|
1513
|
+
};
|
|
1514
|
+
Object.defineProperty(f, "value", {
|
|
1515
|
+
get() {
|
|
1516
|
+
if (_LV.currentEffect) {
|
|
1517
|
+
subscribers.add(_LV.currentEffect);
|
|
1518
|
+
_LV.currentEffect.dependencies.add(subscribers);
|
|
1519
|
+
}
|
|
1520
|
+
return value;
|
|
1521
|
+
},
|
|
1522
|
+
set(newValue) {
|
|
1523
|
+
if (value !== newValue) {
|
|
1524
|
+
value = newValue;
|
|
1525
|
+
if (name && storage) {
|
|
1526
|
+
try {
|
|
1527
|
+
storage.setItem(name, JSON.stringify(value));
|
|
1528
|
+
} catch (e) {
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1531
|
+
[...subscribers].forEach((effect2) => effect2());
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
});
|
|
1535
|
+
if (name) {
|
|
1536
|
+
if (_LV.registry.has(name)) {
|
|
1537
|
+
if (_LV.registry.get(name) !== f) {
|
|
1538
|
+
throw new Error(`Lightview: A signal or state with the name "${name}" is already registered.`);
|
|
1539
|
+
}
|
|
1540
|
+
} else {
|
|
1541
|
+
_LV.registry.set(name, f);
|
|
1542
|
+
}
|
|
1543
|
+
}
|
|
1544
|
+
return f;
|
|
1545
|
+
};
|
|
1546
|
+
const getSignal = (name, defaultValue) => {
|
|
1547
|
+
if (!_LV.registry.has(name) && defaultValue !== void 0) {
|
|
1548
|
+
return signal(defaultValue, name);
|
|
1549
|
+
}
|
|
1550
|
+
return _LV.registry.get(name);
|
|
1551
|
+
};
|
|
1552
|
+
signal.get = getSignal;
|
|
1553
|
+
const effect = (fn) => {
|
|
1554
|
+
const execute = () => {
|
|
1555
|
+
if (!execute.active || execute.running) return;
|
|
1556
|
+
execute.dependencies.forEach((dep) => dep.delete(execute));
|
|
1557
|
+
execute.dependencies.clear();
|
|
1558
|
+
execute.running = true;
|
|
1559
|
+
_LV.currentEffect = execute;
|
|
1560
|
+
try {
|
|
1561
|
+
fn();
|
|
1562
|
+
} finally {
|
|
1563
|
+
_LV.currentEffect = null;
|
|
1564
|
+
execute.running = false;
|
|
1565
|
+
}
|
|
1566
|
+
};
|
|
1567
|
+
execute.active = true;
|
|
1568
|
+
execute.running = false;
|
|
1569
|
+
execute.dependencies = /* @__PURE__ */ new Set();
|
|
1570
|
+
execute.stop = () => {
|
|
1571
|
+
execute.dependencies.forEach((dep) => dep.delete(execute));
|
|
1572
|
+
execute.dependencies.clear();
|
|
1573
|
+
execute.active = false;
|
|
1574
|
+
};
|
|
1575
|
+
execute();
|
|
1576
|
+
return execute;
|
|
1577
|
+
};
|
|
1578
|
+
const getRegistry = () => _LV.registry;
|
|
1579
|
+
const stateCache = /* @__PURE__ */ new WeakMap();
|
|
1580
|
+
const stateSignals = /* @__PURE__ */ new WeakMap();
|
|
1581
|
+
const parents = /* @__PURE__ */ new WeakMap();
|
|
1582
|
+
const protoMethods = (proto, test) => Object.getOwnPropertyNames(proto).filter((k) => typeof proto[k] === "function" && test(k));
|
|
1583
|
+
const DATE_TRACKING = protoMethods(Date.prototype, (k) => /^(to|get|valueOf)/.test(k));
|
|
1584
|
+
const DATE_MUTATING = protoMethods(Date.prototype, (k) => /^set/.test(k));
|
|
1585
|
+
const ARRAY_TRACKING = [
|
|
1586
|
+
"map",
|
|
1587
|
+
"forEach",
|
|
1588
|
+
"filter",
|
|
1589
|
+
"find",
|
|
1590
|
+
"findIndex",
|
|
1591
|
+
"some",
|
|
1592
|
+
"every",
|
|
1593
|
+
"reduce",
|
|
1594
|
+
"reduceRight",
|
|
1595
|
+
"includes",
|
|
1596
|
+
"indexOf",
|
|
1597
|
+
"lastIndexOf",
|
|
1598
|
+
"join",
|
|
1599
|
+
"slice",
|
|
1600
|
+
"concat",
|
|
1601
|
+
"flat",
|
|
1602
|
+
"flatMap",
|
|
1603
|
+
"at",
|
|
1604
|
+
"entries",
|
|
1605
|
+
"keys",
|
|
1606
|
+
"values"
|
|
1607
|
+
];
|
|
1608
|
+
const ARRAY_MUTATING = ["push", "pop", "shift", "unshift", "splice", "sort", "reverse", "fill", "copyWithin"];
|
|
1609
|
+
const ARRAY_ITERATION = ["map", "forEach", "filter", "find", "findIndex", "some", "every", "flatMap"];
|
|
1610
|
+
const getOrSet = (map2, key, factory) => {
|
|
1611
|
+
let v = map2.get(key);
|
|
1612
|
+
if (!v) {
|
|
1613
|
+
v = factory();
|
|
1614
|
+
map2.set(key, v);
|
|
1615
|
+
}
|
|
1616
|
+
return v;
|
|
1617
|
+
};
|
|
1618
|
+
const proxyGet = (target, prop, receiver, signals) => {
|
|
1619
|
+
if (prop === "__parent__") return parents.get(receiver);
|
|
1620
|
+
if (!signals.has(prop)) {
|
|
1621
|
+
signals.set(prop, signal(Reflect.get(target, prop, receiver)));
|
|
1622
|
+
}
|
|
1623
|
+
const signal$1 = signals.get(prop);
|
|
1624
|
+
const val = signal$1.value;
|
|
1625
|
+
if (typeof val === "object" && val !== null) {
|
|
1626
|
+
const childProxy = state(val);
|
|
1627
|
+
parents.set(childProxy, receiver);
|
|
1628
|
+
return childProxy;
|
|
1629
|
+
}
|
|
1630
|
+
return val;
|
|
1631
|
+
};
|
|
1632
|
+
const proxySet = (target, prop, value, receiver, signals) => {
|
|
1633
|
+
if (!signals.has(prop)) {
|
|
1634
|
+
signals.set(prop, signal(Reflect.get(target, prop, receiver)));
|
|
1635
|
+
}
|
|
1636
|
+
const success = Reflect.set(target, prop, value, receiver);
|
|
1637
|
+
const signal$1 = signals.get(prop);
|
|
1638
|
+
if (success && signal$1) signal$1.value = value;
|
|
1639
|
+
return success;
|
|
1640
|
+
};
|
|
1641
|
+
const createSpecialProxy = (obj, monitor, trackingProps = []) => {
|
|
1642
|
+
const signals = getOrSet(stateSignals, obj, () => /* @__PURE__ */ new Map());
|
|
1643
|
+
if (!signals.has(monitor)) {
|
|
1644
|
+
const initialValue = typeof obj[monitor] === "function" ? obj[monitor].call(obj) : obj[monitor];
|
|
1645
|
+
signals.set(monitor, signal(initialValue));
|
|
1646
|
+
}
|
|
1647
|
+
const isDate = obj instanceof Date;
|
|
1648
|
+
const isArray = Array.isArray(obj);
|
|
1649
|
+
const trackingMethods = isDate ? DATE_TRACKING : isArray ? ARRAY_TRACKING : trackingProps;
|
|
1650
|
+
const mutatingMethods = isDate ? DATE_MUTATING : isArray ? ARRAY_MUTATING : [];
|
|
1651
|
+
return new Proxy(obj, {
|
|
1652
|
+
get(target, prop, receiver) {
|
|
1653
|
+
if (prop === "__parent__") return parents.get(receiver);
|
|
1654
|
+
const value = target[prop];
|
|
1655
|
+
if (typeof value === "function") {
|
|
1656
|
+
const isTracking = trackingMethods.includes(prop);
|
|
1657
|
+
const isMutating = mutatingMethods.includes(prop);
|
|
1658
|
+
return function(...args) {
|
|
1659
|
+
if (isTracking) {
|
|
1660
|
+
const sig = signals.get(monitor);
|
|
1661
|
+
if (sig) void sig.value;
|
|
1662
|
+
}
|
|
1663
|
+
const startValue = typeof target[monitor] === "function" ? target[monitor].call(target) : target[monitor];
|
|
1664
|
+
if (isArray && ARRAY_ITERATION.includes(prop) && typeof args[0] === "function") {
|
|
1665
|
+
const originalCallback = args[0];
|
|
1666
|
+
args[0] = function(element, index2, array) {
|
|
1667
|
+
const wrappedElement = typeof element === "object" && element !== null ? state(element) : element;
|
|
1668
|
+
if (wrappedElement && typeof wrappedElement === "object") {
|
|
1669
|
+
parents.set(wrappedElement, receiver);
|
|
1670
|
+
}
|
|
1671
|
+
return originalCallback.call(this, wrappedElement, index2, array);
|
|
1672
|
+
};
|
|
1673
|
+
}
|
|
1674
|
+
const result = value.apply(target, args);
|
|
1675
|
+
const endValue = typeof target[monitor] === "function" ? target[monitor].call(target) : target[monitor];
|
|
1676
|
+
if (startValue !== endValue || isMutating) {
|
|
1677
|
+
const sig = signals.get(monitor);
|
|
1678
|
+
if (sig && sig.value !== endValue) {
|
|
1679
|
+
sig.value = endValue;
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1682
|
+
return result;
|
|
1683
|
+
};
|
|
1684
|
+
}
|
|
1685
|
+
if (prop === monitor) {
|
|
1686
|
+
const sig = signals.get(monitor);
|
|
1687
|
+
return sig ? sig.value : Reflect.get(target, prop, receiver);
|
|
1688
|
+
}
|
|
1689
|
+
if (isArray && !isNaN(parseInt(prop))) {
|
|
1690
|
+
const monitorSig = signals.get(monitor);
|
|
1691
|
+
if (monitorSig) void monitorSig.value;
|
|
1692
|
+
}
|
|
1693
|
+
return proxyGet(target, prop, receiver, signals);
|
|
1694
|
+
},
|
|
1695
|
+
set(target, prop, value, receiver) {
|
|
1696
|
+
if (prop === monitor) {
|
|
1697
|
+
const success = Reflect.set(target, prop, value, receiver);
|
|
1698
|
+
if (success) {
|
|
1699
|
+
const sig = signals.get(monitor);
|
|
1700
|
+
if (sig) sig.value = value;
|
|
1701
|
+
}
|
|
1702
|
+
return success;
|
|
1703
|
+
}
|
|
1704
|
+
return proxySet(target, prop, value, receiver, signals);
|
|
1705
|
+
}
|
|
1706
|
+
});
|
|
1707
|
+
};
|
|
1708
|
+
const state = (obj, optionsOrName) => {
|
|
1709
|
+
if (typeof obj !== "object" || obj === null) return obj;
|
|
1710
|
+
const name = typeof optionsOrName === "string" ? optionsOrName : optionsOrName == null ? void 0 : optionsOrName.name;
|
|
1711
|
+
const storage = optionsOrName == null ? void 0 : optionsOrName.storage;
|
|
1712
|
+
if (name && storage) {
|
|
1713
|
+
try {
|
|
1714
|
+
const item = storage.getItem(name);
|
|
1715
|
+
if (item) {
|
|
1716
|
+
const loaded = JSON.parse(item);
|
|
1717
|
+
Array.isArray(obj) && Array.isArray(loaded) ? (obj.length = 0, obj.push(...loaded)) : Object.assign(obj, loaded);
|
|
1718
|
+
}
|
|
1719
|
+
} catch (e) {
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1722
|
+
let proxy = stateCache.get(obj);
|
|
1723
|
+
if (!proxy) {
|
|
1724
|
+
const isArray = Array.isArray(obj), isDate = obj instanceof Date;
|
|
1725
|
+
const isSpecial = isArray || isDate;
|
|
1726
|
+
const monitor = isArray ? "length" : isDate ? "getTime" : null;
|
|
1727
|
+
if (isSpecial || !(obj instanceof RegExp || obj instanceof Map || obj instanceof Set || obj instanceof WeakMap || obj instanceof WeakSet)) {
|
|
1728
|
+
proxy = isSpecial ? createSpecialProxy(obj, monitor) : new Proxy(obj, {
|
|
1729
|
+
get(t, p, r) {
|
|
1730
|
+
if (p === "__parent__") return parents.get(r);
|
|
1731
|
+
return proxyGet(t, p, r, getOrSet(stateSignals, t, () => /* @__PURE__ */ new Map()));
|
|
1732
|
+
},
|
|
1733
|
+
set(t, p, v, r) {
|
|
1734
|
+
return proxySet(t, p, v, r, getOrSet(stateSignals, t, () => /* @__PURE__ */ new Map()));
|
|
1735
|
+
}
|
|
1736
|
+
});
|
|
1737
|
+
stateCache.set(obj, proxy);
|
|
1738
|
+
} else return obj;
|
|
1739
|
+
}
|
|
1740
|
+
if (name && storage) {
|
|
1741
|
+
effect(() => {
|
|
1742
|
+
try {
|
|
1743
|
+
storage.setItem(name, JSON.stringify(proxy));
|
|
1744
|
+
} catch (e) {
|
|
1745
|
+
}
|
|
1746
|
+
});
|
|
1747
|
+
}
|
|
1748
|
+
if (name) {
|
|
1749
|
+
const registry = getRegistry();
|
|
1750
|
+
if (registry.has(name)) {
|
|
1751
|
+
if (registry.get(name) !== proxy) {
|
|
1752
|
+
throw new Error(`Lightview: A signal or state with the name "${name}" is already registered.`);
|
|
1753
|
+
}
|
|
1754
|
+
} else {
|
|
1755
|
+
registry.set(name, proxy);
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
return proxy;
|
|
1759
|
+
};
|
|
1760
|
+
const getState = (name, defaultValue) => {
|
|
1761
|
+
const registry = getRegistry();
|
|
1762
|
+
if (!registry.has(name) && defaultValue !== void 0) {
|
|
1763
|
+
return state(defaultValue, name);
|
|
1764
|
+
}
|
|
1765
|
+
return registry.get(name);
|
|
1766
|
+
};
|
|
1767
|
+
state.get = getState;
|
|
1768
|
+
registerMathHelpers(registerHelper);
|
|
1769
|
+
registerLogicHelpers(registerHelper);
|
|
1770
|
+
registerStringHelpers(registerHelper);
|
|
1771
|
+
registerArrayHelpers(registerHelper);
|
|
1772
|
+
registerCompareHelpers(registerHelper);
|
|
1773
|
+
registerConditionalHelpers(registerHelper);
|
|
1774
|
+
registerDateTimeHelpers(registerHelper);
|
|
1775
|
+
registerFormatHelpers(registerHelper);
|
|
1776
|
+
registerLookupHelpers(registerHelper);
|
|
1777
|
+
registerStatsHelpers(registerHelper);
|
|
1778
|
+
registerStateHelpers((name, fn) => registerHelper(name, fn, { pathAware: true }));
|
|
1779
|
+
registerNetworkHelpers(registerHelper);
|
|
1780
|
+
registerOperator("increment", "++", "prefix", 80);
|
|
1781
|
+
registerOperator("increment", "++", "postfix", 80);
|
|
1782
|
+
registerOperator("decrement", "--", "prefix", 80);
|
|
1783
|
+
registerOperator("decrement", "--", "postfix", 80);
|
|
1784
|
+
registerOperator("toggle", "!!", "prefix", 80);
|
|
1785
|
+
registerOperator("+", "+", "infix", 50);
|
|
1786
|
+
registerOperator("-", "-", "infix", 50);
|
|
1787
|
+
registerOperator("*", "*", "infix", 60);
|
|
1788
|
+
registerOperator("/", "/", "infix", 60);
|
|
1789
|
+
registerOperator("gt", ">", "infix", 40);
|
|
1790
|
+
registerOperator("lt", "<", "infix", 40);
|
|
1791
|
+
registerOperator("gte", ">=", "infix", 40);
|
|
1792
|
+
registerOperator("lte", "<=", "infix", 40);
|
|
1793
|
+
registerOperator("neq", "!=", "infix", 40);
|
|
1794
|
+
const localStates = /* @__PURE__ */ new WeakMap();
|
|
1795
|
+
const getContext = (node, event = null) => {
|
|
1796
|
+
const chain = [];
|
|
1797
|
+
let cur = node;
|
|
1798
|
+
const ShadowRoot = globalThis.ShadowRoot;
|
|
1799
|
+
while (cur) {
|
|
1800
|
+
const local = localStates.get(cur) || (cur && typeof cur === "object" ? cur.__state__ : null);
|
|
1801
|
+
if (local) chain.unshift(local);
|
|
1802
|
+
cur = cur.parentElement || (cur && typeof cur === "object" ? cur.__parent__ : null) || (ShadowRoot && cur.parentNode instanceof ShadowRoot ? cur.parentNode.host : null);
|
|
1803
|
+
}
|
|
1804
|
+
const globalRegistry = getRegistry();
|
|
1805
|
+
const handler = {
|
|
1806
|
+
get(target, prop, receiver) {
|
|
1807
|
+
var _a;
|
|
1808
|
+
if (prop === "$event" || prop === "event") return event;
|
|
1809
|
+
if (prop === "__parent__") return void 0;
|
|
1810
|
+
for (let i = chain.length - 1; i >= 0; i--) {
|
|
1811
|
+
const s = chain[i];
|
|
1812
|
+
if (prop in s) return s[prop];
|
|
1813
|
+
}
|
|
1814
|
+
if (globalRegistry && globalRegistry.has(prop)) return unwrapSignal(globalRegistry.get(prop));
|
|
1815
|
+
const globalState = (_a = globalThis.Lightview) == null ? void 0 : _a.state;
|
|
1816
|
+
if (globalState && prop in globalState) return unwrapSignal(globalState[prop]);
|
|
1817
|
+
return void 0;
|
|
1818
|
+
},
|
|
1819
|
+
set(target, prop, value, receiver) {
|
|
1820
|
+
var _a;
|
|
1821
|
+
for (let i = chain.length - 1; i >= 0; i--) {
|
|
1822
|
+
const s = chain[i];
|
|
1823
|
+
if (prop in s) {
|
|
1824
|
+
s[prop] = value;
|
|
1825
|
+
return true;
|
|
1826
|
+
}
|
|
1827
|
+
}
|
|
1828
|
+
if (chain.length > 0) {
|
|
1829
|
+
chain[chain.length - 1][prop] = value;
|
|
1830
|
+
return true;
|
|
1831
|
+
}
|
|
1832
|
+
const globalState = (_a = globalThis.Lightview) == null ? void 0 : _a.state;
|
|
1833
|
+
if (globalState && prop in globalState) {
|
|
1834
|
+
globalState[prop] = value;
|
|
1835
|
+
return true;
|
|
1836
|
+
}
|
|
1837
|
+
if (globalRegistry && globalRegistry.has(prop)) {
|
|
1838
|
+
const s = globalRegistry.get(prop);
|
|
1839
|
+
if (s && (typeof s === "object" || typeof s === "function") && "value" in s) {
|
|
1840
|
+
s.value = value;
|
|
1841
|
+
return true;
|
|
1842
|
+
}
|
|
1843
|
+
}
|
|
1844
|
+
return false;
|
|
1845
|
+
},
|
|
1846
|
+
has(target, prop) {
|
|
1847
|
+
var _a;
|
|
1848
|
+
const exists = prop === "$event" || prop === "event" || !!chain.find((s) => prop in s);
|
|
1849
|
+
const inGlobal = ((_a = globalThis.Lightview) == null ? void 0 : _a.state) && prop in globalThis.Lightview.state || globalRegistry && globalRegistry.has(prop);
|
|
1850
|
+
return exists || inGlobal;
|
|
1851
|
+
},
|
|
1852
|
+
ownKeys(target) {
|
|
1853
|
+
var _a;
|
|
1854
|
+
const keys = /* @__PURE__ */ new Set();
|
|
1855
|
+
if (event) {
|
|
1856
|
+
keys.add("$event");
|
|
1857
|
+
keys.add("event");
|
|
1858
|
+
}
|
|
1859
|
+
for (const s of chain) {
|
|
1860
|
+
for (const key in s) keys.add(key);
|
|
1861
|
+
}
|
|
1862
|
+
const globalState = (_a = globalThis.Lightview) == null ? void 0 : _a.state;
|
|
1863
|
+
if (globalState) {
|
|
1864
|
+
for (const key in globalState) keys.add(key);
|
|
1865
|
+
}
|
|
1866
|
+
return Array.from(keys);
|
|
1867
|
+
},
|
|
1868
|
+
getOwnPropertyDescriptor(target, prop) {
|
|
1869
|
+
return { enumerable: true, configurable: true };
|
|
1870
|
+
}
|
|
1871
|
+
};
|
|
1872
|
+
return new Proxy({}, handler);
|
|
1873
|
+
};
|
|
1874
|
+
const handleCDOMState = (node) => {
|
|
1875
|
+
var _a;
|
|
1876
|
+
const attr = node["cdom-state"] || node.getAttribute && node.getAttribute("cdom-state");
|
|
1877
|
+
if (!attr || localStates.has(node)) return;
|
|
1878
|
+
try {
|
|
1879
|
+
const data = typeof attr === "object" ? attr : JSON.parse(attr);
|
|
1880
|
+
const s = state(data);
|
|
1881
|
+
localStates.set(node, s);
|
|
1882
|
+
if (node && typeof node === "object") {
|
|
1883
|
+
node.__state__ = s;
|
|
1884
|
+
}
|
|
1885
|
+
} catch (e) {
|
|
1886
|
+
(_a = globalThis.console) == null ? void 0 : _a.error("LightviewCDOM: Failed to parse cdom-state", e);
|
|
1887
|
+
}
|
|
1888
|
+
};
|
|
1889
|
+
const handleCDOMBind = (node) => {
|
|
1890
|
+
const path = node["cdom-bind"] || node.getAttribute("cdom-bind");
|
|
1891
|
+
if (!path) return;
|
|
1892
|
+
const type = node.type || "";
|
|
1893
|
+
const tagName = node.tagName.toLowerCase();
|
|
1894
|
+
let prop = "value";
|
|
1895
|
+
let event = "input";
|
|
1896
|
+
if (type === "checkbox" || type === "radio") {
|
|
1897
|
+
prop = "checked";
|
|
1898
|
+
event = "change";
|
|
1899
|
+
} else if (tagName === "select") {
|
|
1900
|
+
event = "change";
|
|
1901
|
+
}
|
|
1902
|
+
const context = getContext(node);
|
|
1903
|
+
let target = resolvePathAsContext(path, context);
|
|
1904
|
+
if (target && target.isBindingTarget && target.value === void 0) {
|
|
1905
|
+
const val = node[prop];
|
|
1906
|
+
if (val !== void 0 && val !== "") {
|
|
1907
|
+
set(context, { [target.key]: val });
|
|
1908
|
+
target = resolvePathAsContext(path, context);
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
effect(() => {
|
|
1912
|
+
const val = unwrapSignal(target);
|
|
1913
|
+
if (node[prop] !== val) {
|
|
1914
|
+
node[prop] = val === void 0 ? "" : val;
|
|
1915
|
+
}
|
|
1916
|
+
});
|
|
1917
|
+
node.addEventListener(event, () => {
|
|
1918
|
+
const val = node[prop];
|
|
1919
|
+
if (target && target.isBindingTarget) {
|
|
1920
|
+
target.value = val;
|
|
1921
|
+
} else {
|
|
1922
|
+
set(context, { [path]: val });
|
|
1923
|
+
}
|
|
1924
|
+
});
|
|
1925
|
+
};
|
|
1926
|
+
const activate = (root = document.body) => {
|
|
1927
|
+
const walk = (node) => {
|
|
1928
|
+
if (node.nodeType === 1) {
|
|
1929
|
+
if (node.hasAttribute("cdom-state")) handleCDOMState(node);
|
|
1930
|
+
if (node.hasAttribute("cdom-bind")) handleCDOMBind(node);
|
|
1931
|
+
}
|
|
1932
|
+
let child = node.firstChild;
|
|
1933
|
+
while (child) {
|
|
1934
|
+
walk(child);
|
|
1935
|
+
child = child.nextSibling;
|
|
1936
|
+
}
|
|
1937
|
+
};
|
|
1938
|
+
walk(root);
|
|
1939
|
+
};
|
|
1940
|
+
const hydrate = (node, parent = null) => {
|
|
1941
|
+
if (!node) return node;
|
|
1942
|
+
if (typeof node === "string" && node.startsWith("$")) {
|
|
1943
|
+
return parseExpression(node, parent);
|
|
1944
|
+
}
|
|
1945
|
+
if (Array.isArray(node)) {
|
|
1946
|
+
return node.map((item) => hydrate(item, parent));
|
|
1947
|
+
}
|
|
1948
|
+
if (node instanceof String) {
|
|
1949
|
+
return node.toString();
|
|
1950
|
+
}
|
|
1951
|
+
if (typeof node === "object" && node !== null) {
|
|
1952
|
+
if (parent && !("__parent__" in node)) {
|
|
1953
|
+
Object.defineProperty(node, "__parent__", {
|
|
1954
|
+
value: parent,
|
|
1955
|
+
enumerable: false,
|
|
1956
|
+
writable: true,
|
|
1957
|
+
configurable: true
|
|
1958
|
+
});
|
|
1959
|
+
}
|
|
1960
|
+
if (!node.tag) {
|
|
1961
|
+
let potentialTag = null;
|
|
1962
|
+
for (const key in node) {
|
|
1963
|
+
if (key === "children" || key === "attributes" || key === "tag" || key.startsWith("cdom-") || key.startsWith("on") || key === "__parent__") {
|
|
1964
|
+
continue;
|
|
1965
|
+
}
|
|
1966
|
+
const attrNames = [
|
|
1967
|
+
// Form/input attributes
|
|
1968
|
+
"type",
|
|
1969
|
+
"name",
|
|
1970
|
+
"value",
|
|
1971
|
+
"placeholder",
|
|
1972
|
+
"step",
|
|
1973
|
+
"min",
|
|
1974
|
+
"max",
|
|
1975
|
+
"pattern",
|
|
1976
|
+
"disabled",
|
|
1977
|
+
"checked",
|
|
1978
|
+
"selected",
|
|
1979
|
+
"readonly",
|
|
1980
|
+
"required",
|
|
1981
|
+
"multiple",
|
|
1982
|
+
"rows",
|
|
1983
|
+
"cols",
|
|
1984
|
+
"size",
|
|
1985
|
+
"maxlength",
|
|
1986
|
+
"minlength",
|
|
1987
|
+
"autocomplete",
|
|
1988
|
+
// Common element attributes
|
|
1989
|
+
"id",
|
|
1990
|
+
"class",
|
|
1991
|
+
"className",
|
|
1992
|
+
"style",
|
|
1993
|
+
"title",
|
|
1994
|
+
"tabindex",
|
|
1995
|
+
"role",
|
|
1996
|
+
"href",
|
|
1997
|
+
"src",
|
|
1998
|
+
"alt",
|
|
1999
|
+
"width",
|
|
2000
|
+
"height",
|
|
2001
|
+
"target",
|
|
2002
|
+
"rel",
|
|
2003
|
+
// Data attributes
|
|
2004
|
+
"data",
|
|
2005
|
+
"label",
|
|
2006
|
+
"text",
|
|
2007
|
+
"description",
|
|
2008
|
+
"content",
|
|
2009
|
+
// Common data property names
|
|
2010
|
+
"price",
|
|
2011
|
+
"qty",
|
|
2012
|
+
"items",
|
|
2013
|
+
"count",
|
|
2014
|
+
"total",
|
|
2015
|
+
"amount",
|
|
2016
|
+
"url"
|
|
2017
|
+
];
|
|
2018
|
+
if (attrNames.includes(key)) {
|
|
2019
|
+
continue;
|
|
2020
|
+
}
|
|
2021
|
+
potentialTag = key;
|
|
2022
|
+
break;
|
|
2023
|
+
}
|
|
2024
|
+
if (potentialTag) {
|
|
2025
|
+
const content = node[potentialTag];
|
|
2026
|
+
if (content !== void 0 && content !== null) {
|
|
2027
|
+
node.tag = potentialTag;
|
|
2028
|
+
if (Array.isArray(content)) {
|
|
2029
|
+
node.children = content;
|
|
2030
|
+
} else if (typeof content === "object") {
|
|
2031
|
+
node.attributes = node.attributes || {};
|
|
2032
|
+
for (const k in content) {
|
|
2033
|
+
if (k === "children") {
|
|
2034
|
+
node.children = content[k];
|
|
2035
|
+
} else if (k.startsWith("cdom-")) {
|
|
2036
|
+
node[k] = content[k];
|
|
2037
|
+
} else {
|
|
2038
|
+
node.attributes[k] = content[k];
|
|
2039
|
+
}
|
|
2040
|
+
}
|
|
2041
|
+
} else {
|
|
2042
|
+
node.children = [content];
|
|
2043
|
+
}
|
|
2044
|
+
delete node[potentialTag];
|
|
2045
|
+
}
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
2048
|
+
if (node["cdom-state"]) {
|
|
2049
|
+
handleCDOMState(node);
|
|
2050
|
+
}
|
|
2051
|
+
for (const key in node) {
|
|
2052
|
+
const value = node[key];
|
|
2053
|
+
if (key === "cdom-state") {
|
|
2054
|
+
continue;
|
|
2055
|
+
}
|
|
2056
|
+
if (typeof value === "string" && value.startsWith("$")) {
|
|
2057
|
+
if (key.startsWith("on")) {
|
|
2058
|
+
node[key] = (event) => {
|
|
2059
|
+
const element = event.currentTarget;
|
|
2060
|
+
const context = getContext(element, event);
|
|
2061
|
+
const result = resolveExpression(value, context);
|
|
2062
|
+
if (result && typeof result === "object" && result.isLazy && typeof result.resolve === "function") {
|
|
2063
|
+
return result.resolve(event);
|
|
2064
|
+
}
|
|
2065
|
+
return result;
|
|
2066
|
+
};
|
|
2067
|
+
} else if (key === "children") {
|
|
2068
|
+
node[key] = [parseExpression(value, node)];
|
|
2069
|
+
} else {
|
|
2070
|
+
node[key] = parseExpression(value, node);
|
|
2071
|
+
}
|
|
2072
|
+
} else if (key === "attributes" && typeof value === "object" && value !== null) {
|
|
2073
|
+
for (const attrKey in value) {
|
|
2074
|
+
const attrValue = value[attrKey];
|
|
2075
|
+
if (typeof attrValue === "string" && attrValue.startsWith("$")) {
|
|
2076
|
+
if (attrKey.startsWith("on")) {
|
|
2077
|
+
value[attrKey] = (event) => {
|
|
2078
|
+
const element = event.currentTarget;
|
|
2079
|
+
const context = getContext(element, event);
|
|
2080
|
+
const result = resolveExpression(attrValue, context);
|
|
2081
|
+
if (result && typeof result === "object" && result.isLazy && typeof result.resolve === "function") {
|
|
2082
|
+
return result.resolve(event);
|
|
2083
|
+
}
|
|
2084
|
+
return result;
|
|
2085
|
+
};
|
|
2086
|
+
} else {
|
|
2087
|
+
value[attrKey] = parseExpression(attrValue, node);
|
|
2088
|
+
}
|
|
2089
|
+
}
|
|
2090
|
+
}
|
|
2091
|
+
node[key] = value;
|
|
2092
|
+
} else {
|
|
2093
|
+
node[key] = hydrate(value, node);
|
|
2094
|
+
}
|
|
2095
|
+
}
|
|
2096
|
+
return node;
|
|
2097
|
+
}
|
|
2098
|
+
return node;
|
|
2099
|
+
};
|
|
2100
|
+
const LightviewCDOM2 = {
|
|
2101
|
+
registerHelper,
|
|
2102
|
+
registerOperator,
|
|
2103
|
+
parseExpression,
|
|
2104
|
+
resolvePath,
|
|
2105
|
+
resolvePathAsContext,
|
|
2106
|
+
resolveExpression,
|
|
2107
|
+
parseCDOMC,
|
|
2108
|
+
parseJPRX,
|
|
2109
|
+
unwrapSignal,
|
|
2110
|
+
getContext,
|
|
2111
|
+
handleCDOMState,
|
|
2112
|
+
handleCDOMBind,
|
|
2113
|
+
activate,
|
|
2114
|
+
hydrate,
|
|
2115
|
+
version: "1.0.0"
|
|
2116
|
+
};
|
|
2117
|
+
if (typeof window !== "undefined") {
|
|
2118
|
+
globalThis.LightviewCDOM = LightviewCDOM2;
|
|
2119
|
+
}
|
|
2120
|
+
exports.activate = activate;
|
|
2121
|
+
exports.default = LightviewCDOM2;
|
|
2122
|
+
exports.getContext = getContext;
|
|
2123
|
+
exports.handleCDOMBind = handleCDOMBind;
|
|
2124
|
+
exports.handleCDOMState = handleCDOMState;
|
|
2125
|
+
exports.hydrate = hydrate;
|
|
2126
|
+
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
|
2127
|
+
return exports;
|
|
2128
|
+
}({});
|