@fluffjs/fluff 0.2.3 → 0.3.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 +1 -0
- package/decorators/Component.d.ts +0 -8
- package/decorators/Component.js +0 -11
- package/decorators/Input.d.ts +1 -1
- package/decorators/InputOutputHelper.d.ts +2 -1
- package/decorators/InputOutputHelper.js +3 -1
- package/decorators/Output.d.ts +1 -1
- package/decorators/Pipe.d.ts +1 -0
- package/decorators/Pipe.js +1 -1
- package/decorators/Reactive.d.ts +2 -1
- package/decorators/Reactive.js +1 -1
- package/index.d.ts +2 -1
- package/index.js +1 -1
- package/interfaces/FluffHostElement.d.ts +13 -3
- package/interfaces/ReactiveOptions.d.ts +6 -0
- package/interfaces/ReactiveOptions.js +1 -0
- package/package.json +1 -1
- package/runtime/FluffBase.d.ts +12 -1
- package/runtime/FluffBase.js +70 -22
- package/runtime/FluffElementImpl.d.ts +9 -21
- package/runtime/FluffElementImpl.js +48 -149
- package/runtime/ForController.js +1 -2
- package/runtime/IfController.js +1 -2
- package/runtime/MarkerConfigGuards.d.ts +0 -2
- package/runtime/MarkerConfigGuards.js +0 -3
- package/runtime/MarkerController.d.ts +1 -9
- package/runtime/MarkerController.js +28 -144
- package/runtime/MarkerManager.d.ts +2 -1
- package/runtime/MarkerManager.js +1 -2
- package/runtime/MarkerManagerInterface.d.ts +3 -1
- package/runtime/SwitchController.js +1 -2
- package/runtime/TextController.d.ts +0 -1
- package/runtime/TextController.js +5 -19
- package/runtime/tests/TestChildTasksListComponent.js +2 -2
- package/runtime/tests/TestForComponent.js +2 -2
- package/runtime/tests/TestForReinsertBindsInputParentComponent.js +2 -2
- package/runtime/tests/TestForTextMarkerCollisionNoTrackParentComponent.js +2 -2
- package/runtime/tests/TestForTextMarkerCollisionParentComponent.js +2 -2
- package/runtime/tests/TestForUnsubscribeNestedParentComponent.js +2 -2
- package/runtime/tests/TestGetterReactivityComponent.js +2 -2
- package/runtime/tests/TestHarness.d.ts +9 -0
- package/runtime/tests/TestHarness.js +29 -0
- package/runtime/tests/TestIfReinsertBindsInputChildComponent.js +2 -2
- package/runtime/tests/TestIfReinsertBindsInputParentComponent.js +2 -2
- package/runtime/tests/TestIfUnsubscribeNestedParentComponent.js +2 -2
- package/runtime/tests/TestInterpolationNestedPropertyComponentBase.js +2 -2
- package/runtime/tests/TestLateDefineForComponent.js +2 -2
- package/runtime/tests/TestNullInputTextComponent.js +2 -2
- package/runtime/tests/TestOutputBindingParentComponent.js +2 -2
- package/runtime/tests/TestParentBindsTasksComponent.js +2 -2
- package/runtime/tests/TestSwitchReinsertBindsInputChildComponent.js +2 -2
- package/runtime/tests/TestSwitchReinsertBindsInputParentComponent.js +2 -2
- package/runtime/tests/TestSwitchUnsubscribeNestedParentComponent.js +2 -2
- package/runtime/tests/TestTemplateNestedMarkersComponent.js +2 -2
- package/runtime/tests/TestUnsubscribeNestedGrandchildComponent.js +2 -2
- package/runtime/tests/createPipeUnwrapTestComponent.js +2 -2
- package/runtime/tests/createPropertyUnwrapNativeTestComponents.d.ts +4 -0
- package/runtime/tests/createPropertyUnwrapNativeTestComponents.js +23 -0
- package/runtime/tests/createTestInterpolationPipeComponent.js +2 -2
- package/runtime/tests/createTestInterpolationPipeWithArgsComponent.js +2 -2
- package/runtime/tests/typeguards.d.ts +21 -0
- package/runtime/tests/typeguards.js +48 -0
- package/utils/Property.d.ts +8 -2
- package/utils/Property.js +48 -8
- package/utils/DomUtils.d.ts +0 -3
- package/utils/DomUtils.js +0 -6
package/bundle.min.js
ADDED
|
@@ -0,0 +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,10 +1,3 @@
|
|
|
1
|
-
interface PipeInstance {
|
|
2
|
-
transform: (value: unknown, ...args: unknown[]) => unknown;
|
|
3
|
-
}
|
|
4
|
-
interface PipeClass {
|
|
5
|
-
__pipeName?: string;
|
|
6
|
-
new (): PipeInstance;
|
|
7
|
-
}
|
|
8
1
|
type Constructor = new (...args: unknown[]) => object;
|
|
9
2
|
export interface ComponentConfig {
|
|
10
3
|
selector: string;
|
|
@@ -12,7 +5,6 @@ export interface ComponentConfig {
|
|
|
12
5
|
template?: string;
|
|
13
6
|
styleUrl?: string;
|
|
14
7
|
styles?: string;
|
|
15
|
-
pipes?: PipeClass[];
|
|
16
8
|
}
|
|
17
9
|
export interface ComponentMetadata extends ComponentConfig {
|
|
18
10
|
inputs: Map<string, string>;
|
package/decorators/Component.js
CHANGED
|
@@ -5,17 +5,6 @@ export function Component(config) {
|
|
|
5
5
|
...config, inputs: new Map(), outputs: new Map()
|
|
6
6
|
};
|
|
7
7
|
componentRegistry.set(target, metadata);
|
|
8
|
-
if (config.pipes && config.pipes.length > 0) {
|
|
9
|
-
const pipesObj = {};
|
|
10
|
-
for (const PipeClassItem of config.pipes) {
|
|
11
|
-
const pipeName = PipeClassItem.__pipeName;
|
|
12
|
-
if (pipeName) {
|
|
13
|
-
const instance = new PipeClassItem();
|
|
14
|
-
pipesObj[pipeName] = (value, ...args) => instance.transform(value, ...args);
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
Reflect.set(target.prototype, '__pipes', pipesObj);
|
|
18
|
-
}
|
|
19
8
|
return target;
|
|
20
9
|
};
|
|
21
10
|
}
|
package/decorators/Input.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const Input: (bindingName?: string) => PropertyDecorator;
|
|
1
|
+
export declare const Input: (bindingName?: string | import("../index.js").ReactiveOptions) => PropertyDecorator;
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import type { ReactiveOptions } from '../interfaces/ReactiveOptions.js';
|
|
2
|
+
export declare function createInputOutputDecorator(type: 'inputs' | 'outputs'): (bindingName?: string | ReactiveOptions) => PropertyDecorator;
|
|
@@ -10,7 +10,9 @@ export function createInputOutputDecorator(type) {
|
|
|
10
10
|
return;
|
|
11
11
|
const metadata = getComponentMetadata(constructor);
|
|
12
12
|
if (metadata) {
|
|
13
|
-
const name = bindingName
|
|
13
|
+
const name = typeof bindingName === 'string'
|
|
14
|
+
? bindingName
|
|
15
|
+
: bindingName?.alias ?? String(propertyKey);
|
|
14
16
|
metadata[type].set(String(propertyKey), name);
|
|
15
17
|
}
|
|
16
18
|
};
|
package/decorators/Output.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const Output: (bindingName?: string) => PropertyDecorator;
|
|
1
|
+
export declare const Output: (bindingName?: string | import("../index.js").ReactiveOptions) => PropertyDecorator;
|
package/decorators/Pipe.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ interface PipeInstance {
|
|
|
4
4
|
type PipeConstructor = (new () => PipeInstance) & {
|
|
5
5
|
__pipeName?: string;
|
|
6
6
|
};
|
|
7
|
+
export declare const pipeRegistry: Map<string, PipeConstructor>;
|
|
7
8
|
export declare function getPipeTransform(name: string): ((value: unknown, ...args: unknown[]) => unknown) | undefined;
|
|
8
9
|
export declare function Pipe(name: string): <T extends PipeConstructor>(target: T) => T;
|
|
9
10
|
export interface PipeTransform<TArgs extends unknown[] = unknown[], TReturn = unknown> {
|
package/decorators/Pipe.js
CHANGED
package/decorators/Reactive.d.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import type { ReactiveOptions } from '../interfaces/ReactiveOptions.js';
|
|
2
|
+
export declare function Reactive(_options?: ReactiveOptions): PropertyDecorator;
|
package/decorators/Reactive.js
CHANGED
package/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export { HostListener } from './decorators/HostListener.js';
|
|
|
5
5
|
export { Input } from './decorators/Input.js';
|
|
6
6
|
export { LinkedProperty } from './decorators/LinkedProperty.js';
|
|
7
7
|
export { Output } from './decorators/Output.js';
|
|
8
|
-
export { getPipeTransform, Pipe } from './decorators/Pipe.js';
|
|
8
|
+
export { getPipeTransform, Pipe, pipeRegistry } from './decorators/Pipe.js';
|
|
9
9
|
export type { PipeTransform } from './decorators/Pipe.js';
|
|
10
10
|
export { Reactive } from './decorators/Reactive.js';
|
|
11
11
|
export { ViewChild } from './decorators/ViewChild.js';
|
|
@@ -16,6 +16,7 @@ export { MarkerManager } from './runtime/FluffMarkers.js';
|
|
|
16
16
|
export { Property } from './utils/Property.js';
|
|
17
17
|
export { Publisher } from './utils/Publisher.js';
|
|
18
18
|
export { Direction } from './enums/Direction.js';
|
|
19
|
+
export type { ReactiveOptions } from './interfaces/ReactiveOptions.js';
|
|
19
20
|
export type { OnInit } from './interfaces/OnInit.js';
|
|
20
21
|
export type { OnDestroy } from './interfaces/OnDestroy.js';
|
|
21
22
|
export type { Subscription } from './interfaces/Subscription.js';
|
package/index.js
CHANGED
|
@@ -4,7 +4,7 @@ export { HostListener } from './decorators/HostListener.js';
|
|
|
4
4
|
export { Input } from './decorators/Input.js';
|
|
5
5
|
export { LinkedProperty } from './decorators/LinkedProperty.js';
|
|
6
6
|
export { Output } from './decorators/Output.js';
|
|
7
|
-
export { getPipeTransform, Pipe } from './decorators/Pipe.js';
|
|
7
|
+
export { getPipeTransform, Pipe, pipeRegistry } from './decorators/Pipe.js';
|
|
8
8
|
export { Reactive } from './decorators/Reactive.js';
|
|
9
9
|
export { ViewChild } from './decorators/ViewChild.js';
|
|
10
10
|
export { Watch } from './decorators/Watch.js';
|
|
@@ -1,5 +1,15 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { PropertyChain } from './PropertyChain.js';
|
|
2
|
+
import type { Subscription } from './Subscription.js';
|
|
3
|
+
export interface FluffHostScope {
|
|
4
|
+
host: FluffHostElement;
|
|
5
|
+
locals: Record<string, unknown>;
|
|
6
|
+
parent?: FluffHostScope;
|
|
7
|
+
}
|
|
2
8
|
export interface FluffHostElement extends HTMLElement {
|
|
3
|
-
|
|
4
|
-
|
|
9
|
+
__subscribeToExpression?: (deps: PropertyChain[], scope: FluffHostScope, callback: () => void, subscriptions: Subscription[]) => void;
|
|
10
|
+
__evaluateExpr?: (exprId: number, locals: Record<string, unknown>) => unknown;
|
|
11
|
+
__applyPipesForController?: (value: unknown, pipes: {
|
|
12
|
+
name: string;
|
|
13
|
+
argExprIds: number[];
|
|
14
|
+
}[], locals: Record<string, unknown>) => unknown;
|
|
5
15
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
package/runtime/FluffBase.d.ts
CHANGED
|
@@ -21,10 +21,21 @@ export declare abstract class FluffBase extends HTMLElement {
|
|
|
21
21
|
static __e: ExpressionFn[];
|
|
22
22
|
static __h: HandlerFn[];
|
|
23
23
|
static __bindings: Record<string, BindingInfo[]>;
|
|
24
|
+
private static __expressionsReady;
|
|
25
|
+
private static readonly __pendingInitCallbacks;
|
|
26
|
+
static __setExpressionTable(expressions: ExpressionFn[], handlers: HandlerFn[]): void;
|
|
27
|
+
static __areExpressionsReady(): boolean;
|
|
28
|
+
static __addPendingInit(callback: () => void): void;
|
|
24
29
|
__parentScope?: Scope;
|
|
25
30
|
__loopContext: Record<string, unknown>;
|
|
26
31
|
protected __baseSubscriptions: Subscription[];
|
|
27
32
|
__getScope(): Scope;
|
|
33
|
+
__subscribeToExpression(deps: PropertyChain[], scope: Scope, callback: () => void, subscriptions: Subscription[]): void;
|
|
34
|
+
__evaluateExpr(exprId: number, locals: Record<string, unknown>): unknown;
|
|
35
|
+
__applyPipesForController(value: unknown, pipes: {
|
|
36
|
+
name: string;
|
|
37
|
+
argExprIds: number[];
|
|
38
|
+
}[], locals: Record<string, unknown>): unknown;
|
|
28
39
|
protected __processBindingsOnElement(el: Element, scope: Scope, subscriptions?: Subscription[]): void;
|
|
29
40
|
private __getBindingsForLid;
|
|
30
41
|
private __isBindingsMap;
|
|
@@ -35,13 +46,13 @@ export declare abstract class FluffBase extends HTMLElement {
|
|
|
35
46
|
n: string;
|
|
36
47
|
a: number[];
|
|
37
48
|
}[], locals: Record<string, unknown>): unknown;
|
|
38
|
-
private __applyPipe;
|
|
39
49
|
protected __getPipeFn(_name: string): ((value: unknown, ...args: unknown[]) => unknown) | undefined;
|
|
40
50
|
protected __subscribeToExpressionInScope(deps: PropertyChain[] | undefined, scope: Scope, callback: () => void, subscriptions?: Subscription[]): void;
|
|
41
51
|
private __subscribeToPropertyChain;
|
|
42
52
|
private __subscribeToNestedChain;
|
|
43
53
|
protected __getReactivePropFromScope(propName: string, scope: Scope): Property<unknown> | undefined;
|
|
44
54
|
protected __setChildProperty(el: Element, propName: string, value: unknown): void;
|
|
55
|
+
private __unwrap;
|
|
45
56
|
private __applyPropertyBindingWithScope;
|
|
46
57
|
private __applyEventBindingWithScope;
|
|
47
58
|
private __applyOutputBinding;
|
package/runtime/FluffBase.js
CHANGED
|
@@ -4,6 +4,23 @@ export class FluffBase extends HTMLElement {
|
|
|
4
4
|
static __e = [];
|
|
5
5
|
static __h = [];
|
|
6
6
|
static __bindings = {};
|
|
7
|
+
static __expressionsReady = false;
|
|
8
|
+
static __pendingInitCallbacks = [];
|
|
9
|
+
static __setExpressionTable(expressions, handlers) {
|
|
10
|
+
FluffBase.__e = expressions;
|
|
11
|
+
FluffBase.__h = handlers;
|
|
12
|
+
FluffBase.__expressionsReady = true;
|
|
13
|
+
const pending = FluffBase.__pendingInitCallbacks.splice(0, FluffBase.__pendingInitCallbacks.length);
|
|
14
|
+
for (const callback of pending) {
|
|
15
|
+
callback();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
static __areExpressionsReady() {
|
|
19
|
+
return FluffBase.__expressionsReady;
|
|
20
|
+
}
|
|
21
|
+
static __addPendingInit(callback) {
|
|
22
|
+
FluffBase.__pendingInitCallbacks.push(callback);
|
|
23
|
+
}
|
|
7
24
|
__parentScope;
|
|
8
25
|
__loopContext = {};
|
|
9
26
|
__baseSubscriptions = [];
|
|
@@ -14,6 +31,34 @@ export class FluffBase extends HTMLElement {
|
|
|
14
31
|
parent: this.__parentScope
|
|
15
32
|
};
|
|
16
33
|
}
|
|
34
|
+
__subscribeToExpression(deps, scope, callback, subscriptions) {
|
|
35
|
+
this.__subscribeToExpressionInScope(deps, scope, callback, subscriptions);
|
|
36
|
+
}
|
|
37
|
+
__evaluateExpr(exprId, locals) {
|
|
38
|
+
const fn = this.__getCompiledExprFn(exprId);
|
|
39
|
+
try {
|
|
40
|
+
return fn(this, locals);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
__applyPipesForController(value, pipes, locals) {
|
|
47
|
+
let result = value;
|
|
48
|
+
if (result instanceof Property) {
|
|
49
|
+
result = result.getValue();
|
|
50
|
+
}
|
|
51
|
+
for (const pipe of pipes) {
|
|
52
|
+
const pipeFn = this.__getPipeFn(pipe.name);
|
|
53
|
+
if (!pipeFn) {
|
|
54
|
+
console.warn(`Pipe "${pipe.name}" not found`);
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const args = pipe.argExprIds.map(id => this.__getCompiledExprFn(id)(this, locals));
|
|
58
|
+
result = pipeFn(result, ...args);
|
|
59
|
+
}
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
17
62
|
__processBindingsOnElement(el, scope, subscriptions) {
|
|
18
63
|
const lid = el.getAttribute('data-lid');
|
|
19
64
|
if (!lid)
|
|
@@ -74,23 +119,7 @@ export class FluffBase extends HTMLElement {
|
|
|
74
119
|
return fn;
|
|
75
120
|
}
|
|
76
121
|
__applyPipes(value, pipes, locals) {
|
|
77
|
-
|
|
78
|
-
if (result instanceof Property) {
|
|
79
|
-
result = result.getValue();
|
|
80
|
-
}
|
|
81
|
-
for (const pipe of pipes) {
|
|
82
|
-
result = this.__applyPipe(pipe.n, result, pipe.a, locals);
|
|
83
|
-
}
|
|
84
|
-
return result;
|
|
85
|
-
}
|
|
86
|
-
__applyPipe(name, value, argExprIds, locals) {
|
|
87
|
-
const pipeFn = this.__getPipeFn(name);
|
|
88
|
-
if (!pipeFn) {
|
|
89
|
-
console.warn(`Pipe "${name}" not found`);
|
|
90
|
-
return value;
|
|
91
|
-
}
|
|
92
|
-
const args = argExprIds.map(id => this.__getCompiledExprFn(id)(this, locals));
|
|
93
|
-
return pipeFn(value, ...args);
|
|
122
|
+
return this.__applyPipesForController(value, pipes.map(p => ({ name: p.n, argExprIds: p.a })), locals);
|
|
94
123
|
}
|
|
95
124
|
__getPipeFn(_name) {
|
|
96
125
|
return undefined;
|
|
@@ -156,7 +185,13 @@ export class FluffBase extends HTMLElement {
|
|
|
156
185
|
}
|
|
157
186
|
}
|
|
158
187
|
}
|
|
159
|
-
else if (
|
|
188
|
+
else if (first in scope.locals) {
|
|
189
|
+
const localValue = scope.locals[first];
|
|
190
|
+
if (localValue !== null && localValue !== undefined && rest.length > 0) {
|
|
191
|
+
this.__subscribeToNestedChain(localValue, rest, callback, addSub);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
else if (!(first in scope.host)) {
|
|
160
195
|
console.warn(`Binding dependency "${first}" not found on component ${scope.host.constructor.name}`);
|
|
161
196
|
}
|
|
162
197
|
}
|
|
@@ -220,12 +255,21 @@ export class FluffBase extends HTMLElement {
|
|
|
220
255
|
if (prop instanceof Property) {
|
|
221
256
|
prop.setValue(value, true);
|
|
222
257
|
}
|
|
223
|
-
else if (
|
|
258
|
+
else if (el instanceof FluffBase) {
|
|
224
259
|
Reflect.set(el, propName, value);
|
|
225
260
|
}
|
|
261
|
+
else if (propName in el && el instanceof HTMLElement) {
|
|
262
|
+
Reflect.set(el, propName, this.__unwrap(value));
|
|
263
|
+
}
|
|
226
264
|
else {
|
|
227
|
-
el.setAttribute(propName, String(value));
|
|
265
|
+
el.setAttribute(propName, String(this.__unwrap(value)));
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
__unwrap(value) {
|
|
269
|
+
if (value instanceof Property) {
|
|
270
|
+
return value.getValue();
|
|
228
271
|
}
|
|
272
|
+
return value;
|
|
229
273
|
}
|
|
230
274
|
__applyPropertyBindingWithScope(el, binding, scope, subscriptions) {
|
|
231
275
|
const tagName = el.tagName.toLowerCase();
|
|
@@ -270,6 +314,10 @@ export class FluffBase extends HTMLElement {
|
|
|
270
314
|
}
|
|
271
315
|
}
|
|
272
316
|
__applyEventBindingWithScope(el, binding, scope) {
|
|
317
|
+
const boundKey = `__fluff_event_${binding.n}`;
|
|
318
|
+
if (Reflect.has(el, boundKey))
|
|
319
|
+
return;
|
|
320
|
+
Reflect.set(el, boundKey, true);
|
|
273
321
|
if (typeof binding.h !== 'number') {
|
|
274
322
|
throw new Error(`Event binding for ${binding.n} is missing handlerId`);
|
|
275
323
|
}
|
|
@@ -343,7 +391,7 @@ export class FluffBase extends HTMLElement {
|
|
|
343
391
|
throw new Error(`Class binding for ${binding.n} is missing exprId`);
|
|
344
392
|
}
|
|
345
393
|
const fn = this.__getCompiledExprFn(binding.e);
|
|
346
|
-
const value = fn(this, scope.locals);
|
|
394
|
+
const value = this.__unwrap(fn(this, scope.locals));
|
|
347
395
|
if (value) {
|
|
348
396
|
el.classList.add(binding.n);
|
|
349
397
|
}
|
|
@@ -365,7 +413,7 @@ export class FluffBase extends HTMLElement {
|
|
|
365
413
|
throw new Error(`Style binding for ${binding.n} is missing exprId`);
|
|
366
414
|
}
|
|
367
415
|
const fn = this.__getCompiledExprFn(binding.e);
|
|
368
|
-
const value = fn(this, scope.locals);
|
|
416
|
+
const value = this.__unwrap(fn(this, scope.locals));
|
|
369
417
|
if (this.__hasStyle(el)) {
|
|
370
418
|
el.style.setProperty(binding.n, String(value));
|
|
371
419
|
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import type { Subscription } from '../interfaces/Subscription.js';
|
|
2
2
|
import { Property } from '../utils/Property.js';
|
|
3
|
-
import { Publisher } from '../utils/Publisher.js';
|
|
4
3
|
import { FluffBase } from './FluffBase.js';
|
|
5
|
-
import type { MarkerManagerInterface } from './MarkerManagerInterface.js';
|
|
4
|
+
import type { MarkerConfigEntries, MarkerManagerInterface } from './MarkerManagerInterface.js';
|
|
6
5
|
import { type Scope } from './ScopeRegistry.js';
|
|
7
6
|
export declare abstract class FluffElement extends FluffBase {
|
|
8
7
|
protected __pipes: Record<string, (value: unknown, ...args: unknown[]) => unknown>;
|
|
9
8
|
protected readonly _shadowRoot: ShadowRoot;
|
|
10
9
|
private _subscriptions;
|
|
11
10
|
private _initialized;
|
|
11
|
+
private _pendingInit;
|
|
12
12
|
private _markerManager;
|
|
13
|
-
private
|
|
13
|
+
private _markerConfigEntries;
|
|
14
14
|
private _MarkerManagerClass;
|
|
15
15
|
constructor();
|
|
16
16
|
connectedCallback(): void;
|
|
@@ -19,32 +19,20 @@ export declare abstract class FluffElement extends FluffBase {
|
|
|
19
19
|
__processBindingsOnElementPublic(el: Element, scope: Scope, subscriptions?: Subscription[]): void;
|
|
20
20
|
protected abstract __render(): void;
|
|
21
21
|
protected __setupBindings(): void;
|
|
22
|
-
protected __addSubscription(sub: Subscription): void;
|
|
23
22
|
protected __pipe(name: string, value: unknown, ...args: unknown[]): unknown;
|
|
24
23
|
protected __getPipeFn(name: string): ((value: unknown, ...args: unknown[]) => unknown) | undefined;
|
|
25
24
|
protected __getShadowRoot(): ShadowRoot;
|
|
26
|
-
protected
|
|
25
|
+
protected __createProp<T>(name: string, options: T | {
|
|
26
|
+
initialValue: T;
|
|
27
|
+
[key: string]: unknown;
|
|
28
|
+
}): Property<T>;
|
|
29
|
+
protected __defineClassHostBinding(name: string, className: string, privateName: string): void;
|
|
30
|
+
protected __setMarkerConfigs(entries: MarkerConfigEntries): void;
|
|
27
31
|
protected __initializeMarkers(MarkerManagerClass: new (host: FluffElement, shadowRoot: ShadowRoot) => MarkerManagerInterface): void;
|
|
28
32
|
private __initializeMarkersInternal;
|
|
29
|
-
protected __getElement(id: string): Element | null;
|
|
30
|
-
protected __setText(id: string, text: string): void;
|
|
31
|
-
protected __bindText(id: string, getter: () => string): void;
|
|
32
|
-
protected __setProperty(id: string, prop: string, value: unknown): void;
|
|
33
|
-
protected __addClass(id: string, className: string): void;
|
|
34
|
-
protected __removeClass(id: string, className: string): void;
|
|
35
|
-
protected __bindEvent(id: string, event: string, handler: (e: Event) => void): void;
|
|
36
|
-
protected __bindPropertyChange<T>(prop: Property<T>, callback: (val: T) => void): void;
|
|
37
|
-
protected __connectProperties<T>(source: Property<T>, target: Property<T>): void;
|
|
38
|
-
protected __connectOutput<T>(source: Publisher<T>, handler: (val: T) => void): void;
|
|
39
|
-
protected __bindOutput(id: string, outputName: string, handler: (val: Event) => void): void;
|
|
40
33
|
protected __setChildProperty(el: Element, propName: string, value: unknown): void;
|
|
41
|
-
protected __bindToChild(id: string, propName: string, value: unknown): void;
|
|
42
|
-
protected __setChildPropertyDeferred(el: Element, propName: string, value: unknown): void;
|
|
43
|
-
protected __bindOutputOnElement(el: Element, outputName: string, handler: (val: Event) => void): void;
|
|
44
34
|
protected __getReactivePropFromScope(propName: string, scope: Scope): Property<unknown> | undefined;
|
|
45
35
|
protected __processBindings(): void;
|
|
46
36
|
private __applyPendingProps;
|
|
47
|
-
private isHTMLElement;
|
|
48
37
|
private isRecord;
|
|
49
|
-
private __getReactiveProp;
|
|
50
38
|
}
|