@livenetworks/ashlar 2.0.6 → 2.0.7

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.
Files changed (33) hide show
  1. package/components/ln-accordion/ln-accordion.js +1 -1
  2. package/components/ln-accordion/src/ln-accordion.js +1 -0
  3. package/components/ln-couchdb-connector/README.md +4 -0
  4. package/components/ln-couchdb-connector/ln-couchdb-connector.js +1 -1
  5. package/components/ln-couchdb-connector/src/ln-couchdb-connector.js +18 -1
  6. package/components/ln-data-coordinator/ln-data-coordinator.js +1 -1
  7. package/components/ln-data-coordinator/src/ln-data-coordinator.js +15 -6
  8. package/components/ln-data-store/README.md +3 -2
  9. package/components/ln-data-store/ln-data-store.js +1 -1
  10. package/components/ln-data-store/src/data-store-model.js +29 -0
  11. package/components/ln-data-store/src/ln-data-store.js +57 -10
  12. package/components/ln-date/README.md +4 -0
  13. package/components/ln-date/ln-date.js +1 -1
  14. package/components/ln-date/src/ln-date.js +3 -3
  15. package/components/ln-list/ln-list.js +1 -1
  16. package/components/ln-list/src/ln-list.js +4 -4
  17. package/components/ln-modal/README.md +4 -6
  18. package/components/ln-modal/ln-modal.js +1 -1
  19. package/components/ln-modal/src/ln-modal.js +28 -8
  20. package/components/ln-options/ln-options.js +1 -1
  21. package/components/ln-options/src/ln-options.js +1 -0
  22. package/components/ln-popover/README.md +4 -0
  23. package/components/ln-popover/ln-popover.js +1 -1
  24. package/components/ln-popover/src/ln-popover.js +9 -0
  25. package/components/ln-table/ln-table.js +1 -1
  26. package/components/ln-table/src/ln-table.js +2 -0
  27. package/components/ln-table-coordinator/ln-table-coordinator.js +1 -1
  28. package/components/ln-table-coordinator/src/ln-table-coordinator.js +3 -3
  29. package/components/ln-tabs/README.md +2 -2
  30. package/components/ln-tabs/ln-tabs.js +1 -1
  31. package/components/ln-tabs/src/ln-tabs.js +1 -0
  32. package/package.json +1 -1
  33. package/web-types.json +1 -1
@@ -543,6 +543,7 @@ import { MutationReceipts } from './mutation-receipts';
543
543
 
544
544
  // ─── Connector Response Handlers (direct + queued paths) ──
545
545
  connFetched: function (e) {
546
+ if (!e.detail) return;
546
547
  const meta = e.detail.meta || {};
547
548
  const children = self.findChildren();
548
549
 
@@ -625,8 +626,13 @@ import { MutationReceipts } from './mutation-receipts';
625
626
  },
626
627
 
627
628
  connCreated: function (e) {
629
+ if (!e.detail) return;
628
630
  const children = self.findChildren();
629
631
  const meta = e.detail.meta || {};
632
+ if (!e.detail.record) {
633
+ self._reportReconciliationError('create-empty-response', new Error('Create response missing record payload'), meta);
634
+ return;
635
+ }
630
636
  const serverRecord = self.mapper.ingress(e.detail.record);
631
637
  const reconciled = children.storeEl
632
638
  ? self._requestStoreMutation(children, 'update', { id: meta.tempId, data: serverRecord })
@@ -649,10 +655,11 @@ import { MutationReceipts } from './mutation-receipts';
649
655
  },
650
656
 
651
657
  connUpdated: function (e) {
658
+ if (!e.detail) return;
652
659
  const children = self.findChildren();
653
660
  const meta = e.detail.meta || {};
654
- const serverRecord = self.mapper.ingress(e.detail.record);
655
- const reconciled = children.storeEl
661
+ const serverRecord = e.detail.record ? self.mapper.ingress(e.detail.record) : null;
662
+ const reconciled = (children.storeEl && serverRecord)
656
663
  ? self._requestStoreMutation(children, 'update', { id: meta.id, data: serverRecord })
657
664
  : Promise.resolve();
658
665
 
@@ -669,19 +676,21 @@ import { MutationReceipts } from './mutation-receipts';
669
676
  },
670
677
 
671
678
  connDeleted: function (e) {
679
+ const detail = e.detail || {};
672
680
  const children = self.findChildren();
673
- const meta = e.detail.meta || {};
681
+ const meta = detail.meta || {};
674
682
  // Optimistic delete already applied; no local reconciliation.
675
- self._toastFromMessage(e.detail.message); // null on 204 → silent
683
+ self._toastFromMessage(detail.message); // null on 204 → silent
676
684
  if (meta.queued && children.queue) {
677
685
  dispatch(children.queueEl, 'ln-api-queue:ack', { entryId: meta.entryId });
678
686
  }
679
687
  },
680
688
 
681
689
  connBulkDeleted: function (e) {
690
+ const detail = e.detail || {};
682
691
  const children = self.findChildren();
683
- const meta = e.detail.meta || {};
684
- self._toastFromMessage(e.detail.message);
692
+ const meta = detail.meta || {};
693
+ self._toastFromMessage(detail.message);
685
694
  if (meta.queued && children.queue) {
686
695
  dispatch(children.queueEl, 'ln-api-queue:ack', { entryId: meta.entryId });
687
696
  }
@@ -107,7 +107,7 @@ store.setPresenters({
107
107
  | `count(filters)` | `Promise<Number>` | Returns the total count of records. If filters are provided, returns the filtered count. |
108
108
  | `aggregate(field, fn)` | `Promise<Number>` | Performs aggregation. `fn` must be `'count'`, `'sum'`, or `'avg'`. |
109
109
  | `setPresenters(presenters)` | `void` | Registers presenters (decorators) for computed fields. |
110
- | `applySync(upserted, deleted, syncedAt)` | `Promise<void>` | Feeds synchronization delta updates into the cache. |
110
+ | `applySync(upserted, deleted, syncedAt, meta)` | `Promise<{ ok: boolean, error?: string }>` | Feeds synchronization delta updates into the cache. Resolves `{ ok: true }` on success, or `{ ok: false, error }` on failure while dispatching `ln-data-store:sync-error`. |
111
111
  | `forceSync()` | `void` | Dispatches `ln-data-store:request-remote-sync` with the current last sync timestamp. |
112
112
  | `fullReload()` | `Promise<void>` | Clears the IndexedDB store, resets sync metadata, and triggers a sync. |
113
113
  | `destroy()` | `void` | Cleans up the instance, removes event listeners, and deletes the DOM reference. |
@@ -192,7 +192,8 @@ These events bubble up and can be listened to by coordinators or rendering views
192
192
  | `ln-data-store:updated` | `{ store, record, previous, requestId? }` | Emitted after optimistic update or id-swap rekey. |
193
193
  | `ln-data-store:deleted` | `{ store, id \| ids, requestId? }` | Emitted after optimistic delete or bulk delete. |
194
194
  | `ln-data-store:synced` | `{ store, added, deleted, changed }` | Emitted after subsequent delta sync merges. |
195
- | `ln-data-store:sync-error` | `{ store, error, status }` | A connector sync failed; `isSyncing` has been cleared so online/visibility retry can proceed. |
195
+ | `ln-data-store:sync-error` | `{ store, error, status? }` | A sync failed (remote fetch or local storage commit). `status` is present on remote HTTP failures and omitted on local commit failures. |
196
+ | `ln-data-store:blocked` | `{ db }` | Emitted on document if an IndexedDB version upgrade is blocked by open connections in other tabs. |
196
197
  | `ln-data-store:mutation-error` | `{ store, action, requestId, error }` | A serialized local mutation failed. `requestId` lets a coordinator correlate reconciliation failures. |
197
198
 
198
199
  ### Global System Events
@@ -1 +1 @@
1
- (function(){"use strict";function ie(){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 Z(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 n=e.closest("[data-ln-debug]");return!(!n||typeof document<"u"&&n===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(...n){if(typeof n[0]=="string"&&(n[0].startsWith("[ln-")||n[0].startsWith("[lnCore"))){let i=null;for(let a=1;a<n.length;a++)if(n[a]&&n[a].nodeType===1){i=n[a];break}if(!Z(i))return}e.apply(console,n)}}function v(e,n,o){const i=o||{};window.lnCore._debugSink&&window.lnCore._debugSink("event",n,e,i),e.dispatchEvent(new CustomEvent(n,{bubbles:!0,detail:i}))}function G(e,n){if(!document.body){document.addEventListener("DOMContentLoaded",function(){G(e,n)}),console.warn("["+n+'] Script loaded before <body> — add "defer" to your <script> tag');return}e()}const ae={};function qe(e,n){ae[e]=n}function Le(e){return ae[e]||{ingress:n=>n,egress:n=>n}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.registerDataMapper=qe,window.lnCore.getDataMapper=Le);function Ne(){typeof window>"u"||(window.lnCore=window.lnCore||{},!window.lnCore._localeObserverBound&&(window.lnCore._localeObserverBound=!0,G(function(){new MutationObserver(function(){v(document,"ln-core:locale-change",{})}).observe(document.documentElement,{attributes:!0,attributeFilter:["lang"],subtree:!0})},"ln-core")))}const se={};function De(e,n){if(!e||typeof n!="object")return;const o=e.toLowerCase().split("-")[0];se[o]=n}function Te(e){if(!e)return null;const n=e.toLowerCase().split("-")[0];return se[n]||null}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.registerLocaleFallback=De,window.lnCore.getLocaleFallback=Te,window.lnCore.ensureLocaleObserver=Ne);const X={};function ze(e,n){X[e]||(X[e]=document.querySelector('[data-ln-template="'+e+'"]'));const o=X[e];return o?o.content.cloneNode(!0):(console.warn("["+(n||"ln-core")+'] Template "'+e+'" not found'),null)}function le(e,n){if(!e||!n)return e;const o=e.querySelectorAll("[data-ln-field]");for(let c=0;c<o.length;c++){const f=o[c],h=f.getAttribute("data-ln-field");n[h]!=null&&(f.textContent=n[h])}const i=e.querySelectorAll("[data-ln-attr]");for(let c=0;c<i.length;c++){const f=i[c],h=f.getAttribute("data-ln-attr").split(",");for(let p=0;p<h.length;p++){const b=h[p].trim().split(":");if(b.length!==2)continue;const _=b[0].trim(),k=b[1].trim();n[k]!=null&&f.setAttribute(_,n[k])}}const a=e.querySelectorAll("[data-ln-show]");for(let c=0;c<a.length;c++){const f=a[c],h=f.getAttribute("data-ln-show");h in n&&f.classList.toggle("hidden",!n[h])}const s=e.querySelectorAll("[data-ln-class]");for(let c=0;c<s.length;c++){const f=s[c],h=f.getAttribute("data-ln-class").split(",");for(let p=0;p<h.length;p++){const b=h[p].trim().split(":");if(b.length!==2)continue;const _=b[0].trim(),k=b[1].trim();k in n&&f.classList.toggle(_,!!n[k])}}return e}function Oe(e,n){e.matches&&e.matches("[data-ln-form], [data-ln-fillable]")&&(window.lnCore._debugSink&&window.lnCore._debugSink("event","ln-fill",e,n??null),e.dispatchEvent(new CustomEvent("ln-fill",{detail:n??null,bubbles:!0})));const o=e.querySelectorAll("[data-ln-form], [data-ln-fillable]");for(let i=0;i<o.length;i++)window.lnCore._debugSink&&window.lnCore._debugSink("event","ln-fill",o[i],n??null),o[i].dispatchEvent(new CustomEvent("ln-fill",{detail:n??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)le(e.target,e.detail);else{const n=e.target.querySelectorAll("[data-ln-field]");for(let o=0;o<n.length;o++)n[o].textContent=""}})));function ce(e,n){if(!e||!n)return e;const o=document.createTreeWalker(e,NodeFilter.SHOW_TEXT);for(;o.nextNode();){const s=o.currentNode;s.textContent.indexOf("{{")!==-1&&(s.textContent=s.textContent.replace(/\{\{\s*(\w+)\s*\}\}/g,function(c,f){return n[f]!==void 0?n[f]:""}))}const i=function(s,c){return n[c]!==void 0?n[c]:""},a=Array.from(e.querySelectorAll("*"));e.nodeType===1&&a.push(e);for(let s=0;s<a.length;s++){const c=a[s],f=c.attributes;for(let h=0;h<f.length;h++){const p=f[h];p.value.indexOf("{{")!==-1&&c.setAttribute(p.name,p.value.replace(/\{\{\s*(\w+)\s*\}\}/g,i))}}return e}function Re(e,n,o,i,a,s){const c={};for(let h=0;h<e.children.length;h++){const p=e.children[h],b=p.getAttribute("data-ln-render-key");b&&(c[b]=p)}const f=document.createDocumentFragment();for(let h=0;h<n.length;h++){const p=n[h],b=String(i(p));let _=c[b];if(_)a(_,p,h);else{const k=ze(o,s);if(!k||(ce(k,p),_=k.firstElementChild,!_))continue;_.setAttribute("data-ln-render-key",b),a(_,p,h)}f.appendChild(_)}e.textContent="",e.appendChild(f)}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.fillTemplate=ce,window.lnCore.fill=le,window.lnCore.lnFill=Oe,window.lnCore.renderList=Re);function ue(e,n,o){const i=e.getAttribute(n);return i===null?o:i}function Y(e,n,o){const i=parseInt(e.getAttribute(n),10);return isNaN(i)?o:i}function de(e,n,o=!1){const i=e.getAttribute(n);if(i===null)return!!o;const a=i.trim().toLowerCase();return!(a==="false"||a==="0")}function fe(e,n){return(e.getAttribute(n)||"").split(",").map(o=>o.trim()).filter(Boolean)}const ee=new Map;function Pe(e,n){const o=(e?e.join("|"):"")+"::"+n;if(ee.has(o))return ee.get(o);const i=new Set(e||[]),a=function(s,c){const f=s.getAttribute(c);return f!==null&&i.has(f)?f:n};return ee.set(o,a),a}function Be(e,n,o){const i=parseFloat(e.getAttribute(n));return isNaN(i)?o:i}function Me(e,n,o){const i=e.getAttribute(n);if(!i)return o;try{return JSON.parse(i)}catch{return o}}function he(e,n,o,i,a){if(!e||n===null)return!0;const s=i||"ln-component",c=e.type;if(c==="trigger"||c==="marker"||c==="string"||c==="list"||!c||n===""&&e.fallback!==void 0)return!0;const f=h=>{a?console.warn(h,a):console.warn(h)};if(c==="boolean"){const h=n.trim().toLowerCase();return h!==""&&h!=="true"&&h!=="false"&&h!=="1"&&h!=="0"?(f(`[${s}] Invalid value "${n}" for boolean attribute "${o}". Allowed: "true", "false", or presence-only.`),!1):!0}if(c==="enum"){const h=e.values||[];return h.includes(n)?!0:(f(`[${s}] Invalid value "${n}" for attribute "${o}". Allowed: ${h.join(", ")}. Fallback: "${e.fallback}".`),!1)}if(c==="integer"){if(!/^-?\d+$/.test(n))return f(`[${s}] Invalid integer "${n}" for attribute "${o}". Fallback: ${e.fallback}.`),!1;const h=parseInt(n,10);return e.min!==void 0&&h<e.min?(f(`[${s}] Value ${h} for attribute "${o}" is less than min (${e.min}).`),!1):e.max!==void 0&&h>e.max?(f(`[${s}] Value ${h} for attribute "${o}" is greater than max (${e.max}).`),!1):!0}if(c==="float")return isNaN(Number(n))?(f(`[${s}] Invalid float "${n}" for attribute "${o}". Fallback: ${e.fallback}.`),!1):!0;if(c==="json")try{return JSON.parse(n),!0}catch(h){return f(`[${s}] Invalid JSON for attribute "${o}": ${h.message}. Fallback: ${e.fallback}.`),!1}return!0}function Fe(e,n,o){for(const i in o){const[a,s,c]=o[i];Object.defineProperty(e,i,{get:function(){return a(n,s,c)},enumerable:!0,configurable:!0})}return e}function je(e){const n={};for(const o in e){const i=e[o];if(!i||!i.prop)continue;let a=i.read;if(!a&&i.type)switch(i.type){case"enum":a=Pe(i.values,i.fallback);break;case"integer":a=Y;break;case"float":a=Be;break;case"boolean":a=de;break;case"list":a=fe;break;case"json":a=Me;break;case"string":default:a=ue;break}a||(a=ue),n[i.prop]=[a,o,i.fallback]}return n}function $e(e){const n={};for(const o in e){const i=e[o];i&&i.effect&&(n[o]=i.effect)}return Object.keys(n).length?n:null}function Ke(e){if(e.onAttrChange&&!e.declared)return null;const n=new Set;if(e.effects)for(const o in e.effects)n.add(o);if(e.onAttrChange&&e.declared)for(const o of e.declared)n.add(o);return n}function te(e,n,o,i){if(e.nodeType!==1)return;const s=n.indexOf("[")!==-1||n.indexOf(".")!==-1||n.indexOf("#")!==-1?n:"["+n+"]",c=Array.from(e.querySelectorAll(s));e.matches&&e.matches(s)&&c.push(e);for(const f of c)if(!f[o]){window.lnCore._persistSink&&f.hasAttribute("data-ln-persist")&&window.lnCore._persistSink(f,n);try{f[o]=new i(f)}catch(h){console.error("["+o+"] init failed",f,h)}}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore._bootHolds=window.lnCore._bootHolds||0,window.lnCore._bootQueue=window.lnCore._bootQueue||[]);function Ve(){return typeof window<"u"&&window.lnCore&&window.lnCore._bootHolds||0}function Ge(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 we(){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 He(e){const n=we(),o=e.observed||[];for(let i=0;i<o.length;i++){const a=o[i];n.byAttr.has(a)||n.byAttr.set(a,[]),n.byAttr.get(a).push(e)}if(n.byDeclaredAttr=n.byDeclaredAttr||new Map,e.attributes)for(const i in e.attributes){n.byDeclaredAttr.has(i)||n.byDeclaredAttr.set(i,[]);const a=n.byDeclaredAttr.get(i);a.some(s=>s.componentTag===e.componentTag)||a.push({spec:e.attributes[i],componentTag:e.componentTag})}if(e.onAttrChange||e.effects){n.reactive.push(e);const i=Ke(e);if(i===null)n.reactiveWildcard.push(e);else for(const a of i)n.byReactive.has(a)||n.byReactive.set(a,[]),n.byReactive.get(a).push(e)}e.persist&&n.persist.push(e)}function ye(e,n,o,i){for(let a=0;a<e.length;a++){const s=e[a];if(!n[s.attribute])continue;const c=s.effects&&s.effects[o];c?c(n,o,i):s.onAttrChange&&(!s.declared||s.declared.has(o))&&s.onAttrChange(n,o,i)}}function We(e){const n=e.target,o=e.attributeName;if(e.oldValue===n.getAttribute(o))return;const i=we(),a=i.byAttr.get(o);if(ie()&&i.byDeclaredAttr&&i.byDeclaredAttr.has(o)&&Z(n)){const s=i.byDeclaredAttr.get(o),c=n.getAttribute(o);for(let f=0;f<s.length;f++)he(s[f].spec,c,o,s[f].componentTag,n)}if(window.lnCore._debugSink&&(o.indexOf("data-ln-")===0||a)&&window.lnCore._debugSink("attr",o,n,{oldValue:e.oldValue,newValue:n.getAttribute(o)}),o.indexOf("data-ln-")===0){const s=i.byReactive.get(o);s&&ye(s,n,o,e.oldValue),i.reactiveWildcard.length&&ye(i.reactiveWildcard,n,o,e.oldValue)}if(a)for(let s=0;s<a.length;s++){const c=a[s];if(c.handler){c.handler(n,o,e.oldValue);continue}c.onAttributeChange&&n[c.attribute]?c.onAttributeChange(n,o):(te(n,c.selector,c.attribute,c.ComponentFn),c.onInit&&c.onInit(n))}}function Ue(){window.lnCore=window.lnCore||{},!window.lnCore._attrObserverBound&&(window.lnCore._attrObserverBound=!0,G(function(){new MutationObserver(function(n){for(let o=0;o<n.length;o++)try{We(n[o])}catch(i){console.error("[ln-core] mutation handler failed",n[o].target,i)}}).observe(document.body,{attributes:!0,subtree:!0,attributeOldValue:!0})},"ln-core"))}function pe(){return window.lnCore=window.lnCore||{},window.lnCore._lifecycleRegistry=window.lnCore._lifecycleRegistry||[]}function Qe(e){const n=pe();if(n.length){if(e.target)for(let o=0;o<n.length;o++){const i=n[o];if(i.onSubtreeChange){const a=i.query,s=e.target.nodeType===1?e.target.matches(a)?e.target:e.target.closest(a):e.target.parentElement?e.target.parentElement.closest(a):null;s&&i.onSubtreeChange(s,e)}}for(let o=0;o<e.addedNodes.length;o++){const i=e.addedNodes[o];if(i.nodeType===1)for(let a=0;a<n.length;a++){const s=n[a];te(i,s.selector,s.attribute,s.ComponentFn),s.onInit&&s.onInit(i)}}for(let o=0;o<e.removedNodes.length;o++){const i=e.removedNodes[o];if(i.nodeType===1)for(let a=0;a<n.length;a++){const s=n[a],c=s.query,f=Array.from(i.querySelectorAll(c));i.matches&&i.matches(c)&&f.push(i);for(let h=0;h<f.length;h++){const p=f[h];if(!document.contains(p)){const b=p[s.attribute];if(b&&typeof b.destroy=="function")try{b.destroy()}catch(_){console.error("["+s.attribute+"] destroy failed",p,_)}delete p[s.attribute]}}}}}}function Je(){window.lnCore=window.lnCore||{},!window.lnCore._lifecycleObserverBound&&(window.lnCore._lifecycleObserverBound=!0,G(function(){new MutationObserver(function(n){for(let o=0;o<n.length;o++){const i=n[o];if(i.type==="childList")try{Qe(i)}catch(a){console.error("[ln-core] lifecycle handler failed",i.target,a)}}}).observe(document.body,{childList:!0,subtree:!0})},"ln-core"))}function Ze(e,n,o,i,a={}){const s=a.extraAttributes||[],c=a.onAttributeChange||null,f=a.onSubtreeChange||null,h=a.onInit||null,p=a.onAttrChange||null,b=a.effects||null,_=a.attributes||null,k=_?$e(_):b,R=_?new Set(Object.keys(_)):null,P=a.persist||null;function g(E){const I=E||document.body;if(te(I,e,n,o),_&&ie())for(const B in _){const H=_[B],$=Array.from(I.querySelectorAll("["+B+"]"));I.matches&&I.matches("["+B+"]")&&$.push(I);for(let F=0;F<$.length;F++){const O=$[F];Z(O)&&he(H,O.getAttribute(B),B,i,O)}}h&&h(I)}const S=[];if(e.indexOf("[")!==-1){const E=/\[([\w-]+)/g;let I;for(;(I=E.exec(e))!==null;)S.push(I[1])}else S.push(e);He({selector:e,attribute:n,componentTag:i,attributes:_,ComponentFn:o,onInit:h,observed:S.concat(s),onAttributeChange:c,onAttrChange:p,effects:k,declared:R,persist:P}),Ue();const q=e.indexOf("[")!==-1||e.indexOf(".")!==-1||e.indexOf("#")!==-1?e:"["+e+"]";pe().push({selector:e,attribute:n,ComponentFn:o,onInit:h,onSubtreeChange:f,query:q}),Je(),window[n]=g;function A(){Ve()>0?Ge(function(){g(document.body)}):g(document.body)}return document.readyState==="loading"?document.addEventListener("DOMContentLoaded",A):A(),g}function Xe(e){let n=!1;for(let o=0;o<e.length;o++){const i=e[o];if(!(i===""||i==null)&&(n=!0,!Number.isFinite(Number(i))))return"string"}return n?"number":"string"}function Ye(e,n,o,i){if(o==="number"){const c=parseFloat(e),f=parseFloat(n);return(isNaN(c)?0:c)-(isNaN(f)?0:f)}const a=e!=null?String(e):"",s=n!=null?String(n):"";return i?i.compare(a,s):a<s?-1:a>s?1:0}function ge(e){return(e||"").replace(/^#/,"")}function ne(e){const n=e===void 0?location.hash:e,o={},i=ge(n);if(!i)return o;const a=i.split("&");for(let s=0;s<a.length;s++){const c=a[s];if(!c)continue;const f=c.indexOf(":"),h=f>-1?c.slice(0,f):c,p=f>-1?c.slice(f+1):"";if(h)try{o[h]=decodeURIComponent(p)}catch{o[h]=p}}return o}function et(e){if(!e)return null;const n=ne();return e in n?n[e]:null}function tt(e,n){if(!e)return;const o=ne();n==null?delete o[e]:o[e]=String(n);const a=Object.keys(o).map(function(s){const c=o[s];return c===""?s:s+":"+encodeURIComponent(c)}).join("&");ge(location.hash)!==a&&(location.hash=a)}function nt(e){return e.button===1||e.ctrlKey||e.metaKey||e.shiftKey?!1:(e.preventDefault(),!0)}function rt(e,n){if(!e||!e.hasAttribute("data-ln-hash"))return null;const o=e.getAttribute("data-ln-hash");if(o&&o.trim()!=="")return o.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?n?i+"-"+n:i:n||null}function ot(e,n){return!n||n==="none"||e===null||e===void 0?null:String(e)+"."+n}function it(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 at(e,n){return!e||!Array.isArray(n)||n.length===0?null:e+":"+n.map(encodeURIComponent).join(",")}function st(e){if(!e||typeof e!="string")return null;const n=e.indexOf(":");if(n===-1)return null;const o=e.slice(0,n),i=e.slice(n+1),a=i?i.split(",").map(function(s){try{return decodeURIComponent(s)}catch{return s}}).filter(Boolean):[];return{key:o,values:a}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.hashParse=ne,window.lnCore.hashGet=et,window.lnCore.hashSet=tt,window.lnCore.hashLinkClick=nt,window.lnCore.resolveHashNamespace=rt,window.lnCore.hashSortEncode=ot,window.lnCore.hashSortDecode=it,window.lnCore.hashFilterEncode=at,window.lnCore.hashFilterDecode=st);let j=null;const lt="ln-ashlar:storage-salt:v1",me=32768;function be(e){let n="";const o=e.byteLength;for(let i=0;i<o;i+=me)n+=String.fromCharCode.apply(null,e.subarray(i,Math.min(i+me,o)));return btoa(n)}function _e(e){const n=atob(e),o=n.length,i=new Uint8Array(o);for(let a=0;a<o;a++)i[a]=n.charCodeAt(a);return i}function Ce(e,n){let o=j,i={};return typeof CryptoKey<"u"&&e instanceof CryptoKey?o=e:e&&typeof e=="object"&&(i=e,typeof CryptoKey<"u"&&i.key instanceof CryptoKey&&(o=i.key)),{key:o,options:i}}async function ct(e,n={}){if(!e)throw new Error("[ln-crypto] Key derivation failed: Secret string is required");const o=n.method||"pbkdf2",i=new TextEncoder;if(o==="sha256"){const h=await crypto.subtle.digest("SHA-256",i.encode(e));return crypto.subtle.importKey("raw",h,{name:"AES-GCM"},!1,["encrypt","decrypt"])}const a=n.salt||lt,s=typeof a=="string"?i.encode(a):a,c=n.iterations||1e5,f=await crypto.subtle.importKey("raw",i.encode(e),"PBKDF2",!1,["deriveKey"]);return crypto.subtle.deriveKey({name:"PBKDF2",salt:s,iterations:c,hash:"SHA-256"},f,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}async function Se(e,n={}){if(!e){j=null;return}try{const o=n.method||"sha256";j=await ct(e,{...n,method:o})}catch(o){throw console.error("[ln-core/crypto] Key derivation failed:",o),j=null,o}}function z(){return j}async function ut(e,n,o){const{key:i}=Ce(n);if(e==null)return e;if(!i)throw new Error("[ln-crypto] Encryption failed: No active cryptographic key provided");try{const a=new TextEncoder,s=crypto.getRandomValues(new Uint8Array(12)),c=typeof e=="string"?e:JSON.stringify(e),f=await crypto.subtle.encrypt({name:"AES-GCM",iv:s},i,a.encode(c));return{v:1,alg:"AES-GCM",encrypted:!0,iv:be(s),data:be(new Uint8Array(f))}}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 dt(e,n,o){const{key:i,options:a}=Ce(n),s=a.silent===!0;if(!e||!e.encrypted)return e;if(!i){if(s)return{...e,decryptionError:!0};throw new Error("[ln-crypto] Decryption failed: No active cryptographic key provided")}if(!e.iv||!e.data){if(s)return{...e,decryptionError:!0};throw new Error("[ln-crypto] Decryption failed: Malformed envelope (missing iv or data)")}try{const c=new TextDecoder,f=_e(e.iv),h=_e(e.data),p=await crypto.subtle.decrypt({name:"AES-GCM",iv:f},i,h),b=c.decode(p);try{return JSON.parse(b)}catch{return b}}catch(c){if(s)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 ft(e){return String(e||"").trim().toLowerCase()}function ht(e){const n=ft(e);return n?n.split(/\s+/).filter(Boolean):[]}function wt(e,n){if(!n||n.length===0)return!0;if(!e)return!1;const o=String(e).toLowerCase();for(let i=0;i<n.length;i++)if(o.indexOf(n[i])===-1)return!1;return!0}function yt(e,n){if(!n||n.length===0)return!0;if(e==null)return!1;const o=String(e).trim().toLowerCase();for(let i=0;i<n.length;i++)if(String(n[i]).trim().toLowerCase()===o)return!0;return!1}function pt(e={}){let n=e.windowSize>0?e.windowSize:1e3,o=e.pageSize>0?e.pageSize:200,i=e.fetchDebounce!=null?e.fetchDebounce:120;const a=typeof e.requestPage=="function"?e.requestPage:()=>{},s=new Map,c=new Set;let f=0,h=0,p=0,b=!1,_=null;function k(g,S){s.delete(g),s.set(g,S)}function R(){if(s.size<=n)return[];const g=[];for(;s.size>n;){const L=s.keys().next().value;g.push(s.get(L)),s.delete(L)}const S=new Set(s.values());return g.filter(L=>!S.has(L))}function P(g,S){c.add(g),clearTimeout(_),_=setTimeout(()=>a(g,o,S),i)}return{get logicalTotal(){return f},set logicalTotal(g){f=g},get grandTotal(){return h},set grandTotal(g){h=g},get queryGen(){return p},set queryGen(g){p=g},get size(){return s.size},get hasLoaded(){return b},getId:g=>{if(!s.has(g))return;const S=s.get(g);return k(g,S),S},ensure:(g,S,L)=>{if(!b&&!c.has(0))return P(0,L);if(f<=0)return;const q=Math.max(0,g),A=Math.min(f,S);for(let E=q;E<A;E++)if(!s.has(E)){const I=Math.floor(E/o)*o;if(!c.has(I))return P(I,L)}},ingest:(g,S,L,q,A)=>{if(A!=null&&A!==p)return[];b=!0,L!=null&&(h=L),q!=null&&(f=q);for(let E=0;E<S.length;E++)k(g+E,S[E]);return c.delete(g),R()},reset:function(){p++,this.clear()},clear:()=>{b=!1,s.clear(),c.clear(),clearTimeout(_)},configure:(g={})=>{let S=[];return g.windowSize>0&&g.windowSize!==n&&(n=g.windowSize,S=R()),g.pageSize>0&&(o=g.pageSize),g.fetchDebounce>=0&&(i=g.fetchDebounce),S}}}function gt(e,n,o){if(!Array.isArray(e)||!n||!n.field)return e;const{field:i,direction:a}=n,s=a==="desc",c=e.map(h=>h?h[i]:void 0),f=Xe(c);return[...e].sort((h,p)=>{const b=h?h[i]:void 0,_=p?p[i]:void 0,k=Ye(b,_,f,o);return s?-k:k})}function Ae(e,n){if(!Array.isArray(e)||!n||typeof n!="object")return e;const o=Object.keys(n).filter(i=>Array.isArray(n[i])&&n[i].length>0);return o.length?e.filter(i=>i?o.every(a=>yt(i[a],n[a])):!1):e}function mt(e,n,o){if(!Array.isArray(e)||!n||!o||!o.length)return e;const i=ht(n);return i.length?e.filter(a=>a?i.every(s=>o.some(c=>{const f=a[c];return f!=null&&wt(String(f),[s])})):!1):e}function bt(e,n,o){if(!Array.isArray(e)||!e.length)return 0;if(o==="count")return e.length;const i=e.map(s=>s&&s[n]!=null?parseFloat(s[n]):NaN).filter(s=>Number.isFinite(s)),a=i.reduce((s,c)=>s+c,0);return o==="sum"?a:o==="avg"&&i.length?a/i.length:0}function _t(e,n={},o=[],i){if(!Array.isArray(e))return{records:[],total:0,filtered:0};const a=e.length;let s=e;n.filters&&(s=Ae(s,n.filters)),n.search&&(s=mt(s,n.search,o));const c=s.length;if(n.sort&&(s=gt(s,n.sort,i)),n.offset||n.limit){const f=n.offset||0,h=n.limit||s.length;s=s.slice(f,f+h)}return{records:s,total:a,filtered:c}}function Ct(e,n){return!Array.isArray(e)||!n||typeof n!="object"?e:e.map(o=>{if(!o)return null;const i={...o};for(const[a,s]of Object.entries(n))if(typeof s=="function")try{i[a]=s(o)}catch{i[a]=void 0}return i})}(function(){const e="data-ln-data-store",n="lnDataStore";if(window[n]!==void 0)return;function o(t,r,l){const u=t.getAttribute(r);if(u==="never"||u==="-1")return-1;const d=parseInt(u,10);return isNaN(d)?l:d}const i={"data-ln-data-store":{type:"marker",effect:Ie,description:"Identifies the element as a data-store definition container"},"data-ln-data-store-indexes":{type:"list",effect:Ie,description:"Comma-separated index field names for the IndexedDB store"},"data-ln-data-store-stale":{prop:"_staleThreshold",type:"integer",read:o,fallback:300,description:"Cache staleness threshold in seconds, or -1/never"},"data-ln-data-store-search-fields":{prop:"_searchFields",type:"list",read:fe,description:"Record fields to index for client-side search"},"data-ln-data-store-no-local-query":{prop:"noLocalQuery",type:"boolean",read:de,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:jt,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:$t,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=je(i),s="ln_app_cache",c="_meta",f="1.0";let h=null,p=null;const b={};function _(t){t&&t.name==="QuotaExceededError"&&v(document,"ln-data-store:quota-exceeded",{error:t})}function k(){const t={};for(const r of document.querySelectorAll(`[${e}]`)){const l=r.id;if(l){const u=r.getAttribute("data-ln-data-store-indexes")||"";t[l]={indexes:u.split(",").map(d=>d.trim()).filter(Boolean)}}}return t}function R(){return p||(p=new Promise(t=>{if(typeof indexedDB>"u")return console.warn("[ln-data-store] IndexedDB not available — falling back to in-memory store"),t(null);const r=k(),l=Object.keys(r),u=indexedDB.open(s);u.onerror=()=>{console.warn("[ln-data-store] IndexedDB open failed — falling back to in-memory store"),t(null)},u.onsuccess=d=>{const w=d.target.result,y=Array.from(w.objectStoreNames);if(!(!y.includes(c)||l.some(T=>!y.includes(T))))return P(w),h=w,t(w);const C=w.version;w.close();const x=indexedDB.open(s,C+1);x.onblocked=()=>{console.warn("[ln-data-store] Database upgrade blocked — waiting for other tabs to close connection")},x.onerror=()=>{console.warn("[ln-data-store] Database upgrade failed"),t(null)},x.onupgradeneeded=T=>{const N=T.target.result;N.objectStoreNames.contains(c)||N.createObjectStore(c,{keyPath:"key"});for(const M of l)if(!N.objectStoreNames.contains(M)){const V=N.createObjectStore(M,{keyPath:"id"});for(const oe of r[M].indexes)V.createIndex(oe,oe,{unique:!1})}},x.onsuccess=T=>{const N=T.target.result;P(N),h=N,t(N)}}}),p)}function P(t){t.onversionchange=()=>{t.close(),h=null,p=null}}function g(){return h?Promise.resolve(h):(p=null,R())}async function S(t){if(!z()||!t)return t;const r={...t},l=r.id,u=await ut(r);return!u||!u.encrypted?t:{...u,id:l}}async function L(t){return!t||!t.encrypted||!z()?t:dt(t,{silent:!0})}const q=(t,r)=>g().then(l=>l?l.transaction(t,r).objectStore(t):null);function A(t){return new Promise((r,l)=>{t.onsuccess=()=>r(t.result),t.onerror=()=>{_(t.error),l(t.error)}})}const E=t=>q(t,"readonly").then(r=>r?A(r.getAll()):[]).then(r=>z()?Promise.all(r.map(l=>L(l))):r),I=(t,r)=>q(t,"readonly").then(l=>l?A(l.get(r)).then(u=>u!==void 0?u:typeof r=="string"&&r.trim()!==""&&!isNaN(Number(r))?A(l.get(Number(r))):typeof r=="number"?A(l.get(String(r))):null):null).then(l=>l?L(l):null),B=(t,r)=>g().then(l=>{if(!l)return[];const d=l.transaction(t,"readonly").objectStore(t),w=r.map(y=>A(d.get(y)).then(m=>m!==void 0?m:typeof y=="string"&&y.trim()!==""&&!isNaN(Number(y))?A(d.get(Number(y))):typeof y=="number"?A(d.get(String(y))):null));return Promise.all(w).then(y=>z()?Promise.all(y.map(m=>m?L(m):null)):y)}),H=(t,r)=>(z()?S(r):Promise.resolve(r)).then(u=>q(t,"readwrite").then(d=>d?A(d.put(u)):null)),$=(t,r)=>q(t,"readwrite").then(l=>l?A(l.delete(r)).then(()=>{if(typeof r=="string"&&r.trim()!==""&&!isNaN(Number(r)))return A(l.delete(Number(r)));if(typeof r=="number")return A(l.delete(String(r)))}):null),F=t=>q(t,"readwrite").then(r=>r?A(r.clear()):null),O=t=>q(t,"readonly").then(r=>r?A(r.count()):0),St=t=>q(c,"readonly").then(r=>r?A(r.get(t)):null),W=(t,r)=>q(c,"readwrite").then(l=>{if(l)return r.key=t,A(l.put(r))});function D(t){return this.dom=t,this._name=t.id,this._name||console.warn("[ln-data-store] missing id — the store cannot be addressed",t),Fe(this,t,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},t.hasAttribute("data-ln-data-store-window")?this._windowIndex=pt({windowSize:this._windowSize,pageSize:this._windowPageSize,requestPage:(r,l,u)=>{v(this.dom,"ln-data-store:request-page",{store:this._name,offset:r,limit:l,query:u,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,At(this),this.ready=qt(this),this}function At(t){t._handlers={create:r=>U(t,"create",r.detail,()=>vt(t,r.detail)),update:r=>U(t,"update",r.detail,()=>xt(t,r.detail)),delete:r=>U(t,"delete",r.detail,()=>kt(t,r.detail)),"bulk-delete":r=>U(t,"bulk-delete",r.detail,()=>Et(t,r.detail)),"sync-failed":r=>{t.isSyncing=!1,v(t.dom,"ln-data-store:sync-error",{store:t._name,error:r.detail&&r.detail.error,status:r.detail&&r.detail.status})}};for(const[r,l]of Object.entries(t._handlers))t.dom.addEventListener(`ln-data-store:request-${r}`,l);t._queryHandlers={"ln-search:change":r=>{r.preventDefault();const l=r.detail&&r.detail.term!=null?r.detail.term:"";l!==t.query.search&&(t.query.search=l,re(t))},"ln-filter:change":r=>{r.preventDefault();const l=r.detail&&r.detail.key;if(!l)return;const u=(r.detail.values||[]).slice(),d=t.query.filters[l];(d?d.length===u.length&&d.every((y,m)=>y===u[m]):!u.length)||(u.length?t.query.filters[l]=u:delete t.query.filters[l],re(t))},"ln-sort:change":r=>{r.preventDefault();const l=r.detail&&r.detail.field,u=r.detail&&r.detail.direction,d=u&&u!=="none"?{field:l,direction:u}:null,w=t.query.sort;!w&&!d||w&&d&&w.field===d.field&&w.direction===d.direction||(t.query.sort=d,re(t))}};for(const[r,l]of Object.entries(t._queryHandlers))t.dom.addEventListener(r,l)}function U(t,r,l,u){const d=l&&l.requestId;return t._mutationChain=t._mutationChain.then(()=>t.ready).then(()=>{if(t.initializationError)throw t.initializationError;return u()}).catch(w=>It(t,r,d,w)),t._mutationChain}function Q(t,r=0){return O(t._name).then(l=>{if(t._windowIndex||t.windowed){const u=t.totalCount!=null?t.totalCount:l;t.totalCount=Math.max(0,u+r)}else t.totalCount=l;return t.hasCache=!0,t.isLoaded=!0,t.canServe=!0,W(t._name,{schema_version:f,last_synced_at:t.lastSyncedAt,has_cache:!0,record_count:t.totalCount})})}function vt(t,{tempId:r,data:l={},requestId:u}={}){const d={...l,id:r};return H(t._name,d).then(()=>Q(t,1)).then(()=>{v(t.dom,"ln-data-store:created",{store:t._name,record:d,tempId:r,requestId:u})})}function xt(t,{id:r,data:l={},requestId:u}={}){return I(t._name,r).then(d=>{if(!d)throw new Error(`Record not found: ${r}`);const w=d.id,y={...d,...l,id:w},m=l.id,C=m!==void 0&&m!==w;return(C?Lt(t._name,w,{...y,id:m}):H(t._name,y)).then(()=>Q(t,0)).then(()=>{v(t.dom,"ln-data-store:updated",{store:t._name,record:C?{...y,id:m}:y,previous:d,requestId:u})})})}function kt(t,{id:r,requestId:l}={}){return I(t._name,r).then(u=>{if(!u){v(t.dom,"ln-data-store:deleted",{store:t._name,id:r,requestId:l,missing:!0});return}const d=u.id;return $(t._name,d).then(()=>Q(t,-1)).then(()=>{v(t.dom,"ln-data-store:deleted",{store:t._name,id:d,requestId:l})})})}function Et(t,{ids:r=[],requestId:l}={}){return r.length?Promise.all(r.map(u=>I(t._name,u))).then(u=>{const d=u.filter(Boolean).map(w=>w.id);return J(t._name,d).then(()=>Q(t,-d.length)).then(()=>{v(t.dom,"ln-data-store:deleted",{store:t._name,ids:d,requestId:l})})}):(v(t.dom,"ln-data-store:deleted",{store:t._name,ids:[],requestId:l}),Promise.resolve())}function It(t,r,l,u){console.error("[ln-data-store] "+r+" failed:",u),v(t.dom,"ln-data-store:mutation-error",{store:t._name,action:r,requestId:l,error:u})}function qt(t){return R().then(r=>{if(!r)throw new Error("IndexedDB is unavailable");return St(t._name)}).then(r=>{if(t.initializationError=null,r&&r.schema_version===f)t.lastSyncedAt=r.last_synced_at||null,t.totalCount=r.record_count||0,t.hasCache=r.has_cache===!0||t.totalCount>0,t.hasCache&&(t.isLoaded=!0,t.canServe=!0,v(t.dom,"ln-data-store:ready",{store:t._name,count:t.totalCount,source:"cache"})),t.isInitialized=!0,v(t.dom,"ln-data-store:initialized",{store:t._name,hasCache:t.hasCache,lastSyncedAt:t.lastSyncedAt,count:t.totalCount});else{if(r&&r.schema_version!==f)return F(t._name).then(()=>W(t._name,{schema_version:f,last_synced_at:null,has_cache:!1,record_count:0})).then(()=>{t.isInitialized=!0,t.hasCache=!1,v(t.dom,"ln-data-store:initialized",{store:t._name,hasCache:!1,lastSyncedAt:null,count:0})});t.isInitialized=!0,t.hasCache=!1,v(t.dom,"ln-data-store:initialized",{store:t._name,hasCache:!1,lastSyncedAt:null,count:0})}}).catch(r=>(t.isInitialized=!0,t.isLoaded=!1,t.canServe=!1,t.hasCache=!1,t.isSyncing=!1,t.initializationError=r,v(t.dom,"ln-data-store:initialization-error",{store:t._name,error:r}),{ok:!1,error:r}))}function ve(t){t.isSyncing=!0,v(t.dom,"ln-data-store:request-remote-sync",{since:t.lastSyncedAt})}function xe(t,r){return g().then(l=>l?(z()?Promise.all(r.map(d=>S(d))):Promise.resolve(r)).then(d=>new Promise((w,y)=>{const m=l.transaction(t,"readwrite"),C=m.objectStore(t);d.forEach(x=>C.put(x)),m.oncomplete=()=>w(),m.onerror=()=>{_(m.error),y(m.error)}})):void 0)}function J(t,r){return g().then(l=>{if(l)return new Promise((u,d)=>{const w=l.transaction(t,"readwrite"),y=w.objectStore(t);r.forEach(m=>{y.delete(m),typeof m=="string"&&m.trim()!==""&&!isNaN(Number(m))?y.delete(Number(m)):typeof m=="number"&&y.delete(String(m))}),w.oncomplete=()=>u(),w.onerror=()=>d(w.error)})})}function Lt(t,r,l){return(z()?S(l):Promise.resolve(l)).then(d=>g().then(w=>{if(w)return new Promise((y,m)=>{const C=w.transaction(t,"readwrite"),x=C.objectStore(t);x.put(d),x.delete(r),C.oncomplete=()=>y(),C.onerror=()=>{_(C.error),m(C.error)}})}))}const Nt=new Intl.Collator(void 0,{numeric:!0,sensitivity:"base"});function Dt(t){return t?Object.keys(t).filter(r=>Array.isArray(t[r])&&t[r].length>0):[]}function Tt(t,r,l){return r.every(u=>l[u].map(String).includes(String(t[u])))}function zt(t){return String(t||"").toLowerCase().split(/\s+/).filter(Boolean)}function Ot(t,r,l){return r.every(u=>l.some(d=>{const w=t[d];return w!=null&&String(w).toLowerCase().includes(u)}))}function Rt(t,r,l){return bt(t,r,l)}function K(t,r){return Ct(r,t.presenters&&t.presenters.computed)}function Pt(t){return!t.sort&&!z()}function Bt(t,r,l){const u=Dt(r.filters),d=r.search?zt(r.search):[],w=t._searchFields,y=d.length>0&&w&&w.length>0;return q(t._name,"readonly").then(m=>m?new Promise((C,x)=>{const T=[],N=m.openCursor();N.onsuccess=()=>{const M=N.result;if(!M||T.length>=l){C(T);return}const V=M.value;(!u.length||Tt(V,u,r.filters))&&(!y||Ot(V,d,w))&&T.push(V),M.continue()},N.onerror=()=>x(N.error)}):[])}function ke(t,r,l){return _t(r,l,t._searchFields,Nt)}function Ee(t,r,l){const u=[];for(let w=r;w<r+l;w++){const y=t._windowIndex.getId(w);u.push(y)}const d=Array.from(new Set(u.filter(w=>w!==void 0)));return B(t._name,d).then(w=>{const y=new Map;for(let C=0;C<w.length;C++){const x=w[C];x&&y.set(String(x.id),x)}const m=[];for(let C=0;C<u.length;C++){const x=u[C];if(x===void 0)m.push(null);else{const T=y.get(String(x));m.push(T||null)}}return{data:K(t,m),total:t._windowIndex.grandTotal,filtered:t._windowIndex.logicalTotal,offset:r,queryGen:t._windowIndex.queryGen}})}D.prototype.getAll=function(t={}){const r=this;if(r._windowIndex){const l=t.offset||0,u=t.limit||200;if(r._windowIndex.ensure(l,l+u,t),!r._windowIndex.hasLoaded&&!r.noLocalQuery){const d=l+u,w=y=>y.length?{data:K(r,y),offset:l,queryGen:r._windowIndex.queryGen,provisional:!0}:Ee(r,l,u);return Pt(t)?Bt(r,t,d).then(y=>w(y.slice(l,d))):E(r._name).then(y=>w(ke(r,y,t).records))}return Ee(r,l,u)}return E(r._name).then(l=>{const u=ke(r,l,t);return{data:K(r,u.records),total:u.total,filtered:u.filtered}})},D.prototype.getById=function(t){return I(this._name,t).then(r=>r?K(this,[r])[0]:null)},D.prototype.count=function(t){return t&&Object.keys(t).length>0?E(this._name).then(l=>Ae(l,t).length):this.totalCount!=null?Promise.resolve(this.totalCount):O(this._name)},D.prototype.aggregate=function(t,r){return E(this._name).then(l=>Rt(l,t,r))},D.prototype.setPresenters=function(t){this.presenters=t},D.prototype.applySync=function(t,r,l,u){u=u||{};const d=this;if(d._windowIndex&&u.queryGen!=null&&u.queryGen!==d._windowIndex.queryGen)return Promise.resolve();t.length>0||r.length>0;let w=Promise.resolve();return t.length>0&&(w=w.then(()=>xe(d._name,t))),r.length>0&&(w=w.then(()=>J(d._name,r))),w.then(()=>{if(d._windowIndex&&(u.offset!=null||u.total!=null)){const y=u.offset!=null?u.offset:0,m=t.map(x=>x.id),C=d._windowIndex.ingest(y,m,u.total,u.filtered,u.queryGen);if(C&&C.length)return J(d._name,C)}}).then(()=>O(d._name)).then(y=>(d.totalCount=u.total!==void 0?u.total:y,d.hasCache=!0,W(d._name,{schema_version:f,last_synced_at:l,has_cache:!0,record_count:d.totalCount}))).then(()=>{const y=!d.isLoaded;d.isLoaded=!0,d.canServe=!0,d.isSyncing=!1,d.lastSyncedAt=l,y?(v(d.dom,"ln-data-store:loaded",{store:d._name,count:d.totalCount,meta:u}),v(d.dom,"ln-data-store:ready",{store:d._name,count:d.totalCount,source:"server",meta:u})):v(d.dom,"ln-data-store:synced",{store:d._name,added:t.length,deleted:r.length,changed:!0,meta:u})}).catch(y=>{d.isSyncing=!1,console.error("[ln-data-store] applySync failed:",y)})},D.prototype.applyQuery=function(t,r){r=r||{};const l=this;let u=Promise.resolve();return t.length>0&&(u=u.then(()=>xe(l._name,t))),u.then(()=>O(l._name)).then(d=>(l.totalCount=r.total!==void 0?r.total:d,t.length>0&&(l.canServe=!0),K(l,t))).catch(d=>(console.error("[ln-data-store] applyQuery failed:",d),[]))},D.prototype.forceSync=function(){this.isSyncing||ve(this)},D.prototype.fullReload=function(){const t=this;return F(t._name).then(()=>W(t._name,{schema_version:f,last_synced_at:null,has_cache:!1,record_count:0})).then(()=>{t.isLoaded=!1,t.hasCache=!1,t.lastSyncedAt=null,t.totalCount=0,ve(t)})},D.prototype.destroy=function(){if(this._windowIndex&&(this._windowIndex.clear(),this._windowIndex=null,this.windowed=!1),this._handlers){for(const[t,r]of Object.entries(this._handlers))this.dom.removeEventListener(`ln-data-store:request-${t}`,r);this._handlers=null}if(this._queryHandlers){for(const[t,r]of Object.entries(this._queryHandlers))this.dom.removeEventListener(t,r);this._queryHandlers=null}delete b[this._name],delete this.dom[n]};function Mt(){return g().then(t=>{if(!t)return;const r=Array.from(t.objectStoreNames);return new Promise((l,u)=>{const d=t.transaction(r,"readwrite");r.forEach(w=>d.objectStore(w).clear()),d.oncomplete=()=>l(),d.onerror=()=>u(d.error)})}).then(()=>{Object.values(b).forEach(t=>{t.isLoaded=!1,t.canServe=!1,t.isInitialized=!1,t.initializationError=null,t.hasCache=!1,t.isSyncing=!1,t.lastSyncedAt=null,t.totalCount=0})})}function re(t){t._windowIndex&&t._windowIndex.reset(),v(t.dom,"ln-data-store:query-changed",{store:t._name,query:{filters:Object.assign({},t.query.filters),search:t.query.search,sort:t.query.sort?Object.assign({},t.query.sort):null}})}const Ft="data-ln-data-store-frozen";function Ie(t,r){t.setAttribute(Ft,r)}function jt(t){const r=t[n];if(!r._windowIndex)return;const l=r._windowIndex.configure({windowSize:r._windowSize});l.length&&J(r._name,l).catch(u=>{console.error("[ln-data-store] window shrink eviction failed:",u)})}function $t(t){const r=t[n];r._windowIndex&&r._windowIndex.configure({pageSize:r._windowPageSize})}Ze(e,n,D,"ln-data-store",{attributes:i}),window[n].clearAll=Mt,window[n].init=window[n],window[n].setStorageKey=Se,typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.setStorageKey=Se)})()})();
1
+ (function(){"use strict";function ce(){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 ne(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 n=e.closest("[data-ln-debug]");return!(!n||typeof document<"u"&&n===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(...n){if(typeof n[0]=="string"&&(n[0].startsWith("[ln-")||n[0].startsWith("[lnCore"))){let i=null;for(let a=1;a<n.length;a++)if(n[a]&&n[a].nodeType===1){i=n[a];break}if(!ne(i))return}e.apply(console,n)}}function A(e,n,o){const i=o||{};window.lnCore._debugSink&&window.lnCore._debugSink("event",n,e,i),e.dispatchEvent(new CustomEvent(n,{bubbles:!0,detail:i}))}function Q(e,n){if(!document.body){document.addEventListener("DOMContentLoaded",function(){Q(e,n)}),console.warn("["+n+'] Script loaded before <body> — add "defer" to your <script> tag');return}e()}const ue={};function Le(e,n){ue[e]=n}function ze(e){return ue[e]||{ingress:n=>n,egress:n=>n}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.registerDataMapper=Le,window.lnCore.getDataMapper=ze);function Re(){typeof window>"u"||(window.lnCore=window.lnCore||{},!window.lnCore._localeObserverBound&&(window.lnCore._localeObserverBound=!0,Q(function(){new MutationObserver(function(){A(document,"ln-core:locale-change",{})}).observe(document.documentElement,{attributes:!0,attributeFilter:["lang"],subtree:!0})},"ln-core")))}const de={};function Oe(e,n){if(!e||typeof n!="object")return;const o=e.toLowerCase().split("-")[0];de[o]=n}function Be(e){if(!e)return null;const n=e.toLowerCase().split("-")[0];return de[n]||null}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.registerLocaleFallback=Oe,window.lnCore.getLocaleFallback=Be,window.lnCore.ensureLocaleObserver=Re);const re={};function Me(e,n){re[e]||(re[e]=document.querySelector('[data-ln-template="'+e+'"]'));const o=re[e];return o?o.content.cloneNode(!0):(console.warn("["+(n||"ln-core")+'] Template "'+e+'" not found'),null)}function fe(e,n){if(!e||!n)return e;const o=e.querySelectorAll("[data-ln-field]");for(let c=0;c<o.length;c++){const f=o[c],h=f.getAttribute("data-ln-field");n[h]!=null&&(f.textContent=n[h])}const i=e.querySelectorAll("[data-ln-attr]");for(let c=0;c<i.length;c++){const f=i[c],h=f.getAttribute("data-ln-attr").split(",");for(let g=0;g<h.length;g++){const b=h[g].trim().split(":");if(b.length!==2)continue;const _=b[0].trim(),x=b[1].trim();n[x]!=null&&f.setAttribute(_,n[x])}}const a=e.querySelectorAll("[data-ln-show]");for(let c=0;c<a.length;c++){const f=a[c],h=f.getAttribute("data-ln-show");h in n&&f.classList.toggle("hidden",!n[h])}const s=e.querySelectorAll("[data-ln-class]");for(let c=0;c<s.length;c++){const f=s[c],h=f.getAttribute("data-ln-class").split(",");for(let g=0;g<h.length;g++){const b=h[g].trim().split(":");if(b.length!==2)continue;const _=b[0].trim(),x=b[1].trim();x in n&&f.classList.toggle(_,!!n[x])}}return e}function Pe(e,n){e.matches&&e.matches("[data-ln-form], [data-ln-fillable]")&&(window.lnCore._debugSink&&window.lnCore._debugSink("event","ln-fill",e,n??null),e.dispatchEvent(new CustomEvent("ln-fill",{detail:n??null,bubbles:!0})));const o=e.querySelectorAll("[data-ln-form], [data-ln-fillable]");for(let i=0;i<o.length;i++)window.lnCore._debugSink&&window.lnCore._debugSink("event","ln-fill",o[i],n??null),o[i].dispatchEvent(new CustomEvent("ln-fill",{detail:n??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)fe(e.target,e.detail);else{const n=e.target.querySelectorAll("[data-ln-field]");for(let o=0;o<n.length;o++)n[o].textContent=""}})));function he(e,n){if(!e||!n)return e;const o=document.createTreeWalker(e,NodeFilter.SHOW_TEXT);for(;o.nextNode();){const s=o.currentNode;s.textContent.indexOf("{{")!==-1&&(s.textContent=s.textContent.replace(/\{\{\s*(\w+)\s*\}\}/g,function(c,f){return n[f]!==void 0?n[f]:""}))}const i=function(s,c){return n[c]!==void 0?n[c]:""},a=Array.from(e.querySelectorAll("*"));e.nodeType===1&&a.push(e);for(let s=0;s<a.length;s++){const c=a[s],f=c.attributes;for(let h=0;h<f.length;h++){const g=f[h];g.value.indexOf("{{")!==-1&&c.setAttribute(g.name,g.value.replace(/\{\{\s*(\w+)\s*\}\}/g,i))}}return e}function je(e,n,o,i,a,s){const c={};for(let h=0;h<e.children.length;h++){const g=e.children[h],b=g.getAttribute("data-ln-render-key");b&&(c[b]=g)}const f=document.createDocumentFragment();for(let h=0;h<n.length;h++){const g=n[h],b=String(i(g));let _=c[b];if(_)a(_,g,h);else{const x=Me(o,s);if(!x||(he(x,g),_=x.firstElementChild,!_))continue;_.setAttribute("data-ln-render-key",b),a(_,g,h)}f.appendChild(_)}e.textContent="",e.appendChild(f)}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.fillTemplate=he,window.lnCore.fill=fe,window.lnCore.lnFill=Pe,window.lnCore.renderList=je);function we(e,n,o){const i=e.getAttribute(n);return i===null?o:i}function oe(e,n,o){const i=parseInt(e.getAttribute(n),10);return isNaN(i)?o:i}function ye(e,n,o=!1){const i=e.getAttribute(n);if(i===null)return!!o;const a=i.trim().toLowerCase();return!(a==="false"||a==="0")}function ge(e,n){return(e.getAttribute(n)||"").split(",").map(o=>o.trim()).filter(Boolean)}const ie=new Map;function Fe(e,n){const o=(e?e.join("|"):"")+"::"+n;if(ie.has(o))return ie.get(o);const i=new Set(e||[]),a=function(s,c){const f=s.getAttribute(c);return f!==null&&i.has(f)?f:n};return ie.set(o,a),a}function $e(e,n,o){const i=parseFloat(e.getAttribute(n));return isNaN(i)?o:i}function Ke(e,n,o){const i=e.getAttribute(n);if(!i)return o;try{return JSON.parse(i)}catch{return o}}function pe(e,n,o,i,a){if(!e||n===null)return!0;const s=i||"ln-component",c=e.type;if(c==="trigger"||c==="marker"||c==="string"||c==="list"||!c||n===""&&e.fallback!==void 0)return!0;const f=h=>{a?console.warn(h,a):console.warn(h)};if(c==="boolean"){const h=n.trim().toLowerCase();return h!==""&&h!=="true"&&h!=="false"&&h!=="1"&&h!=="0"?(f(`[${s}] Invalid value "${n}" for boolean attribute "${o}". Allowed: "true", "false", or presence-only.`),!1):!0}if(c==="enum"){const h=e.values||[];return h.includes(n)?!0:(f(`[${s}] Invalid value "${n}" for attribute "${o}". Allowed: ${h.join(", ")}. Fallback: "${e.fallback}".`),!1)}if(c==="integer"){if(!/^-?\d+$/.test(n))return f(`[${s}] Invalid integer "${n}" for attribute "${o}". Fallback: ${e.fallback}.`),!1;const h=parseInt(n,10);return e.min!==void 0&&h<e.min?(f(`[${s}] Value ${h} for attribute "${o}" is less than min (${e.min}).`),!1):e.max!==void 0&&h>e.max?(f(`[${s}] Value ${h} for attribute "${o}" is greater than max (${e.max}).`),!1):!0}if(c==="float")return isNaN(Number(n))?(f(`[${s}] Invalid float "${n}" for attribute "${o}". Fallback: ${e.fallback}.`),!1):!0;if(c==="json")try{return JSON.parse(n),!0}catch(h){return f(`[${s}] Invalid JSON for attribute "${o}": ${h.message}. Fallback: ${e.fallback}.`),!1}return!0}function Ve(e,n,o){for(const i in o){const[a,s,c]=o[i];Object.defineProperty(e,i,{get:function(){return a(n,s,c)},enumerable:!0,configurable:!0})}return e}function Ge(e){const n={};for(const o in e){const i=e[o];if(!i||!i.prop)continue;let a=i.read;if(!a&&i.type)switch(i.type){case"enum":a=Fe(i.values,i.fallback);break;case"integer":a=oe;break;case"float":a=$e;break;case"boolean":a=ye;break;case"list":a=ge;break;case"json":a=Ke;break;case"string":default:a=we;break}a||(a=we),n[i.prop]=[a,o,i.fallback]}return n}function He(e){const n={};for(const o in e){const i=e[o];i&&i.effect&&(n[o]=i.effect)}return Object.keys(n).length?n:null}function We(e){if(e.onAttrChange&&!e.declared)return null;const n=new Set;if(e.effects)for(const o in e.effects)n.add(o);if(e.onAttrChange&&e.declared)for(const o of e.declared)n.add(o);return n}function ae(e,n,o,i){if(e.nodeType!==1)return;const s=n.indexOf("[")!==-1||n.indexOf(".")!==-1||n.indexOf("#")!==-1?n:"["+n+"]",c=Array.from(e.querySelectorAll(s));e.matches&&e.matches(s)&&c.push(e);for(const f of c)if(!f[o]){window.lnCore._persistSink&&f.hasAttribute("data-ln-persist")&&window.lnCore._persistSink(f,n);try{f[o]=new i(f)}catch(h){console.error("["+o+"] init failed",f,h)}}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore._bootHolds=window.lnCore._bootHolds||0,window.lnCore._bootQueue=window.lnCore._bootQueue||[]);function Ue(){return typeof window<"u"&&window.lnCore&&window.lnCore._bootHolds||0}function Qe(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 me(){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 Je(e){const n=me(),o=e.observed||[];for(let i=0;i<o.length;i++){const a=o[i];n.byAttr.has(a)||n.byAttr.set(a,[]),n.byAttr.get(a).push(e)}if(n.byDeclaredAttr=n.byDeclaredAttr||new Map,e.attributes)for(const i in e.attributes){n.byDeclaredAttr.has(i)||n.byDeclaredAttr.set(i,[]);const a=n.byDeclaredAttr.get(i);a.some(s=>s.componentTag===e.componentTag)||a.push({spec:e.attributes[i],componentTag:e.componentTag})}if(e.onAttrChange||e.effects){n.reactive.push(e);const i=We(e);if(i===null)n.reactiveWildcard.push(e);else for(const a of i)n.byReactive.has(a)||n.byReactive.set(a,[]),n.byReactive.get(a).push(e)}e.persist&&n.persist.push(e)}function be(e,n,o,i){for(let a=0;a<e.length;a++){const s=e[a];if(!n[s.attribute])continue;const c=s.effects&&s.effects[o];c?c(n,o,i):s.onAttrChange&&(!s.declared||s.declared.has(o))&&s.onAttrChange(n,o,i)}}function Ze(e){const n=e.target,o=e.attributeName;if(e.oldValue===n.getAttribute(o))return;const i=me(),a=i.byAttr.get(o);if(ce()&&i.byDeclaredAttr&&i.byDeclaredAttr.has(o)&&ne(n)){const s=i.byDeclaredAttr.get(o),c=n.getAttribute(o);for(let f=0;f<s.length;f++)pe(s[f].spec,c,o,s[f].componentTag,n)}if(window.lnCore._debugSink&&(o.indexOf("data-ln-")===0||a)&&window.lnCore._debugSink("attr",o,n,{oldValue:e.oldValue,newValue:n.getAttribute(o)}),o.indexOf("data-ln-")===0){const s=i.byReactive.get(o);s&&be(s,n,o,e.oldValue),i.reactiveWildcard.length&&be(i.reactiveWildcard,n,o,e.oldValue)}if(a)for(let s=0;s<a.length;s++){const c=a[s];if(c.handler){c.handler(n,o,e.oldValue);continue}c.onAttributeChange&&n[c.attribute]?c.onAttributeChange(n,o):(ae(n,c.selector,c.attribute,c.ComponentFn),c.onInit&&c.onInit(n))}}function Xe(){window.lnCore=window.lnCore||{},!window.lnCore._attrObserverBound&&(window.lnCore._attrObserverBound=!0,Q(function(){new MutationObserver(function(n){for(let o=0;o<n.length;o++)try{Ze(n[o])}catch(i){console.error("[ln-core] mutation handler failed",n[o].target,i)}}).observe(document.body,{attributes:!0,subtree:!0,attributeOldValue:!0})},"ln-core"))}function _e(){return window.lnCore=window.lnCore||{},window.lnCore._lifecycleRegistry=window.lnCore._lifecycleRegistry||[]}function Ye(e){const n=_e();if(n.length){if(e.target)for(let o=0;o<n.length;o++){const i=n[o];if(i.onSubtreeChange){const a=i.query,s=e.target.nodeType===1?e.target.matches(a)?e.target:e.target.closest(a):e.target.parentElement?e.target.parentElement.closest(a):null;s&&i.onSubtreeChange(s,e)}}for(let o=0;o<e.addedNodes.length;o++){const i=e.addedNodes[o];if(i.nodeType===1)for(let a=0;a<n.length;a++){const s=n[a];ae(i,s.selector,s.attribute,s.ComponentFn),s.onInit&&s.onInit(i)}}for(let o=0;o<e.removedNodes.length;o++){const i=e.removedNodes[o];if(i.nodeType===1)for(let a=0;a<n.length;a++){const s=n[a],c=s.query,f=Array.from(i.querySelectorAll(c));i.matches&&i.matches(c)&&f.push(i);for(let h=0;h<f.length;h++){const g=f[h];if(!document.contains(g)){const b=g[s.attribute];if(b&&typeof b.destroy=="function")try{b.destroy()}catch(_){console.error("["+s.attribute+"] destroy failed",g,_)}delete g[s.attribute]}}}}}}function et(){window.lnCore=window.lnCore||{},!window.lnCore._lifecycleObserverBound&&(window.lnCore._lifecycleObserverBound=!0,Q(function(){new MutationObserver(function(n){for(let o=0;o<n.length;o++){const i=n[o];if(i.type==="childList")try{Ye(i)}catch(a){console.error("[ln-core] lifecycle handler failed",i.target,a)}}}).observe(document.body,{childList:!0,subtree:!0})},"ln-core"))}function tt(e,n,o,i,a={}){const s=a.extraAttributes||[],c=a.onAttributeChange||null,f=a.onSubtreeChange||null,h=a.onInit||null,g=a.onAttrChange||null,b=a.effects||null,_=a.attributes||null,x=_?He(_):b,P=_?new Set(Object.keys(_)):null,j=a.persist||null;function p(k){const I=k||document.body;if(ae(I,e,n,o),_&&ce())for(const F in _){const J=_[F],H=Array.from(I.querySelectorAll("["+F+"]"));I.matches&&I.matches("["+F+"]")&&H.push(I);for(let K=0;K<H.length;K++){const M=H[K];ne(M)&&pe(J,M.getAttribute(F),F,i,M)}}h&&h(I)}const S=[];if(e.indexOf("[")!==-1){const k=/\[([\w-]+)/g;let I;for(;(I=k.exec(e))!==null;)S.push(I[1])}else S.push(e);Je({selector:e,attribute:n,componentTag:i,attributes:_,ComponentFn:o,onInit:h,observed:S.concat(s),onAttributeChange:c,onAttrChange:g,effects:x,declared:P,persist:j}),Xe();const q=e.indexOf("[")!==-1||e.indexOf(".")!==-1||e.indexOf("#")!==-1?e:"["+e+"]";_e().push({selector:e,attribute:n,ComponentFn:o,onInit:h,onSubtreeChange:f,query:q}),et(),window[n]=p;function v(){Ue()>0?Qe(function(){p(document.body)}):p(document.body)}return document.readyState==="loading"?document.addEventListener("DOMContentLoaded",v):v(),p}function nt(e){let n=!1;for(let o=0;o<e.length;o++){const i=e[o];if(!(i===""||i==null)&&(n=!0,!Number.isFinite(Number(i))))return"string"}return n?"number":"string"}function rt(e,n,o,i){if(o==="number"){const c=parseFloat(e),f=parseFloat(n);return(isNaN(c)?0:c)-(isNaN(f)?0:f)}const a=e!=null?String(e):"",s=n!=null?String(n):"";return i?i.compare(a,s):a<s?-1:a>s?1:0}function Ce(e){return(e||"").replace(/^#/,"")}function se(e){const n=e===void 0?location.hash:e,o={},i=Ce(n);if(!i)return o;const a=i.split("&");for(let s=0;s<a.length;s++){const c=a[s];if(!c)continue;const f=c.indexOf(":"),h=f>-1?c.slice(0,f):c,g=f>-1?c.slice(f+1):"";if(h)try{o[h]=decodeURIComponent(g)}catch{o[h]=g}}return o}function ot(e){if(!e)return null;const n=se();return e in n?n[e]:null}function it(e,n){if(!e)return;const o=se();n==null?delete o[e]:o[e]=String(n);const a=Object.keys(o).map(function(s){const c=o[s];return c===""?s:s+":"+encodeURIComponent(c)}).join("&");Ce(location.hash)!==a&&(location.hash=a)}function at(e){return e.button===1||e.ctrlKey||e.metaKey||e.shiftKey?!1:(e.preventDefault(),!0)}function st(e,n){if(!e||!e.hasAttribute("data-ln-hash"))return null;const o=e.getAttribute("data-ln-hash");if(o&&o.trim()!=="")return o.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?n?i+"-"+n:i:n||null}function lt(e,n){return!n||n==="none"||e===null||e===void 0?null:String(e)+"."+n}function ct(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 ut(e,n){return!e||!Array.isArray(n)||n.length===0?null:e+":"+n.map(encodeURIComponent).join(",")}function dt(e){if(!e||typeof e!="string")return null;const n=e.indexOf(":");if(n===-1)return null;const o=e.slice(0,n),i=e.slice(n+1),a=i?i.split(",").map(function(s){try{return decodeURIComponent(s)}catch{return s}}).filter(Boolean):[];return{key:o,values:a}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.hashParse=se,window.lnCore.hashGet=ot,window.lnCore.hashSet=it,window.lnCore.hashLinkClick=at,window.lnCore.resolveHashNamespace=st,window.lnCore.hashSortEncode=lt,window.lnCore.hashSortDecode=ct,window.lnCore.hashFilterEncode=ut,window.lnCore.hashFilterDecode=dt);let G=null;const ft="ln-ashlar:storage-salt:v1",Se=32768;function Ae(e){let n="";const o=e.byteLength;for(let i=0;i<o;i+=Se)n+=String.fromCharCode.apply(null,e.subarray(i,Math.min(i+Se,o)));return btoa(n)}function ve(e){const n=atob(e),o=n.length,i=new Uint8Array(o);for(let a=0;a<o;a++)i[a]=n.charCodeAt(a);return i}function xe(e,n){let o=G,i={};return typeof CryptoKey<"u"&&e instanceof CryptoKey?o=e:e&&typeof e=="object"&&(i=e,typeof CryptoKey<"u"&&i.key instanceof CryptoKey&&(o=i.key)),{key:o,options:i}}async function ht(e,n={}){if(!e)throw new Error("[ln-crypto] Key derivation failed: Secret string is required");const o=n.method||"pbkdf2",i=new TextEncoder;if(o==="sha256"){const h=await crypto.subtle.digest("SHA-256",i.encode(e));return crypto.subtle.importKey("raw",h,{name:"AES-GCM"},!1,["encrypt","decrypt"])}const a=n.salt||ft,s=typeof a=="string"?i.encode(a):a,c=n.iterations||1e5,f=await crypto.subtle.importKey("raw",i.encode(e),"PBKDF2",!1,["deriveKey"]);return crypto.subtle.deriveKey({name:"PBKDF2",salt:s,iterations:c,hash:"SHA-256"},f,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}async function ke(e,n={}){if(!e){G=null;return}try{const o=n.method||"sha256";G=await ht(e,{...n,method:o})}catch(o){throw console.error("[ln-core/crypto] Key derivation failed:",o),G=null,o}}function B(){return G}async function wt(e,n,o){const{key:i}=xe(n);if(e==null)return e;if(!i)throw new Error("[ln-crypto] Encryption failed: No active cryptographic key provided");try{const a=new TextEncoder,s=crypto.getRandomValues(new Uint8Array(12)),c=typeof e=="string"?e:JSON.stringify(e),f=await crypto.subtle.encrypt({name:"AES-GCM",iv:s},i,a.encode(c));return{v:1,alg:"AES-GCM",encrypted:!0,iv:Ae(s),data:Ae(new Uint8Array(f))}}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 yt(e,n,o){const{key:i,options:a}=xe(n),s=a.silent===!0;if(!e||!e.encrypted)return e;if(!i){if(s)return{...e,decryptionError:!0};throw new Error("[ln-crypto] Decryption failed: No active cryptographic key provided")}if(!e.iv||!e.data){if(s)return{...e,decryptionError:!0};throw new Error("[ln-crypto] Decryption failed: Malformed envelope (missing iv or data)")}try{const c=new TextDecoder,f=ve(e.iv),h=ve(e.data),g=await crypto.subtle.decrypt({name:"AES-GCM",iv:f},i,h),b=c.decode(g);try{return JSON.parse(b)}catch{return b}}catch(c){if(s)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 gt(e){return String(e||"").trim().toLowerCase()}function pt(e){const n=gt(e);return n?n.split(/\s+/).filter(Boolean):[]}function mt(e,n){if(!n||n.length===0)return!0;if(!e)return!1;const o=String(e).toLowerCase();for(let i=0;i<n.length;i++)if(o.indexOf(n[i])===-1)return!1;return!0}function bt(e,n){if(!n||n.length===0)return!0;if(e==null)return!1;const o=String(e).trim().toLowerCase();for(let i=0;i<n.length;i++)if(String(n[i]).trim().toLowerCase()===o)return!0;return!1}function _t(e={}){let n=e.windowSize>0?e.windowSize:1e3,o=e.pageSize>0?e.pageSize:200,i=e.fetchDebounce!=null?e.fetchDebounce:120;const a=typeof e.requestPage=="function"?e.requestPage:()=>{},s=new Map,c=new Set;let f=0,h=0,g=0,b=!1,_=null;function x(p,S){s.delete(p),s.set(p,S)}function P(){if(s.size<=n)return[];const p=[];for(;s.size>n;){const T=s.keys().next().value;p.push(s.get(T)),s.delete(T)}const S=new Set(s.values());return p.filter(T=>!S.has(T))}function j(p,S){c.add(p),clearTimeout(_),_=setTimeout(()=>a(p,o,S),i)}return{get logicalTotal(){return f},set logicalTotal(p){f=p},get grandTotal(){return h},set grandTotal(p){h=p},get queryGen(){return g},set queryGen(p){g=p},get size(){return s.size},get hasLoaded(){return b},getId:p=>{if(!s.has(p))return;const S=s.get(p);return x(p,S),S},ensure:(p,S,T)=>{if(!b&&!c.has(0))return j(0,T);if(f<=0)return;const q=Math.max(0,p),v=Math.min(f,S);for(let k=q;k<v;k++)if(!s.has(k)){const I=Math.floor(k/o)*o;if(!c.has(I))return j(I,T)}},ingest:(p,S,T,q,v)=>{if(v!=null&&v!==g)return[];b=!0,T!=null&&(h=T),q!=null&&(f=q);for(let k=0;k<S.length;k++)x(p+k,S[k]);return c.delete(p),P()},reset:function(){g++,this.clear()},clear:()=>{b=!1,s.clear(),c.clear(),clearTimeout(_)},configure:(p={})=>{let S=[];return p.windowSize>0&&p.windowSize!==n&&(n=p.windowSize,S=P()),p.pageSize>0&&(o=p.pageSize),p.fetchDebounce>=0&&(i=p.fetchDebounce),S}}}function Ct(e,n,o){if(!Array.isArray(e)||!n||!n.field)return e;const{field:i,direction:a}=n,s=a==="desc",c=e.map(h=>h?h[i]:void 0),f=nt(c);return[...e].sort((h,g)=>{const b=h?h[i]:void 0,_=g?g[i]:void 0,x=rt(b,_,f,o);return s?-x:x})}function Ie(e,n){if(!Array.isArray(e)||!n||typeof n!="object")return e;const o=Object.keys(n).filter(i=>Array.isArray(n[i])&&n[i].length>0);return o.length?e.filter(i=>i?o.every(a=>bt(i[a],n[a])):!1):e}function St(e,n,o){if(!Array.isArray(e)||!n||!o||!o.length)return e;const i=pt(n);return i.length?e.filter(a=>a?i.every(s=>o.some(c=>{const f=a[c];return f!=null&&mt(String(f),[s])})):!1):e}function At(e,n,o){if(!Array.isArray(e)||!e.length)return 0;if(o==="count")return e.length;const i=e.map(s=>s&&s[n]!=null?parseFloat(s[n]):NaN).filter(s=>Number.isFinite(s)),a=i.reduce((s,c)=>s+c,0);return o==="sum"?a:o==="avg"&&i.length?a/i.length:0}function vt(e,n={},o=[],i){if(!Array.isArray(e))return{records:[],total:0,filtered:0};const a=e.length;let s=e;n.filters&&(s=Ie(s,n.filters)),n.search&&(s=St(s,n.search,o));const c=s.length;if(n.sort&&(s=Ct(s,n.sort,i)),n.offset||n.limit){const f=n.offset||0,h=n.limit||s.length;s=s.slice(f,f+h)}return{records:s,total:a,filtered:c}}function xt(e,n){return!Array.isArray(e)||!n||typeof n!="object"?e:e.map(o=>{if(!o)return null;const i={...o};for(const[a,s]of Object.entries(n))if(typeof s=="function")try{i[a]=s(o)}catch{i[a]=void 0}return i})}function kt(e,n,o,i="_meta"){if(!Array.isArray(e)||!e.includes(i))return!0;for(const a of Object.keys(n||{})){if(!e.includes(a))return!0;const s=n[a]&&n[a].indexes||[],c=o&&o[a]||[];if(s.some(f=>!c.includes(f)))return!0}return!1}function It(e){return{ok:!1,error:e&&e.message?e.message:String(e)}}(function(){const e="data-ln-data-store",n="lnDataStore";if(window[n]!==void 0)return;function o(t,r,l){const u=t.getAttribute(r);if(u==="never"||u==="-1")return-1;const d=parseInt(u,10);return isNaN(d)?l:d}const i={"data-ln-data-store":{type:"marker",effect:De,description:"Identifies the element as a data-store definition container"},"data-ln-data-store-indexes":{type:"list",effect:De,description:"Comma-separated index field names for the IndexedDB store"},"data-ln-data-store-stale":{prop:"_staleThreshold",type:"integer",read:o,fallback:300,description:"Cache staleness threshold in seconds, or -1/never"},"data-ln-data-store-search-fields":{prop:"_searchFields",type:"list",read:ge,description:"Record fields to index for client-side search"},"data-ln-data-store-no-local-query":{prop:"noLocalQuery",type:"boolean",read:ye,description:"Bypasses local IndexedDB query resolution, forcing remote fetching"},"data-ln-data-store-window":{prop:"_windowSize",type:"integer",read:oe,fallback:1e3,min:10,effect:Wt,description:"Virtual scrolling cache window size in records"},"data-ln-data-store-window-page":{prop:"_windowPageSize",type:"integer",read:oe,fallback:200,min:5,effect:Ut,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=Ge(i),s="ln_app_cache",c="_meta",f="1.0";let h=null,g=null;const b={};function _(t){t&&t.name==="QuotaExceededError"&&A(document,"ln-data-store:quota-exceeded",{error:t})}function x(){const t={};for(const r of document.querySelectorAll(`[${e}]`)){const l=r.id;if(l){const u=r.getAttribute("data-ln-data-store-indexes")||"";t[l]={indexes:u.split(",").map(d=>d.trim()).filter(Boolean)}}}return t}function P(){return g||(g=new Promise(t=>{if(typeof indexedDB>"u")return console.warn("[ln-data-store] IndexedDB is not available in this environment"),t(null);const r=x(),l=Object.keys(r),u=indexedDB.open(s);u.onerror=()=>{console.warn("[ln-data-store] IndexedDB open failed"),t(null)},u.onsuccess=d=>{const w=d.target.result,y=Array.from(w.objectStoreNames),m=l.filter(D=>y.includes(D));let C={};if(m.length>0){const D=w.transaction(m,"readonly");for(const L of m)C[L]=Array.from(D.objectStore(L).indexNames)}if(!kt(y,r,C,c))return j(w),h=w,t(w);const $=w.version;w.close();const O=indexedDB.open(s,$+1);let z=!1,R=null;O.onblocked=()=>{console.warn("[ln-data-store] Database upgrade blocked — waiting for other tabs to close connection"),A(document,"ln-data-store:blocked",{db:s}),R||(R=setTimeout(()=>{z||(console.warn("[ln-data-store] Database upgrade timed out while blocked"),z=!0,g=null,t(null))},5e3))},O.onerror=()=>{z||(R&&clearTimeout(R),z=!0,g=null,console.warn("[ln-data-store] Database upgrade failed"),t(null))},O.onupgradeneeded=D=>{const L=D.target.result,Qt=D.target.transaction;L.objectStoreNames.contains(c)||L.createObjectStore(c,{keyPath:"key"});for(const U of l)if(L.objectStoreNames.contains(U)){const te=Qt.objectStore(U);for(const V of r[U].indexes)te.indexNames.contains(V)||te.createIndex(V,V,{unique:!1})}else{const te=L.createObjectStore(U,{keyPath:"id"});for(const V of r[U].indexes)te.createIndex(V,V,{unique:!1})}},O.onsuccess=D=>{if(z){D.target.result&&D.target.result.close();return}R&&clearTimeout(R),z=!0;const L=D.target.result;j(L),h=L,t(L)}}}),g)}function j(t){t.onversionchange=()=>{t.close(),h=null,g=null}}function p(){return h?Promise.resolve(h):(g=null,P())}async function S(t){if(!B()||!t)return t;const r={...t},l=r.id,u=await wt(r);return!u||!u.encrypted?t:{...u,id:l}}async function T(t){return!t||!t.encrypted||!B()?t:yt(t,{silent:!0})}const q=(t,r)=>p().then(l=>l?l.transaction(t,r).objectStore(t):null);function v(t){return new Promise((r,l)=>{t.onsuccess=()=>r(t.result),t.onerror=()=>{_(t.error),l(t.error)}})}const k=t=>q(t,"readonly").then(r=>r?v(r.getAll()):[]).then(r=>B()?Promise.all(r.map(l=>T(l))):r),I=(t,r)=>q(t,"readonly").then(l=>l?v(l.get(r)).then(u=>u!==void 0?u:typeof r=="string"&&r.trim()!==""&&!isNaN(Number(r))?v(l.get(Number(r))):typeof r=="number"?v(l.get(String(r))):null):null).then(l=>l?T(l):null),F=(t,r)=>p().then(l=>{if(!l)return[];const d=l.transaction(t,"readonly").objectStore(t),w=r.map(y=>v(d.get(y)).then(m=>m!==void 0?m:typeof y=="string"&&y.trim()!==""&&!isNaN(Number(y))?v(d.get(Number(y))):typeof y=="number"?v(d.get(String(y))):null));return Promise.all(w).then(y=>B()?Promise.all(y.map(m=>m?T(m):null)):y)}),J=(t,r)=>(B()?S(r):Promise.resolve(r)).then(u=>q(t,"readwrite").then(d=>d?v(d.put(u)):null)),H=(t,r)=>q(t,"readwrite").then(l=>l?v(l.delete(r)).then(()=>{if(typeof r=="string"&&r.trim()!==""&&!isNaN(Number(r)))return v(l.delete(Number(r)));if(typeof r=="number")return v(l.delete(String(r)))}):null),K=t=>q(t,"readwrite").then(r=>r?v(r.clear()):null),M=t=>q(t,"readonly").then(r=>r?v(r.count()):0),Et=t=>q(c,"readonly").then(r=>r?v(r.get(t)):null),Z=(t,r)=>q(c,"readwrite").then(l=>{if(l)return r.key=t,v(l.put(r))});function N(t){return this.dom=t,this._name=t.id,this._name||console.warn("[ln-data-store] missing id — the store cannot be addressed",t),Ve(this,t,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},t.hasAttribute("data-ln-data-store-window")?this._windowIndex=_t({windowSize:this._windowSize,pageSize:this._windowPageSize,requestPage:(r,l,u)=>{A(this.dom,"ln-data-store:request-page",{store:this._name,offset:r,limit:l,query:u,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,qt(this),this.ready=Rt(this),this}function qt(t){t._handlers={create:r=>X(t,"create",r.detail,()=>Tt(t,r.detail)),update:r=>X(t,"update",r.detail,()=>Nt(t,r.detail)),delete:r=>X(t,"delete",r.detail,()=>Dt(t,r.detail)),"bulk-delete":r=>X(t,"bulk-delete",r.detail,()=>Lt(t,r.detail)),"sync-failed":r=>{t.isSyncing=!1,A(t.dom,"ln-data-store:sync-error",{store:t._name,error:r.detail&&r.detail.error,status:r.detail&&r.detail.status})}};for(const[r,l]of Object.entries(t._handlers))t.dom.addEventListener(`ln-data-store:request-${r}`,l);t._queryHandlers={"ln-search:change":r=>{r.preventDefault();const l=r.detail&&r.detail.term!=null?r.detail.term:"";l!==t.query.search&&(t.query.search=l,le(t))},"ln-filter:change":r=>{r.preventDefault();const l=r.detail&&r.detail.key;if(!l)return;const u=(r.detail.values||[]).slice(),d=t.query.filters[l];(d?d.length===u.length&&d.every((y,m)=>y===u[m]):!u.length)||(u.length?t.query.filters[l]=u:delete t.query.filters[l],le(t))},"ln-sort:change":r=>{r.preventDefault();const l=r.detail&&r.detail.field,u=r.detail&&r.detail.direction,d=u&&u!=="none"?{field:l,direction:u}:null,w=t.query.sort;!w&&!d||w&&d&&w.field===d.field&&w.direction===d.direction||(t.query.sort=d,le(t))}};for(const[r,l]of Object.entries(t._queryHandlers))t.dom.addEventListener(r,l)}function X(t,r,l,u){const d=l&&l.requestId;return t._mutationChain=t._mutationChain.then(()=>t.ready).then(()=>{if(t.initializationError)throw t.initializationError;return u()}).catch(w=>zt(t,r,d,w)),t._mutationChain}function Y(t,r=0){return M(t._name).then(l=>{if(t._windowIndex||t.windowed){const u=t.totalCount!=null?t.totalCount:l;t.totalCount=Math.max(0,u+r)}else t.totalCount=l;return t.hasCache=!0,t.isLoaded=!0,t.canServe=!0,Z(t._name,{schema_version:f,last_synced_at:t.lastSyncedAt,has_cache:!0,record_count:t.totalCount})})}function Tt(t,{tempId:r,data:l={},requestId:u}={}){const d={...l,id:r};return J(t._name,d).then(()=>Y(t,1)).then(()=>{A(t.dom,"ln-data-store:created",{store:t._name,record:d,tempId:r,requestId:u})})}function Nt(t,{id:r,data:l={},requestId:u}={}){return I(t._name,r).then(d=>{if(!d)throw new Error(`Record not found: ${r}`);const w=d.id,y={...d,...l,id:w},m=l.id,C=m!==void 0&&m!==w;return(C?Ot(t._name,w,{...y,id:m}):J(t._name,y)).then(()=>Y(t,0)).then(()=>{A(t.dom,"ln-data-store:updated",{store:t._name,record:C?{...y,id:m}:y,previous:d,requestId:u})})})}function Dt(t,{id:r,requestId:l}={}){return I(t._name,r).then(u=>{if(!u){A(t.dom,"ln-data-store:deleted",{store:t._name,id:r,requestId:l,missing:!0});return}const d=u.id;return H(t._name,d).then(()=>Y(t,-1)).then(()=>{A(t.dom,"ln-data-store:deleted",{store:t._name,id:d,requestId:l})})})}function Lt(t,{ids:r=[],requestId:l}={}){return r.length?Promise.all(r.map(u=>I(t._name,u))).then(u=>{const d=u.filter(Boolean).map(w=>w.id);return ee(t._name,d).then(()=>Y(t,-d.length)).then(()=>{A(t.dom,"ln-data-store:deleted",{store:t._name,ids:d,requestId:l})})}):(A(t.dom,"ln-data-store:deleted",{store:t._name,ids:[],requestId:l}),Promise.resolve())}function zt(t,r,l,u){console.error("[ln-data-store] "+r+" failed:",u),A(t.dom,"ln-data-store:mutation-error",{store:t._name,action:r,requestId:l,error:u})}function Rt(t){return P().then(r=>{if(!r)throw new Error("IndexedDB is unavailable");return Et(t._name)}).then(r=>{if(t.initializationError=null,r&&r.schema_version===f)t.lastSyncedAt=r.last_synced_at||null,t.totalCount=r.record_count||0,t.hasCache=r.has_cache===!0||t.totalCount>0,t.hasCache&&(t.isLoaded=!0,t.canServe=!0,A(t.dom,"ln-data-store:ready",{store:t._name,count:t.totalCount,source:"cache"})),t.isInitialized=!0,A(t.dom,"ln-data-store:initialized",{store:t._name,hasCache:t.hasCache,lastSyncedAt:t.lastSyncedAt,count:t.totalCount});else{if(r&&r.schema_version!==f)return K(t._name).then(()=>Z(t._name,{schema_version:f,last_synced_at:null,has_cache:!1,record_count:0})).then(()=>{t.isInitialized=!0,t.hasCache=!1,A(t.dom,"ln-data-store:initialized",{store:t._name,hasCache:!1,lastSyncedAt:null,count:0})});t.isInitialized=!0,t.hasCache=!1,A(t.dom,"ln-data-store:initialized",{store:t._name,hasCache:!1,lastSyncedAt:null,count:0})}}).catch(r=>(t.isInitialized=!0,t.isLoaded=!1,t.canServe=!1,t.hasCache=!1,t.isSyncing=!1,t.initializationError=r,A(t.dom,"ln-data-store:initialization-error",{store:t._name,error:r}),{ok:!1,error:r}))}function Ee(t){t.isSyncing=!0,A(t.dom,"ln-data-store:request-remote-sync",{since:t.lastSyncedAt})}function qe(t,r){return p().then(l=>l?(B()?Promise.all(r.map(d=>S(d))):Promise.resolve(r)).then(d=>new Promise((w,y)=>{const m=l.transaction(t,"readwrite"),C=m.objectStore(t);d.forEach(E=>C.put(E)),m.oncomplete=()=>w(),m.onerror=()=>{_(m.error),y(m.error)}})):void 0)}function ee(t,r){return p().then(l=>{if(l)return new Promise((u,d)=>{const w=l.transaction(t,"readwrite"),y=w.objectStore(t);r.forEach(m=>{y.delete(m),typeof m=="string"&&m.trim()!==""&&!isNaN(Number(m))?y.delete(Number(m)):typeof m=="number"&&y.delete(String(m))}),w.oncomplete=()=>u(),w.onerror=()=>d(w.error)})})}function Ot(t,r,l){return(B()?S(l):Promise.resolve(l)).then(d=>p().then(w=>{if(w)return new Promise((y,m)=>{const C=w.transaction(t,"readwrite"),E=C.objectStore(t);E.put(d),E.delete(r),C.oncomplete=()=>y(),C.onerror=()=>{_(C.error),m(C.error)}})}))}const Bt=new Intl.Collator(void 0,{numeric:!0,sensitivity:"base"});function Mt(t){return t?Object.keys(t).filter(r=>Array.isArray(t[r])&&t[r].length>0):[]}function Pt(t,r,l){return r.every(u=>l[u].map(String).includes(String(t[u])))}function jt(t){return String(t||"").toLowerCase().split(/\s+/).filter(Boolean)}function Ft(t,r,l){return r.every(u=>l.some(d=>{const w=t[d];return w!=null&&String(w).toLowerCase().includes(u)}))}function $t(t,r,l){return At(t,r,l)}function W(t,r){return xt(r,t.presenters&&t.presenters.computed)}function Kt(t){return!t.sort&&!B()}function Vt(t,r,l){const u=Mt(r.filters),d=r.search?jt(r.search):[],w=t._searchFields,y=d.length>0&&w&&w.length>0;return q(t._name,"readonly").then(m=>m?new Promise((C,E)=>{const $=[],O=m.openCursor();O.onsuccess=()=>{const z=O.result;if(!z||$.length>=l){C($);return}const R=z.value;(!u.length||Pt(R,u,r.filters))&&(!y||Ft(R,d,w))&&$.push(R),z.continue()},O.onerror=()=>E(O.error)}):[])}function Te(t,r,l){return vt(r,l,t._searchFields,Bt)}function Ne(t,r,l){const u=[];for(let w=r;w<r+l;w++){const y=t._windowIndex.getId(w);u.push(y)}const d=Array.from(new Set(u.filter(w=>w!==void 0)));return F(t._name,d).then(w=>{const y=new Map;for(let C=0;C<w.length;C++){const E=w[C];E&&y.set(String(E.id),E)}const m=[];for(let C=0;C<u.length;C++){const E=u[C];if(E===void 0)m.push(null);else{const $=y.get(String(E));m.push($||null)}}return{data:W(t,m),total:t._windowIndex.grandTotal,filtered:t._windowIndex.logicalTotal,offset:r,queryGen:t._windowIndex.queryGen}})}N.prototype.getAll=function(t={}){const r=this;if(r._windowIndex){const l=t.offset||0,u=t.limit||200;if(r._windowIndex.ensure(l,l+u,t),!r._windowIndex.hasLoaded&&!r.noLocalQuery){const d=l+u,w=y=>y.length?{data:W(r,y),offset:l,queryGen:r._windowIndex.queryGen,provisional:!0}:Ne(r,l,u);return Kt(t)?Vt(r,t,d).then(y=>w(y.slice(l,d))):k(r._name).then(y=>w(Te(r,y,t).records))}return Ne(r,l,u)}return k(r._name).then(l=>{const u=Te(r,l,t);return{data:W(r,u.records),total:u.total,filtered:u.filtered}})},N.prototype.getById=function(t){return I(this._name,t).then(r=>r?W(this,[r])[0]:null)},N.prototype.count=function(t){return t&&Object.keys(t).length>0?k(this._name).then(l=>Ie(l,t).length):this.totalCount!=null?Promise.resolve(this.totalCount):M(this._name)},N.prototype.aggregate=function(t,r){return k(this._name).then(l=>$t(l,t,r))},N.prototype.setPresenters=function(t){this.presenters=t},N.prototype.applySync=function(t,r,l,u){u=u||{};const d=this;if(d._windowIndex&&u.queryGen!=null&&u.queryGen!==d._windowIndex.queryGen)return Promise.resolve({ok:!0,stale:!0});let w=p().then(y=>{if(!y)throw new Error("IndexedDB unavailable")});return t.length>0&&(w=w.then(()=>qe(d._name,t))),r.length>0&&(w=w.then(()=>ee(d._name,r))),w.then(()=>{if(d._windowIndex&&(u.offset!=null||u.total!=null)){const y=u.offset!=null?u.offset:0,m=t.map(E=>E.id),C=d._windowIndex.ingest(y,m,u.total,u.filtered,u.queryGen);if(C&&C.length)return ee(d._name,C)}}).then(()=>M(d._name)).then(y=>(d.totalCount=u.total!==void 0?u.total:y,d.hasCache=!0,Z(d._name,{schema_version:f,last_synced_at:l,has_cache:!0,record_count:d.totalCount}))).then(()=>{const y=!d.isLoaded;return d.isLoaded=!0,d.canServe=!0,d.isSyncing=!1,d.lastSyncedAt=l,y?(A(d.dom,"ln-data-store:loaded",{store:d._name,count:d.totalCount,meta:u}),A(d.dom,"ln-data-store:ready",{store:d._name,count:d.totalCount,source:"server",meta:u})):A(d.dom,"ln-data-store:synced",{store:d._name,added:t.length,deleted:r.length,changed:!0,meta:u}),{ok:!0}}).catch(y=>{d.isSyncing=!1;const m=y&&y.message?y.message:String(y);return console.error("[ln-data-store] applySync failed:",y),A(d.dom,"ln-data-store:sync-error",{store:d._name,error:m}),It(y)})},N.prototype.applyQuery=function(t,r){r=r||{};const l=this;let u=Promise.resolve();return t.length>0&&(u=u.then(()=>qe(l._name,t))),u.then(()=>M(l._name)).then(d=>(l.totalCount=r.total!==void 0?r.total:d,t.length>0&&(l.canServe=!0),W(l,t))).catch(d=>(console.error("[ln-data-store] applyQuery failed:",d),[]))},N.prototype.forceSync=function(){this.isSyncing||Ee(this)},N.prototype.fullReload=function(){const t=this;return K(t._name).then(()=>Z(t._name,{schema_version:f,last_synced_at:null,has_cache:!1,record_count:0})).then(()=>{t.isLoaded=!1,t.hasCache=!1,t.lastSyncedAt=null,t.totalCount=0,Ee(t)})},N.prototype.destroy=function(){if(this._windowIndex&&(this._windowIndex.clear(),this._windowIndex=null,this.windowed=!1),this._handlers){for(const[t,r]of Object.entries(this._handlers))this.dom.removeEventListener(`ln-data-store:request-${t}`,r);this._handlers=null}if(this._queryHandlers){for(const[t,r]of Object.entries(this._queryHandlers))this.dom.removeEventListener(t,r);this._queryHandlers=null}delete b[this._name],delete this.dom[n]};function Gt(){return p().then(t=>{if(!t)return;const r=Array.from(t.objectStoreNames);return new Promise((l,u)=>{const d=t.transaction(r,"readwrite");r.forEach(w=>d.objectStore(w).clear()),d.oncomplete=()=>l(),d.onerror=()=>u(d.error)})}).then(()=>{Object.values(b).forEach(t=>{t.isLoaded=!1,t.canServe=!1,t.isInitialized=!1,t.initializationError=null,t.hasCache=!1,t.isSyncing=!1,t.lastSyncedAt=null,t.totalCount=0})})}function le(t){t._windowIndex&&t._windowIndex.reset(),A(t.dom,"ln-data-store:query-changed",{store:t._name,query:{filters:Object.assign({},t.query.filters),search:t.query.search,sort:t.query.sort?Object.assign({},t.query.sort):null}})}const Ht="data-ln-data-store-frozen";function De(t,r){t.setAttribute(Ht,r)}function Wt(t){const r=t[n];if(!r._windowIndex)return;const l=r._windowIndex.configure({windowSize:r._windowSize});l.length&&ee(r._name,l).catch(u=>{console.error("[ln-data-store] window shrink eviction failed:",u)})}function Ut(t){const r=t[n];r._windowIndex&&r._windowIndex.configure({pageSize:r._windowPageSize})}tt(e,n,N,"ln-data-store",{attributes:i}),window[n].clearAll=Gt,window[n].init=window[n],window[n].setStorageKey=ke,typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.setStorageKey=ke)})()})();
@@ -153,3 +153,32 @@ export function decorateRecords(records, computed) {
153
153
  return copy;
154
154
  });
155
155
  }
156
+
157
+ /**
158
+ * Pure helper to compute whether an IndexedDB upgrade is needed.
159
+ * @param {string[]} existingStoreNames
160
+ * @param {Record<string, { indexes: string[] }>} requiredStores
161
+ * @param {Record<string, string[]>} existingIndexMap
162
+ * @param {string} [metaStoreName='_meta']
163
+ * @returns {boolean}
164
+ */
165
+ export function checkNeedsUpgrade(existingStoreNames, requiredStores, existingIndexMap, metaStoreName = '_meta') {
166
+ if (!Array.isArray(existingStoreNames) || !existingStoreNames.includes(metaStoreName)) return true;
167
+ for (const name of Object.keys(requiredStores || {})) {
168
+ if (!existingStoreNames.includes(name)) return true;
169
+ const requiredIdxs = (requiredStores[name] && requiredStores[name].indexes) || [];
170
+ const existingIdxs = (existingIndexMap && existingIndexMap[name]) || [];
171
+ if (requiredIdxs.some(idx => !existingIdxs.includes(idx))) return true;
172
+ }
173
+ return false;
174
+ }
175
+
176
+ /**
177
+ * Pure helper to normalize synchronization errors into a standard response shape.
178
+ * @param {any} err
179
+ * @returns {{ ok: false, error: string }}
180
+ */
181
+ export function normalizeSyncError(err) {
182
+ const errorMsg = (err && err.message) ? err.message : String(err);
183
+ return { ok: false, error: errorMsg };
184
+ }
@@ -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 } from './data-store-model.js';
3
+ import { aggregateRecords, decorateRecords, filterRecords, queryRecords, checkNeedsUpgrade, normalizeSyncError } from './data-store-model.js';
4
4
 
5
5
  (function () {
6
6
  const DOM_SELECTOR = 'data-ln-data-store';
@@ -66,7 +66,7 @@ import { aggregateRecords, decorateRecords, filterRecords, queryRecords } from '
66
66
 
67
67
  _dbReady = new Promise(resolve => {
68
68
  if (typeof indexedDB === 'undefined') {
69
- console.warn('[ln-data-store] IndexedDB not available — falling back to in-memory store');
69
+ console.warn('[ln-data-store] IndexedDB is not available in this environment');
70
70
  return resolve(null);
71
71
  }
72
72
 
@@ -75,14 +75,24 @@ import { aggregateRecords, decorateRecords, filterRecords, queryRecords } from '
75
75
  const probe = indexedDB.open(DB_NAME);
76
76
 
77
77
  probe.onerror = () => {
78
- console.warn('[ln-data-store] IndexedDB open failed — falling back to in-memory store');
78
+ console.warn('[ln-data-store] IndexedDB open failed');
79
79
  resolve(null);
80
80
  };
81
81
 
82
82
  probe.onsuccess = e => {
83
83
  const db = e.target.result;
84
84
  const existing = Array.from(db.objectStoreNames);
85
- const needsUpgrade = !existing.includes(META_STORE) || requiredNames.some(name => !existing.includes(name));
85
+ const existingRequired = requiredNames.filter(name => existing.includes(name));
86
+
87
+ let existingIndexMap = {};
88
+ if (existingRequired.length > 0) {
89
+ const tx = db.transaction(existingRequired, 'readonly');
90
+ for (const name of existingRequired) {
91
+ existingIndexMap[name] = Array.from(tx.objectStore(name).indexNames);
92
+ }
93
+ }
94
+
95
+ const needsUpgrade = checkNeedsUpgrade(existing, required, existingIndexMap, META_STORE);
86
96
 
87
97
  if (!needsUpgrade) {
88
98
  _setupVersionChangeHandler(db);
@@ -94,18 +104,35 @@ import { aggregateRecords, decorateRecords, filterRecords, queryRecords } from '
94
104
  db.close();
95
105
 
96
106
  const upgrade = indexedDB.open(DB_NAME, currentVersion + 1);
107
+ let settled = false;
108
+ let blockedTimeout = null;
97
109
 
98
110
  upgrade.onblocked = () => {
99
111
  console.warn('[ln-data-store] Database upgrade blocked — waiting for other tabs to close connection');
112
+ dispatch(document, 'ln-data-store:blocked', { db: DB_NAME });
113
+ if (!blockedTimeout) {
114
+ blockedTimeout = setTimeout(() => {
115
+ if (settled) return;
116
+ console.warn('[ln-data-store] Database upgrade timed out while blocked');
117
+ settled = true;
118
+ _dbReady = null;
119
+ resolve(null);
120
+ }, 5000);
121
+ }
100
122
  };
101
123
 
102
124
  upgrade.onerror = () => {
125
+ if (settled) return;
126
+ if (blockedTimeout) clearTimeout(blockedTimeout);
127
+ settled = true;
128
+ _dbReady = null;
103
129
  console.warn('[ln-data-store] Database upgrade failed');
104
130
  resolve(null);
105
131
  };
106
132
 
107
133
  upgrade.onupgradeneeded = e => {
108
134
  const db = e.target.result;
135
+ const tx = e.target.transaction;
109
136
  if (!db.objectStoreNames.contains(META_STORE)) {
110
137
  db.createObjectStore(META_STORE, { keyPath: 'key' });
111
138
  }
@@ -115,11 +142,24 @@ import { aggregateRecords, decorateRecords, filterRecords, queryRecords } from '
115
142
  for (const idx of required[storeName].indexes) {
116
143
  store.createIndex(idx, idx, { unique: false });
117
144
  }
145
+ } else {
146
+ const store = tx.objectStore(storeName);
147
+ for (const idx of required[storeName].indexes) {
148
+ if (!store.indexNames.contains(idx)) {
149
+ store.createIndex(idx, idx, { unique: false });
150
+ }
151
+ }
118
152
  }
119
153
  }
120
154
  };
121
155
 
122
156
  upgrade.onsuccess = e => {
157
+ if (settled) {
158
+ if (e.target.result) e.target.result.close();
159
+ return;
160
+ }
161
+ if (blockedTimeout) clearTimeout(blockedTimeout);
162
+ settled = true;
123
163
  const db = e.target.result;
124
164
  _setupVersionChangeHandler(db);
125
165
  _db = db;
@@ -791,12 +831,12 @@ import { aggregateRecords, decorateRecords, filterRecords, queryRecords } from '
791
831
  meta = meta || {};
792
832
  const self = this;
793
833
  if (self._windowIndex && meta.queryGen != null && meta.queryGen !== self._windowIndex.queryGen) {
794
- return Promise.resolve();
834
+ return Promise.resolve({ ok: true, stale: true });
795
835
  }
796
836
 
797
- const hasChanges = upsertedRecords.length > 0 || deletedIds.length > 0;
798
-
799
- let chain = Promise.resolve();
837
+ let chain = _getDb().then(db => {
838
+ if (!db) throw new Error('IndexedDB unavailable');
839
+ });
800
840
  if (upsertedRecords.length > 0) chain = chain.then(() => _putBulk(self._name, upsertedRecords));
801
841
  if (deletedIds.length > 0) chain = chain.then(() => _deleteBulk(self._name, deletedIds));
802
842
 
@@ -836,9 +876,16 @@ import { aggregateRecords, decorateRecords, filterRecords, queryRecords } from '
836
876
  meta: meta
837
877
  });
838
878
  }
879
+ return { ok: true };
839
880
  }).catch(err => {
840
881
  self.isSyncing = false;
882
+ const errorMsg = (err && err.message) ? err.message : String(err);
841
883
  console.error('[ln-data-store] applySync failed:', err);
884
+ dispatch(self.dom, 'ln-data-store:sync-error', {
885
+ store: self._name,
886
+ error: errorMsg
887
+ });
888
+ return normalizeSyncError(err);
842
889
  });
843
890
  };
844
891
 
@@ -957,14 +1004,14 @@ import { aggregateRecords, decorateRecords, filterRecords, queryRecords } from '
957
1004
 
958
1005
  // The IndexedDB schema and the store's registered name are fixed at open
959
1006
  // time: createIndex is only legal inside a versionchange transaction
960
- // (see onupgradeneeded, :85-94). A post-init edit is recorded on the host
1007
+ // (see onupgradeneeded). A post-init edit is recorded on the host
961
1008
  // for the dev stylesheet to surface; nothing is applied.
962
1009
  function _markFrozen(el, attrName) {
963
1010
  el.setAttribute(FROZEN_ATTR, attrName);
964
1011
  }
965
1012
 
966
1013
  // Shrinking the window drops positions; the records behind them stop being
967
- // held, exactly as on ingest (:757-758), so they leave IndexedDB too.
1014
+ // held, exactly as on ingest, so they leave IndexedDB too.
968
1015
  function _applyWindowSize(el) {
969
1016
  const inst = el[DOM_ATTRIBUTE];
970
1017
  if (!inst._windowIndex) return;
@@ -207,3 +207,7 @@ On blur: empty → clear + dispatch; unchanged from the current formatted displa
207
207
  ### Observers
208
208
 
209
209
  A shared `document.body` `MutationObserver` auto-initializes new `[data-ln-date]` elements (`childList`) and re-initializes on `data-ln-date` attribute addition (`attributes`). A separate observer on `document.documentElement` watches `lang` and re-formats every active instance when it changes.
210
+
211
+ ### Teardown & Lifecycle (`destroy()`)
212
+
213
+ When an element is destroyed, the component cleanly detaches the global `ln-core:locale-change` event listener regardless of whether the element is an input decorator or a static text display element (`<time>`, `<td>`, `<span>`). For inputs, wrapper children, blur/click listeners, and value interceptors are unhooked to prevent DOM leaks.