@fluffjs/fluff 0.3.9 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bundle.min.js CHANGED
@@ -1 +1 @@
1
- var V=new Map;function N(a){return function(t){let e={...a,inputs:new Map,outputs:new Map};return V.set(t,e),t}}function $(a){return V.get(a)}var C=class{static getOrCreateArray(t,e){let n=Reflect.get(t,e);if(this.isTypedArray(n))return n;let r=[];return Reflect.set(t,e,r),r}static isTypedArray(t){return Array.isArray(t)}};function H(a){return function(t,e){let n=t.constructor;C.getOrCreateArray(n,"__hostBindings").push({property:String(e),hostProperty:a})}}function W(a){return function(t,e,n){let r=t.constructor;return C.getOrCreateArray(r,"__hostListeners").push({method:String(e),event:a}),n}}function z(a){return typeof a=="function"}function I(a){return function(t){return function(e,n){let{constructor:r}=e;if(!z(r))return;let s=$(r);if(s){let i=typeof t=="string"?t:t?.alias??String(n);s[a].set(String(n),i)}}}}var D=I("inputs");function j(a){return(t,e,n)=>{}}var q=I("outputs");var B=new Map;function R(a){let t=B.get(a);if(!t)return;let e=new t;return(n,...r)=>e.transform(n,...r)}function J(a){return function(t){return t.__pipeName=a,B.set(a,t),t}}function G(a){return(t,e)=>{}}function K(a){return function(t,e){let n=t.constructor;C.getOrCreateArray(n,"__viewChildren").push({property:String(e),selector:a})}}function X(...a){return function(t,e,n){let r=n.value;return typeof r=="function"&&Reflect.set(t,`__watch_${String(e)}`,r),n}}var _;(function(a){a[a.Any=0]="Any",a[a.Inbound=1]="Inbound",a[a.Outbound=2]="Outbound"})(_||(_={}));var g=class{callbacks=new Set;emit(t){for(let e of this.callbacks)try{let n=e(t);n instanceof Promise&&n.catch(r=>{console.error(r)})}catch(n){console.error(n)}}async emitAsync(t){for(let e of this.callbacks)try{await e(t)}catch(n){console.error(n)}}subscribe(t){return this.callbacks.add(t),{unsubscribe:()=>{this.callbacks.delete(t)}}}subscribeOnce(t){let e=async n=>{this.callbacks.delete(e),await t(n)};return this.callbacks.add(e),{unsubscribe:()=>{this.callbacks.delete(e)}}}};function T(a){let t=new WeakSet;return JSON.stringify(a,(e,n)=>{if(typeof n=="object"&&n!==null){if(t.has(n))return"[Circular]";t.add(n)}return n})}var p=class a{onChange=new g;onInboundChange=new g;onOutboundChange=new g;onMetadataChange=new g;value;committed=!0;_isChanging=!1;_parentProperty;_parentSubscription;_commitTriggerSub;_pendingCommitValue;_options;constructor(t){this.isOptionsObject(t)?(this._options=t,t.initialValue!==void 0&&(this.value=t.initialValue),t.commitTrigger!==void 0&&this.setCommitTrigger(t.commitTrigger)):this.value=t}prop(){return this._parentProperty}setValue(t,e=!1,n=!0){if(t instanceof a){let s=this._options?.linkHandler;s&&s(t),this.linkToParent(t);return}if(this._isChanging){let s=this._options?.propertyName;console.error((s?s+": ":"")+"Binding loop detected: setValue called while change is in progress");return}if(!(!(t!==this.value&&T(t)!==T(this.value))&&!(n&&!this.committed))){this._isChanging=!0;try{this.value=t,this.onChange.emit(t),n||(this.committed=!1),e?(this.committed=!0,this.onInboundChange.emit(t)):n&&(this.committed=!0,this.value!==void 0&&this.onOutboundChange.emit(this.value)),!e&&this._parentProperty&&this.pushToParent(t)}finally{this._isChanging=!1}}}linkToParent(t){this.clearParentLink();let e=t;for(;e._parentProperty;)e=e._parentProperty;this._parentProperty=e;let n=this._options?.direction??_.Any;this._parentSubscription=e.subscribe(n,s=>{this.setValueInternal(s,!0)});let r=e.getValue();r!==null&&this.setValueInternal(r,!0)}setValueInternal(t,e){if(!(this._isChanging||!(t!==this.value&&T(t)!==T(this.value)))){this._isChanging=!0;try{this.value=t,this.onChange.emit(t),e&&this.onInboundChange.emit(t)}finally{this._isChanging=!1}}}pushToParent(t){if(!this._parentProperty)return;let e=this._options?.commitTrigger;if(e){if(!!!e.getValue()){this._pendingCommitValue={value:t},this._parentProperty.setValue(t,!1,!1);return}this._pendingCommitValue=void 0}let n=this._parentSubscription;this._parentSubscription=void 0,n?.unsubscribe(),this._parentProperty.setValue(t);let r=this._options?.direction??_.Any;this._parentSubscription=this._parentProperty.subscribe(r,s=>{this.setValueInternal(s,!0)})}clearParentLink(){this._parentSubscription&&(this._parentSubscription.unsubscribe(),this._parentSubscription=void 0),this._parentProperty=void 0}setCommitTrigger(t){this._commitTriggerSub&&(this._commitTriggerSub.unsubscribe(),this._commitTriggerSub=void 0),this._options??={},this._options.commitTrigger=t,this._commitTriggerSub=t.onChange.subscribe(e=>{if(!e||!this._parentProperty||!this._pendingCommitValue)return;let n=this._pendingCommitValue.value;this._pendingCommitValue=void 0,this._parentProperty.setValue(n,!1,!0)})}reset(){this.clearParentLink()}triggerChange(t=_.Any){this.value!==void 0&&(this.onChange.emit(this.value),t==_.Outbound&&this.onOutboundChange.emit(this.value),t==_.Inbound&&this.onOutboundChange.emit(this.value))}subscribe(t,e){return t==_.Inbound?this.onInboundChange.subscribe(n=>{e(n)}):t==_.Outbound?this.onOutboundChange.subscribe(n=>{e(n)}):this.onChange.subscribe(n=>{e(n)})}getValue(){return this.value===void 0?null:this.value}isOptionsObject(t){return typeof t=="object"&&t!==null&&"initialValue"in t}};var m=class a extends HTMLElement{static __e=[];static __h=[];static __bindings={};static __expressionsReady=!1;static __pendingInitCallbacks=[];static __setExpressionTable(t,e){a.__e=t,a.__h=e,a.__expressionsReady=!0;let n=a.__pendingInitCallbacks.splice(0,a.__pendingInitCallbacks.length);for(let r of n)r()}static __areExpressionsReady(){return a.__expressionsReady}static __addPendingInit(t){a.__pendingInitCallbacks.push(t)}__parentScope;__loopContext={};__baseSubscriptions=[];__getScope(){return{host:this,locals:this.__loopContext,parent:this.__parentScope}}__subscribeToExpression(t,e,n,r){this.__subscribeToExpressionInScope(t,e,n,r)}__evaluateExpr(t,e){let n=this.__getCompiledExprFn(t);try{return n(this,e)}catch{return}}__applyPipesForController(t,e,n){let r=t;r instanceof p&&(r=r.getValue());for(let s of e){let i=this.__getPipeFn(s.name);if(!i){console.warn(`Pipe "${s.name}" not found`);continue}let o=s.argExprIds.map(c=>this.__getCompiledExprFn(c)(this,n));r=i(r,...o)}return r}__processBindingsOnElement(t,e,n){let r=t.getAttribute("data-lid");if(!r)return;let s=this.__getBindingsForLid(r);if(!(!s||s.length===0))for(let i of s)this.__applyBindingWithScope(t,i,e,n)}__getBindingsForLid(t){let e=this.constructor;if(typeof e=="function"){let n=Reflect.get(e,"__bindings");if(this.__isBindingsMap(n))return n[t]}}__isBindingsMap(t){return!(!t||typeof t!="object")}__applyBindingWithScope(t,e,n,r){switch(e.b){case"property":this.__applyPropertyBindingWithScope(t,e,n,r);break;case"event":this.__applyEventBindingWithScope(t,e,n);break;case"two-way":this.__applyTwoWayBindingWithScope(t,e,n,r);break;case"class":this.__applyClassBindingWithScope(t,e,n,r);break;case"style":this.__applyStyleBindingWithScope(t,e,n,r);break;case"ref":break}}__getCompiledExprFn(t){let e=a.__e[t];if(typeof e!="function")throw new Error(`Missing compiled expression function for exprId ${t}`);return e}__getCompiledHandlerFn(t){let e=a.__h[t];if(typeof e!="function")throw new Error(`Missing compiled handler function for handlerId ${t}`);return e}__applyPipes(t,e,n){return this.__applyPipesForController(t,e.map(r=>({name:r.n,argExprIds:r.a})),n)}__getPipeFn(t){}__subscribeToExpressionInScope(t,e,n,r){if(!t)return;let s=i=>{r?r.push(i):this.__baseSubscriptions.push(i)};for(let i of t)if(Array.isArray(i))this.__subscribeToPropertyChain(i,e,n,s);else{let o=this.__getReactivePropFromScope(i,e);o?s(o.onChange.subscribe(n)):!(i in e.locals)&&!(i in e.host)&&console.warn(`Binding dependency "${i}" not found on component ${e.host.constructor.name}`)}}__subscribeToPropertyChain(t,e,n,r){if(t.length===0)return;let[s,...i]=t,o=this.__getReactivePropFromScope(s,e);if(o)if(i.length===0)r(o.onChange.subscribe(n));else{let c=[],u=()=>{for(let f of c)f.unsubscribe();c=[];let l=o.getValue();l!=null&&this.__subscribeToNestedChain(l,i,n,f=>{c.push(f),r(f)}),n()};r(o.onChange.subscribe(u));let h=o.getValue();h!=null&&this.__subscribeToNestedChain(h,i,n,l=>{c.push(l),r(l)})}else if(s in e.locals){let c=e.locals[s];c!=null&&i.length>0&&this.__subscribeToNestedChain(c,i,n,r)}else s in e.host||console.warn(`Binding dependency "${s}" not found on component ${e.host.constructor.name}`)}__subscribeToNestedChain(t,e,n,r){if(e.length===0||t===null||t===void 0)return;let[s,...i]=e,o=Reflect.get(t,s);if(o instanceof p)if(i.length===0)r(o.onChange.subscribe(n));else{let c=[],u=()=>{for(let f of c)f.unsubscribe();c=[];let l=o.getValue();l!=null&&this.__subscribeToNestedChain(l,i,n,f=>{c.push(f),r(f)}),n()};r(o.onChange.subscribe(u));let h=o.getValue();h!=null&&this.__subscribeToNestedChain(h,i,n,l=>{c.push(l),r(l)})}else i.length>0&&o!==null&&o!==void 0&&this.__subscribeToNestedChain(o,i,n,r)}__getReactivePropFromScope(t,e){if(t in e.locals)return;let n=`__${t}`;if(n in e.host){let r=Reflect.get(e.host,n);if(r instanceof p)return r}if(e.parent)return this.__getReactivePropFromScope(t,e.parent)}__setChildProperty(t,e,n){let r=Reflect.get(t,e);r instanceof p?r.setValue(n,!0):t instanceof a?Reflect.set(t,e,n):e in t&&t instanceof HTMLElement?Reflect.set(t,e,this.__unwrap(n)):t.setAttribute(e,String(this.__unwrap(n)))}__unwrap(t){return t instanceof p?t.getValue():t}__applyPropertyBindingWithScope(t,e,n,r){let s=t.tagName.toLowerCase(),i=customElements.get(s)!==void 0,o=()=>{try{if(typeof e.e!="number")throw new Error(`Binding for ${e.n} is missing exprId`);let u=this.__getCompiledExprFn(e.e)(this,n.locals);e.p&&e.p.length>0&&(u=this.__applyPipes(u,e.p,n.locals)),this.__setChildProperty(t,e.n,u)}catch(c){console.error("Property binding error:",c)}};this.__subscribeToExpressionInScope(e.d,n,o,r),e.s&&this.__subscribeToExpressionInScope([e.s],n,o,r),i?t instanceof a?o():this.__whenDefined(s,()=>{t instanceof a?o():console.warn(`Element <${s}> is not a FluffBase instance after whenDefined - binding for "${e.n}" skipped`)}):o()}__applyEventBindingWithScope(t,e,n){let r=`__fluff_event_${e.n}`;if(Reflect.has(t,r))return;if(Reflect.set(t,r,!0),typeof e.h!="number")throw new Error(`Event binding for ${e.n} is missing handlerId`);let s=this.__getCompiledHandlerFn(e.h);t.hasAttribute("x-fluff-component")?this.__applyOutputBinding(t,e.n,s,n):t.addEventListener(e.n,i=>{try{s(this,n.locals,i)}catch(o){console.error("Event binding error:",o)}})}__applyOutputBinding(t,e,n,r){let s=()=>{let i=Reflect.get(t,e);if(i instanceof g){let o=i.subscribe(c=>{try{n(this,r.locals,c)}catch(u){console.error("Output binding error:",u)}});return this.__baseSubscriptions.push(o),!0}return!1};s()||this.__whenDefined(t.tagName.toLowerCase(),()=>{s()})}__whenDefined(t,e){customElements.whenDefined(t).then(e).catch(console.error)}__applyTwoWayBindingWithScope(t,e,n,r){if(this.__applyPropertyBindingWithScope(t,e,n,r),typeof e.t!="string"||e.t.length===0)throw new Error(`Two-way binding for ${e.n} is missing targetProp`);let s=this.__getReactivePropFromScope(e.t,n),i=Reflect.get(t,e.n);if(s&&i instanceof p){let o=i.onChange.subscribe(c=>{s.setValue(c,!0)});r?r.push(o):this.__baseSubscriptions.push(o)}}__applyClassBindingWithScope(t,e,n,r){let s=()=>{try{if(typeof e.e!="number")throw new Error(`Class binding for ${e.n} is missing exprId`);let i=this.__getCompiledExprFn(e.e);this.__unwrap(i(this,n.locals))?t.classList.add(e.n):t.classList.remove(e.n)}catch(i){console.error("Class binding error:",i)}};this.__subscribeToExpressionInScope(e.d,n,s,r),s()}__applyStyleBindingWithScope(t,e,n,r){let s=()=>{try{if(typeof e.e!="number")throw new Error(`Style binding for ${e.n} is missing exprId`);let i=this.__getCompiledExprFn(e.e),o=this.__unwrap(i(this,n.locals));this.__hasStyle(t)&&t.style.setProperty(e.n,String(o))}catch(i){console.error("Style binding error:",i)}};this.__subscribeToExpressionInScope(e.d,n,s,r),s()}__hasStyle(t){return"style"in t}};var L=new Map,Q=0;function A(a){let t=`scope_${Q++}`;return L.set(t,a),t}function F(a){return L.get(a)}var v=/^fluff:(if|for|switch|text|break):(\d+)$/,d=class{id;startMarker;endMarker;subscriptions=[];host;shadowRoot;parentScope;loopContext={};markerManager;constructor(t,e,n,r,s){this.id=t,this.startMarker=e,this.endMarker=n,this.host=r,this.shadowRoot=s}setParentScope(t){this.parentScope=t}setLoopContext(t){this.loopContext=t}setMarkerManager(t){this.markerManager=t}cleanup(){for(let t of this.subscriptions)t.unsubscribe();this.subscriptions.length=0}updateRenderContext(t){}evaluateExpr(t){let e=this.getScope(),n=this.collectLocalsFromScope(e);if(e.host.__evaluateExpr)return e.host.__evaluateExpr(t,n);let r=m.__e[t];if(typeof r=="function")try{return r(e.host,n)}catch{return}}getScope(){if(this.parentScope)return this.parentScope;let t=this.__getFluffElementHost();return t?t.__getScope():{host:this.host,locals:this.loopContext,parent:void 0}}collectLocalsFromScope(t){let e={};return t.parent&&Object.assign(e,this.collectLocalsFromScope(t.parent)),Object.assign(e,t.locals),e}subscribeAndRun(t,e){let n=this.getScope(),r=t.filter(s=>Array.isArray(s)?s.length>0&&!s[0].startsWith("["):!s.startsWith("["));n.host.__subscribeToExpression&&n.host.__subscribeToExpression(r,n,e,this.subscriptions),e()}createChildScope(t){return{host:this.host,locals:t,parent:this.parentScope}}clearContentBetweenMarkersWithCleanup(t){for(let r of t)r.unsubscribe();if(t.length=0,!this.endMarker)return;let e=this.startMarker.parentNode;if(!e)return;let n=this.startMarker.nextSibling;for(;n&&n!==this.endMarker;){let r=n.nextSibling;if(n instanceof Comment){let s=v.exec(n.data);if(s&&this.markerManager?.cleanupController){let i=parseInt(s[2],10);this.markerManager.cleanupController(i,n)}}n instanceof HTMLTemplateElement||e.removeChild(n),n=r}}insertBeforeEndMarker(t){if(!this.endMarker)return;let e=this.endMarker.parentNode;e&&e.insertBefore(t,this.endMarker)}refreshParentBindings(){let t=this.startMarker.parentNode;if(!(t instanceof HTMLElement)||!t.hasAttribute("data-lid"))return;let e=this.__getFluffElementHost();if(!e)return;let n=this.getScope();e.__processBindingsOnElementPublic(t,n)}__getFluffElementHost(){return this.host instanceof y?this.host:null}setScopeOnChildren(t,e,n,r,s){if(t instanceof Comment){let i=v.exec(t.data);if(i&&r){let[,o,c]=i,u=parseInt(c,10),h=`/fluff:${o}:${u}`,l=r.getController(u,t),f=l===void 0;if(!l&&r.ensureController){let O=null,x=t.nextSibling;for(;x;){if(x instanceof Comment&&x.data===h){O=x;break}x=x.nextSibling}l=r.ensureController(u,o,t,O)}l&&(l.setParentScope(e),l.setLoopContext(e.locals),l.updateRenderContext(n),f&&l.initialize())}}else if(t instanceof y)t.__loopContext=e.locals,t.__parentScope=e,this.processBindingsOnNode(t,e,s);else if(t instanceof HTMLElement&&customElements.get(t.tagName.toLowerCase())!==void 0){let i=A(e);t.setAttribute("data-fluff-scope-id",i),this.processBindingsOnNode(t,e,s)}else t instanceof HTMLElement&&t.hasAttribute("data-lid")&&this.processBindingsOnNode(t,e,s);for(let i of Array.from(t.childNodes))this.setScopeOnChildren(i,e,n,r,s)}cloneAndInsertTemplate(t,e,n,r){let s=t.content.cloneNode(!0);if(!(s instanceof DocumentFragment))throw new Error("Expected DocumentFragment from template clone");let i=Array.from(s.childNodes),o=this.createChildScope(e);this.insertBeforeEndMarker(s);for(let c of i)this.setScopeOnChildren(c,o,n,this.markerManager,r)}processBindingsOnNode(t,e,n){let r=this.__getFluffElementHost();r&&r.__processBindingsOnElementPublic(t,e,n)}};var w=class extends d{constructor(t,e,n,r,s,i){super(t,e,n,r,s)}initialize(){}updateRenderContext(t){t&&(t.shouldBreak=!0)}};var k=class extends d{config;itemTemplate=null;emptyTemplate=null;bindingsSubscriptions=[];constructor(t,e,n,r,s,i){super(t,e,n,r,s),this.config=i}initialize(){let e=`${this.host.tagName.toLowerCase()}-${this.id}`;this.itemTemplate=this.shadowRoot.querySelector(`template[data-fluff-tpl="${e}"]`),this.emptyTemplate=this.shadowRoot.querySelector(`template[data-fluff-empty="${e}"]`);let n=this.config.deps??[],r=()=>{this.clearContentBetweenMarkersWithCleanup(this.bindingsSubscriptions);let s=this.evaluateExpr(this.config.iterableExprId);if(!Array.isArray(s)||s.length===0){this.emptyTemplate&&this.cloneAndInsertTemplate(this.emptyTemplate,this.loopContext,void 0,this.bindingsSubscriptions);return}if(!this.itemTemplate)return;let i={shouldBreak:!1};for(let o=0;o<s.length&&!i.shouldBreak;o++){let c={...this.loopContext,[this.config.iterator]:s[o],$index:o};this.cloneAndInsertTemplate(this.itemTemplate,c,i,this.bindingsSubscriptions)}this.refreshParentBindings()};this.subscribeAndRun(n,r)}};var P=class extends d{config;templates=[];currentBranchIndex=-1;bindingsSubscriptions=[];constructor(t,e,n,r,s,i){super(t,e,n,r,s),this.config=i}initialize(){let e=`${this.host.tagName.toLowerCase()}-${this.id}-`;this.templates=Array.from(this.shadowRoot.querySelectorAll(`template[data-fluff-branch^="${e}"]`));let n=[];for(let s of this.config.branches)s.deps&&n.push(...s.deps);let r=()=>{let s=-1;for(let i=0;i<this.config.branches.length;i++){let o=this.config.branches[i];if(o.exprId===void 0){s=i;break}if(this.evaluateExpr(o.exprId)){s=i;break}}s!==this.currentBranchIndex&&(this.clearContentBetweenMarkersWithCleanup(this.bindingsSubscriptions),this.currentBranchIndex=s,s>=0&&s<this.templates.length&&this.cloneAndInsertTemplate(this.templates[s],this.loopContext,void 0,this.bindingsSubscriptions),this.refreshParentBindings())};this.subscribeAndRun(n,r)}};var b=class{static isIfConfig(t){return t.type==="if"}static isForConfig(t){return t.type==="for"}static isSwitchConfig(t){return t.type==="switch"}static isTextConfig(t){return t.type==="text"}static isBreakConfig(t){return t.type==="break"}};var E=class extends d{config;templates=[];bindingsSubscriptions=[];constructor(t,e,n,r,s,i){super(t,e,n,r,s),this.config=i}initialize(){let e=`${this.host.tagName.toLowerCase()}-${this.id}-`;this.templates=Array.from(this.shadowRoot.querySelectorAll(`template[data-fluff-case^="${e}"]`));let n=this.config.deps??[],r=()=>{this.clearContentBetweenMarkersWithCleanup(this.bindingsSubscriptions);let s=this.evaluateExpr(this.config.expressionExprId),i=!1,o=!1,c={shouldBreak:!1};for(let u=0;u<this.config.cases.length&&!c.shouldBreak;u++){let h=this.config.cases[u],l=this.templates[u];if(!l)continue;let f=h.isDefault||h.valueExprId!==void 0&&this.evaluateExpr(h.valueExprId)===s;(o||!i&&f)&&(i=!0,this.cloneAndInsertTemplate(l,this.loopContext,c,this.bindingsSubscriptions),o=h.fallthrough)}this.refreshParentBindings()};this.subscribeAndRun(n,r)}};var M=class extends d{config;textNode=null;constructor(t,e,n,r,s,i){super(t,e,n,r,s),this.config=i}initialize(){this.textNode=document.createTextNode(""),this.insertBeforeEndMarker(this.textNode);let t=this.config.deps??[],e=this.config.pipes??[],n=()=>{let r=this.evaluateExpr(this.config.exprId);if(this.host.__applyPipesForController){let s=this.getScope(),i=this.collectLocalsFromScope(s);r=this.host.__applyPipesForController(r,e,i)}this.textNode&&(this.textNode.textContent=this.formatValue(r))};this.subscribeAndRun(t,n)}formatValue(t){return t==null?"":typeof t=="object"?JSON.stringify(t):typeof t=="string"?t:typeof t=="number"||typeof t=="boolean"?String(t):""}};var S=class{controllers=new Map;configs=new Map;host;shadowRoot;constructor(t,e){this.host=t,this.shadowRoot=e}initializeFromConfig(t){this.configs.clear();for(let[n,r]of t)this.configs.set(n,r);for(let[n,r]of t){let{startMarker:s,endMarker:i}=this.findMarkers(n,r.type);if(!s)continue;let o=this.createController(n,s,i,r);o&&(o.setMarkerManager(this),this.registerController(n,s,o))}let e=[];for(let n of this.controllers.values())e.push(...n.values());for(let n of e)n.initialize()}ensureController(t,e,n,r){let s=this.getController(t,n);if(s)return s;let i=this.configs.get(t);if(i?.type!==e)return;let o=this.createController(t,n,r,i);if(o)return o.setMarkerManager(this),this.registerController(t,n,o),o}getController(t,e){return this.controllers.get(t)?.get(e)}cleanupController(t,e){let n=this.controllers.get(t);if(n){if(e){let r=n.get(e);if(!r)return;r.cleanup(),n.delete(e),n.size===0&&this.controllers.delete(t);return}for(let r of n.values())r.cleanup();this.controllers.delete(t)}}cleanup(){for(let t of this.controllers.values())for(let e of t.values())e.cleanup();this.controllers.clear()}registerController(t,e,n){let r=this.controllers.get(t);r||(r=new Map,this.controllers.set(t,r)),r.set(e,n)}findMarkers(t,e){let n=`fluff:${e}:${t}`,r=`/fluff:${e}:${t}`,s=null,i=null,o=document.createTreeWalker(this.shadowRoot,NodeFilter.SHOW_COMMENT,null),c=o.nextNode();for(;c;)c instanceof Comment&&(c.data===n?s=c:c.data===r&&(i=c)),c=o.nextNode();return{startMarker:s,endMarker:i}}createController(t,e,n,r){return b.isIfConfig(r)?new P(t,e,n,this.host,this.shadowRoot,r):b.isForConfig(r)?new k(t,e,n,this.host,this.shadowRoot,r):b.isSwitchConfig(r)?new E(t,e,n,this.host,this.shadowRoot,r):b.isTextConfig(r)?new M(t,e,n,this.host,this.shadowRoot,r):b.isBreakConfig(r)?new w(t,e,n,this.host,this.shadowRoot,r):null}};var y=class extends m{__pipes={};_shadowRoot;_subscriptions=[];_initialized=!1;_pendingInit=!1;_markerManager=null;_markerConfigEntries=null;_MarkerManagerClass=null;constructor(){super(),this._shadowRoot=this.attachShadow({mode:"open"})}connectedCallback(){if(!this._initialized){if(!m.__areExpressionsReady()){this._pendingInit||(this._pendingInit=!0,m.__addPendingInit(()=>{this._pendingInit=!1,this.connectedCallback()}));return}let t=this.getAttribute("data-fluff-scope-id");t&&!this.__parentScope&&(this.__parentScope=F(t),this.__parentScope&&(this.__loopContext=this.__parentScope.locals));let e=this.getAttribute("data-fluff-loop-context");if(e&&Object.keys(this.__loopContext).length===0)try{this.__loopContext=JSON.parse(e)}catch{}this.__applyPendingProps(),this.__render(),this.__setupBindings(),this.getAttribute("data-fluff-scope-id")&&this.__processBindings(),this._initialized=!0,"onInit"in this&&typeof this.onInit=="function"&&this.onInit()}}disconnectedCallback(){"onDestroy"in this&&typeof this.onDestroy=="function"&&this.onDestroy(),this._markerManager&&(this._markerManager.cleanup(),this._markerManager=null);for(let t of this._subscriptions)t.unsubscribe();this._subscriptions=[];for(let t of this.__baseSubscriptions)t.unsubscribe();this.__baseSubscriptions=[]}$watch=(t,e)=>(e(""),{unsubscribe:()=>{}});__processBindingsOnElementPublic(t,e,n){this.__processBindingsOnElement(t,e,n)}__setupBindings(){this.__initializeMarkers(S),this.__processBindings(),this.__initializeMarkersInternal()}__pipe(t,e,...n){let r=this.__pipes[t];return r?r(e,...n):(console.warn(`Pipe "${t}" not found`),e)}__getPipeFn(t){return this.__pipes[t]??R(t)}__getShadowRoot(){return this._shadowRoot}__createProp(t,e){let n=new p(e);return Object.defineProperty(this,t,{get(){return n.getValue()},set(r){n.setValue(r)},enumerable:!0,configurable:!0}),n}__defineClassHostBinding(t,e,n){Object.defineProperty(this,t,{get:()=>!!Reflect.get(this,n),set:r=>{Reflect.set(this,n,r),r?this.classList.add(e):this.classList.remove(e)},enumerable:!0,configurable:!0})}__setMarkerConfigs(t){this._markerConfigEntries=t}__initializeMarkers(t){this._MarkerManagerClass=t}__initializeMarkersInternal(){!this._markerConfigEntries||!this._MarkerManagerClass||(this._markerManager=new this._MarkerManagerClass(this,this._shadowRoot),this._markerManager.initializeFromConfig(this._markerConfigEntries))}__setChildProperty(t,e,n){if(t instanceof HTMLElement&&t.hasAttribute("x-fluff-component")){let r=t.tagName.toLowerCase();if(customElements.get(r)===void 0){this.__whenDefined(r,()=>{this.__setChildProperty(t,e,n)});return}}super.__setChildProperty(t,e,n)}__getReactivePropFromScope(t,e){let n=`__${t}`;if(n in e.host){let r=Reflect.get(e.host,n);if(r instanceof p)return r}if(e.parent)return this.__getReactivePropFromScope(t,e.parent)}__processBindings(){let t=this._shadowRoot.querySelectorAll("[data-lid]"),e=this.__getScope();for(let n of Array.from(t)){let r=n.closest("[x-fluff-component]");r&&r!==n||this.__processBindingsOnElement(n,e)}}__applyPendingProps(){let t=Reflect.get(this,"__pendingProps");if(this.isRecord(t)){for(let[e,n]of Object.entries(t)){console.log("apply-pending-prop",{propName:e,value:n,el:this.tagName});let r=`__${e}`;if(r in this){let s=Reflect.get(this,r);s instanceof p&&s.setValue(n,!0)}else e in this&&Reflect.set(this,e,n)}Reflect.deleteProperty(this,"__pendingProps")}}isRecord(t){return t!==null&&typeof t=="object"&&!Array.isArray(t)}};export{N as Component,_ as Direction,m as FluffBase,y as FluffElement,H as HostBinding,W as HostListener,D as Input,j as LinkedProperty,S as MarkerManager,q as Output,J as Pipe,p as Property,g as Publisher,G as Reactive,K as ViewChild,X as Watch,R as getPipeTransform,B as pipeRegistry};
1
+ var V=new Map;function N(o){return function(t){let e={...o,inputs:new Map,outputs:new Map};return V.set(t,e),t}}function $(o){return V.get(o)}var y=class{static getOrCreateArray(t,e){let n=Reflect.get(t,e);if(this.isTypedArray(n))return n;let r=[];return Reflect.set(t,e,r),r}static isTypedArray(t){return Array.isArray(t)}};function H(o){return function(t,e){let n=t.constructor;y.getOrCreateArray(n,"__hostBindings").push({property:String(e),hostProperty:o})}}function W(o){return function(t,e,n){let r=t.constructor;return y.getOrCreateArray(r,"__hostListeners").push({method:String(e),event:o}),n}}function z(o){return typeof o=="function"}function I(o){return function(t){return function(e,n){let{constructor:r}=e;if(!z(r))return;let s=$(r);if(s){let i=typeof t=="string"?t:t?.alias??String(n);s[o].set(String(n),i)}}}}var D=I("inputs");function j(o){return(t,e,n)=>{}}var q=I("outputs");var B=new Map;function R(o){let t=B.get(o);if(!t)return;let e=new t;return(n,...r)=>e.transform(n,...r)}function G(o){return function(t){return t.__pipeName=o,B.set(o,t),t}}function J(o){return(t,e)=>{}}function K(o){return function(t,e){let n=t.constructor;y.getOrCreateArray(n,"__viewChildren").push({property:String(e),selector:o})}}function X(...o){return function(t,e,n){let r=n.value;return typeof r=="function"&&Reflect.set(t,`__watch_${String(e)}`,r),n}}var _;(function(o){o[o.Any=0]="Any",o[o.Inbound=1]="Inbound",o[o.Outbound=2]="Outbound"})(_||(_={}));var g=class{callbacks=new Set;emit(t){for(let e of this.callbacks)try{let n=e(t);n instanceof Promise&&n.catch(r=>{console.error(r)})}catch(n){console.error(n)}}async emitAsync(t){for(let e of this.callbacks)try{await e(t)}catch(n){console.error(n)}}subscribe(t){return this.callbacks.add(t),{unsubscribe:()=>{this.callbacks.delete(t)}}}subscribeOnce(t){let e=async n=>{this.callbacks.delete(e),await t(n)};return this.callbacks.add(e),{unsubscribe:()=>{this.callbacks.delete(e)}}}};function T(o){let t=new WeakSet;return JSON.stringify(o,(e,n)=>{if(typeof n=="object"&&n!==null){if(t.has(n))return"[Circular]";t.add(n)}return n})}var f=class o{onChange=new g;onInboundChange=new g;onOutboundChange=new g;onMetadataChange=new g;value;committed=!0;_isChanging=!1;_parentProperty;_parentSubscription;_commitTriggerSub;_pendingCommitValue;_options;constructor(t){this.isOptionsObject(t)?(this._options=t,t.initialValue!==void 0&&(this.value=t.initialValue),t.commitTrigger!==void 0&&this.setCommitTrigger(t.commitTrigger)):this.value=t}prop(){return this._parentProperty}setValue(t,e=!1,n=!0){if(t instanceof o){let s=this._options?.linkHandler;s&&s(t),this.linkToParent(t);return}if(this._isChanging){let s=this._options?.propertyName;console.error((s?s+": ":"")+"Binding loop detected: setValue called while change is in progress");return}if(!(!(t!==this.value&&T(t)!==T(this.value))&&!(n&&!this.committed))){this._isChanging=!0;try{this.value=t,this.onChange.emit(t),n||(this.committed=!1),e?(this.committed=!0,this.onInboundChange.emit(t)):n&&(this.committed=!0,this.value!==void 0&&this.onOutboundChange.emit(this.value)),!e&&this._parentProperty&&this.pushToParent(t)}finally{this._isChanging=!1}}}linkToParent(t){this.clearParentLink();let e=t;for(;e._parentProperty;)e=e._parentProperty;this._parentProperty=e;let n=this._options?.direction??_.Any;this._parentSubscription=e.subscribe(n,s=>{this.setValueInternal(s,!0)});let r=e.getValue();r!==null&&this.setValueInternal(r,!0)}setValueInternal(t,e){if(!(this._isChanging||!(t!==this.value&&T(t)!==T(this.value)))){this._isChanging=!0;try{this.value=t,this.onChange.emit(t),e&&this.onInboundChange.emit(t)}finally{this._isChanging=!1}}}pushToParent(t){if(!this._parentProperty)return;let e=this._options?.commitTrigger;if(e){if(!!!e.getValue()){this._pendingCommitValue={value:t},this._parentProperty.setValue(t,!1,!1);return}this._pendingCommitValue=void 0}let n=this._parentSubscription;this._parentSubscription=void 0,n?.unsubscribe(),this._parentProperty.setValue(t);let r=this._options?.direction??_.Any;this._parentSubscription=this._parentProperty.subscribe(r,s=>{this.setValueInternal(s,!0)})}clearParentLink(){this._parentSubscription&&(this._parentSubscription.unsubscribe(),this._parentSubscription=void 0),this._parentProperty=void 0}setCommitTrigger(t){this._commitTriggerSub&&(this._commitTriggerSub.unsubscribe(),this._commitTriggerSub=void 0),this._options??={},this._options.commitTrigger=t,this._commitTriggerSub=t.onChange.subscribe(e=>{if(!e||!this._parentProperty||!this._pendingCommitValue)return;let n=this._pendingCommitValue.value;this._pendingCommitValue=void 0,this._parentProperty.setValue(n,!1,!0)})}reset(){this.clearParentLink()}triggerChange(t=_.Any){this.value!==void 0&&(this.onChange.emit(this.value),t==_.Outbound&&this.onOutboundChange.emit(this.value),t==_.Inbound&&this.onOutboundChange.emit(this.value))}subscribe(t,e){return t==_.Inbound?this.onInboundChange.subscribe(n=>{e(n)}):t==_.Outbound?this.onOutboundChange.subscribe(n=>{e(n)}):this.onChange.subscribe(n=>{e(n)})}getValue(){return this.value===void 0?null:this.value}isOptionsObject(t){return typeof t=="object"&&t!==null&&"initialValue"in t}};var Y=["property","event","two-way","class","style","ref"],m=class o extends HTMLElement{static __e=[];static __h=[];static __s=[];static __bindings={};static __expressionsReady=!1;static __pendingInitCallbacks=[];static __setExpressionTable(t,e,n){o.__e=t,o.__h=e,n&&(o.__s=n),o.__expressionsReady=!0;let r=o.__pendingInitCallbacks.splice(0,o.__pendingInitCallbacks.length);for(let s of r)s()}static __decodeDep(t){return Array.isArray(t)?t.map(e=>o.__s[e]):o.__s[t]}static __decodeBinding(t){let[e,n,r,s,i]=t,a=o.__s[e],c=Y[n],u={n:a,b:c};return r&&(u.d=r.map(p=>o.__decodeDep(p))),c==="event"?s!==null&&(u.h=s):s!==null&&(u.e=s),i&&(i.t&&(u.t=i.t),i.s&&(u.s=i.s),i.p&&(u.p=i.p.map(([p,l])=>({n:o.__s[p],a:l})))),u}static __areExpressionsReady(){return o.__expressionsReady}static __addPendingInit(t){o.__pendingInitCallbacks.push(t)}__parentScope;__loopContext={};__baseSubscriptions=[];__getScope(){return{host:this,locals:this.__loopContext,parent:this.__parentScope}}__subscribeToExpression(t,e,n,r){this.__subscribeToExpressionInScope(t,e,n,r)}__evaluateExpr(t,e){let n=this.__getCompiledExprFn(t);try{return n(this,e)}catch{return}}__applyPipesForController(t,e,n){let r=t;r instanceof f&&(r=r.getValue());for(let s of e){let i=this.__getPipeFn(s.name);if(!i){console.warn(`Pipe "${s.name}" not found`);continue}let a=s.argExprIds.map(c=>this.__getCompiledExprFn(c)(this,n));r=i(r,...a)}return r}__processBindingsOnElement(t,e,n){let r=t.getAttribute("data-lid");if(!r)return;let s=this.__getBindingsForLid(r);if(!(!s||s.length===0))for(let i of s)this.__applyBindingWithScope(t,i,e,n)}__getBindingsForLid(t){let e=this.constructor;if(typeof e=="function"){let n=Reflect.get(e,"__bindings");if(this.__isBindingsMap(n)){let r=n[t];if(r)return r.map(s=>o.__decodeBindingAny(s))}}}static __decodeBindingAny(t){return Array.isArray(t)?o.__decodeBinding(t):t}__isBindingsMap(t){return!(!t||typeof t!="object")}__applyBindingWithScope(t,e,n,r){switch(e.b){case"property":this.__applyPropertyBindingWithScope(t,e,n,r);break;case"event":this.__applyEventBindingWithScope(t,e,n);break;case"two-way":this.__applyTwoWayBindingWithScope(t,e,n,r);break;case"class":this.__applyClassBindingWithScope(t,e,n,r);break;case"style":this.__applyStyleBindingWithScope(t,e,n,r);break;case"ref":break}}__getCompiledExprFn(t){let e=o.__e[t];if(typeof e!="function")throw new Error(`Missing compiled expression function for exprId ${t}`);return e}__getCompiledHandlerFn(t){let e=o.__h[t];if(typeof e!="function")throw new Error(`Missing compiled handler function for handlerId ${t}`);return e}__applyPipes(t,e,n){return this.__applyPipesForController(t,e.map(r=>({name:r.n,argExprIds:r.a})),n)}__getPipeFn(t){}__subscribeToExpressionInScope(t,e,n,r){if(!t)return;let s=i=>{r?r.push(i):this.__baseSubscriptions.push(i)};for(let i of t)if(Array.isArray(i))this.__subscribeToPropertyChain(i,e,n,s);else{let a=this.__getReactivePropFromScope(i,e);a?s(a.onChange.subscribe(n)):!(i in e.locals)&&!(i in e.host)&&console.warn(`Binding dependency "${i}" not found on component ${e.host.constructor.name}`)}}__subscribeToPropertyChain(t,e,n,r){if(t.length===0)return;let[s,...i]=t,a=this.__getReactivePropFromScope(s,e);if(a)if(i.length===0)r(a.onChange.subscribe(n));else{let c=[],u=()=>{for(let h of c)h.unsubscribe();c=[];let l=a.getValue();l!=null&&this.__subscribeToNestedChain(l,i,n,h=>{c.push(h),r(h)}),n()};r(a.onChange.subscribe(u));let p=a.getValue();p!=null&&this.__subscribeToNestedChain(p,i,n,l=>{c.push(l),r(l)})}else if(s in e.locals){let c=e.locals[s];c!=null&&i.length>0&&this.__subscribeToNestedChain(c,i,n,r)}else s in e.host||console.warn(`Binding dependency "${s}" not found on component ${e.host.constructor.name}`)}__subscribeToNestedChain(t,e,n,r){if(e.length===0||t===null||t===void 0)return;let[s,...i]=e,a=Reflect.get(t,s);if(a instanceof f)if(i.length===0)r(a.onChange.subscribe(n));else{let c=[],u=()=>{for(let h of c)h.unsubscribe();c=[];let l=a.getValue();l!=null&&this.__subscribeToNestedChain(l,i,n,h=>{c.push(h),r(h)}),n()};r(a.onChange.subscribe(u));let p=a.getValue();p!=null&&this.__subscribeToNestedChain(p,i,n,l=>{c.push(l),r(l)})}else i.length>0&&a!==null&&a!==void 0&&this.__subscribeToNestedChain(a,i,n,r)}__getReactivePropFromScope(t,e){if(t in e.locals)return;let n=`__${t}`;if(n in e.host){let r=Reflect.get(e.host,n);if(r instanceof f)return r}if(e.parent)return this.__getReactivePropFromScope(t,e.parent)}__setChildProperty(t,e,n){let r=Reflect.get(t,e);r instanceof f?r.setValue(n,!0):t instanceof o?Reflect.set(t,e,n):e in t&&t instanceof HTMLElement?Reflect.set(t,e,this.__unwrap(n)):t.setAttribute(e,String(this.__unwrap(n)))}__unwrap(t){return t instanceof f?t.getValue():t}__applyPropertyBindingWithScope(t,e,n,r){let s=t.tagName.toLowerCase(),i=customElements.get(s)!==void 0,a=()=>{try{if(typeof e.e!="number")throw new Error(`Binding for ${e.n} is missing exprId`);let u=this.__getCompiledExprFn(e.e)(this,n.locals);e.p&&e.p.length>0&&(u=this.__applyPipes(u,e.p,n.locals)),this.__setChildProperty(t,e.n,u)}catch(c){console.error("Property binding error:",c)}};this.__subscribeToExpressionInScope(e.d,n,a,r),e.s&&this.__subscribeToExpressionInScope([e.s],n,a,r),i?t instanceof o?a():this.__whenDefined(s,()=>{t instanceof o?a():console.warn(`Element <${s}> is not a FluffBase instance after whenDefined - binding for "${e.n}" skipped`)}):a()}__applyEventBindingWithScope(t,e,n){let r=`__fluff_event_${e.n}`;if(Reflect.has(t,r))return;if(Reflect.set(t,r,!0),typeof e.h!="number")throw new Error(`Event binding for ${e.n} is missing handlerId`);let s=this.__getCompiledHandlerFn(e.h);t.hasAttribute("x-fluff-component")?this.__applyOutputBinding(t,e.n,s,n):t.addEventListener(e.n,i=>{try{s(this,n.locals,i)}catch(a){console.error("Event binding error:",a)}})}__applyOutputBinding(t,e,n,r){let s=()=>{let i=Reflect.get(t,e);if(i instanceof g){let a=i.subscribe(c=>{try{n(this,r.locals,c)}catch(u){console.error("Output binding error:",u)}});return this.__baseSubscriptions.push(a),!0}return!1};s()||this.__whenDefined(t.tagName.toLowerCase(),()=>{s()})}__whenDefined(t,e){customElements.whenDefined(t).then(e).catch(console.error)}__applyTwoWayBindingWithScope(t,e,n,r){if(this.__applyPropertyBindingWithScope(t,e,n,r),typeof e.t!="string"||e.t.length===0)throw new Error(`Two-way binding for ${e.n} is missing targetProp`);let s=this.__getReactivePropFromScope(e.t,n),i=Reflect.get(t,e.n);if(s&&i instanceof f){let a=i.onChange.subscribe(c=>{s.setValue(c,!0)});r?r.push(a):this.__baseSubscriptions.push(a)}}__applyClassBindingWithScope(t,e,n,r){let s=()=>{try{if(typeof e.e!="number")throw new Error(`Class binding for ${e.n} is missing exprId`);let i=this.__getCompiledExprFn(e.e);this.__unwrap(i(this,n.locals))?t.classList.add(e.n):t.classList.remove(e.n)}catch(i){console.error("Class binding error:",i)}};this.__subscribeToExpressionInScope(e.d,n,s,r),s()}__applyStyleBindingWithScope(t,e,n,r){let s=()=>{try{if(typeof e.e!="number")throw new Error(`Style binding for ${e.n} is missing exprId`);let i=this.__getCompiledExprFn(e.e),a=this.__unwrap(i(this,n.locals));this.__hasStyle(t)&&t.style.setProperty(e.n,String(a))}catch(i){console.error("Style binding error:",i)}};this.__subscribeToExpressionInScope(e.d,n,s,r),s()}__hasStyle(t){return"style"in t}};var v=new Map,Q=0;function A(o){let t=`scope_${Q++}`;return v.set(t,o),t}function F(o){return v.get(o)}var L=/^fluff:(if|for|switch|text|break):(\d+)$/,d=class{id;startMarker;endMarker;subscriptions=[];host;shadowRoot;parentScope;loopContext={};markerManager;constructor(t,e,n,r,s){this.id=t,this.startMarker=e,this.endMarker=n,this.host=r,this.shadowRoot=s}setParentScope(t){this.parentScope=t}setLoopContext(t){this.loopContext=t}setMarkerManager(t){this.markerManager=t}cleanup(){for(let t of this.subscriptions)t.unsubscribe();this.subscriptions.length=0}updateRenderContext(t){}evaluateExpr(t){let e=this.getScope(),n=this.collectLocalsFromScope(e);if(e.host.__evaluateExpr)return e.host.__evaluateExpr(t,n);let r=m.__e[t];if(typeof r=="function")try{return r(e.host,n)}catch{return}}getScope(){if(this.parentScope)return this.parentScope;let t=this.__getFluffElementHost();return t?t.__getScope():{host:this.host,locals:this.loopContext,parent:void 0}}collectLocalsFromScope(t){let e={};return t.parent&&Object.assign(e,this.collectLocalsFromScope(t.parent)),Object.assign(e,t.locals),e}subscribeAndRun(t,e){let n=this.getScope(),r=t.filter(s=>Array.isArray(s)?s.length>0&&!s[0].startsWith("["):!s.startsWith("["));n.host.__subscribeToExpression&&n.host.__subscribeToExpression(r,n,e,this.subscriptions),e()}createChildScope(t){return{host:this.host,locals:t,parent:this.parentScope}}clearContentBetweenMarkersWithCleanup(t){for(let r of t)r.unsubscribe();if(t.length=0,!this.endMarker)return;let e=this.startMarker.parentNode;if(!e)return;let n=this.startMarker.nextSibling;for(;n&&n!==this.endMarker;){let r=n.nextSibling;if(n instanceof Comment){let s=L.exec(n.data);if(s&&this.markerManager?.cleanupController){let i=parseInt(s[2],10);this.markerManager.cleanupController(i,n)}}n instanceof HTMLTemplateElement||e.removeChild(n),n=r}}insertBeforeEndMarker(t){if(!this.endMarker)return;let e=this.endMarker.parentNode;e&&e.insertBefore(t,this.endMarker)}refreshParentBindings(){let t=this.startMarker.parentNode;if(!(t instanceof HTMLElement)||!t.hasAttribute("data-lid"))return;let e=this.__getFluffElementHost();if(!e)return;let n=this.getScope();e.__processBindingsOnElementPublic(t,n)}__getFluffElementHost(){return this.host instanceof C?this.host:null}setScopeOnChildren(t,e,n,r,s){if(t instanceof Comment){let i=L.exec(t.data);if(i&&r){let[,a,c]=i,u=parseInt(c,10),p=`/fluff:${a}:${u}`,l=r.getController(u,t),h=l===void 0;if(!l&&r.ensureController){let O=null,x=t.nextSibling;for(;x;){if(x instanceof Comment&&x.data===p){O=x;break}x=x.nextSibling}l=r.ensureController(u,a,t,O)}l&&(l.setParentScope(e),l.setLoopContext(e.locals),l.updateRenderContext(n),h&&l.initialize())}}else if(t instanceof C)t.__loopContext=e.locals,t.__parentScope=e,this.processBindingsOnNode(t,e,s);else if(t instanceof HTMLElement&&customElements.get(t.tagName.toLowerCase())!==void 0){let i=A(e);t.setAttribute("data-fluff-scope-id",i),this.processBindingsOnNode(t,e,s)}else t instanceof HTMLElement&&t.hasAttribute("data-lid")&&this.processBindingsOnNode(t,e,s);for(let i of Array.from(t.childNodes))this.setScopeOnChildren(i,e,n,r,s)}cloneAndInsertTemplate(t,e,n,r){let s=t.content.cloneNode(!0);if(!(s instanceof DocumentFragment))throw new Error("Expected DocumentFragment from template clone");let i=Array.from(s.childNodes),a=this.createChildScope(e);this.insertBeforeEndMarker(s);for(let c of i)this.setScopeOnChildren(c,a,n,this.markerManager,r)}processBindingsOnNode(t,e,n){let r=this.__getFluffElementHost();r&&r.__processBindingsOnElementPublic(t,e,n)}};var w=class extends d{constructor(t,e,n,r,s,i){super(t,e,n,r,s)}initialize(){}updateRenderContext(t){t&&(t.shouldBreak=!0)}};var k=class extends d{config;itemTemplate=null;emptyTemplate=null;bindingsSubscriptions=[];constructor(t,e,n,r,s,i){super(t,e,n,r,s),this.config=i}initialize(){let e=`${this.host.tagName.toLowerCase()}-${this.id}`;this.itemTemplate=this.shadowRoot.querySelector(`template[data-fluff-tpl="${e}"]`),this.emptyTemplate=this.shadowRoot.querySelector(`template[data-fluff-empty="${e}"]`);let n=this.config.deps??[],r=()=>{this.clearContentBetweenMarkersWithCleanup(this.bindingsSubscriptions);let s=this.evaluateExpr(this.config.iterableExprId);if(!Array.isArray(s)||s.length===0){this.emptyTemplate&&this.cloneAndInsertTemplate(this.emptyTemplate,this.loopContext,void 0,this.bindingsSubscriptions);return}if(!this.itemTemplate)return;let i={shouldBreak:!1};for(let a=0;a<s.length&&!i.shouldBreak;a++){let c={...this.loopContext,[this.config.iterator]:s[a],$index:a};this.cloneAndInsertTemplate(this.itemTemplate,c,i,this.bindingsSubscriptions)}this.refreshParentBindings()};this.subscribeAndRun(n,r)}};var P=class extends d{config;templates=[];currentBranchIndex=-1;bindingsSubscriptions=[];constructor(t,e,n,r,s,i){super(t,e,n,r,s),this.config=i}initialize(){let e=`${this.host.tagName.toLowerCase()}-${this.id}-`;this.templates=Array.from(this.shadowRoot.querySelectorAll(`template[data-fluff-branch^="${e}"]`));let n=[];for(let s of this.config.branches)s.deps&&n.push(...s.deps);let r=()=>{let s=-1;for(let i=0;i<this.config.branches.length;i++){let a=this.config.branches[i];if(a.exprId===void 0){s=i;break}if(this.evaluateExpr(a.exprId)){s=i;break}}s!==this.currentBranchIndex&&(this.clearContentBetweenMarkersWithCleanup(this.bindingsSubscriptions),this.currentBranchIndex=s,s>=0&&s<this.templates.length&&this.cloneAndInsertTemplate(this.templates[s],this.loopContext,void 0,this.bindingsSubscriptions),this.refreshParentBindings())};this.subscribeAndRun(n,r)}};var b=class{static isIfConfig(t){return t.type==="if"}static isForConfig(t){return t.type==="for"}static isSwitchConfig(t){return t.type==="switch"}static isTextConfig(t){return t.type==="text"}static isBreakConfig(t){return t.type==="break"}};var E=class extends d{config;templates=[];bindingsSubscriptions=[];constructor(t,e,n,r,s,i){super(t,e,n,r,s),this.config=i}initialize(){let e=`${this.host.tagName.toLowerCase()}-${this.id}-`;this.templates=Array.from(this.shadowRoot.querySelectorAll(`template[data-fluff-case^="${e}"]`));let n=this.config.deps??[],r=()=>{this.clearContentBetweenMarkersWithCleanup(this.bindingsSubscriptions);let s=this.evaluateExpr(this.config.expressionExprId),i=!1,a=!1,c={shouldBreak:!1};for(let u=0;u<this.config.cases.length&&!c.shouldBreak;u++){let p=this.config.cases[u],l=this.templates[u];if(!l)continue;let h=p.isDefault||p.valueExprId!==void 0&&this.evaluateExpr(p.valueExprId)===s;(a||!i&&h)&&(i=!0,this.cloneAndInsertTemplate(l,this.loopContext,c,this.bindingsSubscriptions),a=p.fallthrough)}this.refreshParentBindings()};this.subscribeAndRun(n,r)}};var M=class extends d{config;textNode=null;constructor(t,e,n,r,s,i){super(t,e,n,r,s),this.config=i}initialize(){this.textNode=document.createTextNode(""),this.insertBeforeEndMarker(this.textNode);let t=this.config.deps??[],e=this.config.pipes??[],n=()=>{let r=this.evaluateExpr(this.config.exprId);if(this.host.__applyPipesForController){let s=this.getScope(),i=this.collectLocalsFromScope(s);r=this.host.__applyPipesForController(r,e,i)}this.textNode&&(this.textNode.textContent=this.formatValue(r))};this.subscribeAndRun(t,n)}formatValue(t){return t==null?"":typeof t=="object"?JSON.stringify(t):typeof t=="string"?t:typeof t=="number"||typeof t=="boolean"?String(t):""}};var S=class{controllers=new Map;configs=new Map;host;shadowRoot;constructor(t,e){this.host=t,this.shadowRoot=e}initializeFromConfig(t){this.configs.clear();for(let[n,r]of t)this.configs.set(n,r);for(let[n,r]of t){let{startMarker:s,endMarker:i}=this.findMarkers(n,r.type);if(!s)continue;let a=this.createController(n,s,i,r);a&&(a.setMarkerManager(this),this.registerController(n,s,a))}let e=[];for(let n of this.controllers.values())e.push(...n.values());for(let n of e)n.initialize()}ensureController(t,e,n,r){let s=this.getController(t,n);if(s)return s;let i=this.configs.get(t);if(i?.type!==e)return;let a=this.createController(t,n,r,i);if(a)return a.setMarkerManager(this),this.registerController(t,n,a),a}getController(t,e){return this.controllers.get(t)?.get(e)}cleanupController(t,e){let n=this.controllers.get(t);if(n){if(e){let r=n.get(e);if(!r)return;r.cleanup(),n.delete(e),n.size===0&&this.controllers.delete(t);return}for(let r of n.values())r.cleanup();this.controllers.delete(t)}}cleanup(){for(let t of this.controllers.values())for(let e of t.values())e.cleanup();this.controllers.clear()}registerController(t,e,n){let r=this.controllers.get(t);r||(r=new Map,this.controllers.set(t,r)),r.set(e,n)}findMarkers(t,e){let n=`fluff:${e}:${t}`,r=`/fluff:${e}:${t}`,s=null,i=null,a=document.createTreeWalker(this.shadowRoot,NodeFilter.SHOW_COMMENT,null),c=a.nextNode();for(;c;)c instanceof Comment&&(c.data===n?s=c:c.data===r&&(i=c)),c=a.nextNode();return{startMarker:s,endMarker:i}}createController(t,e,n,r){return b.isIfConfig(r)?new P(t,e,n,this.host,this.shadowRoot,r):b.isForConfig(r)?new k(t,e,n,this.host,this.shadowRoot,r):b.isSwitchConfig(r)?new E(t,e,n,this.host,this.shadowRoot,r):b.isTextConfig(r)?new M(t,e,n,this.host,this.shadowRoot,r):b.isBreakConfig(r)?new w(t,e,n,this.host,this.shadowRoot,r):null}};var C=class extends m{__pipes={};_shadowRoot;_subscriptions=[];_initialized=!1;_pendingInit=!1;_markerManager=null;_markerConfigEntries=null;_MarkerManagerClass=null;constructor(){super(),this._shadowRoot=this.attachShadow({mode:"open"})}connectedCallback(){if(!this._initialized){if(!m.__areExpressionsReady()){this._pendingInit||(this._pendingInit=!0,m.__addPendingInit(()=>{this._pendingInit=!1,this.connectedCallback()}));return}let t=this.getAttribute("data-fluff-scope-id");t&&!this.__parentScope&&(this.__parentScope=F(t),this.__parentScope&&(this.__loopContext=this.__parentScope.locals));let e=this.getAttribute("data-fluff-loop-context");if(e&&Object.keys(this.__loopContext).length===0)try{this.__loopContext=JSON.parse(e)}catch{}this.__applyPendingProps(),this.__render(),this.__setupBindings(),this.getAttribute("data-fluff-scope-id")&&this.__processBindings(),this._initialized=!0,"onInit"in this&&typeof this.onInit=="function"&&this.onInit()}}disconnectedCallback(){"onDestroy"in this&&typeof this.onDestroy=="function"&&this.onDestroy(),this._markerManager&&(this._markerManager.cleanup(),this._markerManager=null);for(let t of this._subscriptions)t.unsubscribe();this._subscriptions=[];for(let t of this.__baseSubscriptions)t.unsubscribe();this.__baseSubscriptions=[]}$watch=(t,e)=>(e(""),{unsubscribe:()=>{}});__processBindingsOnElementPublic(t,e,n){this.__processBindingsOnElement(t,e,n)}__setupBindings(){this.__initializeMarkers(S),this.__processBindings(),this.__initializeMarkersInternal()}__pipe(t,e,...n){let r=this.__pipes[t];return r?r(e,...n):(console.warn(`Pipe "${t}" not found`),e)}__getPipeFn(t){return this.__pipes[t]??R(t)}__getShadowRoot(){return this._shadowRoot}__createProp(t,e){let n=new f(e);return Object.defineProperty(this,t,{get(){return n.getValue()},set(r){n.setValue(r)},enumerable:!0,configurable:!0}),n}__defineClassHostBinding(t,e,n){Object.defineProperty(this,t,{get:()=>!!Reflect.get(this,n),set:r=>{Reflect.set(this,n,r),r?this.classList.add(e):this.classList.remove(e)},enumerable:!0,configurable:!0})}__setMarkerConfigs(t){this._markerConfigEntries=t}__initializeMarkers(t){this._MarkerManagerClass=t}__initializeMarkersInternal(){!this._markerConfigEntries||!this._MarkerManagerClass||(this._markerManager=new this._MarkerManagerClass(this,this._shadowRoot),this._markerManager.initializeFromConfig(this._markerConfigEntries))}__setChildProperty(t,e,n){if(t instanceof HTMLElement&&t.hasAttribute("x-fluff-component")){let r=t.tagName.toLowerCase();if(customElements.get(r)===void 0){this.__whenDefined(r,()=>{this.__setChildProperty(t,e,n)});return}}super.__setChildProperty(t,e,n)}__getReactivePropFromScope(t,e){let n=`__${t}`;if(n in e.host){let r=Reflect.get(e.host,n);if(r instanceof f)return r}if(e.parent)return this.__getReactivePropFromScope(t,e.parent)}__processBindings(){let t=this._shadowRoot.querySelectorAll("[data-lid]"),e=this.__getScope();for(let n of Array.from(t)){let r=n.closest("[x-fluff-component]");r&&r!==n||this.__processBindingsOnElement(n,e)}}__applyPendingProps(){let t=Reflect.get(this,"__pendingProps");if(this.isRecord(t)){for(let[e,n]of Object.entries(t)){console.log("apply-pending-prop",{propName:e,value:n,el:this.tagName});let r=`__${e}`;if(r in this){let s=Reflect.get(this,r);s instanceof f&&s.setValue(n,!0)}else e in this&&Reflect.set(this,e,n)}Reflect.deleteProperty(this,"__pendingProps")}}isRecord(t){return t!==null&&typeof t=="object"&&!Array.isArray(t)}};export{N as Component,_ as Direction,m as FluffBase,C as FluffElement,H as HostBinding,W as HostListener,D as Input,j as LinkedProperty,S as MarkerManager,q as Output,G as Pipe,f as Property,g as Publisher,J as Reactive,K as ViewChild,X as Watch,R as getPipeTransform,B as pipeRegistry};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluffjs/fluff",
3
- "version": "0.3.9",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "module": "./index.js",
@@ -17,13 +17,50 @@ export interface BindingInfo {
17
17
  a: number[];
18
18
  }[];
19
19
  }
20
+ /**
21
+ * Compact Binding Format (Decoder)
22
+ *
23
+ * Bindings are received as tuples to minimize bundle size. All strings are
24
+ * stored in a global string table (FluffBase.__s) and referenced by index.
25
+ *
26
+ * Format: [nameIdx, bindType, deps, id, extras?]
27
+ *
28
+ * - nameIdx: Index into __s for the binding name (e.g., "value", "click")
29
+ * - bindType: Numeric binding type (0=property, 1=event, 2=two-way, 3=class, 4=style, 5=ref)
30
+ * - deps: Array of interned dependency chains, or null. Each dep is either:
31
+ * - A single index (for simple property like "foo")
32
+ * - An array of indices (for nested property chain like ["device", "name"])
33
+ * - id: Expression ID (for property/two-way/class/style) or Handler ID (for event), or null
34
+ * - extras: Optional object with additional binding metadata:
35
+ * - t: Target property name for two-way bindings
36
+ * - s: Subscribe source name
37
+ * - p: Pipes array of [pipeNameIdx, argExprIds[]]
38
+ *
39
+ * The string table is set via FluffBase.__setExpressionTable(exprs, handlers, strings).
40
+ * __decodeBinding() converts CompactBinding back to BindingInfo for runtime use.
41
+ */
42
+ type CompactDep = number | number[];
43
+ export type CompactBinding = [
44
+ number,
45
+ number,
46
+ CompactDep[] | null,
47
+ number | null,
48
+ {
49
+ t?: string;
50
+ s?: string;
51
+ p?: [number, number[]][];
52
+ }?
53
+ ];
20
54
  export declare abstract class FluffBase extends HTMLElement {
21
55
  static __e: ExpressionFn[];
22
56
  static __h: HandlerFn[];
23
- static __bindings: Record<string, BindingInfo[]>;
57
+ static __s: string[];
58
+ static __bindings: Record<string, (CompactBinding | BindingInfo)[]>;
24
59
  private static __expressionsReady;
25
60
  private static readonly __pendingInitCallbacks;
26
- static __setExpressionTable(expressions: ExpressionFn[], handlers: HandlerFn[]): void;
61
+ static __setExpressionTable(expressions: ExpressionFn[], handlers: HandlerFn[], strings?: string[]): void;
62
+ private static __decodeDep;
63
+ private static __decodeBinding;
27
64
  static __areExpressionsReady(): boolean;
28
65
  static __addPendingInit(callback: () => void): void;
29
66
  __parentScope?: Scope;
@@ -38,6 +75,7 @@ export declare abstract class FluffBase extends HTMLElement {
38
75
  }[], locals: Record<string, unknown>): unknown;
39
76
  protected __processBindingsOnElement(el: Element, scope: Scope, subscriptions?: Subscription[]): void;
40
77
  private __getBindingsForLid;
78
+ private static __decodeBindingAny;
41
79
  private __isBindingsMap;
42
80
  protected __applyBindingWithScope(el: Element, binding: BindingInfo, scope: Scope, subscriptions?: Subscription[]): void;
43
81
  protected __getCompiledExprFn(exprId: number): ExpressionFn;
@@ -62,3 +100,4 @@ export declare abstract class FluffBase extends HTMLElement {
62
100
  private __applyStyleBindingWithScope;
63
101
  private __hasStyle;
64
102
  }
103
+ export {};
@@ -1,20 +1,63 @@
1
1
  import { Property } from '../utils/Property.js';
2
2
  import { Publisher } from '../utils/Publisher.js';
3
+ const BINDING_TYPES = ['property', 'event', 'two-way', 'class', 'style', 'ref'];
3
4
  export class FluffBase extends HTMLElement {
4
5
  static __e = [];
5
6
  static __h = [];
7
+ static __s = [];
6
8
  static __bindings = {};
7
9
  static __expressionsReady = false;
8
10
  static __pendingInitCallbacks = [];
9
- static __setExpressionTable(expressions, handlers) {
11
+ static __setExpressionTable(expressions, handlers, strings) {
10
12
  FluffBase.__e = expressions;
11
13
  FluffBase.__h = handlers;
14
+ if (strings) {
15
+ FluffBase.__s = strings;
16
+ }
12
17
  FluffBase.__expressionsReady = true;
13
18
  const pending = FluffBase.__pendingInitCallbacks.splice(0, FluffBase.__pendingInitCallbacks.length);
14
19
  for (const callback of pending) {
15
20
  callback();
16
21
  }
17
22
  }
23
+ static __decodeDep(dep) {
24
+ if (Array.isArray(dep)) {
25
+ return dep.map(idx => FluffBase.__s[idx]);
26
+ }
27
+ return FluffBase.__s[dep];
28
+ }
29
+ static __decodeBinding(compact) {
30
+ const [nameIdx, bType, deps, id, extras] = compact;
31
+ const n = FluffBase.__s[nameIdx];
32
+ const b = BINDING_TYPES[bType];
33
+ const result = { n, b };
34
+ if (deps) {
35
+ result.d = deps.map(d => FluffBase.__decodeDep(d));
36
+ }
37
+ if (b === 'event') {
38
+ if (id !== null) {
39
+ result.h = id;
40
+ }
41
+ }
42
+ else if (id !== null) {
43
+ result.e = id;
44
+ }
45
+ if (extras) {
46
+ if (extras.t) {
47
+ result.t = extras.t;
48
+ }
49
+ if (extras.s) {
50
+ result.s = extras.s;
51
+ }
52
+ if (extras.p) {
53
+ result.p = extras.p.map(([pipeNameIdx, args]) => ({
54
+ n: FluffBase.__s[pipeNameIdx],
55
+ a: args
56
+ }));
57
+ }
58
+ }
59
+ return result;
60
+ }
18
61
  static __areExpressionsReady() {
19
62
  return FluffBase.__expressionsReady;
20
63
  }
@@ -75,11 +118,20 @@ export class FluffBase extends HTMLElement {
75
118
  if (typeof ctor === 'function') {
76
119
  const bindings = Reflect.get(ctor, '__bindings');
77
120
  if (this.__isBindingsMap(bindings)) {
78
- return bindings[lid];
121
+ const lidBindings = bindings[lid];
122
+ if (lidBindings) {
123
+ return lidBindings.map(b => FluffBase.__decodeBindingAny(b));
124
+ }
79
125
  }
80
126
  }
81
127
  return undefined;
82
128
  }
129
+ static __decodeBindingAny(binding) {
130
+ if (Array.isArray(binding)) {
131
+ return FluffBase.__decodeBinding(binding);
132
+ }
133
+ return binding;
134
+ }
83
135
  __isBindingsMap(value) {
84
136
  return !(!value || typeof value !== 'object');
85
137
  }