@livenetworks/ashlar 2.1.10 → 2.1.11

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.
@@ -1000,7 +1000,7 @@ The component calls `_ensureDefaultItemTemplate()` at the top of `_initUpload()`
1000
1000
  | ln-search | Instance | `data-ln-search` | Generic search (textContent filter) |
1001
1001
  | ln-filter | Instance | `data-ln-filter` | Generic filter (data attribute filter) |
1002
1002
  | ln-sort | Instance | `data-ln-sort` | Sort control primitive — 3-trigger cycle (none→asc→desc→none), search-precedent cancelable event; targets ln-table, ln-list, or plain lists |
1003
- | ln-table | Instance | `data-ln-table` | Data table (search, filter, sort, virtual scroll; opt-in server-side windowed virtualization via `data-ln-table-window`) |
1003
+ | ln-table | Instance | `data-ln-table` | Data table (search, filter, sort, and viewport row virtualization) |
1004
1004
  | ln-chart | Instance | `data-ln-chart` | SVG line/area dataset renderer with `ln-data-coordinator` binding |
1005
1005
  | ln-sortable | Instance | `data-ln-sortable` | Drag & drop reorder |
1006
1006
  | ln-picklist | Instance | `data-ln-picklist` | Two-list checkbox selection |
@@ -19,6 +19,24 @@
19
19
  </ul>
20
20
  ```
21
21
 
22
+ ### ⚡ Server-Rendered (SSR) Instant Seed
23
+ Embed authoritative server data directly in a `<script type="application/json">` child (or point to it via `data-ln-data-store-seed="#my-seed"`). The store parses the array on initialization and serves reads with zero network latency:
24
+
25
+ ```html
26
+ <ul id="tenants"
27
+ data-ln-data-store
28
+ data-ln-data-store-indexes="status,package_id"
29
+ data-ln-data-store-search-fields="name,slug"
30
+ hidden>
31
+ <script type="application/json">
32
+ [
33
+ {"id": 1, "name": "Acme Corp", "slug": "acme", "status": "active"},
34
+ {"id": 2, "name": "Globex", "slug": "globex", "status": "pending"}
35
+ ]
36
+ </script>
37
+ </ul>
38
+ ```
39
+
22
40
  ---
23
41
 
24
42
  ## 🌐 Declarative Attributes
@@ -27,6 +45,7 @@
27
45
  |---|---|---|
28
46
  | `id="name"` | Unique identifier of the store (the store name). | *Required* |
29
47
  | `data-ln-data-store` | Marker attribute to declare the component. | *Required* |
48
+ | `data-ln-data-store-seed="…"` | Selector or element ID of an external seed script block containing an initial JSON records array. | *Optional* |
30
49
  | `data-ln-data-store-stale="N"` | Seconds before cache is considered stale. Set to `never` or `-1` to disable staleness. | `300` |
31
50
  | `data-ln-data-store-indexes="…"` | Comma-separated list of IndexedDB index fields. | `""` |
32
51
  | `data-ln-data-store-search-fields="…"` | Comma-separated list of text-search fields for local query search matching. | `""` |
@@ -1 +1 @@
1
- (function(){"use strict";function pe(){return typeof window>"u"?!1:window.lnDebug===!0||window.lnCore&&window.lnCore._debugSink?!0:typeof document<"u"&&document.body?document.body.hasAttribute("data-ln-debug")||document.body.querySelector("[data-ln-debug]")!==null:!1}function oe(e){if(typeof window>"u")return!1;if(window.lnDebug===!0)return!0;if(window.lnCore&&window.lnCore._debugIsContained)return e?window.lnCore._debugIsContained(e):window.lnCore._debugSink!==null;if(e&&e.closest){const t=e.closest("[data-ln-debug]");return!(!t||typeof document<"u"&&t===document.documentElement)}return typeof document<"u"&&document.body?document.body.hasAttribute("data-ln-debug"):!1}if(typeof window<"u"&&(window.lnCore=window.lnCore||{},!window.lnCore._warnBound)){window.lnCore._warnBound=!0;const e=console.warn;console.warn=function(...t){if(typeof t[0]=="string"&&(t[0].startsWith("[ln-")||t[0].startsWith("[lnCore"))){let i=null;for(let a=1;a<t.length;a++)if(t[a]&&t[a].nodeType===1){i=t[a];break}if(!oe(i))return}e.apply(console,t)}}function A(e,t,r){const i=r||{};window.lnCore._debugSink&&window.lnCore._debugSink("event",t,e,i),e.dispatchEvent(new CustomEvent(t,{bubbles:!0,detail:i}))}function Z(e,t){if(!document.body){document.addEventListener("DOMContentLoaded",function(){Z(e,t)}),console.warn("["+t+'] Script loaded before <body> — add "defer" to your <script> tag');return}e()}function Ue(e){const t=e.querySelector('input[name="_method"]');return((t&&t.value!==""?t.value:e.method)||"").toUpperCase()}function Ge(e,t){const r=!!(t&&t.typed),i=t&&t.exclude,a={},l=e.elements,c={};if(r)for(let d=0;d<l.length;d++){const s=l[d];s.name&&s.type==="checkbox"&&!s.disabled&&(c[s.name]=(c[s.name]||0)+1)}for(let d=0;d<l.length;d++){const s=l[d];if(!(!s.name||s.disabled||s.type==="file"||s.type==="submit"||s.type==="button")&&!(i&&s.matches&&s.matches(i)))if(s.type==="checkbox")r&&c[s.name]===1?a[s.name]=s.checked:(a[s.name]||(a[s.name]=[]),s.checked&&a[s.name].push(s.value));else if(s.type==="radio")s.checked&&(a[s.name]=s.value);else if(s.type==="select-multiple"){a[s.name]=[];for(let w=0;w<s.options.length;w++)s.options[w].selected&&a[s.name].push(s.options[w].value)}else if(r&&s.type==="hidden")a[s.name]=s.value;else if(r&&(s.type==="number"||s.type==="range")){const w=Number(s.value);a[s.name]=s.value===""||isNaN(w)?null:w}else a[s.name]=s.value}return a}function Ve(e){if(typeof e!="string")return!!e;const t=e.trim().toLowerCase();return t!=="false"&&t!=="0"&&t!==""&&t!=="off"&&t!=="no"}function We(e,t){const r=e.elements,i=[],a={};for(let l=0;l<r.length;l++){const c=r[l];c.name&&c.type==="checkbox"&&(a[c.name]=(a[c.name]||0)+1)}for(let l=0;l<r.length;l++){const c=r[l];if(c.type==="file"||c.type==="submit"||c.type==="button")continue;const d=c.getAttribute("data-ln-fill-as")||c.name;if(!d||!(d in t))continue;const s=t[d];if(c.type==="checkbox"){if(Array.isArray(s))c.checked=s.indexOf(c.value)!==-1;else if(a[c.name]>1){const w=String(s).split(",").map(function(b){return b.trim()});c.checked=w.indexOf(c.value)!==-1}else c.checked=Ve(s);i.push(c)}else if(c.type==="radio")c.checked=c.value===String(s),i.push(c);else if(c.type==="select-multiple"){if(Array.isArray(s))for(let w=0;w<c.options.length;w++)c.options[w].selected=s.indexOf(c.options[w].value)!==-1;i.push(c)}else c.value=s,c.tagName==="SELECT"&&s!=null&&c.setAttribute("data-ln-value",s),i.push(c)}return i}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.populateForm=We,window.lnCore.serializeForm=Ge,window.lnCore.resolveFormMethod=Ue);const ge={};function He(e,t){ge[e]=t}function Qe(e){return ge[e]||{ingress:t=>t,egress:t=>t}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.registerDataMapper=He,window.lnCore.getDataMapper=Qe);function Je(){typeof window>"u"||(window.lnCore=window.lnCore||{},!window.lnCore._localeObserverBound&&(window.lnCore._localeObserverBound=!0,Z(function(){new MutationObserver(function(){A(document,"ln-core:locale-change",{})}).observe(document.documentElement,{attributes:!0,attributeFilter:["lang"],subtree:!0})},"ln-core")))}const me={};function Ze(e,t){if(!e||typeof t!="object")return;const r=e.toLowerCase().split("-")[0];me[r]=t}function Xe(e){if(!e)return null;const t=e.toLowerCase().split("-")[0];return me[t]||null}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.registerLocaleFallback=Ze,window.lnCore.getLocaleFallback=Xe,window.lnCore.ensureLocaleObserver=Je);const ie={};function Ye(e,t){ie[e]||(ie[e]=document.querySelector('[data-ln-template="'+e+'"]'));const r=ie[e];return r?r.content.cloneNode(!0):(console.warn("["+(t||"ln-core")+'] Template "'+e+'" not found'),null)}function be(e,t){if(!e||!t)return e;const r=e.querySelectorAll("[data-ln-field]");for(let c=0;c<r.length;c++){const d=r[c],s=d.getAttribute("data-ln-field");t[s]!=null&&(d.textContent=t[s])}const i=e.querySelectorAll("[data-ln-attr]");for(let c=0;c<i.length;c++){const d=i[c],s=d.getAttribute("data-ln-attr").split(",");for(let w=0;w<s.length;w++){const b=s[w].trim().split(":");if(b.length!==2)continue;const _=b[0].trim(),x=b[1].trim();t[x]!=null&&d.setAttribute(_,t[x])}}const a=e.querySelectorAll("[data-ln-show]");for(let c=0;c<a.length;c++){const d=a[c],s=d.getAttribute("data-ln-show");s in t&&d.classList.toggle("hidden",!t[s])}const l=e.querySelectorAll("[data-ln-class]");for(let c=0;c<l.length;c++){const d=l[c],s=d.getAttribute("data-ln-class").split(",");for(let w=0;w<s.length;w++){const b=s[w].trim().split(":");if(b.length!==2)continue;const _=b[0].trim(),x=b[1].trim();x in t&&d.classList.toggle(_,!!t[x])}}return e}function et(e,t){e.matches&&e.matches("[data-ln-form], [data-ln-fillable]")&&(window.lnCore._debugSink&&window.lnCore._debugSink("event","ln-fill",e,t??null),e.dispatchEvent(new CustomEvent("ln-fill",{detail:t??null,bubbles:!0})));const r=e.querySelectorAll("[data-ln-form], [data-ln-fillable]");for(let i=0;i<r.length;i++)window.lnCore._debugSink&&window.lnCore._debugSink("event","ln-fill",r[i],t??null),r[i].dispatchEvent(new CustomEvent("ln-fill",{detail:t??null,bubbles:!0}));return e}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore._fillBound||(window.lnCore._fillBound=!0,document.addEventListener("ln-fill",function(e){if(!(!e.target.matches||!e.target.matches("[data-ln-fillable]")))if(e.detail)be(e.target,e.detail);else{const t=e.target.querySelectorAll("[data-ln-field]");for(let r=0;r<t.length;r++)t[r].textContent=""}})));function _e(e,t){if(!e||!t)return e;const r=document.createTreeWalker(e,NodeFilter.SHOW_TEXT);for(;r.nextNode();){const l=r.currentNode;l.textContent.indexOf("{{")!==-1&&(l.textContent=l.textContent.replace(/\{\{\s*(\w+)\s*\}\}/g,function(c,d){return t[d]!==void 0?t[d]:""}))}const i=function(l,c){return t[c]!==void 0?t[c]:""},a=Array.from(e.querySelectorAll("*"));e.nodeType===1&&a.push(e);for(let l=0;l<a.length;l++){const c=a[l],d=c.attributes;for(let s=0;s<d.length;s++){const w=d[s];w.value.indexOf("{{")!==-1&&c.setAttribute(w.name,w.value.replace(/\{\{\s*(\w+)\s*\}\}/g,i))}}return e}function tt(e,t,r,i,a,l){const c={};for(let s=0;s<e.children.length;s++){const w=e.children[s],b=w.getAttribute("data-ln-render-key");b&&(c[b]=w)}const d=document.createDocumentFragment();for(let s=0;s<t.length;s++){const w=t[s],b=String(i(w));let _=c[b];if(_)a(_,w,s);else{const x=Ye(r,l);if(!x||(_e(x,w),_=x.firstElementChild,!_))continue;_.setAttribute("data-ln-render-key",b),a(_,w,s)}d.appendChild(_)}e.textContent="",e.appendChild(d)}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.fillTemplate=_e,window.lnCore.fill=be,window.lnCore.lnFill=et,window.lnCore.renderList=tt);function ae(e,t,r){const i=e.getAttribute(t);return i===null?r:i}function X(e,t,r){const i=parseInt(e.getAttribute(t),10);return isNaN(i)?r:i}function se(e,t,r=!1){const i=e.getAttribute(t);if(i===null)return!!r;const a=i.trim().toLowerCase();return!(a==="false"||a==="0")}function le(e,t){return(e.getAttribute(t)||"").split(",").map(r=>r.trim()).filter(Boolean)}const ce=new Map;function Ce(e,t){const r=(e?e.join("|"):"")+"::"+t;if(ce.has(r))return ce.get(r);const i=new Set(e||[]),a=function(l,c){const d=l.getAttribute(c);return d!==null&&i.has(d)?d:t};return ce.set(r,a),a}function Se(e,t,r){const i=parseFloat(e.getAttribute(t));return isNaN(i)?r:i}function Ae(e,t,r){const i=e.getAttribute(t);if(!i)return r;try{return JSON.parse(i)}catch{return r}}function ve(e,t,r,i,a){if(!e||t===null)return!0;const l=i||"ln-component",c=e.type;if(c==="trigger"||c==="marker"||c==="string"||c==="list"||!c||t===""&&e.fallback!==void 0)return!0;const d=s=>{a?console.warn(s,a):console.warn(s)};if(c==="boolean"){const s=t.trim().toLowerCase();return s!==""&&s!=="true"&&s!=="false"&&s!=="1"&&s!=="0"?(d(`[${l}] Invalid value "${t}" for boolean attribute "${r}". Allowed: "true", "false", or presence-only.`),!1):!0}if(c==="enum"){const s=e.values||[];return s.includes(t)?!0:(d(`[${l}] Invalid value "${t}" for attribute "${r}". Allowed: ${s.join(", ")}. Fallback: "${e.fallback}".`),!1)}if(c==="integer"){if(!/^-?\d+$/.test(t))return d(`[${l}] Invalid integer "${t}" for attribute "${r}". Fallback: ${e.fallback}.`),!1;const s=parseInt(t,10);return e.min!==void 0&&s<e.min?(d(`[${l}] Value ${s} for attribute "${r}" is less than min (${e.min}).`),!1):e.max!==void 0&&s>e.max?(d(`[${l}] Value ${s} for attribute "${r}" is greater than max (${e.max}).`),!1):!0}if(c==="float")return isNaN(Number(t))?(d(`[${l}] Invalid float "${t}" for attribute "${r}". Fallback: ${e.fallback}.`),!1):!0;if(c==="json")try{return JSON.parse(t),!0}catch(s){return d(`[${l}] Invalid JSON for attribute "${r}": ${s.message}. Fallback: ${e.fallback}.`),!1}return!0}function xe(e,t,r){for(const i in r){const[a,l,c]=r[i];Object.defineProperty(e,i,{get:function(){return a(t,l,c)},enumerable:!0,configurable:!0})}return e}function ke(e){const t={};for(const r in e){const i=e[r];if(!i||!i.prop)continue;let a=i.read;if(!a&&i.type)switch(i.type){case"enum":a=Ce(i.values,i.fallback);break;case"integer":a=X;break;case"float":a=Se;break;case"boolean":a=se;break;case"list":a=le;break;case"json":a=Ae;break;case"string":default:a=ae;break}a||(a=ae),t[i.prop]=[a,r,i.fallback]}return t}function nt(e){const t={};for(const r in e){const i=e[r];i&&i.effect&&(t[r]=i.effect)}return Object.keys(t).length?t:null}function rt(e){if(e.onAttrChange&&!e.declared)return null;const t=new Set;if(e.effects)for(const r in e.effects)t.add(r);if(e.onAttrChange&&e.declared)for(const r of e.declared)t.add(r);return t}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.defineAttrs=xe,window.lnCore.attrSpec=ke,window.lnCore.attrStr=ae,window.lnCore.attrInt=X,window.lnCore.attrBool=se,window.lnCore.attrList=le,window.lnCore.attrEnum=Ce,window.lnCore.attrFloat=Se,window.lnCore.attrJson=Ae);function V(e,t){if(!e[t.attribute]){window.lnCore._persistSink&&e.hasAttribute&&e.hasAttribute("data-ln-persist")&&window.lnCore._persistSink(e,t.selector);try{e[t.attribute]=new t.ComponentFn(e)}catch(r){console.error("["+t.attribute+"] init failed",e,r)}}}function qe(e,t,r,i){if(e.nodeType!==1)return;const l=t.indexOf("[")!==-1||t.indexOf(".")!==-1||t.indexOf("#")!==-1?t:"["+t+"]",c={selector:t,attribute:r,ComponentFn:i};if(e.matches&&e.matches(l)&&V(e,c),e.querySelectorAll){const d=e.querySelectorAll(l);for(let s=0;s<d.length;s++)V(d[s],c)}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore._bootHolds=window.lnCore._bootHolds||0,window.lnCore._bootQueue=window.lnCore._bootQueue||[]);function ot(){return typeof window<"u"&&window.lnCore&&window.lnCore._bootHolds||0}function it(e){typeof window<"u"?(window.lnCore=window.lnCore||{},window.lnCore._bootHolds=window.lnCore._bootHolds||0,window.lnCore._bootQueue=window.lnCore._bootQueue||[],window.lnCore._bootHolds>0?window.lnCore._bootQueue.push(e):setTimeout(e,0)):e()}function Ee(){window.lnCore=window.lnCore||{};const e=window.lnCore._attrRegistry=window.lnCore._attrRegistry||{byAttr:new Map,reactive:[],persist:[]};return e.byReactive=e.byReactive||new Map,e.reactiveWildcard=e.reactiveWildcard||[],e}function at(e){const t=Ee(),r=e.observed||[];for(let i=0;i<r.length;i++){const a=r[i];t.byAttr.has(a)||t.byAttr.set(a,[]),t.byAttr.get(a).push(e)}if(t.byDeclaredAttr=t.byDeclaredAttr||new Map,e.attributes)for(const i in e.attributes){t.byDeclaredAttr.has(i)||t.byDeclaredAttr.set(i,[]);const a=t.byDeclaredAttr.get(i);a.some(l=>l.componentTag===e.componentTag)||a.push({spec:e.attributes[i],componentTag:e.componentTag})}if(e.onAttrChange||e.effects){t.reactive.push(e);const i=rt(e);if(i===null)t.reactiveWildcard.push(e);else for(const a of i)t.byReactive.has(a)||t.byReactive.set(a,[]),t.byReactive.get(a).push(e)}e.persist&&t.persist.push(e)}function Ie(e,t,r,i){for(let a=0;a<e.length;a++){const l=e[a];if(!t[l.attribute])continue;const c=l.effects&&l.effects[r];c?c(t,r,i):l.onAttrChange&&(!l.declared||l.declared.has(r))&&l.onAttrChange(t,r,i)}}function st(e){const t=e.attributeName,r=t.indexOf("data-ln-")===0,i=Ee(),a=i.byAttr.get(t),l=pe()&&i.byDeclaredAttr&&i.byDeclaredAttr.has(t);if(!r&&!a&&!l)return;const c=e.target;if(e.oldValue!==c.getAttribute(t)){if(l&&oe(c)){const d=i.byDeclaredAttr.get(t),s=c.getAttribute(t);for(let w=0;w<d.length;w++)ve(d[w].spec,s,t,d[w].componentTag,c)}if(window.lnCore._debugSink&&(r||a)&&window.lnCore._debugSink("attr",t,c,{oldValue:e.oldValue,newValue:c.getAttribute(t)}),r){const d=i.byReactive.get(t);d&&Ie(d,c,t,e.oldValue),i.reactiveWildcard.length&&Ie(i.reactiveWildcard,c,t,e.oldValue)}if(a)for(let d=0;d<a.length;d++){const s=a[d];if(s.handler){s.handler(c,t,e.oldValue);continue}s.onAttributeChange&&c[s.attribute]?s.onAttributeChange(c,t):(qe(c,s.selector,s.attribute,s.ComponentFn),s.onInit&&s.onInit(c))}}}function lt(){window.lnCore=window.lnCore||{},!window.lnCore._attrObserverBound&&(window.lnCore._attrObserverBound=!0,Z(function(){new MutationObserver(function(t){for(let r=0;r<t.length;r++)try{st(t[r])}catch(i){console.error("[ln-core] mutation handler failed",t[r].target,i)}}).observe(document.body,{attributes:!0,subtree:!0,attributeOldValue:!0})},"ln-core"))}function ue(){return window.lnCore=window.lnCore||{},window.lnCore._lifecycleRegistry=window.lnCore._lifecycleRegistry||[]}function de(){return window.lnCore=window.lnCore||{},window.lnCore._subtreeRegistry=window.lnCore._subtreeRegistry||[]}function fe(e,t){if(!document.contains(e))if(t.attribute){const r=e[t.attribute];if(r&&typeof r.destroy=="function")try{r.destroy()}catch(i){console.error("["+t.attribute+"] destroy failed",e,i)}delete e[t.attribute]}else t.onDestroy&&t.onDestroy(e)}function Le(e){const t=ue();if(!t.length)return;const r=e.target;if(r){const a=r.nodeType===1?r:r.parentElement;if(a&&(a.isContentEditable||a.closest&&a.closest('[contenteditable]:not([contenteditable="false"])')))return}const i=de();if(e.target&&i.length)for(let a=0;a<i.length;a++){const l=i[a],c=l.query,d=e.target.nodeType===1?e.target.matches&&e.target.matches(c)?e.target:e.target.closest?e.target.closest(c):null:e.target.parentElement&&e.target.parentElement.closest?e.target.parentElement.closest(c):null;d&&l.onSubtreeChange(d,e)}for(let a=0;a<e.addedNodes.length;a++){const l=e.addedNodes[a];if(l.nodeType===1){const c=!!(l.firstElementChild||l.children&&l.children.length);for(let d=0;d<t.length;d++){const s=t[d];if(s.selector&&s.attribute&&s.ComponentFn){if(!c)l.matches&&l.matches(s.query)&&V(l,s);else if(l.matches&&l.matches(s.query)&&V(l,s),l.querySelectorAll){const w=l.querySelectorAll(s.query);for(let b=0;b<w.length;b++)V(w[b],s)}}s.onInit&&s.onInit(l)}}}for(let a=0;a<e.removedNodes.length;a++){const l=e.removedNodes[a];if(l.nodeType===1){if(document.contains(l))continue;const c=!!(l.firstElementChild||l.children&&l.children.length);for(let d=0;d<t.length;d++){const s=t[d],w=s.query;if(w){if(!c)l.matches&&l.matches(w)&&fe(l,s);else if(l.matches&&l.matches(w)&&fe(l,s),l.querySelectorAll){const b=l.querySelectorAll(w);for(let _=0;_<b.length;_++)fe(b[_],s)}}}}}}function De(){window.lnCore=window.lnCore||{},!window.lnCore._lifecycleObserverBound&&(window.lnCore._lifecycleObserverBound=!0,Z(function(){const e=new MutationObserver(function(t){for(let r=0;r<t.length;r++){const i=t[r];if(i.type==="childList")try{Le(i)}catch(a){console.error("[ln-core] lifecycle handler failed",i.target,a)}}});window.lnCore._lifecycleObserver=e,e.observe(document.body,{childList:!0,subtree:!0})},"ln-core"))}function ct(e){if(typeof window>"u")return e();window.lnCore=window.lnCore||{};const t=window.lnCore._lifecycleObserver;if(!t)return e();const r=t.takeRecords();for(let i=0;i<r.length;i++){const a=r[i];if(a.type==="childList")try{Le(a)}catch(l){console.error("[ln-core] lifecycle handler failed",a.target,l)}}t.disconnect();try{return e()}finally{t.observe(document.body,{childList:!0,subtree:!0})}}function ut(e){ue().push(e),e.onSubtreeChange&&e.query&&de().push(e),De()}function Ne(e,t,r,i,a={}){const l=a.extraAttributes||[],c=a.onAttributeChange||null,d=a.onSubtreeChange||null,s=a.onInit||null,w=a.onAttrChange||null,b=a.effects||null,_=a.attributes||null,x=_?nt(_):b,j=_?new Set(Object.keys(_)):null,$=a.persist||null;function g(L){const D=L||document.body;if(qe(D,e,t,r),_&&pe())for(const M in _){const we=_[M],U=Array.from(D.querySelectorAll("["+M+"]"));D.matches&&D.matches("["+M+"]")&&U.push(D);for(let P=0;P<U.length;P++){const H=U[P];oe(H)&&ve(we,H.getAttribute(M),M,i,H)}}s&&s(D)}const S=[];if(e.indexOf("[")!==-1){const L=/\[([\w-]+)/g;let D;for(;(D=L.exec(e))!==null;)S.push(D[1])}else S.push(e);at({selector:e,attribute:t,componentTag:i,attributes:_,ComponentFn:r,onInit:s,observed:S.concat(l),onAttributeChange:c,onAttrChange:w,effects:x,declared:j,persist:$}),lt();const I=e.indexOf("[")!==-1||e.indexOf(".")!==-1||e.indexOf("#")!==-1,k=a.subtreeQuery||(I?e:"["+e+"]"),v={selector:e,attribute:t,ComponentFn:r,onInit:s,onSubtreeChange:d,query:k};ue().push(v),d&&k&&de().push(v),De(),window[t]=g,typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.registerComponent=Ne,window.lnCore.observeLifecycle=ut,window.lnCore.withoutLifecycle=ct);function q(){ot()>0?it(function(){g(document.body)}):g(document.body)}return document.readyState==="loading"?document.addEventListener("DOMContentLoaded",q):q(),g}function dt(e){let t=!1;for(let r=0;r<e.length;r++){const i=e[r];if(!(i===""||i==null)&&(t=!0,!Number.isFinite(Number(i))))return"string"}return t?"number":"string"}function ft(e,t,r,i){if(r==="number"){const c=parseFloat(e),d=parseFloat(t);return(isNaN(c)?0:c)-(isNaN(d)?0:d)}const a=e!=null?String(e):"",l=t!=null?String(t):"";return i?i.compare(a,l):a<l?-1:a>l?1:0}function Te(e){return(e||"").replace(/^#/,"")}function he(e){const t=e===void 0?location.hash:e,r={},i=Te(t);if(!i)return r;const a=i.split("&");for(let l=0;l<a.length;l++){const c=a[l];if(!c)continue;const d=c.indexOf(":"),s=d>-1?c.slice(0,d):c,w=d>-1?c.slice(d+1):"";if(s)try{r[s]=decodeURIComponent(w)}catch{r[s]=w}}return r}function ht(e){if(!e)return null;const t=he();return e in t?t[e]:null}function wt(e,t){if(!e)return;const r=he();t==null?delete r[e]:r[e]=String(t);const a=Object.keys(r).map(function(l){const c=r[l];return c===""?l:l+":"+encodeURIComponent(c)}).join("&");Te(location.hash)!==a&&(location.hash=a)}function yt(e){return e.button===1||e.ctrlKey||e.metaKey||e.shiftKey?!1:(e.preventDefault(),!0)}function pt(e,t){if(!e||!e.hasAttribute("data-ln-hash"))return null;const r=e.getAttribute("data-ln-hash");if(r&&r.trim()!=="")return r.trim();const i=e.getAttribute("data-ln-sort")||e.getAttribute("data-ln-search-for")||e.getAttribute("data-ln-search")||e.getAttribute("data-ln-filter")||e.id;return i?t?i+"-"+t:i:t||null}function gt(e,t){return!t||t==="none"||e===null||e===void 0?null:String(e)+"."+t}function mt(e){return!e||typeof e!="string"?null:e.endsWith(".asc")?{fieldOrColumn:e.slice(0,-4),direction:"asc"}:e.endsWith(".desc")?{fieldOrColumn:e.slice(0,-5),direction:"desc"}:null}function bt(e,t){return!e||!Array.isArray(t)||t.length===0?null:e+":"+t.map(encodeURIComponent).join(",")}function _t(e){if(!e||typeof e!="string")return null;const t=e.indexOf(":");if(t===-1)return null;const r=e.slice(0,t),i=e.slice(t+1),a=i?i.split(",").map(function(l){try{return decodeURIComponent(l)}catch{return l}}).filter(Boolean):[];return{key:r,values:a}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.hashParse=he,window.lnCore.hashGet=ht,window.lnCore.hashSet=wt,window.lnCore.hashLinkClick=yt,window.lnCore.resolveHashNamespace=pt,window.lnCore.hashSortEncode=gt,window.lnCore.hashSortDecode=mt,window.lnCore.hashFilterEncode=bt,window.lnCore.hashFilterDecode=_t);function Ct(e){return(e||"").replace(/^\?/,"")}function St(e){const t=e===void 0?typeof window<"u"?window.location.search:"":e,r={},i=Ct(t);if(!i)return r;const a=new URLSearchParams(i);for(const[l,c]of a.entries())r[l]=c;return r}function At(e){if(!e||typeof window>"u")return null;const t=new URLSearchParams(window.location.search);return t.has(e)?t.get(e):null}function vt(e,t){if(!e||typeof window>"u")return;const r=new URL(window.location.href);if(t==null||t===""?r.searchParams.delete(e):r.searchParams.set(e,String(t)),r.search===window.location.search)return;const i=r.pathname+r.search+r.hash;window.history.replaceState(window.history.state,"",i)}function xt(e,t){if(!e||!e.hasAttribute("data-ln-query"))return null;const r=e.getAttribute("data-ln-query");if(r&&r.trim()!=="")return r.trim();const i=e.getAttribute("data-ln-sort")||e.getAttribute("data-ln-search-for")||e.getAttribute("data-ln-search")||e.getAttribute("data-ln-filter")||e.id;return i?t?i+"_"+t:i:t||null}function kt(e,t){return!t||t==="none"||e===null||e===void 0?null:String(e)+"."+t}function qt(e,t){if(e&&typeof e=="string"){if(e.endsWith(".asc"))return{fieldOrColumn:e.slice(0,-4),direction:"asc"};if(e.endsWith(".desc"))return{fieldOrColumn:e.slice(0,-5),direction:"desc"}}if(t&&typeof t=="object"){const r=t.sort_field||t.sort_by;if(r){const i=t.sort_dir&&String(t.sort_dir).toLowerCase()==="desc"?"desc":"asc";return{fieldOrColumn:r,direction:i}}}return null}function Et(e){return!Array.isArray(e)||e.length===0?null:e.map(encodeURIComponent).join(",")}function It(e){return!e||typeof e!="string"?[]:e.split(",").map(function(t){try{return decodeURIComponent(t.trim())}catch{return t.trim()}}).filter(Boolean)}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.queryParse=St,window.lnCore.queryGet=At,window.lnCore.querySet=vt,window.lnCore.resolveQueryParam=xt,window.lnCore.querySortEncode=kt,window.lnCore.querySortDecode=qt,window.lnCore.queryFilterEncode=Et,window.lnCore.queryFilterDecode=It);let W=null;const Lt="ln-ashlar:storage-salt:v1",Re=32768;function ze(e){let t="";const r=e.byteLength;for(let i=0;i<r;i+=Re)t+=String.fromCharCode.apply(null,e.subarray(i,Math.min(i+Re,r)));return btoa(t)}function Oe(e){const t=atob(e),r=t.length,i=new Uint8Array(r);for(let a=0;a<r;a++)i[a]=t.charCodeAt(a);return i}function Fe(e,t){let r=W,i={};return typeof CryptoKey<"u"&&e instanceof CryptoKey?r=e:e&&typeof e=="object"&&(i=e,typeof CryptoKey<"u"&&i.key instanceof CryptoKey&&(r=i.key)),{key:r,options:i}}async function Dt(e,t={}){if(!e)throw new Error("[ln-crypto] Key derivation failed: Secret string is required");const r=t.method||"pbkdf2",i=new TextEncoder;if(r==="sha256"){const s=await crypto.subtle.digest("SHA-256",i.encode(e));return crypto.subtle.importKey("raw",s,{name:"AES-GCM"},!1,["encrypt","decrypt"])}const a=t.salt||Lt,l=typeof a=="string"?i.encode(a):a,c=t.iterations||1e5,d=await crypto.subtle.importKey("raw",i.encode(e),"PBKDF2",!1,["deriveKey"]);return crypto.subtle.deriveKey({name:"PBKDF2",salt:l,iterations:c,hash:"SHA-256"},d,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}async function Be(e,t={}){if(!e){W=null;return}try{const r=t.method||"sha256";W=await Dt(e,{...t,method:r})}catch(r){throw console.error("[ln-core/crypto] Key derivation failed:",r),W=null,r}}function B(){return W}async function Nt(e,t,r){const{key:i}=Fe(t);if(e==null)return e;if(!i)throw new Error("[ln-crypto] Encryption failed: No active cryptographic key provided");try{const a=new TextEncoder,l=crypto.getRandomValues(new Uint8Array(12)),c=typeof e=="string"?e:JSON.stringify(e),d=await crypto.subtle.encrypt({name:"AES-GCM",iv:l},i,a.encode(c));return{v:1,alg:"AES-GCM",encrypted:!0,iv:ze(l),data:ze(new Uint8Array(d))}}catch(a){throw console.error("[ln-core/crypto] Encryption failed:",a),new Error("[ln-crypto] Encryption failed: "+(a&&a.message?a.message:String(a)))}}async function Tt(e,t,r){const{key:i,options:a}=Fe(t),l=a.silent===!0;if(!e||!e.encrypted)return e;if(!i){if(l)return{...e,decryptionError:!0};throw new Error("[ln-crypto] Decryption failed: No active cryptographic key provided")}if(!e.iv||!e.data){if(l)return{...e,decryptionError:!0};throw new Error("[ln-crypto] Decryption failed: Malformed envelope (missing iv or data)")}try{const c=new TextDecoder,d=Oe(e.iv),s=Oe(e.data),w=await crypto.subtle.decrypt({name:"AES-GCM",iv:d},i,s),b=c.decode(w);try{return JSON.parse(b)}catch{return b}}catch(c){if(l)return{...e,decryptionError:!0};throw console.error("[ln-core/crypto] Decryption failed. Key may be incorrect or payload tampered:",c),new Error("[ln-crypto] Decryption failed. Key may be incorrect or payload tampered: "+(c&&c.message?c.message:String(c)))}}function Rt(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{const t=Math.random()*16|0;return(e==="x"?t:t&3|8).toString(16)})}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.uuid=Rt);function zt(e){return String(e||"").trim().toLowerCase()}function Ot(e){const t=zt(e);return t?t.split(/\s+/).filter(Boolean):[]}function Ft(e,t){if(!t||t.length===0)return!0;if(!e)return!1;const r=String(e).toLowerCase();for(let i=0;i<t.length;i++)if(r.indexOf(t[i])===-1)return!1;return!0}function Bt(e,t){if(!t||t.length===0)return!0;if(e==null)return!1;const r=String(e).trim().toLowerCase();for(let i=0;i<t.length;i++)if(String(t[i]).trim().toLowerCase()===r)return!0;return!1}function Mt(e={}){let t=e.windowSize>0?e.windowSize:1e3,r=e.pageSize>0?e.pageSize:200,i=e.fetchDebounce!=null?e.fetchDebounce:120;const a=typeof e.requestPage=="function"?e.requestPage:()=>{},l=new Map,c=new Set;let d=0,s=0,w=0,b=!1,_=null;function x(g,S){l.delete(g),l.set(g,S)}function j(){if(l.size<=t)return[];const g=[];for(;l.size>t;){const I=l.keys().next().value;g.push(l.get(I)),l.delete(I)}const S=new Set(l.values());return g.filter(I=>!S.has(I))}function $(g,S){c.add(g),clearTimeout(_),_=setTimeout(()=>a(g,r,S),i)}return{get logicalTotal(){return d},set logicalTotal(g){d=g},get grandTotal(){return s},set grandTotal(g){s=g},get queryGen(){return w},set queryGen(g){w=g},get size(){return l.size},get hasLoaded(){return b},getId:g=>{if(!l.has(g))return;const S=l.get(g);return x(g,S),S},ensure:(g,S,I)=>{if(!b&&!c.has(0))return $(0,I);if(d<=0)return;const k=Math.max(0,g),v=Math.min(d,S);for(let q=k;q<v;q++)if(!l.has(q)){const L=Math.floor(q/r)*r;if(!c.has(L))return $(L,I)}},ingest:(g,S,I,k,v)=>{if(v!=null&&v!==w)return[];b=!0,I!=null&&(s=I),k!=null&&(d=k);for(let q=0;q<S.length;q++)x(g+q,S[q]);return c.delete(g),j()},reset:function(){w++,this.clear()},clear:()=>{b=!1,l.clear(),c.clear(),clearTimeout(_)},configure:(g={})=>{let S=[];return g.windowSize>0&&g.windowSize!==t&&(t=g.windowSize,S=j()),g.pageSize>0&&(r=g.pageSize),g.fetchDebounce>=0&&(i=g.fetchDebounce),S}}}function Pt(e,t,r){if(!Array.isArray(e)||!t||!t.field)return e;const{field:i,direction:a}=t,l=a==="desc",c=e.map(s=>s?s[i]:void 0),d=dt(c);return[...e].sort((s,w)=>{const b=s?s[i]:void 0,_=w?w[i]:void 0,x=ft(b,_,d,r);return l?-x:x})}function Me(e,t){if(!Array.isArray(e)||!t||typeof t!="object")return e;const r=Object.keys(t).filter(i=>Array.isArray(t[i])&&t[i].length>0);return r.length?e.filter(i=>i?r.every(a=>Bt(i[a],t[a])):!1):e}function jt(e,t,r){if(!Array.isArray(e)||!t||!r||!r.length)return e;const i=Ot(t);return i.length?e.filter(a=>a?i.every(l=>r.some(c=>{const d=a[c];return d!=null&&Ft(String(d),[l])})):!1):e}function $t(e,t,r){if(!Array.isArray(e)||!e.length)return 0;if(r==="count")return e.length;const i=e.map(l=>l&&l[t]!=null?parseFloat(l[t]):NaN).filter(l=>Number.isFinite(l)),a=i.reduce((l,c)=>l+c,0);return r==="sum"?a:r==="avg"&&i.length?a/i.length:0}function Kt(e,t={},r=[],i){if(!Array.isArray(e))return{records:[],total:0,filtered:0};const a=e.length;let l=e;t.filters&&(l=Me(l,t.filters)),t.search&&(l=jt(l,t.search,r));const c=l.length;if(t.sort&&(l=Pt(l,t.sort,i)),t.offset||t.limit){const d=t.offset||0,s=t.limit||l.length;l=l.slice(d,d+s)}return{records:l,total:a,filtered:c}}function Ut(e,t){return!Array.isArray(e)||!t||typeof t!="object"?e:e.map(r=>{if(!r)return null;const i={...r};for(const[a,l]of Object.entries(t))if(typeof l=="function")try{i[a]=l(r)}catch{i[a]=void 0}return i})}function Gt(e,t,r,i="_meta"){if(!Array.isArray(e)||!e.includes(i))return!0;for(const a of Object.keys(t||{})){if(!e.includes(a))return!0;const l=t[a]&&t[a].indexes||[],c=r&&r[a]||[];if(l.some(d=>!c.includes(d)))return!0}return!1}function Vt(e){return{ok:!1,error:e&&e.message?e.message:String(e)}}(function(){const e="data-ln-data-store",t="lnDataStore";if(window[t]!==void 0)return;function r(n,o,u){const f=n.getAttribute(o);if(f==="never"||f==="-1")return-1;const h=parseInt(f,10);return isNaN(h)?u:h}const i={"data-ln-data-store":{type:"marker",effect:Ke,description:"Identifies the element as a data-store definition container"},"data-ln-data-store-indexes":{type:"list",effect:Ke,description:"Comma-separated index field names for the IndexedDB store"},"data-ln-data-store-stale":{prop:"_staleThreshold",type:"integer",read:r,fallback:300,description:"Cache staleness threshold in seconds, or -1/never"},"data-ln-data-store-search-fields":{prop:"_searchFields",type:"list",read:le,description:"Record fields to index for client-side search"},"data-ln-data-store-no-local-query":{prop:"noLocalQuery",type:"boolean",read:se,description:"Bypasses local IndexedDB query resolution, forcing remote fetching"},"data-ln-data-store-window":{prop:"_windowSize",type:"integer",read:X,fallback:1e3,min:10,effect:hn,description:"Virtual scrolling cache window size in records"},"data-ln-data-store-window-page":{prop:"_windowPageSize",type:"integer",read:X,fallback:200,min:5,effect:wn,description:"Virtual scrolling slice page size"},"data-ln-data-store-frozen":{type:"marker",description:"Applied at runtime to indicate store schema is locked in IndexedDB"}},a=ke(i),l="ln_app_cache",c="_meta",d="1.0";let s=null,w=null;const b={};function _(n){n&&n.name==="QuotaExceededError"&&A(document,"ln-data-store:quota-exceeded",{error:n})}function x(){const n={};for(const o of document.querySelectorAll(`[${e}]`)){const u=o.id;if(u){const f=o.getAttribute("data-ln-data-store-indexes")||"";n[u]={indexes:f.split(",").map(h=>h.trim()).filter(Boolean)}}}return n}function j(){return w||(w=new Promise(n=>{if(typeof indexedDB>"u")return console.warn("[ln-data-store] IndexedDB is not available in this environment"),n(null);const o=x(),u=Object.keys(o),f=indexedDB.open(l);f.onerror=()=>{console.warn("[ln-data-store] IndexedDB open failed"),n(null)},f.onsuccess=h=>{const y=h.target.result,p=Array.from(y.objectStoreNames),m=u.filter(T=>p.includes(T));let C={};if(m.length>0){const T=y.transaction(m,"readonly");for(const R of m)C[R]=Array.from(T.objectStore(R).indexNames)}if(!Gt(p,o,C,c))return $(y),s=y,n(y);const K=y.version;y.close();const F=indexedDB.open(l,K+1);let z=!1,O=null;F.onblocked=()=>{console.warn("[ln-data-store] Database upgrade blocked — waiting for other tabs to close connection"),A(document,"ln-data-store:blocked",{db:l}),O||(O=setTimeout(()=>{z||(console.warn("[ln-data-store] Database upgrade timed out while blocked"),z=!0,w=null,n(null))},5e3))},F.onerror=()=>{z||(O&&clearTimeout(O),z=!0,w=null,console.warn("[ln-data-store] Database upgrade failed"),n(null))},F.onupgradeneeded=T=>{const R=T.target.result,yn=T.target.transaction;R.objectStoreNames.contains(c)||R.createObjectStore(c,{keyPath:"key"});for(const J of u)if(R.objectStoreNames.contains(J)){const re=yn.objectStore(J);for(const G of o[J].indexes)re.indexNames.contains(G)||re.createIndex(G,G,{unique:!1})}else{const re=R.createObjectStore(J,{keyPath:"id"});for(const G of o[J].indexes)re.createIndex(G,G,{unique:!1})}},F.onsuccess=T=>{if(z){T.target.result&&T.target.result.close();return}O&&clearTimeout(O),z=!0;const R=T.target.result;$(R),s=R,n(R)}}}),w)}function $(n){n.onversionchange=()=>{n.close(),s=null,w=null}}function g(){return s?Promise.resolve(s):(w=null,j())}async function S(n){if(!B()||!n)return n;const o={...n},u=o.id,f=await Nt(o);return!f||!f.encrypted?n:{...f,id:u}}async function I(n){return!n||!n.encrypted||!B()?n:Tt(n,{silent:!0})}const k=(n,o)=>g().then(u=>u?u.transaction(n,o).objectStore(n):null);function v(n){return new Promise((o,u)=>{n.onsuccess=()=>o(n.result),n.onerror=()=>{_(n.error),u(n.error)}})}const q=n=>k(n,"readonly").then(o=>o?v(o.getAll()):[]).then(o=>B()?Promise.all(o.map(u=>I(u))):o),L=(n,o)=>k(n,"readonly").then(u=>u?v(u.get(o)).then(f=>f!==void 0?f:typeof o=="string"&&o.trim()!==""&&!isNaN(Number(o))?v(u.get(Number(o))):typeof o=="number"?v(u.get(String(o))):null):null).then(u=>u?I(u):null),D=(n,o)=>g().then(u=>{if(!u)return[];const h=u.transaction(n,"readonly").objectStore(n),y=o.map(p=>v(h.get(p)).then(m=>m!==void 0?m:typeof p=="string"&&p.trim()!==""&&!isNaN(Number(p))?v(h.get(Number(p))):typeof p=="number"?v(h.get(String(p))):null));return Promise.all(y).then(p=>B()?Promise.all(p.map(m=>m?I(m):null)):p)}),M=(n,o)=>(B()?S(o):Promise.resolve(o)).then(f=>k(n,"readwrite").then(h=>h?v(h.put(f)):null)),we=(n,o)=>k(n,"readwrite").then(u=>u?v(u.delete(o)).then(()=>{if(typeof o=="string"&&o.trim()!==""&&!isNaN(Number(o)))return v(u.delete(Number(o)));if(typeof o=="number")return v(u.delete(String(o)))}):null),U=n=>k(n,"readwrite").then(o=>o?v(o.clear()):null),P=n=>k(n,"readonly").then(o=>o?v(o.count()):0),H=n=>k(c,"readonly").then(o=>o?v(o.get(n)):null),Y=(n,o)=>k(c,"readwrite").then(u=>{if(u)return o.key=n,v(u.put(o))});function N(n){return this.dom=n,this._name=n.id,this._name||console.warn("[ln-data-store] missing id — the store cannot be addressed",n),xe(this,n,a),this._handlers=null,this.isLoaded=!1,this.canServe=!1,this.isInitialized=!1,this.initializationError=null,this.hasCache=!1,this.isSyncing=!1,this.lastSyncedAt=null,this.query={filters:{},search:"",sort:null},n.hasAttribute("data-ln-data-store-window")?this._windowIndex=Mt({windowSize:this._windowSize,pageSize:this._windowPageSize,requestPage:(o,u,f)=>{A(this.dom,"ln-data-store:request-page",{store:this._name,offset:o,limit:u,query:f,queryGen:this._windowIndex.queryGen})}}):this._windowIndex=null,this.windowed=this._windowIndex!==null,this.totalCount=0,this.presenters=null,this._mutationChain=Promise.resolve(),b[this._name]=this,Wt(this),this.ready=Yt(this),this}function Wt(n){n._handlers={create:o=>ee(n,"create",o.detail,()=>Ht(n,o.detail)),update:o=>ee(n,"update",o.detail,()=>Qt(n,o.detail)),delete:o=>ee(n,"delete",o.detail,()=>Jt(n,o.detail)),"bulk-delete":o=>ee(n,"bulk-delete",o.detail,()=>Zt(n,o.detail)),"sync-failed":o=>{n.isSyncing=!1,A(n.dom,"ln-data-store:sync-error",{store:n._name,error:o.detail&&o.detail.error,status:o.detail&&o.detail.status})}};for(const[o,u]of Object.entries(n._handlers))n.dom.addEventListener(`ln-data-store:request-${o}`,u);n._queryHandlers={"ln-search:change":o=>{o.preventDefault();const u=o.detail&&o.detail.term!=null?o.detail.term:"";u!==n.query.search&&(n.query.search=u,ye(n))},"ln-filter:change":o=>{o.preventDefault();const u=o.detail&&o.detail.key;if(!u)return;const f=(o.detail.values||[]).slice(),h=n.query.filters[u];(h?h.length===f.length&&h.every((p,m)=>p===f[m]):!f.length)||(f.length?n.query.filters[u]=f:delete n.query.filters[u],ye(n))},"ln-sort:change":o=>{o.preventDefault();const u=o.detail&&o.detail.field,f=o.detail&&o.detail.direction,h=f&&f!=="none"?{field:u,direction:f}:null,y=n.query.sort;!y&&!h||y&&h&&y.field===h.field&&y.direction===h.direction||(n.query.sort=h,ye(n))}};for(const[o,u]of Object.entries(n._queryHandlers))n.dom.addEventListener(o,u)}function ee(n,o,u,f){const h=u&&u.requestId;return n._mutationChain=n._mutationChain.then(()=>n.ready).then(()=>{if(n.initializationError)throw n.initializationError;return f()}).catch(y=>Xt(n,o,h,y)),n._mutationChain}function te(n,o=0){return P(n._name).then(u=>{if(n._windowIndex||n.windowed){const f=n.totalCount!=null?n.totalCount:u;n.totalCount=Math.max(0,f+o)}else n.totalCount=u;return n.hasCache=!0,n.isLoaded=!0,n.canServe=!0,Y(n._name,{schema_version:d,last_synced_at:n.lastSyncedAt,has_cache:!0,record_count:n.totalCount})})}function Ht(n,{tempId:o,data:u={},requestId:f}={}){const h={...u,id:o};return M(n._name,h).then(()=>te(n,1)).then(()=>{A(n.dom,"ln-data-store:created",{store:n._name,record:h,tempId:o,requestId:f})})}function Qt(n,{id:o,data:u={},requestId:f}={}){return L(n._name,o).then(h=>{if(!h)throw new Error(`Record not found: ${o}`);const y=h.id,p={...h,...u,id:y},m=u.id,C=m!==void 0&&m!==y;return(C?en(n._name,y,{...p,id:m}):M(n._name,p)).then(()=>te(n,0)).then(()=>{A(n.dom,"ln-data-store:updated",{store:n._name,record:C?{...p,id:m}:p,previous:h,requestId:f})})})}function Jt(n,{id:o,requestId:u}={}){return L(n._name,o).then(f=>{if(!f){A(n.dom,"ln-data-store:deleted",{store:n._name,id:o,requestId:u,missing:!0});return}const h=f.id;return we(n._name,h).then(()=>te(n,-1)).then(()=>{A(n.dom,"ln-data-store:deleted",{store:n._name,id:h,requestId:u})})})}function Zt(n,{ids:o=[],requestId:u}={}){return o.length?Promise.all(o.map(f=>L(n._name,f))).then(f=>{const h=f.filter(Boolean).map(y=>y.id);return ne(n._name,h).then(()=>te(n,-h.length)).then(()=>{A(n.dom,"ln-data-store:deleted",{store:n._name,ids:h,requestId:u})})}):(A(n.dom,"ln-data-store:deleted",{store:n._name,ids:[],requestId:u}),Promise.resolve())}function Xt(n,o,u,f){console.error("[ln-data-store] "+o+" failed:",f),A(n.dom,"ln-data-store:mutation-error",{store:n._name,action:o,requestId:u,error:f})}function Yt(n){return j().then(o=>{if(!o)throw new Error("IndexedDB is unavailable");return H(n._name)}).then(o=>{if(n.initializationError=null,o&&o.schema_version===d)n.lastSyncedAt=o.last_synced_at||null,n.totalCount=o.record_count||0,n.hasCache=o.has_cache===!0||n.totalCount>0,n.hasCache&&(n.isLoaded=!0,n.canServe=!0,A(n.dom,"ln-data-store:ready",{store:n._name,count:n.totalCount,source:"cache"})),n.isInitialized=!0,A(n.dom,"ln-data-store:initialized",{store:n._name,hasCache:n.hasCache,lastSyncedAt:n.lastSyncedAt,count:n.totalCount});else{if(o&&o.schema_version!==d)return U(n._name).then(()=>Y(n._name,{schema_version:d,last_synced_at:null,has_cache:!1,record_count:0})).then(()=>{n.isInitialized=!0,n.hasCache=!1,A(n.dom,"ln-data-store:initialized",{store:n._name,hasCache:!1,lastSyncedAt:null,count:0})});n.isInitialized=!0,n.hasCache=!1,A(n.dom,"ln-data-store:initialized",{store:n._name,hasCache:!1,lastSyncedAt:null,count:0})}}).catch(o=>(n.isInitialized=!0,n.isLoaded=!1,n.canServe=!1,n.hasCache=!1,n.isSyncing=!1,n.initializationError=o,A(n.dom,"ln-data-store:initialization-error",{store:n._name,error:o}),{ok:!1,error:o}))}function Pe(n){n.isSyncing=!0,A(n.dom,"ln-data-store:request-remote-sync",{since:n.lastSyncedAt})}function je(n,o){return g().then(u=>u?(B()?Promise.all(o.map(h=>S(h))):Promise.resolve(o)).then(h=>new Promise((y,p)=>{const m=u.transaction(n,"readwrite"),C=m.objectStore(n);h.forEach(E=>C.put(E)),m.oncomplete=()=>y(),m.onerror=()=>{_(m.error),p(m.error)}})):void 0)}function ne(n,o){return g().then(u=>{if(u)return new Promise((f,h)=>{const y=u.transaction(n,"readwrite"),p=y.objectStore(n);o.forEach(m=>{p.delete(m),typeof m=="string"&&m.trim()!==""&&!isNaN(Number(m))?p.delete(Number(m)):typeof m=="number"&&p.delete(String(m))}),y.oncomplete=()=>f(),y.onerror=()=>h(y.error)})})}function en(n,o,u){return(B()?S(u):Promise.resolve(u)).then(h=>g().then(y=>{if(y)return new Promise((p,m)=>{const C=y.transaction(n,"readwrite"),E=C.objectStore(n);E.put(h),E.delete(o),C.oncomplete=()=>p(),C.onerror=()=>{_(C.error),m(C.error)}})}))}const tn=new Intl.Collator(void 0,{numeric:!0,sensitivity:"base"});function nn(n){return n?Object.keys(n).filter(o=>Array.isArray(n[o])&&n[o].length>0):[]}function rn(n,o,u){return o.every(f=>u[f].map(String).includes(String(n[f])))}function on(n){return String(n||"").toLowerCase().split(/\s+/).filter(Boolean)}function an(n,o,u){return o.every(f=>u.some(h=>{const y=n[h];return y!=null&&String(y).toLowerCase().includes(f)}))}function sn(n,o,u){return $t(n,o,u)}function Q(n,o){return Ut(o,n.presenters&&n.presenters.computed)}function ln(n){return!n.sort&&!B()}function cn(n,o,u){const f=nn(o.filters),h=o.search?on(o.search):[],y=n._searchFields,p=h.length>0&&y&&y.length>0;return k(n._name,"readonly").then(m=>m?new Promise((C,E)=>{const K=[],F=m.openCursor();F.onsuccess=()=>{const z=F.result;if(!z||K.length>=u){C(K);return}const O=z.value;(!f.length||rn(O,f,o.filters))&&(!p||an(O,h,y))&&K.push(O),z.continue()},F.onerror=()=>E(F.error)}):[])}function $e(n,o,u){return Kt(o,u,n._searchFields,tn)}function un(n,o,u){const f=[];for(let y=o;y<o+u;y++){const p=n._windowIndex.getId(y);f.push(p)}const h=Array.from(new Set(f.filter(y=>y!==void 0)));return D(n._name,h).then(y=>{const p=new Map;for(let C=0;C<y.length;C++){const E=y[C];E&&p.set(String(E.id),E)}const m=[];for(let C=0;C<f.length;C++){const E=f[C];if(E===void 0)m.push(null);else{const K=p.get(String(E));m.push(K||null)}}return{data:Q(n,m),total:n._windowIndex.grandTotal,filtered:n._windowIndex.logicalTotal,offset:o,queryGen:n._windowIndex.queryGen}})}N.prototype.getAll=function(n={}){const o=this;if(o._windowIndex){const u=n.offset||0,f=n.limit||200;if(o._windowIndex.ensure(u,u+f,n),!o._windowIndex.hasLoaded&&!o.noLocalQuery){const h=u+f,y=p=>({data:Q(o,p),offset:u,queryGen:o._windowIndex.queryGen,provisional:!0});return ln(n)?cn(o,n,h).then(p=>y(p.slice(u,h))):q(o._name).then(p=>y($e(o,p,n).records))}return un(o,u,f)}return q(o._name).then(u=>{const f=$e(o,u,n);return{data:Q(o,f.records),total:f.total,filtered:f.filtered}})},N.prototype.getById=function(n){return L(this._name,n).then(o=>o?Q(this,[o])[0]:null)},N.prototype.count=function(n){return n&&Object.keys(n).length>0?q(this._name).then(u=>Me(u,n).length):this.windowed&&this.totalCount!=null?Promise.resolve(this.totalCount):P(this._name)},N.prototype.aggregate=function(n,o){return q(this._name).then(u=>sn(u,n,o))},N.prototype.setPresenters=function(n){this.presenters=n},N.prototype.applySync=function(n,o,u,f){f=f||{};const h=this;if(h._windowIndex&&f.queryGen!=null&&f.queryGen!==h._windowIndex.queryGen)return Promise.resolve({ok:!0,stale:!0});let y=g().then(p=>{if(!p)throw new Error("IndexedDB unavailable")});return n.length>0&&(y=y.then(()=>je(h._name,n))),o.length>0&&(y=y.then(()=>ne(h._name,o))),y.then(()=>{if(h._windowIndex&&(f.offset!=null||f.total!=null)){const p=f.offset!=null?f.offset:0,m=n.map(E=>E.id),C=h._windowIndex.ingest(p,m,f.total,f.filtered,f.queryGen);if(C&&C.length)return ne(h._name,C)}}).then(()=>P(h._name)).then(p=>(h.totalCount=f.total!==void 0?f.total:p,h.hasCache=!0,Y(h._name,{schema_version:d,last_synced_at:u,has_cache:!0,record_count:h.totalCount}))).then(()=>{const p=!h.isLoaded;return h.isLoaded=!0,h.canServe=!0,h.isSyncing=!1,h.lastSyncedAt=u,p?(A(h.dom,"ln-data-store:loaded",{store:h._name,count:h.totalCount,meta:f}),A(h.dom,"ln-data-store:ready",{store:h._name,count:h.totalCount,source:"server",meta:f})):A(h.dom,"ln-data-store:synced",{store:h._name,added:n.length,deleted:o.length,changed:!0,meta:f}),{ok:!0}}).catch(p=>{h.isSyncing=!1;const m=p&&p.message?p.message:String(p);return console.error("[ln-data-store] applySync failed:",p),A(h.dom,"ln-data-store:sync-error",{store:h._name,error:m}),Vt(p)})},N.prototype.applyQuery=function(n,o){o=o||{};const u=this;let f=Promise.resolve();return n.length>0&&(f=f.then(()=>je(u._name,n))),f.then(()=>P(u._name)).then(h=>(u.totalCount=o.total!==void 0?o.total:h,n.length>0&&(u.canServe=!0),Q(u,n))).catch(h=>(console.error("[ln-data-store] applyQuery failed:",h),[]))},N.prototype.forceSync=function(){this.isSyncing||Pe(this)},N.prototype.fullReload=function(){const n=this;return U(n._name).then(()=>Y(n._name,{schema_version:d,last_synced_at:null,has_cache:!1,record_count:0})).then(()=>{n.isLoaded=!1,n.hasCache=!1,n.lastSyncedAt=null,n.totalCount=0,Pe(n)})},N.prototype.destroy=function(){if(this._windowIndex&&(this._windowIndex.clear(),this._windowIndex=null,this.windowed=!1),this._handlers){for(const[n,o]of Object.entries(this._handlers))this.dom.removeEventListener(`ln-data-store:request-${n}`,o);this._handlers=null}if(this._queryHandlers){for(const[n,o]of Object.entries(this._queryHandlers))this.dom.removeEventListener(n,o);this._queryHandlers=null}delete b[this._name],delete this.dom[t]};function dn(){return g().then(n=>{if(!n)return;const o=Array.from(n.objectStoreNames);return new Promise((u,f)=>{const h=n.transaction(o,"readwrite");o.forEach(y=>h.objectStore(y).clear()),h.oncomplete=()=>u(),h.onerror=()=>f(h.error)})}).then(()=>{Object.values(b).forEach(n=>{n.isLoaded=!1,n.canServe=!1,n.isInitialized=!1,n.initializationError=null,n.hasCache=!1,n.isSyncing=!1,n.lastSyncedAt=null,n.totalCount=0})})}function ye(n){n._windowIndex&&n._windowIndex.reset(),A(n.dom,"ln-data-store:query-changed",{store:n._name,query:{filters:Object.assign({},n.query.filters),search:n.query.search,sort:n.query.sort?Object.assign({},n.query.sort):null}})}const fn="data-ln-data-store-frozen";function Ke(n,o){n.setAttribute(fn,o)}function hn(n){const o=n[t];if(!o._windowIndex)return;const u=o._windowIndex.configure({windowSize:o._windowSize});u.length&&ne(o._name,u).catch(f=>{console.error("[ln-data-store] window shrink eviction failed:",f)})}function wn(n){const o=n[t];o._windowIndex&&o._windowIndex.configure({pageSize:o._windowPageSize})}Ne(e,t,N,"ln-data-store",{attributes:i}),window[t].clearAll=dn,window[t].init=window[t],window[t].setStorageKey=Be,typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.setStorageKey=Be)})()})();
1
+ (function(){"use strict";function be(){return typeof window>"u"?!1:window.lnDebug===!0||window.lnCore&&window.lnCore._debugSink?!0:typeof document<"u"&&document.body?document.body.hasAttribute("data-ln-debug")||document.body.querySelector("[data-ln-debug]")!==null:!1}function oe(e){if(typeof window>"u")return!1;if(window.lnDebug===!0)return!0;if(window.lnCore&&window.lnCore._debugIsContained)return e?window.lnCore._debugIsContained(e):window.lnCore._debugSink!==null;if(e&&e.closest){const t=e.closest("[data-ln-debug]");return!(!t||typeof document<"u"&&t===document.documentElement)}return typeof document<"u"&&document.body?document.body.hasAttribute("data-ln-debug"):!1}if(typeof window<"u"&&(window.lnCore=window.lnCore||{},!window.lnCore._warnBound)){window.lnCore._warnBound=!0;const e=console.warn;console.warn=function(...t){if(typeof t[0]=="string"&&(t[0].startsWith("[ln-")||t[0].startsWith("[lnCore"))){let i=null;for(let a=1;a<t.length;a++)if(t[a]&&t[a].nodeType===1){i=t[a];break}if(!oe(i))return}e.apply(console,t)}}function C(e,t,r){const i=r||{};window.lnCore._debugSink&&window.lnCore._debugSink("event",t,e,i),e.dispatchEvent(new CustomEvent(t,{bubbles:!0,detail:i}))}function X(e,t){if(!document.body){document.addEventListener("DOMContentLoaded",function(){X(e,t)}),console.warn("["+t+'] Script loaded before <body> — add "defer" to your <script> tag');return}e()}function Ue(e){const t=e.querySelector('input[name="_method"]');return((t&&t.value!==""?t.value:e.method)||"").toUpperCase()}function Ge(e,t){const r=!!(t&&t.typed),i=t&&t.exclude,a={},l=e.elements,c={};if(r)for(let d=0;d<l.length;d++){const s=l[d];s.name&&s.type==="checkbox"&&!s.disabled&&(c[s.name]=(c[s.name]||0)+1)}for(let d=0;d<l.length;d++){const s=l[d];if(!(!s.name||s.disabled||s.type==="file"||s.type==="submit"||s.type==="button")&&!(i&&s.matches&&s.matches(i)))if(s.type==="checkbox")r&&c[s.name]===1?a[s.name]=s.checked:(a[s.name]||(a[s.name]=[]),s.checked&&a[s.name].push(s.value));else if(s.type==="radio")s.checked&&(a[s.name]=s.value);else if(s.type==="select-multiple"){a[s.name]=[];for(let w=0;w<s.options.length;w++)s.options[w].selected&&a[s.name].push(s.options[w].value)}else if(r&&s.type==="hidden")a[s.name]=s.value;else if(r&&(s.type==="number"||s.type==="range")){const w=Number(s.value);a[s.name]=s.value===""||isNaN(w)?null:w}else a[s.name]=s.value}return a}function Ve(e){if(typeof e!="string")return!!e;const t=e.trim().toLowerCase();return t!=="false"&&t!=="0"&&t!==""&&t!=="off"&&t!=="no"}function We(e,t){const r=e.elements,i=[],a={};for(let l=0;l<r.length;l++){const c=r[l];c.name&&c.type==="checkbox"&&(a[c.name]=(a[c.name]||0)+1)}for(let l=0;l<r.length;l++){const c=r[l];if(c.type==="file"||c.type==="submit"||c.type==="button")continue;const d=c.getAttribute("data-ln-fill-as")||c.name;if(!d||!(d in t))continue;const s=t[d];if(c.type==="checkbox"){if(Array.isArray(s))c.checked=s.indexOf(c.value)!==-1;else if(a[c.name]>1){const w=String(s).split(",").map(function(b){return b.trim()});c.checked=w.indexOf(c.value)!==-1}else c.checked=Ve(s);i.push(c)}else if(c.type==="radio")c.checked=c.value===String(s),i.push(c);else if(c.type==="select-multiple"){if(Array.isArray(s))for(let w=0;w<c.options.length;w++)c.options[w].selected=s.indexOf(c.options[w].value)!==-1;i.push(c)}else c.value=s,c.tagName==="SELECT"&&s!=null&&c.setAttribute("data-ln-value",s),i.push(c)}return i}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.populateForm=We,window.lnCore.serializeForm=Ge,window.lnCore.resolveFormMethod=Ue);const _e={};function He(e,t){_e[e]=t}function Qe(e){return _e[e]||{ingress:t=>t,egress:t=>t}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.registerDataMapper=He,window.lnCore.getDataMapper=Qe);function Je(){typeof window>"u"||(window.lnCore=window.lnCore||{},!window.lnCore._localeObserverBound&&(window.lnCore._localeObserverBound=!0,X(function(){new MutationObserver(function(){C(document,"ln-core:locale-change",{})}).observe(document.documentElement,{attributes:!0,attributeFilter:["lang"],subtree:!0})},"ln-core")))}const Ce={};function Ze(e,t){if(!e||typeof t!="object")return;const r=e.toLowerCase().split("-")[0];Ce[r]=t}function Xe(e){if(!e)return null;const t=e.toLowerCase().split("-")[0];return Ce[t]||null}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.registerLocaleFallback=Ze,window.lnCore.getLocaleFallback=Xe,window.lnCore.ensureLocaleObserver=Je);const ie={};function Ye(e,t){ie[e]||(ie[e]=document.querySelector('[data-ln-template="'+e+'"]'));const r=ie[e];return r?r.content.cloneNode(!0):(console.warn("["+(t||"ln-core")+'] Template "'+e+'" not found'),null)}function Se(e,t){if(!e||!t)return e;const r=e.querySelectorAll("[data-ln-field]");for(let c=0;c<r.length;c++){const d=r[c],s=d.getAttribute("data-ln-field");t[s]!=null&&(d.textContent=t[s])}const i=e.querySelectorAll("[data-ln-attr]");for(let c=0;c<i.length;c++){const d=i[c],s=d.getAttribute("data-ln-attr").split(",");for(let w=0;w<s.length;w++){const b=s[w].trim().split(":");if(b.length!==2)continue;const _=b[0].trim(),x=b[1].trim();t[x]!=null&&d.setAttribute(_,t[x])}}const a=e.querySelectorAll("[data-ln-show]");for(let c=0;c<a.length;c++){const d=a[c],s=d.getAttribute("data-ln-show");s in t&&d.classList.toggle("hidden",!t[s])}const l=e.querySelectorAll("[data-ln-class]");for(let c=0;c<l.length;c++){const d=l[c],s=d.getAttribute("data-ln-class").split(",");for(let w=0;w<s.length;w++){const b=s[w].trim().split(":");if(b.length!==2)continue;const _=b[0].trim(),x=b[1].trim();x in t&&d.classList.toggle(_,!!t[x])}}return e}function et(e,t){e.matches&&e.matches("[data-ln-form], [data-ln-fillable]")&&(window.lnCore._debugSink&&window.lnCore._debugSink("event","ln-fill",e,t??null),e.dispatchEvent(new CustomEvent("ln-fill",{detail:t??null,bubbles:!0})));const r=e.querySelectorAll("[data-ln-form], [data-ln-fillable]");for(let i=0;i<r.length;i++)window.lnCore._debugSink&&window.lnCore._debugSink("event","ln-fill",r[i],t??null),r[i].dispatchEvent(new CustomEvent("ln-fill",{detail:t??null,bubbles:!0}));return e}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore._fillBound||(window.lnCore._fillBound=!0,document.addEventListener("ln-fill",function(e){if(!(!e.target.matches||!e.target.matches("[data-ln-fillable]")))if(e.detail)Se(e.target,e.detail);else{const t=e.target.querySelectorAll("[data-ln-field]");for(let r=0;r<t.length;r++)t[r].textContent=""}})));function Ae(e,t){if(!e||!t)return e;const r=document.createTreeWalker(e,NodeFilter.SHOW_TEXT);for(;r.nextNode();){const l=r.currentNode;l.textContent.indexOf("{{")!==-1&&(l.textContent=l.textContent.replace(/\{\{\s*(\w+)\s*\}\}/g,function(c,d){return t[d]!==void 0?t[d]:""}))}const i=function(l,c){return t[c]!==void 0?t[c]:""},a=Array.from(e.querySelectorAll("*"));e.nodeType===1&&a.push(e);for(let l=0;l<a.length;l++){const c=a[l],d=c.attributes;for(let s=0;s<d.length;s++){const w=d[s];w.value.indexOf("{{")!==-1&&c.setAttribute(w.name,w.value.replace(/\{\{\s*(\w+)\s*\}\}/g,i))}}return e}function tt(e,t,r,i,a,l){const c={};for(let s=0;s<e.children.length;s++){const w=e.children[s],b=w.getAttribute("data-ln-render-key");b&&(c[b]=w)}const d=document.createDocumentFragment();for(let s=0;s<t.length;s++){const w=t[s],b=String(i(w));let _=c[b];if(_)a(_,w,s);else{const x=Ye(r,l);if(!x||(Ae(x,w),_=x.firstElementChild,!_))continue;_.setAttribute("data-ln-render-key",b),a(_,w,s)}d.appendChild(_)}e.textContent="",e.appendChild(d)}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.fillTemplate=Ae,window.lnCore.fill=Se,window.lnCore.lnFill=et,window.lnCore.renderList=tt);function ae(e,t,r){const i=e.getAttribute(t);return i===null?r:i}function Y(e,t,r){const i=parseInt(e.getAttribute(t),10);return isNaN(i)?r:i}function se(e,t,r=!1){const i=e.getAttribute(t);if(i===null)return!!r;const a=i.trim().toLowerCase();return!(a==="false"||a==="0")}function le(e,t){return(e.getAttribute(t)||"").split(",").map(r=>r.trim()).filter(Boolean)}const ce=new Map;function ve(e,t){const r=(e?e.join("|"):"")+"::"+t;if(ce.has(r))return ce.get(r);const i=new Set(e||[]),a=function(l,c){const d=l.getAttribute(c);return d!==null&&i.has(d)?d:t};return ce.set(r,a),a}function xe(e,t,r){const i=parseFloat(e.getAttribute(t));return isNaN(i)?r:i}function ke(e,t,r){const i=e.getAttribute(t);if(!i)return r;try{return JSON.parse(i)}catch{return r}}function qe(e,t,r,i,a){if(!e||t===null)return!0;const l=i||"ln-component",c=e.type;if(c==="trigger"||c==="marker"||c==="string"||c==="list"||!c||t===""&&e.fallback!==void 0)return!0;const d=s=>{a?console.warn(s,a):console.warn(s)};if(c==="boolean"){const s=t.trim().toLowerCase();return s!==""&&s!=="true"&&s!=="false"&&s!=="1"&&s!=="0"?(d(`[${l}] Invalid value "${t}" for boolean attribute "${r}". Allowed: "true", "false", or presence-only.`),!1):!0}if(c==="enum"){const s=e.values||[];return s.includes(t)?!0:(d(`[${l}] Invalid value "${t}" for attribute "${r}". Allowed: ${s.join(", ")}. Fallback: "${e.fallback}".`),!1)}if(c==="integer"){if(!/^-?\d+$/.test(t))return d(`[${l}] Invalid integer "${t}" for attribute "${r}". Fallback: ${e.fallback}.`),!1;const s=parseInt(t,10);return e.min!==void 0&&s<e.min?(d(`[${l}] Value ${s} for attribute "${r}" is less than min (${e.min}).`),!1):e.max!==void 0&&s>e.max?(d(`[${l}] Value ${s} for attribute "${r}" is greater than max (${e.max}).`),!1):!0}if(c==="float")return isNaN(Number(t))?(d(`[${l}] Invalid float "${t}" for attribute "${r}". Fallback: ${e.fallback}.`),!1):!0;if(c==="json")try{return JSON.parse(t),!0}catch(s){return d(`[${l}] Invalid JSON for attribute "${r}": ${s.message}. Fallback: ${e.fallback}.`),!1}return!0}function Ee(e,t,r){for(const i in r){const[a,l,c]=r[i];Object.defineProperty(e,i,{get:function(){return a(t,l,c)},enumerable:!0,configurable:!0})}return e}function Ie(e){const t={};for(const r in e){const i=e[r];if(!i||!i.prop)continue;let a=i.read;if(!a&&i.type)switch(i.type){case"enum":a=ve(i.values,i.fallback);break;case"integer":a=Y;break;case"float":a=xe;break;case"boolean":a=se;break;case"list":a=le;break;case"json":a=ke;break;case"string":default:a=ae;break}a||(a=ae),t[i.prop]=[a,r,i.fallback]}return t}function nt(e){const t={};for(const r in e){const i=e[r];i&&i.effect&&(t[r]=i.effect)}return Object.keys(t).length?t:null}function rt(e){if(e.onAttrChange&&!e.declared)return null;const t=new Set;if(e.effects)for(const r in e.effects)t.add(r);if(e.onAttrChange&&e.declared)for(const r of e.declared)t.add(r);return t}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.defineAttrs=Ee,window.lnCore.attrSpec=Ie,window.lnCore.attrStr=ae,window.lnCore.attrInt=Y,window.lnCore.attrBool=se,window.lnCore.attrList=le,window.lnCore.attrEnum=ve,window.lnCore.attrFloat=xe,window.lnCore.attrJson=ke);function W(e,t){if(!e[t.attribute]){window.lnCore._persistSink&&e.hasAttribute&&e.hasAttribute("data-ln-persist")&&window.lnCore._persistSink(e,t.selector);try{e[t.attribute]=new t.ComponentFn(e)}catch(r){console.error("["+t.attribute+"] init failed",e,r)}}}function Le(e,t,r,i){if(e.nodeType!==1)return;const l=t.indexOf("[")!==-1||t.indexOf(".")!==-1||t.indexOf("#")!==-1?t:"["+t+"]",c={selector:t,attribute:r,ComponentFn:i};if(e.matches&&e.matches(l)&&W(e,c),e.querySelectorAll){const d=e.querySelectorAll(l);for(let s=0;s<d.length;s++)W(d[s],c)}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore._bootHolds=window.lnCore._bootHolds||0,window.lnCore._bootQueue=window.lnCore._bootQueue||[]);function ot(){return typeof window<"u"&&window.lnCore&&window.lnCore._bootHolds||0}function it(e){typeof window<"u"?(window.lnCore=window.lnCore||{},window.lnCore._bootHolds=window.lnCore._bootHolds||0,window.lnCore._bootQueue=window.lnCore._bootQueue||[],window.lnCore._bootHolds>0?window.lnCore._bootQueue.push(e):setTimeout(e,0)):e()}function De(){window.lnCore=window.lnCore||{};const e=window.lnCore._attrRegistry=window.lnCore._attrRegistry||{byAttr:new Map,reactive:[],persist:[]};return e.byReactive=e.byReactive||new Map,e.reactiveWildcard=e.reactiveWildcard||[],e}function at(e){const t=De(),r=e.observed||[];for(let i=0;i<r.length;i++){const a=r[i];t.byAttr.has(a)||t.byAttr.set(a,[]),t.byAttr.get(a).push(e)}if(t.byDeclaredAttr=t.byDeclaredAttr||new Map,e.attributes)for(const i in e.attributes){t.byDeclaredAttr.has(i)||t.byDeclaredAttr.set(i,[]);const a=t.byDeclaredAttr.get(i);a.some(l=>l.componentTag===e.componentTag)||a.push({spec:e.attributes[i],componentTag:e.componentTag})}if(e.onAttrChange||e.effects){t.reactive.push(e);const i=rt(e);if(i===null)t.reactiveWildcard.push(e);else for(const a of i)t.byReactive.has(a)||t.byReactive.set(a,[]),t.byReactive.get(a).push(e)}e.persist&&t.persist.push(e)}function Re(e,t,r,i){for(let a=0;a<e.length;a++){const l=e[a];if(!t[l.attribute])continue;const c=l.effects&&l.effects[r];c?c(t,r,i):l.onAttrChange&&(!l.declared||l.declared.has(r))&&l.onAttrChange(t,r,i)}}function st(e){const t=e.attributeName,r=t.indexOf("data-ln-")===0,i=De(),a=i.byAttr.get(t),l=be()&&i.byDeclaredAttr&&i.byDeclaredAttr.has(t);if(!r&&!a&&!l)return;const c=e.target;if(e.oldValue!==c.getAttribute(t)){if(l&&oe(c)){const d=i.byDeclaredAttr.get(t),s=c.getAttribute(t);for(let w=0;w<d.length;w++)qe(d[w].spec,s,t,d[w].componentTag,c)}if(window.lnCore._debugSink&&(r||a)&&window.lnCore._debugSink("attr",t,c,{oldValue:e.oldValue,newValue:c.getAttribute(t)}),r){const d=i.byReactive.get(t);d&&Re(d,c,t,e.oldValue),i.reactiveWildcard.length&&Re(i.reactiveWildcard,c,t,e.oldValue)}if(a)for(let d=0;d<a.length;d++){const s=a[d];if(s.handler){s.handler(c,t,e.oldValue);continue}s.onAttributeChange&&c[s.attribute]?s.onAttributeChange(c,t):(Le(c,s.selector,s.attribute,s.ComponentFn),s.onInit&&s.onInit(c))}}}function lt(){window.lnCore=window.lnCore||{},!window.lnCore._attrObserverBound&&(window.lnCore._attrObserverBound=!0,X(function(){new MutationObserver(function(t){for(let r=0;r<t.length;r++)try{st(t[r])}catch(i){console.error("[ln-core] mutation handler failed",t[r].target,i)}}).observe(document.body,{attributes:!0,subtree:!0,attributeOldValue:!0})},"ln-core"))}function ue(){return window.lnCore=window.lnCore||{},window.lnCore._lifecycleRegistry=window.lnCore._lifecycleRegistry||[]}function de(){return window.lnCore=window.lnCore||{},window.lnCore._subtreeRegistry=window.lnCore._subtreeRegistry||[]}function fe(e,t){if(!document.contains(e))if(t.attribute){const r=e[t.attribute];if(r&&typeof r.destroy=="function")try{r.destroy()}catch(i){console.error("["+t.attribute+"] destroy failed",e,i)}delete e[t.attribute]}else t.onDestroy&&t.onDestroy(e)}function Ne(e){const t=ue();if(!t.length)return;const r=e.target;if(r){const a=r.nodeType===1?r:r.parentElement;if(a&&(a.isContentEditable||a.closest&&a.closest('[contenteditable]:not([contenteditable="false"])')))return}const i=de();if(e.target&&i.length)for(let a=0;a<i.length;a++){const l=i[a],c=l.query,d=e.target.nodeType===1?e.target.matches&&e.target.matches(c)?e.target:e.target.closest?e.target.closest(c):null:e.target.parentElement&&e.target.parentElement.closest?e.target.parentElement.closest(c):null;d&&l.onSubtreeChange(d,e)}for(let a=0;a<e.addedNodes.length;a++){const l=e.addedNodes[a];if(l.nodeType===1){const c=!!(l.firstElementChild||l.children&&l.children.length);for(let d=0;d<t.length;d++){const s=t[d];if(s.selector&&s.attribute&&s.ComponentFn){if(!c)l.matches&&l.matches(s.query)&&W(l,s);else if(l.matches&&l.matches(s.query)&&W(l,s),l.querySelectorAll){const w=l.querySelectorAll(s.query);for(let b=0;b<w.length;b++)W(w[b],s)}}s.onInit&&s.onInit(l)}}}for(let a=0;a<e.removedNodes.length;a++){const l=e.removedNodes[a];if(l.nodeType===1){if(document.contains(l))continue;const c=!!(l.firstElementChild||l.children&&l.children.length);for(let d=0;d<t.length;d++){const s=t[d],w=s.query;if(w){if(!c)l.matches&&l.matches(w)&&fe(l,s);else if(l.matches&&l.matches(w)&&fe(l,s),l.querySelectorAll){const b=l.querySelectorAll(w);for(let _=0;_<b.length;_++)fe(b[_],s)}}}}}}function Te(){window.lnCore=window.lnCore||{},!window.lnCore._lifecycleObserverBound&&(window.lnCore._lifecycleObserverBound=!0,X(function(){const e=new MutationObserver(function(t){for(let r=0;r<t.length;r++){const i=t[r];if(i.type==="childList")try{Ne(i)}catch(a){console.error("[ln-core] lifecycle handler failed",i.target,a)}}});window.lnCore._lifecycleObserver=e,e.observe(document.body,{childList:!0,subtree:!0})},"ln-core"))}function ct(e){if(typeof window>"u")return e();window.lnCore=window.lnCore||{};const t=window.lnCore._lifecycleObserver;if(!t)return e();const r=t.takeRecords();for(let i=0;i<r.length;i++){const a=r[i];if(a.type==="childList")try{Ne(a)}catch(l){console.error("[ln-core] lifecycle handler failed",a.target,l)}}t.disconnect();try{return e()}finally{t.observe(document.body,{childList:!0,subtree:!0})}}function ut(e){ue().push(e),e.onSubtreeChange&&e.query&&de().push(e),Te()}function ze(e,t,r,i,a={}){const l=a.extraAttributes||[],c=a.onAttributeChange||null,d=a.onSubtreeChange||null,s=a.onInit||null,w=a.onAttrChange||null,b=a.effects||null,_=a.attributes||null,x=_?nt(_):b,M=_?new Set(Object.keys(_)):null,$=a.persist||null;function m(L){const D=L||document.body;if(Le(D,e,t,r),_&&be())for(const B in _){const ye=_[B],K=Array.from(D.querySelectorAll("["+B+"]"));D.matches&&D.matches("["+B+"]")&&K.push(D);for(let j=0;j<K.length;j++){const Q=K[j];oe(Q)&&qe(ye,Q.getAttribute(B),B,i,Q)}}s&&s(D)}const A=[];if(e.indexOf("[")!==-1){const L=/\[([\w-]+)/g;let D;for(;(D=L.exec(e))!==null;)A.push(D[1])}else A.push(e);at({selector:e,attribute:t,componentTag:i,attributes:_,ComponentFn:r,onInit:s,observed:A.concat(l),onAttributeChange:c,onAttrChange:w,effects:x,declared:M,persist:$}),lt();const I=e.indexOf("[")!==-1||e.indexOf(".")!==-1||e.indexOf("#")!==-1,k=a.subtreeQuery||(I?e:"["+e+"]"),v={selector:e,attribute:t,ComponentFn:r,onInit:s,onSubtreeChange:d,query:k};ue().push(v),d&&k&&de().push(v),Te(),window[t]=m,typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.registerComponent=ze,window.lnCore.observeLifecycle=ut,window.lnCore.withoutLifecycle=ct);function q(){ot()>0?it(function(){m(document.body)}):m(document.body)}return document.readyState==="loading"?document.addEventListener("DOMContentLoaded",q):q(),m}function dt(e){let t=!1;for(let r=0;r<e.length;r++){const i=e[r];if(!(i===""||i==null)&&(t=!0,!Number.isFinite(Number(i))))return"string"}return t?"number":"string"}function ft(e,t,r,i){if(r==="number"){const c=parseFloat(e),d=parseFloat(t);return(isNaN(c)?0:c)-(isNaN(d)?0:d)}const a=e!=null?String(e):"",l=t!=null?String(t):"";return i?i.compare(a,l):a<l?-1:a>l?1:0}function Oe(e){return(e||"").replace(/^#/,"")}function he(e){const t=e===void 0?location.hash:e,r={},i=Oe(t);if(!i)return r;const a=i.split("&");for(let l=0;l<a.length;l++){const c=a[l];if(!c)continue;const d=c.indexOf(":"),s=d>-1?c.slice(0,d):c,w=d>-1?c.slice(d+1):"";if(s)try{r[s]=decodeURIComponent(w)}catch{r[s]=w}}return r}function ht(e){if(!e)return null;const t=he();return e in t?t[e]:null}function wt(e,t){if(!e)return;const r=he();t==null?delete r[e]:r[e]=String(t);const a=Object.keys(r).map(function(l){const c=r[l];return c===""?l:l+":"+encodeURIComponent(c)}).join("&");Oe(location.hash)!==a&&(location.hash=a)}function yt(e){return e.button===1||e.ctrlKey||e.metaKey||e.shiftKey?!1:(e.preventDefault(),!0)}function pt(e,t){if(!e||!e.hasAttribute("data-ln-hash"))return null;const r=e.getAttribute("data-ln-hash");if(r&&r.trim()!=="")return r.trim();const i=e.getAttribute("data-ln-sort")||e.getAttribute("data-ln-search-for")||e.getAttribute("data-ln-search")||e.getAttribute("data-ln-filter")||e.id;return i?t?i+"-"+t:i:t||null}function mt(e,t){return!t||t==="none"||e===null||e===void 0?null:String(e)+"."+t}function gt(e){return!e||typeof e!="string"?null:e.endsWith(".asc")?{fieldOrColumn:e.slice(0,-4),direction:"asc"}:e.endsWith(".desc")?{fieldOrColumn:e.slice(0,-5),direction:"desc"}:null}function bt(e,t){return!e||!Array.isArray(t)||t.length===0?null:e+":"+t.map(encodeURIComponent).join(",")}function _t(e){if(!e||typeof e!="string")return null;const t=e.indexOf(":");if(t===-1)return null;const r=e.slice(0,t),i=e.slice(t+1),a=i?i.split(",").map(function(l){try{return decodeURIComponent(l)}catch{return l}}).filter(Boolean):[];return{key:r,values:a}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.hashParse=he,window.lnCore.hashGet=ht,window.lnCore.hashSet=wt,window.lnCore.hashLinkClick=yt,window.lnCore.resolveHashNamespace=pt,window.lnCore.hashSortEncode=mt,window.lnCore.hashSortDecode=gt,window.lnCore.hashFilterEncode=bt,window.lnCore.hashFilterDecode=_t);function Ct(e){return(e||"").replace(/^\?/,"")}function St(e){const t=e===void 0?typeof window<"u"?window.location.search:"":e,r={},i=Ct(t);if(!i)return r;const a=new URLSearchParams(i);for(const[l,c]of a.entries())r[l]=c;return r}function At(e){if(!e||typeof window>"u")return null;const t=new URLSearchParams(window.location.search);return t.has(e)?t.get(e):null}function vt(e,t){if(!e||typeof window>"u")return;const r=new URL(window.location.href);if(t==null||t===""?r.searchParams.delete(e):r.searchParams.set(e,String(t)),r.search===window.location.search)return;const i=r.pathname+r.search+r.hash;window.history.replaceState(window.history.state,"",i)}function xt(e,t){if(!e||!e.hasAttribute("data-ln-query"))return null;const r=e.getAttribute("data-ln-query");if(r&&r.trim()!=="")return r.trim();const i=e.getAttribute("data-ln-sort")||e.getAttribute("data-ln-search-for")||e.getAttribute("data-ln-search")||e.getAttribute("data-ln-filter")||e.id;return i?t?i+"_"+t:i:t||null}function kt(e,t){return!t||t==="none"||e===null||e===void 0?null:String(e)+"."+t}function qt(e,t){if(e&&typeof e=="string"){if(e.endsWith(".asc"))return{fieldOrColumn:e.slice(0,-4),direction:"asc"};if(e.endsWith(".desc"))return{fieldOrColumn:e.slice(0,-5),direction:"desc"}}if(t&&typeof t=="object"){const r=t.sort_field||t.sort_by;if(r){const i=t.sort_dir&&String(t.sort_dir).toLowerCase()==="desc"?"desc":"asc";return{fieldOrColumn:r,direction:i}}}return null}function Et(e){return!Array.isArray(e)||e.length===0?null:e.map(encodeURIComponent).join(",")}function It(e){return!e||typeof e!="string"?[]:e.split(",").map(function(t){try{return decodeURIComponent(t.trim())}catch{return t.trim()}}).filter(Boolean)}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.queryParse=St,window.lnCore.queryGet=At,window.lnCore.querySet=vt,window.lnCore.resolveQueryParam=xt,window.lnCore.querySortEncode=kt,window.lnCore.querySortDecode=qt,window.lnCore.queryFilterEncode=Et,window.lnCore.queryFilterDecode=It);let H=null;const Lt="ln-ashlar:storage-salt:v1",Pe=32768;function Fe(e){let t="";const r=e.byteLength;for(let i=0;i<r;i+=Pe)t+=String.fromCharCode.apply(null,e.subarray(i,Math.min(i+Pe,r)));return btoa(t)}function Me(e){const t=atob(e),r=t.length,i=new Uint8Array(r);for(let a=0;a<r;a++)i[a]=t.charCodeAt(a);return i}function Be(e,t){let r=H,i={};return typeof CryptoKey<"u"&&e instanceof CryptoKey?r=e:e&&typeof e=="object"&&(i=e,typeof CryptoKey<"u"&&i.key instanceof CryptoKey&&(r=i.key)),{key:r,options:i}}async function Dt(e,t={}){if(!e)throw new Error("[ln-crypto] Key derivation failed: Secret string is required");const r=t.method||"pbkdf2",i=new TextEncoder;if(r==="sha256"){const s=await crypto.subtle.digest("SHA-256",i.encode(e));return crypto.subtle.importKey("raw",s,{name:"AES-GCM"},!1,["encrypt","decrypt"])}const a=t.salt||Lt,l=typeof a=="string"?i.encode(a):a,c=t.iterations||1e5,d=await crypto.subtle.importKey("raw",i.encode(e),"PBKDF2",!1,["deriveKey"]);return crypto.subtle.deriveKey({name:"PBKDF2",salt:l,iterations:c,hash:"SHA-256"},d,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}async function je(e,t={}){if(!e){H=null;return}try{const r=t.method||"sha256";H=await Dt(e,{...t,method:r})}catch(r){throw console.error("[ln-core/crypto] Key derivation failed:",r),H=null,r}}function F(){return H}async function Rt(e,t,r){const{key:i}=Be(t);if(e==null)return e;if(!i)throw new Error("[ln-crypto] Encryption failed: No active cryptographic key provided");try{const a=new TextEncoder,l=crypto.getRandomValues(new Uint8Array(12)),c=typeof e=="string"?e:JSON.stringify(e),d=await crypto.subtle.encrypt({name:"AES-GCM",iv:l},i,a.encode(c));return{v:1,alg:"AES-GCM",encrypted:!0,iv:Fe(l),data:Fe(new Uint8Array(d))}}catch(a){throw console.error("[ln-core/crypto] Encryption failed:",a),new Error("[ln-crypto] Encryption failed: "+(a&&a.message?a.message:String(a)))}}async function Nt(e,t,r){const{key:i,options:a}=Be(t),l=a.silent===!0;if(!e||!e.encrypted)return e;if(!i){if(l)return{...e,decryptionError:!0};throw new Error("[ln-crypto] Decryption failed: No active cryptographic key provided")}if(!e.iv||!e.data){if(l)return{...e,decryptionError:!0};throw new Error("[ln-crypto] Decryption failed: Malformed envelope (missing iv or data)")}try{const c=new TextDecoder,d=Me(e.iv),s=Me(e.data),w=await crypto.subtle.decrypt({name:"AES-GCM",iv:d},i,s),b=c.decode(w);try{return JSON.parse(b)}catch{return b}}catch(c){if(l)return{...e,decryptionError:!0};throw console.error("[ln-core/crypto] Decryption failed. Key may be incorrect or payload tampered:",c),new Error("[ln-crypto] Decryption failed. Key may be incorrect or payload tampered: "+(c&&c.message?c.message:String(c)))}}function Tt(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{const t=Math.random()*16|0;return(e==="x"?t:t&3|8).toString(16)})}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.uuid=Tt);function zt(e){return String(e||"").trim().toLowerCase()}function Ot(e){const t=zt(e);return t?t.split(/\s+/).filter(Boolean):[]}function Pt(e,t){if(!t||t.length===0)return!0;if(!e)return!1;const r=String(e).toLowerCase();for(let i=0;i<t.length;i++)if(r.indexOf(t[i])===-1)return!1;return!0}function Ft(e,t){if(!t||t.length===0)return!0;if(e==null)return!1;const r=String(e).trim().toLowerCase();for(let i=0;i<t.length;i++)if(String(t[i]).trim().toLowerCase()===r)return!0;return!1}function Mt(e={}){let t=e.windowSize>0?e.windowSize:1e3,r=e.pageSize>0?e.pageSize:200,i=e.fetchDebounce!=null?e.fetchDebounce:120;const a=typeof e.requestPage=="function"?e.requestPage:()=>{},l=new Map,c=new Set;let d=0,s=0,w=0,b=!1,_=null;function x(m,A){l.delete(m),l.set(m,A)}function M(){if(l.size<=t)return[];const m=[];for(;l.size>t;){const I=l.keys().next().value;m.push(l.get(I)),l.delete(I)}const A=new Set(l.values());return m.filter(I=>!A.has(I))}function $(m,A){c.add(m),clearTimeout(_),_=setTimeout(()=>a(m,r,A),i)}return{get logicalTotal(){return d},set logicalTotal(m){d=m},get grandTotal(){return s},set grandTotal(m){s=m},get queryGen(){return w},set queryGen(m){w=m},get size(){return l.size},get hasLoaded(){return b},getId:m=>{if(!l.has(m))return;const A=l.get(m);return x(m,A),A},ensure:(m,A,I)=>{if(!b&&!c.has(0))return $(0,I);if(d<=0)return;const k=Math.max(0,m),v=Math.min(d,A);for(let q=k;q<v;q++)if(!l.has(q)){const L=Math.floor(q/r)*r;if(!c.has(L))return $(L,I)}},ingest:(m,A,I,k,v)=>{if(v!=null&&v!==w)return[];b=!0,I!=null&&(s=I),k!=null&&(d=k);for(let q=0;q<A.length;q++)x(m+q,A[q]);return c.delete(m),M()},reset:function(){w++,this.clear()},clear:()=>{b=!1,l.clear(),c.clear(),clearTimeout(_)},configure:(m={})=>{let A=[];return m.windowSize>0&&m.windowSize!==t&&(t=m.windowSize,A=M()),m.pageSize>0&&(r=m.pageSize),m.fetchDebounce>=0&&(i=m.fetchDebounce),A}}}function Bt(e,t,r){if(!Array.isArray(e)||!t||!t.field)return e;const{field:i,direction:a}=t,l=a==="desc",c=e.map(s=>s?s[i]:void 0),d=dt(c);return[...e].sort((s,w)=>{const b=s?s[i]:void 0,_=w?w[i]:void 0,x=ft(b,_,d,r);return l?-x:x})}function we(e,t){if(!Array.isArray(e)||!t||typeof t!="object")return e;const r=Object.keys(t).filter(i=>Array.isArray(t[i])&&t[i].length>0);return r.length?e.filter(i=>i?r.every(a=>Ft(i[a],t[a])):!1):e}function jt(e,t,r){if(!Array.isArray(e)||!t||!r||!r.length)return e;const i=Ot(t);return i.length?e.filter(a=>a?i.every(l=>r.some(c=>{const d=a[c];return d!=null&&Pt(String(d),[l])})):!1):e}function $t(e,t,r){if(!Array.isArray(e)||!e.length)return 0;if(r==="count")return e.length;const i=e.map(l=>l&&l[t]!=null?parseFloat(l[t]):NaN).filter(l=>Number.isFinite(l)),a=i.reduce((l,c)=>l+c,0);return r==="sum"?a:r==="avg"&&i.length?a/i.length:0}function Kt(e,t={},r=[],i){if(!Array.isArray(e))return{records:[],total:0,filtered:0};const a=e.length;let l=e;t.filters&&(l=we(l,t.filters)),t.search&&(l=jt(l,t.search,r));const c=l.length;if(t.sort&&(l=Bt(l,t.sort,i)),t.offset||t.limit){const d=t.offset||0,s=t.limit||l.length;l=l.slice(d,d+s)}return{records:l,total:a,filtered:c}}function Ut(e,t){return!Array.isArray(e)||!t||typeof t!="object"?e:e.map(r=>{if(!r)return null;const i={...r};for(const[a,l]of Object.entries(t))if(typeof l=="function")try{i[a]=l(r)}catch{i[a]=void 0}return i})}function Gt(e,t,r,i="_meta"){if(!Array.isArray(e)||!e.includes(i))return!0;for(const a of Object.keys(t||{})){if(!e.includes(a))return!0;const l=t[a]&&t[a].indexes||[],c=r&&r[a]||[];if(l.some(d=>!c.includes(d)))return!0}return!1}function Vt(e){return{ok:!1,error:e&&e.message?e.message:String(e)}}function Wt(e){if(!e||typeof e!="string")return null;const t=e.trim();if(!t)return null;try{const r=JSON.parse(t);return Array.isArray(r)?r:null}catch{return null}}(function(){const e="data-ln-data-store",t="lnDataStore";if(window[t]!==void 0)return;function r(n,o,u){const f=n.getAttribute(o);if(f==="never"||f==="-1")return-1;const h=parseInt(f,10);return isNaN(h)?u:h}const i={"data-ln-data-store":{type:"marker",effect:Ke,description:"Identifies the element as a data-store definition container"},"data-ln-data-store-indexes":{type:"list",effect:Ke,description:"Comma-separated index field names for the IndexedDB store"},"data-ln-data-store-seed":{type:"string",description:"Selector or element ID of an external seed script block"},"data-ln-data-store-stale":{prop:"_staleThreshold",type:"integer",read:r,fallback:300,description:"Cache staleness threshold in seconds, or -1/never"},"data-ln-data-store-search-fields":{prop:"_searchFields",type:"list",read:le,description:"Record fields to index for client-side search"},"data-ln-data-store-no-local-query":{prop:"noLocalQuery",type:"boolean",read:se,description:"Bypasses local IndexedDB query resolution, forcing remote fetching"},"data-ln-data-store-window":{prop:"_windowSize",type:"integer",read:Y,fallback:1e3,min:10,effect:yn,description:"Virtual scrolling cache window size in records"},"data-ln-data-store-window-page":{prop:"_windowPageSize",type:"integer",read:Y,fallback:200,min:5,effect:pn,description:"Virtual scrolling slice page size"},"data-ln-data-store-frozen":{type:"marker",description:"Applied at runtime to indicate store schema is locked in IndexedDB"}},a=Ie(i),l="ln_app_cache",c="_meta",d="1.0";let s=null,w=null;const b={};function _(n){n&&n.name==="QuotaExceededError"&&C(document,"ln-data-store:quota-exceeded",{error:n})}function x(){const n={};for(const o of document.querySelectorAll(`[${e}]`)){const u=o.id;if(u){const f=o.getAttribute("data-ln-data-store-indexes")||"";n[u]={indexes:f.split(",").map(h=>h.trim()).filter(Boolean)}}}return n}function M(){return w||(w=new Promise(n=>{if(typeof indexedDB>"u")return console.warn("[ln-data-store] IndexedDB is not available in this environment"),n(null);const o=x(),u=Object.keys(o),f=indexedDB.open(l);f.onerror=()=>{console.warn("[ln-data-store] IndexedDB open failed"),n(null)},f.onsuccess=h=>{const y=h.target.result,p=Array.from(y.objectStoreNames),g=u.filter(N=>p.includes(N));let S={};if(g.length>0){const N=y.transaction(g,"readonly");for(const T of g)S[T]=Array.from(N.objectStore(T).indexNames)}if(!Gt(p,o,S,c))return $(y),s=y,n(y);const U=y.version;y.close();const P=indexedDB.open(l,U+1);let z=!1,O=null;P.onblocked=()=>{console.warn("[ln-data-store] Database upgrade blocked — waiting for other tabs to close connection"),C(document,"ln-data-store:blocked",{db:l}),O||(O=setTimeout(()=>{z||(console.warn("[ln-data-store] Database upgrade timed out while blocked"),z=!0,w=null,n(null))},5e3))},P.onerror=()=>{z||(O&&clearTimeout(O),z=!0,w=null,console.warn("[ln-data-store] Database upgrade failed"),n(null))},P.onupgradeneeded=N=>{const T=N.target.result,mn=N.target.transaction;T.objectStoreNames.contains(c)||T.createObjectStore(c,{keyPath:"key"});for(const Z of u)if(T.objectStoreNames.contains(Z)){const re=mn.objectStore(Z);for(const V of o[Z].indexes)re.indexNames.contains(V)||re.createIndex(V,V,{unique:!1})}else{const re=T.createObjectStore(Z,{keyPath:"id"});for(const V of o[Z].indexes)re.createIndex(V,V,{unique:!1})}},P.onsuccess=N=>{if(z){N.target.result&&N.target.result.close();return}O&&clearTimeout(O),z=!0;const T=N.target.result;$(T),s=T,n(T)}}}),w)}function $(n){n.onversionchange=()=>{n.close(),s=null,w=null}}function m(){return s?Promise.resolve(s):(w=null,M())}async function A(n){if(!F()||!n)return n;const o={...n},u=o.id,f=await Rt(o);return!f||!f.encrypted?n:{...f,id:u}}async function I(n){return!n||!n.encrypted||!F()?n:Nt(n,{silent:!0})}const k=(n,o)=>m().then(u=>u?u.transaction(n,o).objectStore(n):null);function v(n){return new Promise((o,u)=>{n.onsuccess=()=>o(n.result),n.onerror=()=>{_(n.error),u(n.error)}})}const q=n=>k(n,"readonly").then(o=>o?v(o.getAll()):[]).then(o=>F()?Promise.all(o.map(u=>I(u))):o),L=(n,o)=>k(n,"readonly").then(u=>u?v(u.get(o)).then(f=>f!==void 0?f:typeof o=="string"&&o.trim()!==""&&!isNaN(Number(o))?v(u.get(Number(o))):typeof o=="number"?v(u.get(String(o))):null):null).then(u=>u?I(u):null),D=(n,o)=>m().then(u=>{if(!u)return[];const h=u.transaction(n,"readonly").objectStore(n),y=o.map(p=>v(h.get(p)).then(g=>g!==void 0?g:typeof p=="string"&&p.trim()!==""&&!isNaN(Number(p))?v(h.get(Number(p))):typeof p=="number"?v(h.get(String(p))):null));return Promise.all(y).then(p=>F()?Promise.all(p.map(g=>g?I(g):null)):p)}),B=(n,o)=>(F()?A(o):Promise.resolve(o)).then(f=>k(n,"readwrite").then(h=>h?v(h.put(f)):null)),ye=(n,o)=>k(n,"readwrite").then(u=>u?v(u.delete(o)).then(()=>{if(typeof o=="string"&&o.trim()!==""&&!isNaN(Number(o)))return v(u.delete(Number(o)));if(typeof o=="number")return v(u.delete(String(o)))}):null),K=n=>k(n,"readwrite").then(o=>o?v(o.clear()):null),j=n=>k(n,"readonly").then(o=>o?v(o.count()):0),Q=n=>k(c,"readonly").then(o=>o?v(o.get(n)):null),J=(n,o)=>k(c,"readwrite").then(u=>{if(u)return o.key=n,v(u.put(o))});function R(n){return this.dom=n,this._name=n.id,this._name||console.warn("[ln-data-store] missing id — the store cannot be addressed",n),Ee(this,n,a),this._handlers=null,this.isLoaded=!1,this.canServe=!1,this.isInitialized=!1,this.initializationError=null,this.hasCache=!1,this.isSyncing=!1,this.lastSyncedAt=null,this.query={filters:{},search:"",sort:null},n.hasAttribute("data-ln-data-store-window")?this._windowIndex=Mt({windowSize:this._windowSize,pageSize:this._windowPageSize,requestPage:(o,u,f)=>{C(this.dom,"ln-data-store:request-page",{store:this._name,offset:o,limit:u,query:f,queryGen:this._windowIndex.queryGen})}}):this._windowIndex=null,this.windowed=this._windowIndex!==null,this.totalCount=0,this.presenters=null,this._mutationChain=Promise.resolve(),b[this._name]=this,Ht(this),this.ready=tn(this),this}function Ht(n){n._handlers={create:o=>ee(n,"create",o.detail,()=>Qt(n,o.detail)),update:o=>ee(n,"update",o.detail,()=>Jt(n,o.detail)),delete:o=>ee(n,"delete",o.detail,()=>Zt(n,o.detail)),"bulk-delete":o=>ee(n,"bulk-delete",o.detail,()=>Xt(n,o.detail)),"sync-failed":o=>{n.isSyncing=!1,C(n.dom,"ln-data-store:sync-error",{store:n._name,error:o.detail&&o.detail.error,status:o.detail&&o.detail.status})}};for(const[o,u]of Object.entries(n._handlers))n.dom.addEventListener(`ln-data-store:request-${o}`,u);n._queryHandlers={"ln-search:change":o=>{o.preventDefault();const u=o.detail&&o.detail.term!=null?o.detail.term:"";u!==n.query.search&&(n.query.search=u,ge(n))},"ln-filter:change":o=>{o.preventDefault();const u=o.detail&&o.detail.key;if(!u)return;const f=(o.detail.values||[]).slice(),h=n.query.filters[u];(h?h.length===f.length&&h.every((p,g)=>p===f[g]):!f.length)||(f.length?n.query.filters[u]=f:delete n.query.filters[u],ge(n))},"ln-sort:change":o=>{o.preventDefault();const u=o.detail&&o.detail.field,f=o.detail&&o.detail.direction,h=f&&f!=="none"?{field:u,direction:f}:null,y=n.query.sort;!y&&!h||y&&h&&y.field===h.field&&y.direction===h.direction||(n.query.sort=h,ge(n))}};for(const[o,u]of Object.entries(n._queryHandlers))n.dom.addEventListener(o,u)}function ee(n,o,u,f){const h=u&&u.requestId;return n._mutationChain=n._mutationChain.then(()=>n.ready).then(()=>{if(n.initializationError)throw n.initializationError;return f()}).catch(y=>Yt(n,o,h,y)),n._mutationChain}function te(n,o=0){return j(n._name).then(u=>{if(n._windowIndex||n.windowed){const f=n.totalCount!=null?n.totalCount:u;n.totalCount=Math.max(0,f+o)}else n.totalCount=u;return n.hasCache=!0,n.isLoaded=!0,n.canServe=!0,J(n._name,{schema_version:d,last_synced_at:n.lastSyncedAt,has_cache:!0,record_count:n.totalCount})})}function Qt(n,{tempId:o,data:u={},requestId:f}={}){const h={...u,id:o};return B(n._name,h).then(()=>te(n,1)).then(()=>{C(n.dom,"ln-data-store:created",{store:n._name,record:h,tempId:o,requestId:f})})}function Jt(n,{id:o,data:u={},requestId:f}={}){return L(n._name,o).then(h=>{if(!h)throw new Error(`Record not found: ${o}`);const y=h.id,p={...h,...u,id:y},g=u.id,S=g!==void 0&&g!==y;return(S?nn(n._name,y,{...p,id:g}):B(n._name,p)).then(()=>te(n,0)).then(()=>{C(n.dom,"ln-data-store:updated",{store:n._name,record:S?{...p,id:g}:p,previous:h,requestId:f})})})}function Zt(n,{id:o,requestId:u}={}){return L(n._name,o).then(f=>{if(!f){C(n.dom,"ln-data-store:deleted",{store:n._name,id:o,requestId:u,missing:!0});return}const h=f.id;return ye(n._name,h).then(()=>te(n,-1)).then(()=>{C(n.dom,"ln-data-store:deleted",{store:n._name,id:h,requestId:u})})})}function Xt(n,{ids:o=[],requestId:u}={}){return o.length?Promise.all(o.map(f=>L(n._name,f))).then(f=>{const h=f.filter(Boolean).map(y=>y.id);return ne(n._name,h).then(()=>te(n,-h.length)).then(()=>{C(n.dom,"ln-data-store:deleted",{store:n._name,ids:h,requestId:u})})}):(C(n.dom,"ln-data-store:deleted",{store:n._name,ids:[],requestId:u}),Promise.resolve())}function Yt(n,o,u,f){console.error("[ln-data-store] "+o+" failed:",f),C(n.dom,"ln-data-store:mutation-error",{store:n._name,action:o,requestId:u,error:f})}function en(n){let o=null;const u=n.dom.getAttribute("data-ln-data-store-seed");if(u&&(o=document.getElementById(u),!o))try{o=document.querySelector(u)}catch{}return o||(o=n.dom.querySelector('script[type="application/json"]')||n.dom.querySelector("script")),o&&o.textContent?Wt(o.textContent):null}function tn(n){const o=en(n);return n._seedRecords=o,o?(n.lastSyncedAt=Math.floor(Date.now()/1e3),n.totalCount=o.length,n.hasCache=!0,n.isLoaded=!0,n.canServe=!0,n.isInitialized=!0,setTimeout(()=>{C(n.dom,"ln-data-store:ready",{store:n._name,count:n.totalCount,source:"seed"}),C(n.dom,"ln-data-store:initialized",{store:n._name,hasCache:!0,lastSyncedAt:n.lastSyncedAt,count:n.totalCount,source:"seed"})},0),M().then(u=>{if(u)return K(n._name).then(()=>pe(n._name,o)).then(()=>J(n._name,{schema_version:d,last_synced_at:n.lastSyncedAt,has_cache:!0,record_count:n.totalCount}))}).catch(()=>{}),Promise.resolve({ok:!0,source:"seed"})):M().then(u=>{if(!u)throw new Error("IndexedDB is unavailable");return Q(n._name)}).then(u=>{if(!o)if(n.initializationError=null,u&&u.schema_version===d)n.lastSyncedAt=u.last_synced_at||null,n.totalCount=u.record_count||0,n.hasCache=u.has_cache===!0||n.totalCount>0,n.hasCache&&(n.isLoaded=!0,n.canServe=!0,C(n.dom,"ln-data-store:ready",{store:n._name,count:n.totalCount,source:"cache"})),n.isInitialized=!0,C(n.dom,"ln-data-store:initialized",{store:n._name,hasCache:n.hasCache,lastSyncedAt:n.lastSyncedAt,count:n.totalCount});else{if(u&&u.schema_version!==d)return K(n._name).then(()=>J(n._name,{schema_version:d,last_synced_at:null,has_cache:!1,record_count:0})).then(()=>{n.isInitialized=!0,n.hasCache=!1,C(n.dom,"ln-data-store:initialized",{store:n._name,hasCache:!1,lastSyncedAt:null,count:0})});n.isInitialized=!0,n.hasCache=!1,C(n.dom,"ln-data-store:initialized",{store:n._name,hasCache:!1,lastSyncedAt:null,count:0})}}).catch(u=>o?(n.lastSyncedAt=Math.floor(Date.now()/1e3),n.totalCount=o.length,n.hasCache=!0,n.isLoaded=!0,n.canServe=!0,n.isInitialized=!0,C(n.dom,"ln-data-store:ready",{store:n._name,count:n.totalCount,source:"seed"}),C(n.dom,"ln-data-store:initialized",{store:n._name,hasCache:!0,lastSyncedAt:n.lastSyncedAt,count:n.totalCount,source:"seed"}),{ok:!0,source:"seed"}):(n.isInitialized=!0,n.isLoaded=!1,n.canServe=!1,n.hasCache=!1,n.isSyncing=!1,n.initializationError=u,C(n.dom,"ln-data-store:initialization-error",{store:n._name,error:u}),{ok:!1,error:u}))}function $e(n){n.isSyncing=!0,C(n.dom,"ln-data-store:request-remote-sync",{since:n.lastSyncedAt})}function pe(n,o){return m().then(u=>u?(F()?Promise.all(o.map(h=>A(h))):Promise.resolve(o)).then(h=>new Promise((y,p)=>{const g=u.transaction(n,"readwrite"),S=g.objectStore(n);h.forEach(E=>S.put(E)),g.oncomplete=()=>y(),g.onerror=()=>{_(g.error),p(g.error)}})):void 0)}function ne(n,o){return m().then(u=>{if(u)return new Promise((f,h)=>{const y=u.transaction(n,"readwrite"),p=y.objectStore(n);o.forEach(g=>{p.delete(g),typeof g=="string"&&g.trim()!==""&&!isNaN(Number(g))?p.delete(Number(g)):typeof g=="number"&&p.delete(String(g))}),y.oncomplete=()=>f(),y.onerror=()=>h(y.error)})})}function nn(n,o,u){return(F()?A(u):Promise.resolve(u)).then(h=>m().then(y=>{if(y)return new Promise((p,g)=>{const S=y.transaction(n,"readwrite"),E=S.objectStore(n);E.put(h),E.delete(o),S.oncomplete=()=>p(),S.onerror=()=>{_(S.error),g(S.error)}})}))}const rn=new Intl.Collator(void 0,{numeric:!0,sensitivity:"base"});function on(n){return n?Object.keys(n).filter(o=>Array.isArray(n[o])&&n[o].length>0):[]}function an(n,o,u){return o.every(f=>u[f].map(String).includes(String(n[f])))}function sn(n){return String(n||"").toLowerCase().split(/\s+/).filter(Boolean)}function ln(n,o,u){return o.every(f=>u.some(h=>{const y=n[h];return y!=null&&String(y).toLowerCase().includes(f)}))}function cn(n,o,u){return $t(n,o,u)}function G(n,o){return Ut(o,n.presenters&&n.presenters.computed)}function un(n){return!n.sort&&!F()}function dn(n,o,u){const f=on(o.filters),h=o.search?sn(o.search):[],y=n._searchFields,p=h.length>0&&y&&y.length>0;return k(n._name,"readonly").then(g=>g?new Promise((S,E)=>{const U=[],P=g.openCursor();P.onsuccess=()=>{const z=P.result;if(!z||U.length>=u){S(U);return}const O=z.value;(!f.length||an(O,f,o.filters))&&(!p||ln(O,h,y))&&U.push(O),z.continue()},P.onerror=()=>E(P.error)}):[])}function me(n,o,u){return Kt(o,u,n._searchFields,rn)}function fn(n,o,u){const f=[];for(let y=o;y<o+u;y++){const p=n._windowIndex.getId(y);f.push(p)}const h=Array.from(new Set(f.filter(y=>y!==void 0)));return D(n._name,h).then(y=>{const p=new Map;for(let S=0;S<y.length;S++){const E=y[S];E&&p.set(String(E.id),E)}const g=[];for(let S=0;S<f.length;S++){const E=f[S];if(E===void 0)g.push(null);else{const U=p.get(String(E));g.push(U||null)}}return{data:G(n,g),total:n._windowIndex.grandTotal,filtered:n._windowIndex.logicalTotal,offset:o,queryGen:n._windowIndex.queryGen}})}R.prototype.getAll=function(n={}){const o=this;if(o._seedRecords){const u=me(o,o._seedRecords,n);return Promise.resolve({data:G(o,u.records),total:u.total,filtered:u.filtered})}if(o._windowIndex){const u=n.offset||0,f=n.limit||200;if(o._windowIndex.ensure(u,u+f,n),!o._windowIndex.hasLoaded&&!o.noLocalQuery){const h=u+f,y=p=>({data:G(o,p),offset:u,queryGen:o._windowIndex.queryGen,provisional:!0});return un(n)?dn(o,n,h).then(p=>y(p.slice(u,h))):q(o._name).then(p=>y(me(o,p,n).records))}return fn(o,u,f)}return q(o._name).then(u=>{const f=me(o,u,n);return{data:G(o,f.records),total:f.total,filtered:f.filtered}})},R.prototype.getById=function(n){return L(this._name,n).then(o=>o?G(this,[o])[0]:null)},R.prototype.count=function(n){if(this._seedRecords){const u=n&&Object.keys(n).length>0;return Promise.resolve(u?we(this._seedRecords,n).length:this._seedRecords.length)}return n&&Object.keys(n).length>0?q(this._name).then(u=>we(u,n).length):this.windowed&&this.totalCount!=null?Promise.resolve(this.totalCount):j(this._name)},R.prototype.aggregate=function(n,o){return q(this._name).then(u=>cn(u,n,o))},R.prototype.setPresenters=function(n){this.presenters=n},R.prototype.applySync=function(n,o,u,f){f=f||{};const h=this;if(h._windowIndex&&f.queryGen!=null&&f.queryGen!==h._windowIndex.queryGen)return Promise.resolve({ok:!0,stale:!0});let y=m().then(p=>{if(!p)throw new Error("IndexedDB unavailable")});return n.length>0&&(y=y.then(()=>pe(h._name,n))),o.length>0&&(y=y.then(()=>ne(h._name,o))),y.then(()=>{if(h._windowIndex&&(f.offset!=null||f.total!=null)){const p=f.offset!=null?f.offset:0,g=n.map(E=>E.id),S=h._windowIndex.ingest(p,g,f.total,f.filtered,f.queryGen);if(S&&S.length)return ne(h._name,S)}}).then(()=>j(h._name)).then(p=>(h.totalCount=f.total!==void 0?f.total:p,h.hasCache=!0,J(h._name,{schema_version:d,last_synced_at:u,has_cache:!0,record_count:h.totalCount}))).then(()=>{const p=!h.isLoaded;return h.isLoaded=!0,h.canServe=!0,h.isSyncing=!1,h.lastSyncedAt=u,p?(C(h.dom,"ln-data-store:loaded",{store:h._name,count:h.totalCount,meta:f}),C(h.dom,"ln-data-store:ready",{store:h._name,count:h.totalCount,source:"server",meta:f})):C(h.dom,"ln-data-store:synced",{store:h._name,added:n.length,deleted:o.length,changed:!0,meta:f}),{ok:!0}}).catch(p=>{h.isSyncing=!1;const g=p&&p.message?p.message:String(p);return console.error("[ln-data-store] applySync failed:",p),C(h.dom,"ln-data-store:sync-error",{store:h._name,error:g}),Vt(p)})},R.prototype.applyQuery=function(n,o){o=o||{};const u=this;let f=Promise.resolve();return n.length>0&&(f=f.then(()=>pe(u._name,n))),f.then(()=>j(u._name)).then(h=>(u.totalCount=o.total!==void 0?o.total:h,n.length>0&&(u.canServe=!0),G(u,n))).catch(h=>(console.error("[ln-data-store] applyQuery failed:",h),[]))},R.prototype.forceSync=function(){this.isSyncing||$e(this)},R.prototype.fullReload=function(){const n=this;return K(n._name).then(()=>J(n._name,{schema_version:d,last_synced_at:null,has_cache:!1,record_count:0})).then(()=>{n.isLoaded=!1,n.hasCache=!1,n.lastSyncedAt=null,n.totalCount=0,$e(n)})},R.prototype.destroy=function(){if(this._windowIndex&&(this._windowIndex.clear(),this._windowIndex=null,this.windowed=!1),this._handlers){for(const[n,o]of Object.entries(this._handlers))this.dom.removeEventListener(`ln-data-store:request-${n}`,o);this._handlers=null}if(this._queryHandlers){for(const[n,o]of Object.entries(this._queryHandlers))this.dom.removeEventListener(n,o);this._queryHandlers=null}delete b[this._name],delete this.dom[t]};function hn(){return m().then(n=>{if(!n)return;const o=Array.from(n.objectStoreNames);return new Promise((u,f)=>{const h=n.transaction(o,"readwrite");o.forEach(y=>h.objectStore(y).clear()),h.oncomplete=()=>u(),h.onerror=()=>f(h.error)})}).then(()=>{Object.values(b).forEach(n=>{n.isLoaded=!1,n.canServe=!1,n.isInitialized=!1,n.initializationError=null,n.hasCache=!1,n.isSyncing=!1,n.lastSyncedAt=null,n.totalCount=0})})}function ge(n){n._windowIndex&&n._windowIndex.reset(),C(n.dom,"ln-data-store:query-changed",{store:n._name,query:{filters:Object.assign({},n.query.filters),search:n.query.search,sort:n.query.sort?Object.assign({},n.query.sort):null}})}const wn="data-ln-data-store-frozen";function Ke(n,o){n.setAttribute(wn,o)}function yn(n){const o=n[t];if(!o._windowIndex)return;const u=o._windowIndex.configure({windowSize:o._windowSize});u.length&&ne(o._name,u).catch(f=>{console.error("[ln-data-store] window shrink eviction failed:",f)})}function pn(n){const o=n[t];o._windowIndex&&o._windowIndex.configure({pageSize:o._windowPageSize})}ze(e,t,R,"ln-data-store",{attributes:i}),window[t].clearAll=hn,window[t].init=window[t],window[t].setStorageKey=je,typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.setStorageKey=je)})()})();
@@ -1,84 +1,92 @@
1
- {
2
- "$comment": "This file is partly generated. The $comment, component, generator, and each attribute's direction, sources, type, values, fallback, and description keys are owned by the generator and synchronized from JS source code. All other keys are preserved and safe to hand-author. Regenerate with `npm run sync:ln-schemas`.",
3
- "component": "ln-data-store",
4
- "generator": "scripts/sync-ln-schemas.mjs",
5
- "attributes": {
6
- "data-ln-data-store": {
7
- "direction": "author",
8
- "sources": [
9
- "ln-data-store-dev.scss",
10
- "src/ln-data-store.js"
11
- ],
12
- "type": "marker",
13
- "description": "Identifies the element as a data-store definition container"
14
- },
15
- "data-ln-data-store-frozen": {
16
- "direction": "runtime",
17
- "sources": [
18
- "ln-data-store-dev.scss",
19
- "src/ln-data-store.js"
20
- ],
21
- "type": "marker",
22
- "description": "Applied at runtime to indicate store schema is locked in IndexedDB"
23
- },
24
- "data-ln-data-store-indexes": {
25
- "direction": "author",
26
- "sources": [
27
- "src/ln-data-store.js"
28
- ],
29
- "type": "list",
30
- "description": "Comma-separated index field names for the IndexedDB store"
31
- },
32
- "data-ln-data-store-no-local-query": {
33
- "direction": null,
34
- "sources": [
35
- "src/ln-data-store.js"
36
- ],
37
- "type": "boolean",
38
- "description": "Bypasses local IndexedDB query resolution, forcing remote fetching"
39
- },
40
- "data-ln-data-store-search-fields": {
41
- "direction": null,
42
- "sources": [
43
- "src/ln-data-store.js"
44
- ],
45
- "type": "list",
46
- "description": "Record fields to index for client-side search"
47
- },
48
- "data-ln-data-store-stale": {
49
- "direction": null,
50
- "sources": [
51
- "src/ln-data-store.js"
52
- ],
53
- "type": "integer",
54
- "fallback": 300,
55
- "description": "Cache staleness threshold in seconds, or -1/never"
56
- },
57
- "data-ln-data-store-window": {
58
- "direction": "author",
59
- "sources": [
60
- "src/ln-data-store.js"
61
- ],
62
- "type": "integer",
63
- "fallback": 1000,
64
- "min": 10,
65
- "description": "Virtual scrolling cache window size in records"
66
- },
67
- "data-ln-data-store-window-page": {
68
- "direction": null,
69
- "sources": [
70
- "src/ln-data-store.js"
71
- ],
72
- "type": "integer",
73
- "fallback": 200,
74
- "min": 5,
75
- "description": "Virtual scrolling slice page size"
76
- },
77
- "data-ln-debug": {
78
- "direction": null,
79
- "sources": [
80
- "ln-data-store-dev.scss"
81
- ]
82
- }
83
- }
84
- }
1
+ {
2
+ "$comment": "This file is partly generated. The $comment, component, generator, and each attribute's direction, sources, type, values, fallback, and description keys are owned by the generator and synchronized from JS source code. All other keys are preserved and safe to hand-author. Regenerate with `npm run sync:ln-schemas`.",
3
+ "component": "ln-data-store",
4
+ "generator": "scripts/sync-ln-schemas.mjs",
5
+ "attributes": {
6
+ "data-ln-data-store": {
7
+ "direction": "author",
8
+ "sources": [
9
+ "ln-data-store-dev.scss",
10
+ "src/ln-data-store.js"
11
+ ],
12
+ "type": "marker",
13
+ "description": "Identifies the element as a data-store definition container"
14
+ },
15
+ "data-ln-data-store-frozen": {
16
+ "direction": "runtime",
17
+ "sources": [
18
+ "ln-data-store-dev.scss",
19
+ "src/ln-data-store.js"
20
+ ],
21
+ "type": "marker",
22
+ "description": "Applied at runtime to indicate store schema is locked in IndexedDB"
23
+ },
24
+ "data-ln-data-store-indexes": {
25
+ "direction": "author",
26
+ "sources": [
27
+ "src/ln-data-store.js"
28
+ ],
29
+ "type": "list",
30
+ "description": "Comma-separated index field names for the IndexedDB store"
31
+ },
32
+ "data-ln-data-store-no-local-query": {
33
+ "direction": null,
34
+ "sources": [
35
+ "src/ln-data-store.js"
36
+ ],
37
+ "type": "boolean",
38
+ "description": "Bypasses local IndexedDB query resolution, forcing remote fetching"
39
+ },
40
+ "data-ln-data-store-search-fields": {
41
+ "direction": null,
42
+ "sources": [
43
+ "src/ln-data-store.js"
44
+ ],
45
+ "type": "list",
46
+ "description": "Record fields to index for client-side search"
47
+ },
48
+ "data-ln-data-store-seed": {
49
+ "direction": "author",
50
+ "sources": [
51
+ "src/ln-data-store.js"
52
+ ],
53
+ "type": "string",
54
+ "description": "Selector or element ID of an external seed script block"
55
+ },
56
+ "data-ln-data-store-stale": {
57
+ "direction": null,
58
+ "sources": [
59
+ "src/ln-data-store.js"
60
+ ],
61
+ "type": "integer",
62
+ "fallback": 300,
63
+ "description": "Cache staleness threshold in seconds, or -1/never"
64
+ },
65
+ "data-ln-data-store-window": {
66
+ "direction": "author",
67
+ "sources": [
68
+ "src/ln-data-store.js"
69
+ ],
70
+ "type": "integer",
71
+ "fallback": 1000,
72
+ "min": 10,
73
+ "description": "Virtual scrolling cache window size in records"
74
+ },
75
+ "data-ln-data-store-window-page": {
76
+ "direction": null,
77
+ "sources": [
78
+ "src/ln-data-store.js"
79
+ ],
80
+ "type": "integer",
81
+ "fallback": 200,
82
+ "min": 5,
83
+ "description": "Virtual scrolling slice page size"
84
+ },
85
+ "data-ln-debug": {
86
+ "direction": null,
87
+ "sources": [
88
+ "ln-data-store-dev.scss"
89
+ ]
90
+ }
91
+ }
92
+ }
@@ -182,3 +182,20 @@ export function normalizeSyncError(err) {
182
182
  const errorMsg = (err && err.message) ? err.message : String(err);
183
183
  return { ok: false, error: errorMsg };
184
184
  }
185
+
186
+ /**
187
+ * Parses raw JSON seed string into an array of record objects.
188
+ * @param {string} raw
189
+ * @returns {Array<Record<string, any>> | null}
190
+ */
191
+ export function parseSeedRecords(raw) {
192
+ if (!raw || typeof raw !== 'string') return null;
193
+ const trimmed = raw.trim();
194
+ if (!trimmed) return null;
195
+ try {
196
+ const parsed = JSON.parse(trimmed);
197
+ return Array.isArray(parsed) ? parsed : null;
198
+ } catch (_) {
199
+ return null;
200
+ }
201
+ }
@@ -1,6 +1,6 @@
1
1
  import { registerComponent, dispatch, setCryptoKey, getCryptoKey, encryptData, decryptData, defineAttrs, attrSpec, attrInt, attrBool, attrList } from '../../ln-core';
2
2
  import { createWindowIndex } from './window-index.js';
3
- import { aggregateRecords, decorateRecords, filterRecords, queryRecords, checkNeedsUpgrade, normalizeSyncError } from './data-store-model.js';
3
+ import { aggregateRecords, decorateRecords, filterRecords, queryRecords, checkNeedsUpgrade, normalizeSyncError, parseSeedRecords } from './data-store-model.js';
4
4
 
5
5
  (function () {
6
6
  const DOM_SELECTOR = 'data-ln-data-store';
@@ -21,6 +21,7 @@ import { aggregateRecords, decorateRecords, filterRecords, queryRecords, checkNe
21
21
  const ATTRIBUTES = {
22
22
  'data-ln-data-store': { type: 'marker', effect: _markFrozen, description: 'Identifies the element as a data-store definition container' },
23
23
  'data-ln-data-store-indexes': { type: 'list', effect: _markFrozen, description: 'Comma-separated index field names for the IndexedDB store' },
24
+ 'data-ln-data-store-seed': { type: 'string', description: 'Selector or element ID of an external seed script block' },
24
25
  'data-ln-data-store-stale': { prop: '_staleThreshold', type: 'integer', read: _readStale, fallback: 300, description: 'Cache staleness threshold in seconds, or -1/never' },
25
26
  'data-ln-data-store-search-fields': { prop: '_searchFields', type: 'list', read: attrList, description: 'Record fields to index for client-side search' },
26
27
  'data-ln-data-store-no-local-query': { prop: 'noLocalQuery', type: 'boolean', read: attrBool, description: 'Bypasses local IndexedDB query resolution, forcing remote fetching' },
@@ -515,11 +516,63 @@ import { aggregateRecords, decorateRecords, filterRecords, queryRecords, checkNe
515
516
 
516
517
  // ─── Initialization ────────────────────────────────────
517
518
 
519
+ function _readSeedRecords(self) {
520
+ let scriptEl = null;
521
+ const seedSelector = self.dom.getAttribute('data-ln-data-store-seed');
522
+ if (seedSelector) {
523
+ scriptEl = document.getElementById(seedSelector);
524
+ if (!scriptEl) {
525
+ try {
526
+ scriptEl = document.querySelector(seedSelector);
527
+ } catch (_) {}
528
+ }
529
+ }
530
+ if (!scriptEl) {
531
+ scriptEl = self.dom.querySelector('script[type="application/json"]') || self.dom.querySelector('script');
532
+ }
533
+ if (scriptEl && scriptEl.textContent) {
534
+ return parseSeedRecords(scriptEl.textContent);
535
+ }
536
+ return null;
537
+ }
538
+
518
539
  function _initStore(self) {
540
+ const seedRecords = _readSeedRecords(self);
541
+ self._seedRecords = seedRecords;
542
+
543
+ if (seedRecords) {
544
+ self.lastSyncedAt = Math.floor(Date.now() / 1000);
545
+ self.totalCount = seedRecords.length;
546
+ self.hasCache = true;
547
+ self.isLoaded = true;
548
+ self.canServe = true;
549
+ self.isInitialized = true;
550
+ setTimeout(() => {
551
+ dispatch(self.dom, 'ln-data-store:ready', { store: self._name, count: self.totalCount, source: 'seed' });
552
+ dispatch(self.dom, 'ln-data-store:initialized', { store: self._name, hasCache: true, lastSyncedAt: self.lastSyncedAt, count: self.totalCount, source: 'seed' });
553
+ }, 0);
554
+
555
+ // Persist seed asynchronously to IndexedDB in background without blocking immediate queries
556
+ _openDatabase().then(db => {
557
+ if (!db) return;
558
+ return _clearStore(self._name)
559
+ .then(() => _putBulk(self._name, seedRecords))
560
+ .then(() => _setMeta(self._name, {
561
+ schema_version: SCHEMA_VERSION,
562
+ last_synced_at: self.lastSyncedAt,
563
+ has_cache: true,
564
+ record_count: self.totalCount
565
+ }));
566
+ }).catch(() => {});
567
+
568
+ return Promise.resolve({ ok: true, source: 'seed' });
569
+ }
570
+
519
571
  return _openDatabase().then(db => {
520
572
  if (!db) throw new Error('IndexedDB is unavailable');
521
573
  return _getMeta(self._name);
522
574
  }).then(meta => {
575
+ if (seedRecords) return;
523
576
  self.initializationError = null;
524
577
  if (meta && meta.schema_version === SCHEMA_VERSION) {
525
578
  self.lastSyncedAt = meta.last_synced_at || null;
@@ -548,6 +601,17 @@ import { aggregateRecords, decorateRecords, filterRecords, queryRecords, checkNe
548
601
  dispatch(self.dom, 'ln-data-store:initialized', { store: self._name, hasCache: false, lastSyncedAt: null, count: 0 });
549
602
  }
550
603
  }).catch(error => {
604
+ if (seedRecords) {
605
+ self.lastSyncedAt = Math.floor(Date.now() / 1000);
606
+ self.totalCount = seedRecords.length;
607
+ self.hasCache = true;
608
+ self.isLoaded = true;
609
+ self.canServe = true;
610
+ self.isInitialized = true;
611
+ dispatch(self.dom, 'ln-data-store:ready', { store: self._name, count: self.totalCount, source: 'seed' });
612
+ dispatch(self.dom, 'ln-data-store:initialized', { store: self._name, hasCache: true, lastSyncedAt: self.lastSyncedAt, count: self.totalCount, source: 'seed' });
613
+ return { ok: true, source: 'seed' };
614
+ }
551
615
  self.isInitialized = true;
552
616
  self.isLoaded = false;
553
617
  self.canServe = false;
@@ -752,6 +816,14 @@ import { aggregateRecords, decorateRecords, filterRecords, queryRecords, checkNe
752
816
 
753
817
  _component.prototype.getAll = function (options = {}) {
754
818
  const self = this;
819
+ if (self._seedRecords) {
820
+ const r = _queryLocal(self, self._seedRecords, options);
821
+ return Promise.resolve({
822
+ data: _decorate(self, r.records),
823
+ total: r.total,
824
+ filtered: r.filtered
825
+ });
826
+ }
755
827
  if (self._windowIndex) {
756
828
  const offset = options.offset || 0;
757
829
  const limit = options.limit || 200;
@@ -807,6 +879,10 @@ import { aggregateRecords, decorateRecords, filterRecords, queryRecords, checkNe
807
879
  };
808
880
 
809
881
  _component.prototype.count = function (filters) {
882
+ if (this._seedRecords) {
883
+ const hasFilters = filters && Object.keys(filters).length > 0;
884
+ return Promise.resolve(hasFilters ? filterRecords(this._seedRecords, filters).length : this._seedRecords.length);
885
+ }
810
886
  const hasFilters = filters && Object.keys(filters).length > 0;
811
887
  if (!hasFilters) {
812
888
  if (this.windowed && this.totalCount != null) return Promise.resolve(this.totalCount);