native-document 1.0.18 โ 1.0.20
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/dist/native-document.dev.js +51 -37
- package/dist/native-document.dev.js.map +1 -0
- package/dist/native-document.min.js +1 -1
- package/docs/anchor.md +3 -0
- package/docs/conditional-rendering.md +3 -0
- package/docs/core-concepts.md +3 -0
- package/docs/elements.md +3 -0
- package/docs/extending-native-document-element.md +268 -0
- package/docs/getting-started.md +3 -0
- package/docs/lifecycle-events.md +3 -0
- package/docs/list-rendering.md +6 -0
- package/docs/native-document-element.md +279 -0
- package/docs/observables.md +3 -0
- package/docs/routing.md +3 -0
- package/docs/state-management.md +3 -0
- package/docs/validation.md +4 -2
- package/eslint.config.js +22 -0
- package/index.js +1 -0
- package/package.json +6 -3
- package/readme.md +4 -21
- package/rollup.config.js +14 -1
- package/src/data/ObservableChecker.js +2 -0
- package/src/data/ObservableItem.js +2 -0
- package/src/data/observable-helpers/object.js +3 -2
- package/src/elements/control/for-each-array.js +0 -2
- package/src/router/link.js +0 -1
- package/src/utils/debug-manager.js +36 -24
- package/src/utils/validator.js +3 -3
- package/src/wrappers/NDElement.js +14 -7
- package/src/wrappers/NdPrototype.js +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
var NativeDocument=function(t){"use strict";const n={enabled:!1,enable(){this.enabled=!0,console.log("๐ NativeDocument Debug Mode enabled")},disable(){this.enabled=!1},log(e,t,n){this.enabled&&(console.group(`๐ [${e}] ${t}`),n&&console.log(n),console.trace(),console.groupEnd())},warn(e,t,n){this.enabled&&console.warn(`โ ๏ธ [${e}] ${t}`,n)},error(e,t,n){console.error(`โ [${e}] ${t}`,n)}},r=function(){let e=0;const t=new Map;return{register(n){const r=++e;return t.set(r,new WeakRef(n)),r},unregister(e){t.delete(e)},getObservableById:e=>t.get(e)?.deref(),cleanup(){for(const[e,n]of t){const e=n.deref();e&&e.cleanup()}t.clear()},cleanObservables(e){if(t.size<e)return;let r=0;for(const[e,n]of t)n.deref()||(t.delete(e),r++);r>0&&n.log("Memory Auto Clean",`๐งน Cleaned ${r} orphaned observables`)}}}();class o extends Error{constructor(e,t={}){super(e),this.name="NativeDocumentError",this.context=t,this.timestamp=(new Date).toISOString()}}function i(e,t){this.observable=e,this.checker=t,this.unSubscriptions=[]}function s(e){if(void 0===e)throw new o("ObservableItem requires an initial value");if(e instanceof s)throw new o("ObservableItem cannot be an Observable");this.$previousValue=e,this.$currentValue=e,this.$isCleanedUp=!1,this.$listeners=null,this.$watchers=null,this.$memoryId=r.register(this)}i.prototype.subscribe=function(e){const t=this.observable.subscribe(t=>{e&&e(this.checker(t))});return this.unSubscriptions.push(t),t},i.prototype.check=function(e){return this.observable.check(()=>e(this.val()))},i.prototype.val=function(){return this.checker&&this.checker(this.observable.val())},i.prototype.set=function(e){return this.observable.set(e)},i.prototype.trigger=function(){return this.observable.trigger()},i.prototype.cleanup=function(){return this.observable.cleanup()},Object.defineProperty(s.prototype,"$value",{get(){return this.$currentValue},set(e){this.set(e)},configurable:!0}),s.prototype.triggerListeners=function(e){const t=this.$listeners,n=this.$previousValue,r=this.$currentValue;if(e=e||{},t?.length)for(let o=0,i=t.length;o<i;o++)t[o](r,n,e)},s.prototype.triggerWatchers=function(){if(!this.$watchers)return;const e=this.$watchers,t=this.$previousValue,n=this.$currentValue;if(e.has(n)){e.get(n).forEach(e=>{e.ifTrue.called||(e.ifTrue.callback(),e.else.called=!1)})}if(e.has(t)){e.get(t).forEach(e=>{e.else.called||(e.else.callback(),e.ifTrue.called=!1)})}},s.prototype.trigger=function(e){this.triggerListeners(e),this.triggerWatchers()},s.prototype.set=function(e){const t="function"==typeof e?e(this.$currentValue):e;this.$currentValue!==t&&(this.$previousValue=this.$currentValue,this.$currentValue=t,this.trigger())},s.prototype.val=function(){return this.$currentValue},s.prototype.disconnectAll=function(){if(this.$listeners?.splice(0),this.$previousValue=null,this.$currentValue=null,this.$watchers)for(const[e,t]of this.$watchers){for(const e of t)e.ifTrue.callback=null,e.else.callback=null;t.clear()}this.$watchers?.clear(),this.$listeners=null,this.$watchers=null},s.prototype.cleanup=function(){r.unregister(this.$memoryId),this.disconnectAll(),this.$isCleanedUp=!0,delete this.$value},s.prototype.subscribe=function(e){if(this.$listeners=this.$listeners??[],this.$isCleanedUp)return n.warn("Observable subscription","โ ๏ธ Attempted to subscribe to a cleaned up observable."),()=>{};if("function"!=typeof e)throw new o("Callback must be a function");return this.$listeners.push(e),()=>this.unsubscribe(e)},s.prototype.on=function(e,t,n){this.$watchers=this.$watchers??new Map;let r=this.$watchers.get(e);r||(r=new Set,this.$watchers.set(e,r));let o={ifTrue:{callback:t,called:!1},else:{callback:n,called:!1}};return r.add(o),()=>{r?.delete(o),0===r.size&&this.$watchers?.delete(e),r=null,o=null}},s.prototype.unsubscribe=function(e){const t=this.$listeners.indexOf(e);t>-1&&this.$listeners.splice(t,1)},s.prototype.check=function(e){return new i(this,e)},s.prototype.get=s.prototype.check,s.prototype.toString=function(){return"{{#ObItem::("+this.$memoryId+")}}"};const a=(e,t,n)=>{if(h.isFunction(n))return n(e,t);if(h.isObservable(e)){const r=e.val();return r&&n?r[n]:t}return h.isObject(e)?e[n]??t:e},u=function(e,t){return e.replace(new RegExp(`^[${t}]+|[${t}]+$`,"g"),"")},l={mounted:new WeakMap,mountedSupposedSize:0,unmounted:new WeakMap,unmountedSupposedSize:0,observer:null,checkMutation:function(e){for(const t of e){if(l.mountedSupposedSize>0)for(const e of t.addedNodes){const t=l.mounted.get(e);t&&(t.inDom=!0,t.mounted&&t.mounted(e))}if(l.unmountedSupposedSize>0)for(const e of t.removedNodes){const t=l.unmounted.get(e);t&&(t.inDom=!1,t.unmounted&&!0===t.unmounted(e)&&(t.disconnect(),e.nd?.remove()))}}},watch:function(e,t=!1){let n={inDom:t,mounted:null,unmounted:null,disconnect:()=>{l.mounted.delete(e),l.unmounted.delete(e),l.mountedSupposedSize--,l.unmountedSupposedSize--,n=null}};return{disconnect:n.disconnect,mounted:t=>{n.mounted=t,l.mounted.set(e,n),l.mountedSupposedSize++},unmounted:t=>{n.unmounted=t,l.unmounted.set(e,n),l.unmountedSupposedSize++}}}};l.observer=new MutationObserver(l.checkMutation),l.observer.observe(document.body,{childList:!0,subtree:!0});const c=["Click","DblClick","MouseDown","MouseEnter","MouseLeave","MouseMove","MouseOut","MouseOver","MouseUp","Wheel","KeyDown","KeyPress","KeyUp","Blur","Change","Focus","Input","Invalid","Reset","Search","Select","Submit","Drag","DragEnd","DragEnter","DragLeave","DragOver","DragStart","Drop","AfterPrint","BeforePrint","BeforeUnload","Error","HashChange","Load","Offline","Online","PageHide","PageShow","Resize","Scroll","Unload","Abort","CanPlay","CanPlayThrough","DurationChange","Emptied","Ended","LoadedData","LoadedMetadata","LoadStart","Pause","Play","Playing","Progress","RateChange","Seeked","Seeking","Stalled","Suspend","TimeUpdate","VolumeChange","Waiting"];function d(e){this.$element=e,this.$observer=null}for(const e of c){const t=e.toLowerCase();d.prototype["on"+e]=function(e){return this.$element.addEventListener(t,e),this},d.prototype["onPrevent"+e]=function(e){return this.$element.addEventListener(t,function(t){t.preventDefault(),e(t)}),this},d.prototype["onStop"+e]=function(e){return this.$element.addEventListener(t,function(t){t.stopPropagation(),e(t)}),this},d.prototype["onPreventStop"+e]=function(e){return this.$element.addEventListener(t,function(t){t.stopPropagation(),t.preventDefault(),e(t)}),this}}d.prototype.ref=function(e,t){return e[t]=element,this},d.prototype.unmountChildren=function(){let e=this.$element;for(let t=0,n=e.children.length;t<n;t++){let n=e.children[t];n.$ndProx||n.nd?.remove(),n=null}return e=null,this},d.prototype.remove=function(){let e=this.$element;return e.nd.unmountChildren(),e.$ndProx=null,delete e.nd?.on?.prevent,delete e.nd?.on,delete e.nd,e=null,this},d.prototype.lifecycle=function(e){return this.$observer=this.$observer||l.watch(this.$element),e.mounted&&this.$observer.mounted(e.mounted),e.unmounted&&this.$observer.unmounted(e.unmounted),this},d.prototype.mounted=function(e){return this.lifecycle({mounted:e})},d.prototype.mounted=function(e){return this.lifecycle({unmounted:e})};const h={isObservable:e=>e instanceof s||e instanceof i,isProxy:e=>e?.__isProxy__,isObservableChecker:e=>e instanceof i,isArray:e=>Array.isArray(e),isString:e=>"string"==typeof e,isNumber:e=>"number"==typeof e,isBoolean:e=>"boolean"==typeof e,isFunction:e=>"function"==typeof e,isAsyncFunction:e=>"function"==typeof e&&"AsyncFunction"===e.constructor.name,isObject:e=>"object"==typeof e,isJson:e=>"object"==typeof e&&null!==e&&"Object"===e.constructor.name&&!Array.isArray(e),isElement:e=>e instanceof HTMLElement||e instanceof DocumentFragment||e instanceof Text,isFragment:e=>e instanceof DocumentFragment,isStringOrObservable(e){return this.isString(e)||this.isObservable(e)},isValidChild(e){return null===e||this.isElement(e)||this.isObservable(e)||this.isNDElement(e)||["string","number","boolean"].includes(typeof e)},isNDElement:e=>e instanceof d,isValidChildren(e){Array.isArray(e)||(e=[e]);return 0===e.filter(e=>!this.isValidChild(e)).length},validateChildren(e){Array.isArray(e)||(e=[e]);const t=e.filter(e=>!this.isValidChild(e));if(t.length>0)throw new o(`Invalid children detected: ${t.map(e=>typeof e).join(", ")}`);return e},containsObservables:e=>!!e&&(h.isObject(e)&&Object.values(e).some(e=>h.isObservable(e))),containsObservableReference:e=>!(!e||"string"!=typeof e)&&/\{\{#ObItem::\([0-9]+\)\}\}/.test(e),validateAttributes(e){if(!e||"object"!=typeof e)return e;const t=[],r=Object.keys(e).filter(e=>t.includes(e));return r.length>0&&n.warn("Validator",`Reserved attributes found: ${r.join(", ")}`),e},validateEventCallback(e){if("function"!=typeof e)throw new o("Event callback must be a function")}};function p(e){const t=document.createDocumentFragment(),r=document.createComment("Anchor Start : "+e),o=document.createComment("/ Anchor End "+e);t.appendChild(r),t.appendChild(o),t.nativeInsertBefore=t.insertBefore,t.nativeAppendChild=t.appendChild;const i=function(e,n,r){e!==t?e.insertBefore(C.getChild(n),r):e.nativeInsertBefore(C.getChild(n),r)};return t.appendElement=function(e,n=null){o.parentNode!==t?o.parentNode?.insertBefore(e,n||o):o.parentNode.nativeInsertBefore(e,n||o)},t.appendChild=function(e,r=null){const s=o.parentNode;if(s){if(r=r??o,h.isArray(e)){const n=document.createDocumentFragment();for(let t=0,r=e.length;t<r;t++)n.appendChild(C.getChild(e[t]));return i(s,n,r),t}i(s,e,r)}else n.error("Anchor","Anchor : parent not found",e)},t.removeChildren=function(){const e=o.parentNode;if(e===t)return;if(e.firstChild===r&&e.lastChild===o)return void e.replaceChildren(r,o);let n,i=r.nextSibling;const s=document.createDocumentFragment();for(;i&&i!==o;)n=i.nextSibling,s.append(i),i=n;s.replaceChildren()},t.remove=function(){if(o.parentNode===t)return;let e,n=r.nextSibling;for(;n!==o;)e=n.nextSibling,t.nativeAppendChild(n),n=e},t.removeWithAnchors=function(){t.removeChildren(),r.remove(),o.remove()},t.replaceContent=function(e){const n=o.parentNode;n&&(n.firstChild!==r||n.lastChild!==o?(t.removeChildren(),n.insertBefore(e,o)):n.replaceChildren(r,e,o))},t.insertBefore=function(e,n=null){t.appendChild(e,n)},t.clear=function(){t.remove()},t.endElement=function(){return o},t.startElement=function(){return r},t}const f=["checked","selected","disabled","readonly","required","autofocus","multiple","autocomplete","hidden","contenteditable","spellcheck","translate","draggable","async","defer","autoplay","controls","loop","muted","download","reversed","open","default","formnovalidate","novalidate","scoped","itemscope","allowfullscreen","allowpaymentrequest","playsinline"];function m(e){return new s(e)}function b(e,t){for(let n in t){const r=t[n];h.isObservable(r)?(e.classList.toggle(n,r.val()),r.subscribe(t=>e.classList.toggle(n,t))):e.classList.toggle(n,r)}}function g(e,t){for(let n in t){const r=t[n];h.isObservable(r)?(e.style[n]=r.val(),r.subscribe(t=>{e.style[n]=t})):e.style[n]=r}}function v(e,t,n){const r=h.isObservable(n)?n.val():n;h.isBoolean(r)?e[t]=r:e[t]=r===e.value,h.isObservable(n)&&(["checked"].includes(t)&&e.addEventListener("input",()=>{h.isBoolean(r)?n.set(e[t]):n.set(e.value)}),n.subscribe(n=>{h.isBoolean(n)?e[t]=n:e[t]=n===e.value}))}function y(e,t,n){const r=n=>{"value"!==t?e.setAttribute(t,n):e.value=n};r(n.val()),n.subscribe(r),"value"===t&&e.addEventListener("input",()=>n.set(e.value))}m.getById=function(e){const t=r.getObservableById(parseInt(e));if(!t)throw new o("Observable.getById : No observable found with id "+e);return t},m.cleanup=function(e){e.cleanup()},m.autoCleanup=function(e=!1,t={}){if(!e)return;const{interval:n=6e4,threshold:o=100}=t;window.addEventListener("beforeunload",()=>{r.cleanup()}),setInterval(()=>r.cleanObservables(o),n)};const w=new Map;let $=null;const C={createTextNode:()=>($||($=document.createTextNode("")),$.cloneNode()),createObservableNode(e,t){const n=C.createTextNode();return t.subscribe(e=>n.nodeValue=String(e)),n.nodeValue=t.val(),e&&e.appendChild(n),n},createStaticTextNode(e,t){let n=C.createTextNode();return n.nodeValue=String(t),e&&e.appendChild(n),n},createElement(e){if(e){if(w.has(e))return w.get(e).cloneNode();const t=document.createElement(e);return w.set(e,t),t.cloneNode()}return new p("Fragment")},processChildren(e,t){if(null===e)return;const n=Array.isArray(e)?e:[e];for(let e=0,r=n.length;e<r;e++){let r=this.getChild(n[e]);null!==r&&t.appendChild(r)}},getChild(e){if(null===e)return null;if(h.isString(e)&&h.isFunction(e.resolveObservableTemplate)&&(e=e.resolveObservableTemplate()),h.isString(e))return C.createStaticTextNode(null,e);if(h.isObservable(e))return C.createObservableNode(null,e);if(h.isArray(e)){const t=document.createDocumentFragment();for(let n=0,r=e.length;n<r;n++)t.appendChild(this.getChild(e[n]));return t}return h.isFunction(e)?this.getChild(e()):h.isElement(e)?e:h.isNDElement(e)?e.$element:C.createStaticTextNode(null,e)},processAttributes(e,t){h.isFragment(e)||t&&function(e,t){if(h.validateAttributes(t),!h.isObject(t))throw new o("Attributes must be an object");for(let n in t){const r=n.toLowerCase();let o=t[r];if(h.isString(o)&&h.isFunction(o.resolveObservableTemplate)&&(o=o.resolveObservableTemplate(),h.isArray(o))){const e=o.filter(e=>h.isObservable(e));o=m.computed(()=>o.map(e=>h.isObservable(e)?e.val():e).join(" ")||" ",e)}f.includes(r)?v(e,r,o):h.isObservable(o)?y(e,r,o):"class"===r&&h.isJson(o)?b(e,o):"style"===r&&h.isJson(o)?g(e,o):e.setAttribute(r,o)}}(e,t)},setup:(e,t,n)=>e};function O(e,t){const r=e.toLowerCase();return function(e,o=null){try{if(!h.isJson(e)){const t=o;o=e,e=t}const n=C.createElement(r),i="function"==typeof t?t(n):n;return C.processAttributes(i,e),C.processChildren(o,i),C.setup(i,e,t)}catch(e){n.error("ElementCreation",`Error creating ${r}`,e)}}}Object.defineProperty(HTMLElement.prototype,"nd",{get(){return this.$nd||(this.$nd=new d(this),this.$nd.nd=this.$nd),this.$nd}});class S extends Error{constructor(e,t){super(`${e}\n\n${t.join("\n")}\n\n`)}}const E={string:e=>({name:e,type:"string",validate:e=>h.isString(e)}),number:e=>({name:e,type:"number",validate:e=>h.isNumber(e)}),boolean:e=>({name:e,type:"boolean",validate:e=>h.isBoolean(e)}),observable:e=>({name:e,type:"observable",validate:e=>h.isObservable(e)}),element:e=>({name:e,type:"element",validate:e=>h.isElement(e)}),function:e=>({name:e,type:"function",validate:e=>h.isFunction(e)}),object:e=>({name:e,type:"object",validate:e=>h.isObject(e)}),objectNotNull:e=>({name:e,type:"object",validate:e=>h.isObject(e)&&null!==e}),children:e=>({name:e,type:"children",validate:e=>h.validateChildren(e)}),attributes:e=>({name:e,type:"attributes",validate:e=>h.validateAttributes(e)}),optional:e=>({...e,optional:!0}),oneOf:(e,...t)=>({name:e,type:"oneOf",types:t,validate:e=>t.some(t=>t.validate(e))})},k=(e,t,n="Function")=>{if(!h.isArray(t))throw new o("withValidation : argSchema must be an array");return function(...r){return((e,t,n="Function")=>{if(!t)return;const r=[],o=t.filter(e=>!e.optional).length;if(e.length<o&&r.push(`${n}: Expected at least ${o} arguments, got ${e.length}`),t.forEach((t,o)=>{const i=o+1,s=e[o];if(void 0!==s){if(!t.validate(s)){const e=s?.constructor?.name||typeof s;r.push(`${n}: Invalid argument '${t.name}' at position ${i}, expected ${t.type}, got ${e}`)}}else t.optional||r.push(`${n}: Missing required argument '${t.name}' at position ${i}`)}),r.length>0)throw new S("Argument validation failed",r)})(r,t,e.name||n),e.apply(this,r)}};Function.prototype.args=function(...e){return k(this,e)},Function.prototype.errorBoundary=function(e){return(...t)=>{try{return this.apply(this,t)}catch(t){return e(t)}}},String.prototype.use=function(e){const t=this;return m.computed(()=>t.replace(/\$\{(.*?)}/g,(t,n)=>{const r=e[n];return h.isObservable(r)?r.val():r}),Object.values(e))},String.prototype.resolveObservableTemplate=function(){return h.containsObservableReference(this)?this.split(/(\{\{#ObItem::\([0-9]+\)\}\})/g).filter(Boolean).map(e=>{if(!h.containsObservableReference(e))return e;const[t,n]=e.match(/\{\{#ObItem::\(([0-9]+)\)\}\}/);return m.getById(n)}):this.valueOf()};const A=["push","pop","shift","unshift","reverse","sort","splice"];m.array=function(e){if(!Array.isArray(e))throw new o("Observable.array : target must be an array");const t=m(e);A.forEach(e=>{t[e]=function(...n){const r=t.val()[e](...n);return t.trigger({action:e,args:n,result:r}),r}}),t.clear=function(){return t.$value.length=0,t.trigger({action:"clear"}),!0},t.merge=function(e){t.$value=[...t.$value,...e]},t.populateAndRender=function(e,n){t.trigger({action:"populate",args:[t.$value,e,n]})},t.remove=function(e){const n=t.$value.splice(e,1);return 0===n.length?[]:(t.trigger({action:"remove",args:[e],result:n[0]}),n)},t.swap=function(e,n){const r=t.$value,o=r.length;if(o<e||o<n)return!1;if(n<e){const t=e;e=n,n=t}const i=r[e],s=r[n];return r[e]=s,r[n]=i,t.trigger({action:"swap",args:[e,n],result:[i,s]}),!0},t.length=function(){return t.$value.length};return["map","filter","reduce","some","every","find","findIndex","concat"].forEach(e=>{t[e]=function(...n){return t.val()[e](...n)}}),t},m.batch=function(e){const t=m(0),n=function(){if(h.isAsyncFunction(e))return e(...arguments).then(()=>{t.trigger()}).catch(e=>{throw e});e(...arguments),t.trigger()};return n.$observer=t,n},m.init=function(e){const t={};for(const n in e){const r=e[n];h.isJson(r)?t[n]=m.init(r):h.isArray(r)?t[n]=m.array(r):t[n]=m(r)}const n=function(){};return new Proxy(t,{get:(e,r)=>"__isProxy__"===r||("$value"===r?function(){const e={};for(const n in t){const r=t[n];h.isObservable(r)?e[n]=r.val():h.isProxy(r)?e[n]=r.$value:e[n]=r}return e}():"$clone"===r?n:void 0!==e[r]?e[r]:void 0),set(e,t,n){void 0!==e[t]&&e[t].set(n)}})},m.value=function(e){if(h.isObservable(e))return e.val();if(h.isProxy(e))return e.$value;if(h.isArray(e)){const t=[];return e.forEach(e=>{t.push(m.value(e))}),t}return e},m.update=function(e,t){for(const n in t){const r=e[n],o=t[n];if(h.isObservable(r)){if(h.isArray(o)){m.update(r,o);continue}r.set(o)}else h.isProxy(r)?m.update(r,o):e[n]=o}},m.object=m.init,m.json=m.init,m.computed=function(e,t=[]){const n=new s(e()),r=()=>n.set(e());if(h.isFunction(t)){if(!h.isObservable(t.$observer))throw new o("Observable.computed : dependencies must be valid batch function");return t.$observer.subscribe(r),n}return t.forEach(e=>e.subscribe(r)),n};const I=function(){const e=new Map;return{use(t){const{observer:n,subscribers:r}=e.get(t),o=m(n.val()),i=n.subscribe(e=>o.set(e)),s=o.subscribe(e=>n.set(e));return o.destroy=()=>{i(),s(),o.cleanup()},r.add(o),o},follow(e){return this.use(e)},create(t,n){const r=m(n);return e.set(t,{observer:r,subscribers:new Set}),r},get(t){const n=e.get(t);return n?n.observer:null},getWithSubscribers:t=>e.get(t),delete(t){const n=e.get(t);n&&(n.observer.cleanup(),n.subscribers.forEach(e=>e.destroy()),n.observer.clear())}}}();const F=function(e,t,r=null){if(!h.isObservable(e))return n.warn("ShowIf","ShowIf : condition must be an Observable / "+r,e);const o=new p("Show if : "+(r||""));let i=null;const s=()=>i||(i=C.getChild(t),i);return e.val()&&o.appendChild(s()),e.subscribe(e=>{e?o.appendChild(s()):o.remove()}),o},x=function(e,t,n=!0){if(!h.isObservable(e))throw new o("Toggle : condition must be an Observable");const r=new p,i=new Map,s=function(e){if(n&&i.has(e))return i.get(e);let r=t[e];return r?(r=C.getChild(r),n&&i.set(e,r),r):null},a=e.val(),u=s(a);return u&&r.appendChild(u),e.subscribe(e=>{const t=s(e);r.remove(),t&&r.appendChild(t)}),r},D=function(e,t,n){if(!h.isObservable(e))throw new o("Toggle : condition must be an Observable");return x(e,{true:t,false:n})},R=O("div"),T=O("span"),N=O("label"),L=O("p"),P=L,q=O("strong"),M=O("h1"),B=O("h2"),j=O("h3"),V=O("h4"),H=O("h5"),W=O("h6"),z=O("br"),_=O("a"),U=O("pre"),J=O("code"),K=O("blockquote"),Q=O("hr"),G=O("em"),X=O("small"),Y=O("mark"),Z=O("del"),ee=O("ins"),te=O("sub"),ne=O("sup"),re=O("abbr"),oe=O("cite"),ie=O("q"),se=O("dl"),ae=O("dt"),ue=O("dd"),le=O("form",function(e){return e.submit=function(t){return"function"==typeof t?(e.onSubmit(e=>{e.preventDefault(),t(e)}),e):(this.setAttribute("action",t),e)},e.multipartFormData=function(){return this.setAttribute("enctype","multipart/form-data"),e},e.post=function(t){return this.setAttribute("method","post"),this.setAttribute("action",t),e},e.get=function(e){this.setAttribute("method","get"),this.setAttribute("action",e)},e}),ce=O("input"),de=O("textarea"),he=de,pe=O("select"),fe=O("fieldset"),me=O("option"),be=O("legend"),ge=O("datalist"),ve=O("output"),ye=O("progress"),we=O("meter"),$e=O("button"),Ce=O("main"),Oe=O("section"),Se=O("article"),Ee=O("aside"),ke=O("nav"),Ae=O("figure"),Ie=O("figcaption"),Fe=O("header"),xe=O("footer"),De=O("img"),Re=function(e,t){return De({src:e,...t})},Te=O("details"),Ne=O("summary"),Le=O("dialog"),Pe=O("menu"),qe=O("ol"),Me=O("ul"),Be=O("li"),je=Be,Ve=qe,He=Me,We=O("audio"),ze=O("video"),_e=O("source"),Ue=O("track"),Je=O("canvas"),Ke=O("svg"),Qe=O("time"),Ge=O("data"),Xe=O("address"),Ye=O("kbd"),Ze=O("samp"),et=O("var"),tt=O("wbr"),nt=O("caption"),rt=O("table"),ot=O("thead"),it=O("tfoot"),st=O("tbody"),at=O("tr"),ut=at,lt=O("th"),ct=lt,dt=lt,ht=O("td"),pt=ht,ft=O("");var mt=Object.freeze({__proto__:null,Abbr:re,Address:Xe,Anchor:p,Article:Se,Aside:Ee,AsyncImg:function(e,t,n,r){const i=Re(t||e,n),s=new Image;return s.onload=()=>{h.isFunction(r)&&r(null,i),i.src=e},s.onerror=()=>{h.isFunction(r)&&r(new o("Image not found"))},h.isObservable(e)&&e.subscribe(e=>{s.src=e}),s.src=e,i},Audio:We,BaseImage:De,Blockquote:K,Br:z,Button:$e,Canvas:Je,Caption:nt,Checkbox:e=>ce({type:"checkbox",...e}),Cite:oe,Code:J,ColorInput:e=>ce({type:"color",...e}),Data:Ge,Datalist:ge,DateInput:e=>ce({type:"date",...e}),DateTimeInput:e=>ce({type:"datetime-local",...e}),Dd:ue,Del:Z,Details:Te,Dialog:Le,Div:R,Dl:se,Dt:ae,Em:G,EmailInput:e=>ce({type:"email",...e}),FieldSet:fe,FigCaption:Ie,Figure:Ae,FileInput:e=>ce({type:"file",...e}),Footer:xe,ForEach:function(e,t,r){const o=new p("ForEach"),i=o.endElement();o.startElement();let s=new Map,u=null;const l=new Set,c=e=>{for(const[t,n]of s.entries()){if(l.has(t))continue;const r=n.child?.deref();e&&r&&e.removeChild(r),n.indexObserver?.cleanup(),n.child=null,n.indexObserver=null,s.delete(n.keyId),u&&u.delete(n.keyId)}},d=(e,o)=>{const i=a(e,o,r);if(s.has(i)){const e=s.get(i);if(e.indexObserver?.set(o),e.isNew=!1,e.child?.deref())return i;s.delete(i)}try{const n=t.length>=2?m(o):null;let r=C.getChild(t(e,n));s.set(i,{keyId:i,isNew:!0,child:new WeakRef(r),indexObserver:n})}catch(e){throw n.error("ForEach",`Error creating element for key ${i}`,e),e}return i},f=()=>{const t=i.parentNode;if(!t)return;const n=h.isObservable(e)?e.val():e;if(l.clear(),Array.isArray(n))for(let e=0,t=n.length;e<t;e++){const t=d(n[e],e);l.add(t)}else for(const e in n){const t=d(n[e],e);l.add(t)}if(0===l.size)return o.removeChildren(),c(),void u?.clear();c(t),u&&0!==u.size?(()=>{let e=document.createDocumentFragment();const t=Array.from(l);Array.from(u);for(const n in t){const r=t[n],o=s.get(r);if(!o)continue;const i=o.child.deref();i&&e.appendChild(i)}o.replaceContent(e)})():(e=>{const t=document.createDocumentFragment();for(const e of l){const n=s.get(e);if(!n)continue;const r=n.child?.deref();r&&t.appendChild(r)}e.insertBefore(t,i)})(t),u?.clear(),u=new Set([...l])};return f(),h.isObservable(e)&&e.subscribe(f),o},ForEachArray:function(e,t,r,o={}){const i=new p("ForEach Array"),s=i.endElement(),u=i.startElement();let l=new Map,c=new WeakMap,d=0;const f=new WeakMap,b=()=>{i.removeChildren(),y(),d=0},g=(e,t)=>f.has(e)?f.get(e):a(e,t,r),v=(e,t=!0)=>{if(!e)return;const n=e.child?.deref();e.indexObserver?.deref()?.cleanup(),e.child=null,e.indexObserver=null,c.delete(e.item),f.delete(e.item),e.item=null,t&&(n?.remove(),l.delete(e.keyId))},y=()=>{for(const[e,t]of l.entries())v(t,!1);l.clear()},w=(e,r)=>{const o=g(e,r);if(l.has(o)){const e=l.get(o);e.indexObserver?.deref()?.set(r),e.isNew=!1;const t=e.child?.deref();if(t)return t;l.delete(o)}try{const n=t.length>=2?m(r):null;let i=C.getChild(t(e,n));return l.set(o,{keyId:o,isNew:!0,item:e,child:new WeakRef(i),indexObserver:n?new WeakRef(n):null}),f.set(e,o),h.isObject(e)&&c.set(e,i),i}catch(e){throw n.error("ForEach",`Error creating element for key ${o}`,e),e}},$=function(e,t){const n=l.get(e);if(!n)return null;const r=n.child?.deref();if(!r)return null;t?t.appendChild(r):r.remove()},O={toFragment(e,t=0){const n=document.createDocumentFragment();for(let t=0,r=e.length;t<r;t++)n.append(w(e[t],d)),d++;return n},add(e,t=0){setTimeout(()=>{i.appendElement(O.toFragment(e))},t)},replace(e){b(),O.add(e)},reOrder(e){let t=null;const n=document.createDocumentFragment();for(const r of e)t=c.get(r),t&&n.appendChild(t);t=null,i.appendElement(n,s)},removeOne(e,t){let n=c.get(e);n&&(n.remove(),c.delete(e),((e,t=!0)=>{v(l.get(e),t)})(g(e,t))),n=null},clear:b,merge(e){O.add(e,0)},push(e){let t=0;o.pushDelay&&(t=o.pushDelay(e)??0),O.add(e,t)},populate([e,t,n]){const r=document.createDocumentFragment();for(let o=0;o<t;o++){const t=n(o);e.push(t),r.append(w(t,o)),d++}i.appendChild(r),r.replaceChildren()},unshift(e){i.insertBefore(O.toFragment(e),u.nextSibling)},splice(e,t){const[n,r,...o]=e;let a=null;const u=document.createDocumentFragment();if(t.length>0){let e=g(t[0],n);if(1===t.length)$(e,u);else if(t.length>1){const r=function(e){const t=l.get(e);if(!t)return null;const n=t.child?.deref();return n||(v(t,!1),null)}(e);a=r?.previousSibling;for(let e=0;e<t.length;e++){const r=g(t[e],n+e);$(r,u)}}}else a=s;u.replaceChildren(),o&&o.length&&a&&i.insertBefore(O.toFragment(o),a.nextSibling)},reverse(e,t){O.reOrder(t)},sort(e,t){O.reOrder(t)},remove(e,t){O.removeOne(t)},pop(e,t){O.removeOne(t)},shift(e,t){O.removeOne(t)},swap(e,t){const n=s.parentNode;let r=c.get(t[0]),o=c.get(t[1]);if(!r||!o)return;const i=o.nextSibling;n.insertBefore(o,r),n.insertBefore(r,i),r=null,o=null}},S=(e,n,r)=>{if("populate"===r?.action)O.populate(r.args,r.result);else{if(console.log(d),"clear"===r.action||!e.length){if(0===d)return;b()}if(r?.action)O[r.action]&&O[r.action](r.args,r.result);else{if(0===d)return void O.add(e);O.replace(e)}}console.log(e),((e,n=0)=>{if(t.length<2)return;let r=n;for(let t=n,o=e?.length;t<o;t++){const n=l.get(g(e[t],t));n&&(n.indexObserver?.deref()?.set(r),r++)}})(e,0)};return S(e.val(),0,{action:null}),h.isObservable(e)&&e.subscribe(S),i},Form:le,Fragment:ft,H1:M,H2:B,H3:j,H4:V,H5:H,H6:W,Header:Fe,HiddenInput:e=>ce({type:"hidden",...e}),HideIf:function(e,t,n){const r=m(!e.val());return e.subscribe(e=>r.set(!e)),F(r,t,n)},HideIfNot:function(e,t,n){return F(e,t,n)},Hr:Q,Img:Re,Input:ce,Ins:ee,Kbd:Ye,Label:N,LazyImg:function(e,t){return Re(e,{...t,loading:"lazy"})},Legend:be,Li:je,Link:_,ListItem:Be,Main:Ce,Mark:Y,Match:x,Menu:Pe,Meter:we,MonthInput:e=>ce({type:"month",...e}),NativeDocumentFragment:p,Nav:ke,NumberInput:e=>ce({type:"number",...e}),Ol:Ve,Option:me,OrderedList:qe,Output:ve,P:L,Paragraph:P,PasswordInput:e=>ce({type:"password",...e}),Pre:U,Progress:ye,Quote:ie,Radio:e=>ce({type:"radio",...e}),RangeInput:e=>ce({type:"range",...e}),ReadonlyInput:e=>ce({readonly:!0,...e}),Samp:Ze,SearchInput:e=>ce({type:"search",...e}),Section:Oe,Select:pe,ShowIf:F,SimpleButton:(e,t)=>$e(e,{type:"button",...t}),Small:X,Source:_e,Span:T,Strong:q,Sub:te,SubmitButton:(e,t)=>$e(e,{type:"submit",...t}),Summary:Ne,Sup:ne,Svg:Ke,Switch:D,TBody:st,TBodyCell:pt,TFoot:it,TFootCell:dt,THead:ot,THeadCell:ct,TRow:ut,Table:rt,Td:ht,TelInput:e=>ce({type:"tel",...e}),TextArea:de,TextInput:he,Th:lt,Time:Qe,TimeInput:e=>ce({type:"time",...e}),Tr:at,Track:Ue,Ul:He,UnorderedList:Me,UrlInput:e=>ce({type:"url",...e}),Var:et,Video:ze,Wbr:tt,WeekInput:e=>ce({type:"week",...e}),When:function(e){if(!h.isObservable(e))throw new o("When : condition must be an Observable");let t=null,n=null;return{show(e){return t=e,this},otherwise:r=>(n=r,D(e,t,n))}}});const bt={};function gt(e,t,n={}){e="/"+u(e,"/");let r=null,o=n.name||null;const i=n.middlewares||[],s=n.shouldRebuild||!1,a=n.with||{},l={},c=[],d=e=>{if(!e)return null;const[t,n]=e.split(":");let r=a[t];return!r&&n&&(r=bt[n]),r||(r="[^/]+"),r=r.replace("(","(?:"),{name:t,pattern:`(${r})`}},h=()=>{if(r)return r;const t=e.replace(/\{(.*?)}/gi,(e,t)=>{const n=d(t);return n&&n.pattern?(l[n.name]=n.pattern,c.push(n.name),n.pattern):e});return r=new RegExp("^"+t+"$"),r};this.name=()=>o,this.component=()=>t,this.middlewares=()=>i,this.shouldRebuild=()=>s,this.path=()=>e,this.match=function(e){e="/"+u(e,"/");if(!h().exec(e))return!1;const t={};return h().exec(e).forEach((e,n)=>{if(n<1)return;const r=c[n-1];t[r]=e}),t},this.url=function(t){const n=e.replace(/\{(.*?)}/gi,(e,n)=>{const r=d(n);if(t.params&&t.params[r.name])return t.params[r.name];throw new Error(`Missing parameter '${r.name}'`)}),r="object"==typeof t.query?new URLSearchParams(t.query).toString():null;return(t.basePath?t.basePath:"")+(r?`${n}?${r}`:n)}}class vt extends Error{constructor(e,t){super(e),this.context=t}}const yt=(e,t)=>{const n=[];return e.forEach(e=>{n.push(u(e.suffix,"/"))}),n.push(u(t,"/")),n.join("/")},wt=(e,t)=>{const n=[];return e.forEach(e=>{e.options.middlewares&&n.push(...e.options.middlewares)}),t&&n.push(...t),n},$t=(e,t)=>{const n=[];return e.forEach(e=>{e.options?.name&&n.push(e.options.name)}),t&&n.push(t),n.join(".")};function Ct(){const e=[];let t=0;const n=n=>{const o=t+n;if(!e[o])return;t=o;const{route:i,params:s,query:a,path:u}=e[o];r(u)},r=e=>{window.location.replace(`${window.location.pathname}${window.location.search}#${e}`)},o=()=>window.location.hash.slice(1);this.push=function(n){const{route:i,params:s,query:a,path:u}=this.resolve(n);u!==o()&&(e.splice(t+1),e.push({route:i,params:s,query:a,path:u}),t++,r(u))},this.replace=function(n){const{route:r,params:i,query:s,path:a}=this.resolve(n);a!==o()&&(e[t]={route:r,params:i,query:s,path:a})},this.forward=function(){return t<e.length-1&&n(1)},this.back=function(){return t>0&&n(-1)},this.init=function(n){window.addEventListener("hashchange",()=>{const{route:e,params:t,query:n,path:r}=this.resolve(o());this.handleRouteChange(e,t,n,r)});const{route:r,params:i,query:s,path:a}=this.resolve(n||o());e.push({route:r,params:i,query:s,path:a}),t=0,this.handleRouteChange(r,i,s,a)}}function Ot(){this.push=function(e){try{const{route:t,path:n,params:r,query:o}=this.resolve(e);if(window.history.state&&window.history.state.path===n)return;window.history.pushState({name:t.name(),params:r,path:n},t.name()||n,n),this.handleRouteChange(t,r,o,n)}catch(e){n.error("HistoryRouter","Error in pushState",e)}},this.replace=function(e){const{route:t,path:r,params:o}=this.resolve(e);try{window.history.replaceState({name:t.name(),params:o,path:r},t.name()||r,r),this.handleRouteChange(t,o,{},r)}catch(e){n.error("HistoryRouter","Error in replaceState",e)}},this.forward=function(){window.history.forward()},this.back=function(){window.history.back()},this.init=function(e){window.addEventListener("popstate",e=>{try{if(!e.state||!e.state.path)return;const t=e.state.path,{route:n,params:r,query:o,path:i}=this.resolve(t);if(!n)return;this.handleRouteChange(n,r,o,i)}catch(e){n.error("HistoryRouter","Error in popstate event",e)}});const{route:t,params:r,query:o,path:i}=this.resolve(e||window.location.pathname+window.location.search);this.handleRouteChange(t,r,o,i)}}function St(){const e=[];let t=0;const n=n=>{const r=t+n;if(!e[r])return;t=r;const{route:o,params:i,query:s,path:a}=e[r];this.handleRouteChange(o,i,s,a)};this.push=function(n){const{route:r,params:o,query:i,path:s}=this.resolve(n);e[t]&&e[t].path===s||(e.splice(t+1),e.push({route:r,params:o,query:i,path:s}),t++,this.handleRouteChange(r,o,i,s))},this.replace=function(n){const{route:r,params:o,query:i,path:s}=this.resolve(n);e[t]={route:r,params:o,query:i,path:s},this.handleRouteChange(r,o,i,s)},this.forward=function(){return t<e.length-1&&n(1)},this.back=function(){return t>0&&n(-1)},this.init=function(n){const r=n||window.location.pathname+window.location.search,{route:o,params:i,query:s,path:a}=this.resolve(r);e.push({route:o,params:i,query:s,path:a}),t=0,this.handleRouteChange(o,i,s,a)}}const Et="default";function kt(e={}){const t=[],r={},o=[],i=[],s={route:null,params:null,query:null,path:null,hash:null};if("hash"===e.mode)Ct.apply(this,[]);else if("history"===e.mode)Ot.apply(this,[]);else{if("memory"!==e.mode)throw new vt("Invalid router mode "+e.mode);St.apply(this,[])}const a=function(e,t){for(const r of i)try{r(e),t&&t(e)}catch(e){n.warn("Route Listener","Error in listener:",e)}};this.routes=()=>[...t],this.currentState=()=>({...s}),this.add=function(e,n,i){const s=new gt(yt(o,e),n,{...i,middlewares:wt(o,i?.middlewares||[]),name:i?.name?$t(o,i.name):null});return t.push(s),s.name()&&(r[s.name()]=s),this},this.group=function(e,t,n){if(!h.isFunction(n))throw new vt("Callback must be a function");return o.push({suffix:e,options:t}),n(),o.pop(),this},this.generateUrl=function(e,t={},n={}){const o=r[e];if(!o)throw new vt(`Route not found for name: ${e}`);return o.url({params:t,query:n})},this.resolve=function(e){if(h.isJson(e)){const t=r[e.name];if(!t)throw new vt(`Route not found for name: ${e.name}`);return{route:t,params:e.params,query:e.query,path:t.url({...e})}}const[n,o]=e.split("?"),i="/"+u(n,"/");let s,a=null;for(const e of t)if(s=e.match(i),s){a=e;break}if(!a)throw new vt(`Route not found for url: ${n}`);const l={};if(o){const e=new URLSearchParams(o).entries();for(const[t,n]of e)l[t]=n}return{route:a,params:s,query:l,path:e}},this.subscribe=function(e){if(!h.isFunction(e))throw new vt("Listener must be a function");return i.push(e),()=>{i.splice(i.indexOf(e),1)}},this.handleRouteChange=function(e,t,n,r){s.route=e,s.params=t,s.query=n,s.path=r;const o=[...e.middlewares(),a];let i=0;const u={...s},l=e=>{if(i++,!(i>=o.length))return o[i](e||u,l)};return o[i](u,l)}}function At(e,t){const{to:n,href:r,...o}=e,i=n||r;if(h.isString(i)){const e=kt.get();return _({...o,href:i},t).nd.onPreventClick(()=>{e.push(i)})}const s=i.router||Et,a=kt.get(s);if(console.log(s),!a)throw new vt('Router not found "'+s+'" for link "'+i.name+'"');const u=a.generateUrl(i.name,i.params,i.query);return _({...o,href:u},t).nd.onPreventClick(()=>{a.push(u)})}kt.routers={},kt.create=function(t,r){if(!h.isFunction(r))throw n.error("Router","Callback must be a function",e),new vt("Callback must be a function");const o=new kt(t);return kt.routers[t.name||Et]=o,r(o),o.init(t.entry),o.mount=function(e){if(h.isString(e)){const t=document.querySelector(e);if(!t)throw new vt(`Container not found for selector: ${e}`);e=t}else if(!h.isElement(e))throw new vt("Container must be a string or an Element");return function(e,t){const n=new Map,r=function(e){t.innerHTML="",t.appendChild(e)},o=function(e){if(!e.route)return;const{route:t,params:o,query:i,path:s}=e;if(n.has(s)){const e=n.get(s);return void r(e)}const a=t.component()({params:o,query:i});n.set(s,a),r(a)};return e.subscribe(o),o(e.currentState()),t}(o,e)},o},kt.get=function(e){const t=kt.routers[e||Et];if(!t)throw new vt(`Router not found for name: ${e}`);return t},kt.push=function(e,t=null){return kt.get(t).push(e)},kt.replace=function(e,t=null){return kt.get(t).replace(e)},kt.forward=function(e=null){return kt.get(e).forward()},kt.back=function(e=null){return kt.get(e).back()},At.blank=function(e,t){return _({...e,target:"_blank"},t)};var It=Object.freeze({__proto__:null,Link:At,RouteParamPatterns:bt,Router:kt});return t.ArgTypes=E,t.ElementCreator=C,t.HtmlElementWrapper=O,t.Observable=m,t.Store=I,t.elements=mt,t.router=It,t.withValidation=k,t}({});
|
|
1
|
+
var NativeDocument=function(t){"use strict";let n={};n={log(){},warn(){},error(){},disable(){}};var r=n;const o=function(){let e=0;const t=new Map;return{register(n){const r=++e;return t.set(r,new WeakRef(n)),r},unregister(e){t.delete(e)},getObservableById:e=>t.get(e)?.deref(),cleanup(){for(const[e,n]of t){const e=n.deref();e&&e.cleanup()}t.clear()},cleanObservables(e){if(t.size<e)return;let n=0;for(const[e,r]of t)r.deref()||(t.delete(e),n++);n>0&&r.log("Memory Auto Clean",`๐งน Cleaned ${n} orphaned observables`)}}}();class i extends Error{constructor(e,t={}){super(e),this.name="NativeDocumentError",this.context=t,this.timestamp=(new Date).toISOString()}}function s(e,t){this.observable=e,this.checker=t,this.unSubscriptions=[]}function a(e){if(void 0===e)throw new i("ObservableItem requires an initial value");if(e instanceof a)throw new i("ObservableItem cannot be an Observable");this.$previousValue=e,this.$currentValue=e,this.$isCleanedUp=!1,this.$listeners=null,this.$watchers=null,this.$memoryId=o.register(this)}s.prototype.subscribe=function(e){const t=this.observable.subscribe(t=>{e&&e(this.checker(t))});return this.unSubscriptions.push(t),t},s.prototype.check=function(e){return this.observable.check(()=>e(this.val()))},s.prototype.val=function(){return this.checker&&this.checker(this.observable.val())},s.prototype.set=function(e){return this.observable.set(e)},s.prototype.trigger=function(){return this.observable.trigger()},s.prototype.cleanup=function(){return this.observable.cleanup()},Object.defineProperty(a.prototype,"$value",{get(){return this.$currentValue},set(e){this.set(e)},configurable:!0}),a.prototype.triggerListeners=function(e){const t=this.$listeners,n=this.$previousValue,r=this.$currentValue;if(e=e||{},t?.length)for(let o=0,i=t.length;o<i;o++)t[o](r,n,e)},a.prototype.triggerWatchers=function(){if(!this.$watchers)return;const e=this.$watchers,t=this.$previousValue,n=this.$currentValue;if(e.has(n)){e.get(n).forEach(e=>{e.ifTrue.called||(e.ifTrue.callback(),e.else.called=!1)})}if(e.has(t)){e.get(t).forEach(e=>{e.else.called||(e.else.callback(),e.ifTrue.called=!1)})}},a.prototype.trigger=function(e){this.triggerListeners(e),this.triggerWatchers()},a.prototype.set=function(e){const t="function"==typeof e?e(this.$currentValue):e;this.$currentValue!==t&&(this.$previousValue=this.$currentValue,this.$currentValue=t,this.trigger())},a.prototype.val=function(){return this.$currentValue},a.prototype.disconnectAll=function(){if(this.$listeners?.splice(0),this.$previousValue=null,this.$currentValue=null,this.$watchers)for(const[e,t]of this.$watchers){for(const e of t)e.ifTrue.callback=null,e.else.callback=null;t.clear()}this.$watchers?.clear(),this.$listeners=null,this.$watchers=null},a.prototype.cleanup=function(){o.unregister(this.$memoryId),this.disconnectAll(),this.$isCleanedUp=!0,delete this.$value},a.prototype.subscribe=function(e){if(this.$listeners=this.$listeners??[],this.$isCleanedUp)return r.warn("Observable subscription","โ ๏ธ Attempted to subscribe to a cleaned up observable."),()=>{};if("function"!=typeof e)throw new i("Callback must be a function");return this.$listeners.push(e),()=>this.unsubscribe(e)},a.prototype.on=function(e,t,n){this.$watchers=this.$watchers??new Map;let r=this.$watchers.get(e);r||(r=new Set,this.$watchers.set(e,r));let o={ifTrue:{callback:t,called:!1},else:{callback:n,called:!1}};return r.add(o),()=>{r?.delete(o),0===r.size&&this.$watchers?.delete(e),r=null,o=null}},a.prototype.unsubscribe=function(e){const t=this.$listeners.indexOf(e);t>-1&&this.$listeners.splice(t,1)},a.prototype.check=function(e){return new s(this,e)},a.prototype.get=a.prototype.check,a.prototype.toString=function(){return"{{#ObItem::("+this.$memoryId+")}}"};const u=(e,t,n)=>{if(p.isFunction(n))return n(e,t);if(p.isObservable(e)){const r=e.val();return r&&n?r[n]:t}return p.isObject(e)?e[n]??t:e},l=function(e,t){return e.replace(new RegExp(`^[${t}]+|[${t}]+$`,"g"),"")},c={mounted:new WeakMap,mountedSupposedSize:0,unmounted:new WeakMap,unmountedSupposedSize:0,observer:null,checkMutation:function(e){for(const t of e){if(c.mountedSupposedSize>0)for(const e of t.addedNodes){const t=c.mounted.get(e);t&&(t.inDom=!0,t.mounted&&t.mounted(e))}if(c.unmountedSupposedSize>0)for(const e of t.removedNodes){const t=c.unmounted.get(e);t&&(t.inDom=!1,t.unmounted&&!0===t.unmounted(e)&&(t.disconnect(),e.nd?.remove()))}}},watch:function(e,t=!1){let n={inDom:t,mounted:null,unmounted:null,disconnect:()=>{c.mounted.delete(e),c.unmounted.delete(e),c.mountedSupposedSize--,c.unmountedSupposedSize--,n=null}};return{disconnect:n.disconnect,mounted:t=>{n.mounted=t,c.mounted.set(e,n),c.mountedSupposedSize++},unmounted:t=>{n.unmounted=t,c.unmounted.set(e,n),c.unmountedSupposedSize++}}}};c.observer=new MutationObserver(c.checkMutation),c.observer.observe(document.body,{childList:!0,subtree:!0});const d=["Click","DblClick","MouseDown","MouseEnter","MouseLeave","MouseMove","MouseOut","MouseOver","MouseUp","Wheel","KeyDown","KeyPress","KeyUp","Blur","Change","Focus","Input","Invalid","Reset","Search","Select","Submit","Drag","DragEnd","DragEnter","DragLeave","DragOver","DragStart","Drop","AfterPrint","BeforePrint","BeforeUnload","Error","HashChange","Load","Offline","Online","PageHide","PageShow","Resize","Scroll","Unload","Abort","CanPlay","CanPlayThrough","DurationChange","Emptied","Ended","LoadedData","LoadedMetadata","LoadStart","Pause","Play","Playing","Progress","RateChange","Seeked","Seeking","Stalled","Suspend","TimeUpdate","VolumeChange","Waiting"];function h(e){this.$element=e,this.$observer=null}for(const e of d){const t=e.toLowerCase();h.prototype["on"+e]=function(e){return this.$element.addEventListener(t,e),this},h.prototype["onPrevent"+e]=function(e){return this.$element.addEventListener(t,function(t){t.preventDefault(),e(t)}),this},h.prototype["onStop"+e]=function(e){return this.$element.addEventListener(t,function(t){t.stopPropagation(),e(t)}),this},h.prototype["onPreventStop"+e]=function(e){return this.$element.addEventListener(t,function(t){t.stopPropagation(),t.preventDefault(),e(t)}),this}}h.prototype.ref=function(e,t){return e[t]=element,this},h.prototype.unmountChildren=function(){let e=this.$element;for(let t=0,n=e.children.length;t<n;t++){let n=e.children[t];n.$ndProx||n.nd?.remove(),n=null}return e=null,this},h.prototype.remove=function(){let e=this.$element;return e.nd.unmountChildren(),e.$ndProx=null,delete e.nd?.on?.prevent,delete e.nd?.on,delete e.nd,e=null,this},h.prototype.lifecycle=function(e){return this.$observer=this.$observer||c.watch(this.$element),e.mounted&&this.$observer.mounted(e.mounted),e.unmounted&&this.$observer.unmounted(e.unmounted),this},h.prototype.mounted=function(e){return this.lifecycle({mounted:e})},h.prototype.mounted=function(e){return this.lifecycle({unmounted:e})},h.prototype.htmlElement=function(){return this.$element},h.prototype.node=h.prototype.htmlElement;const p={isObservable:e=>e instanceof a||e instanceof s,isProxy:e=>e?.__isProxy__,isObservableChecker:e=>e instanceof s,isArray:e=>Array.isArray(e),isString:e=>"string"==typeof e,isNumber:e=>"number"==typeof e,isBoolean:e=>"boolean"==typeof e,isFunction:e=>"function"==typeof e,isAsyncFunction:e=>"function"==typeof e&&"AsyncFunction"===e.constructor.name,isObject:e=>"object"==typeof e,isJson:e=>"object"==typeof e&&null!==e&&"Object"===e.constructor.name&&!Array.isArray(e),isElement:e=>e instanceof HTMLElement||e instanceof DocumentFragment||e instanceof Text,isFragment:e=>e instanceof DocumentFragment,isStringOrObservable(e){return this.isString(e)||this.isObservable(e)},isValidChild(e){return null===e||this.isElement(e)||this.isObservable(e)||this.isNDElement(e)||["string","number","boolean"].includes(typeof e)},isNDElement:e=>e instanceof h,isValidChildren(e){Array.isArray(e)||(e=[e]);return 0===e.filter(e=>!this.isValidChild(e)).length},validateChildren(e){Array.isArray(e)||(e=[e]);const t=e.filter(e=>!this.isValidChild(e));if(t.length>0)throw new i(`Invalid children detected: ${t.map(e=>typeof e).join(", ")}`);return e},containsObservables:e=>!!e&&(p.isObject(e)&&Object.values(e).some(e=>p.isObservable(e))),containsObservableReference:e=>!(!e||"string"!=typeof e)&&/\{\{#ObItem::\([0-9]+\)\}\}/.test(e),validateAttributes(e){if(!e||"object"!=typeof e)return e;const t=[],n=Object.keys(e).filter(e=>t.includes(e));return n.length>0&&r.warn("Validator",`Reserved attributes found: ${n.join(", ")}`),e},validateEventCallback(e){if("function"!=typeof e)throw new i("Event callback must be a function")}};function f(e){const t=document.createDocumentFragment(),n=document.createComment("Anchor Start : "+e),o=document.createComment("/ Anchor End "+e);t.appendChild(n),t.appendChild(o),t.nativeInsertBefore=t.insertBefore,t.nativeAppendChild=t.appendChild;const i=function(e,n,r){e!==t?e.insertBefore(O.getChild(n),r):e.nativeInsertBefore(O.getChild(n),r)};return t.appendElement=function(e,n=null){o.parentNode!==t?o.parentNode?.insertBefore(e,n||o):o.parentNode.nativeInsertBefore(e,n||o)},t.appendChild=function(e,n=null){const s=o.parentNode;if(s){if(n=n??o,p.isArray(e)){const r=document.createDocumentFragment();for(let t=0,n=e.length;t<n;t++)r.appendChild(O.getChild(e[t]));return i(s,r,n),t}i(s,e,n)}else r.error("Anchor","Anchor : parent not found",e)},t.removeChildren=function(){const e=o.parentNode;if(e===t)return;if(e.firstChild===n&&e.lastChild===o)return void e.replaceChildren(n,o);let r,i=n.nextSibling;const s=document.createDocumentFragment();for(;i&&i!==o;)r=i.nextSibling,s.append(i),i=r;s.replaceChildren()},t.remove=function(){if(o.parentNode===t)return;let e,r=n.nextSibling;for(;r!==o;)e=r.nextSibling,t.nativeAppendChild(r),r=e},t.removeWithAnchors=function(){t.removeChildren(),n.remove(),o.remove()},t.replaceContent=function(e){const r=o.parentNode;r&&(r.firstChild!==n||r.lastChild!==o?(t.removeChildren(),r.insertBefore(e,o)):r.replaceChildren(n,e,o))},t.insertBefore=function(e,n=null){t.appendChild(e,n)},t.clear=function(){t.remove()},t.endElement=function(){return o},t.startElement=function(){return n},t}const m=["checked","selected","disabled","readonly","required","autofocus","multiple","autocomplete","hidden","contenteditable","spellcheck","translate","draggable","async","defer","autoplay","controls","loop","muted","download","reversed","open","default","formnovalidate","novalidate","scoped","itemscope","allowfullscreen","allowpaymentrequest","playsinline"];function b(e){return new a(e)}function g(e,t){for(let n in t){const r=t[n];p.isObservable(r)?(e.classList.toggle(n,r.val()),r.subscribe(t=>e.classList.toggle(n,t))):e.classList.toggle(n,r)}}function v(e,t){for(let n in t){const r=t[n];p.isObservable(r)?(e.style[n]=r.val(),r.subscribe(t=>{e.style[n]=t})):e.style[n]=r}}function y(e,t,n){const r=p.isObservable(n)?n.val():n;p.isBoolean(r)?e[t]=r:e[t]=r===e.value,p.isObservable(n)&&(["checked"].includes(t)&&e.addEventListener("input",()=>{p.isBoolean(r)?n.set(e[t]):n.set(e.value)}),n.subscribe(n=>{p.isBoolean(n)?e[t]=n:e[t]=n===e.value}))}function w(e,t,n){const r=n=>{"value"!==t?e.setAttribute(t,n):e.value=n};r(n.val()),n.subscribe(r),"value"===t&&e.addEventListener("input",()=>n.set(e.value))}b.getById=function(e){const t=o.getObservableById(parseInt(e));if(!t)throw new i("Observable.getById : No observable found with id "+e);return t},b.cleanup=function(e){e.cleanup()},b.autoCleanup=function(e=!1,t={}){if(!e)return;const{interval:n=6e4,threshold:r=100}=t;window.addEventListener("beforeunload",()=>{o.cleanup()}),setInterval(()=>o.cleanObservables(r),n)};const $=new Map;let C=null;const O={createTextNode:()=>(C||(C=document.createTextNode("")),C.cloneNode()),createObservableNode(e,t){const n=O.createTextNode();return t.subscribe(e=>n.nodeValue=String(e)),n.nodeValue=t.val(),e&&e.appendChild(n),n},createStaticTextNode(e,t){let n=O.createTextNode();return n.nodeValue=String(t),e&&e.appendChild(n),n},createElement(e){if(e){if($.has(e))return $.get(e).cloneNode();const t=document.createElement(e);return $.set(e,t),t.cloneNode()}return new f("Fragment")},processChildren(e,t){if(null===e)return;const n=Array.isArray(e)?e:[e];for(let e=0,r=n.length;e<r;e++){let r=this.getChild(n[e]);null!==r&&t.appendChild(r)}},getChild(e){if(null===e)return null;if(p.isString(e)&&p.isFunction(e.resolveObservableTemplate)&&(e=e.resolveObservableTemplate()),p.isString(e))return O.createStaticTextNode(null,e);if(p.isObservable(e))return O.createObservableNode(null,e);if(p.isArray(e)){const t=document.createDocumentFragment();for(let n=0,r=e.length;n<r;n++)t.appendChild(this.getChild(e[n]));return t}return p.isFunction(e)?this.getChild(e()):p.isElement(e)?e:p.isNDElement(e)?e.$element:O.createStaticTextNode(null,e)},processAttributes(e,t){p.isFragment(e)||t&&function(e,t){if(p.validateAttributes(t),!p.isObject(t))throw new i("Attributes must be an object");for(let n in t){const r=n.toLowerCase();let o=t[r];if(p.isString(o)&&p.isFunction(o.resolveObservableTemplate)&&(o=o.resolveObservableTemplate(),p.isArray(o))){const e=o.filter(e=>p.isObservable(e));o=b.computed(()=>o.map(e=>p.isObservable(e)?e.val():e).join(" ")||" ",e)}m.includes(r)?y(e,r,o):p.isObservable(o)?w(e,r,o):"class"===r&&p.isJson(o)?g(e,o):"style"===r&&p.isJson(o)?v(e,o):e.setAttribute(r,o)}}(e,t)},setup:(e,t,n)=>e};function S(e,t){const n=e.toLowerCase();return function(e,o=null){try{if(!p.isJson(e)){const t=o;o=e,e=t}const r=O.createElement(n),i="function"==typeof t?t(r):r;return O.processAttributes(i,e),O.processChildren(o,i),O.setup(i,e,t)}catch(e){r.error("ElementCreation",`Error creating ${n}`,e)}}}Object.defineProperty(HTMLElement.prototype,"nd",{get(){return this.$nd||(this.$nd=new h(this),this.$nd.nd=this.$nd),this.$nd}});class E extends Error{constructor(e,t){super(`${e}\n\n${t.join("\n")}\n\n`)}}const k={string:e=>({name:e,type:"string",validate:e=>p.isString(e)}),number:e=>({name:e,type:"number",validate:e=>p.isNumber(e)}),boolean:e=>({name:e,type:"boolean",validate:e=>p.isBoolean(e)}),observable:e=>({name:e,type:"observable",validate:e=>p.isObservable(e)}),element:e=>({name:e,type:"element",validate:e=>p.isElement(e)}),function:e=>({name:e,type:"function",validate:e=>p.isFunction(e)}),object:e=>({name:e,type:"object",validate:e=>p.isObject(e)}),objectNotNull:e=>({name:e,type:"object",validate:e=>p.isObject(e)&&null!==e}),children:e=>({name:e,type:"children",validate:e=>p.validateChildren(e)}),attributes:e=>({name:e,type:"attributes",validate:e=>p.validateAttributes(e)}),optional:e=>({...e,optional:!0}),oneOf:(e,...t)=>({name:e,type:"oneOf",types:t,validate:e=>t.some(t=>t.validate(e))})},A=(e,t,n="Function")=>{if(!p.isArray(t))throw new i("withValidation : argSchema must be an array");return function(...r){return((e,t,n="Function")=>{if(!t)return;const r=[],o=t.filter(e=>!e.optional).length;if(e.length<o&&r.push(`${n}: Expected at least ${o} arguments, got ${e.length}`),t.forEach((t,o)=>{const i=o+1,s=e[o];if(void 0!==s){if(!t.validate(s)){const e=s?.constructor?.name||typeof s;r.push(`${n}: Invalid argument '${t.name}' at position ${i}, expected ${t.type}, got ${e}`)}}else t.optional||r.push(`${n}: Missing required argument '${t.name}' at position ${i}`)}),r.length>0)throw new E("Argument validation failed",r)})(r,t,e.name||n),e.apply(this,r)}};Function.prototype.args=function(...e){return A(this,e)},Function.prototype.errorBoundary=function(e){return(...t)=>{try{return this.apply(this,t)}catch(t){return e(t)}}},String.prototype.use=function(e){const t=this;return b.computed(()=>t.replace(/\$\{(.*?)}/g,(t,n)=>{const r=e[n];return p.isObservable(r)?r.val():r}),Object.values(e))},String.prototype.resolveObservableTemplate=function(){return p.containsObservableReference(this)?this.split(/(\{\{#ObItem::\([0-9]+\)\}\})/g).filter(Boolean).map(e=>{if(!p.containsObservableReference(e))return e;const[t,n]=e.match(/\{\{#ObItem::\(([0-9]+)\)\}\}/);return b.getById(n)}):this.valueOf()};const I=["push","pop","shift","unshift","reverse","sort","splice"];b.array=function(e){if(!Array.isArray(e))throw new i("Observable.array : target must be an array");const t=b(e);I.forEach(e=>{t[e]=function(...n){const r=t.val()[e](...n);return t.trigger({action:e,args:n,result:r}),r}}),t.clear=function(){return t.$value.length=0,t.trigger({action:"clear"}),!0},t.merge=function(e){t.$value=[...t.$value,...e]},t.populateAndRender=function(e,n){t.trigger({action:"populate",args:[t.$value,e,n]})},t.remove=function(e){const n=t.$value.splice(e,1);return 0===n.length?[]:(t.trigger({action:"remove",args:[e],result:n[0]}),n)},t.swap=function(e,n){const r=t.$value,o=r.length;if(o<e||o<n)return!1;if(n<e){const t=e;e=n,n=t}const i=r[e],s=r[n];return r[e]=s,r[n]=i,t.trigger({action:"swap",args:[e,n],result:[i,s]}),!0},t.length=function(){return t.$value.length};return["map","filter","reduce","some","every","find","findIndex","concat"].forEach(e=>{t[e]=function(...n){return t.val()[e](...n)}}),t},b.batch=function(e){const t=b(0),n=function(){if(p.isAsyncFunction(e))return e(...arguments).then(()=>{t.trigger()}).catch(e=>{throw e});e(...arguments),t.trigger()};return n.$observer=t,n},b.init=function(e){const t={};for(const n in e){const r=e[n];p.isJson(r)?t[n]=b.init(r):p.isArray(r)?t[n]=b.array(r):t[n]=b(r)}const n=function(){};return new Proxy(t,{get:(e,r)=>"__isProxy__"===r||("$value"===r?function(){const e={};for(const n in t){const r=t[n];p.isObservable(r)?e[n]=r.val():p.isProxy(r)?e[n]=r.$value:e[n]=r}return e}():"$clone"===r?n:void 0!==e[r]?e[r]:void 0),set(e,t,n){void 0!==e[t]&&e[t].set(n)}})},b.value=function(e){if(p.isObservable(e))return e.val();if(p.isProxy(e))return e.$value;if(p.isArray(e)){const t=[];return e.forEach(e=>{t.push(b.value(e))}),t}return e},b.update=function(e,t){for(const n in t){const r=e[n],o=t[n];if(p.isObservable(r)){if(p.isArray(o)){b.update(r,o);continue}r.set(o)}else p.isProxy(r)?b.update(r,o):e[n]=o}},b.object=b.init,b.json=b.init,b.computed=function(e,t=[]){const n=new a(e()),r=()=>n.set(e());if(p.isFunction(t)){if(!p.isObservable(t.$observer))throw new i("Observable.computed : dependencies must be valid batch function");return t.$observer.subscribe(r),n}return t.forEach(e=>e.subscribe(r)),n};const F=function(){const e=new Map;return{use(t){const{observer:n,subscribers:r}=e.get(t),o=b(n.val()),i=n.subscribe(e=>o.set(e)),s=o.subscribe(e=>n.set(e));return o.destroy=()=>{i(),s(),o.cleanup()},r.add(o),o},follow(e){return this.use(e)},create(t,n){const r=b(n);return e.set(t,{observer:r,subscribers:new Set}),r},get(t){const n=e.get(t);return n?n.observer:null},getWithSubscribers:t=>e.get(t),delete(t){const n=e.get(t);n&&(n.observer.cleanup(),n.subscribers.forEach(e=>e.destroy()),n.observer.clear())}}}();const x=function(e,t,n=null){if(!p.isObservable(e))return r.warn("ShowIf","ShowIf : condition must be an Observable / "+n,e);const o=new f("Show if : "+(n||""));let i=null;const s=()=>i||(i=O.getChild(t),i);return e.val()&&o.appendChild(s()),e.subscribe(e=>{e?o.appendChild(s()):o.remove()}),o},D=function(e,t,n=!0){if(!p.isObservable(e))throw new i("Toggle : condition must be an Observable");const r=new f,o=new Map,s=function(e){if(n&&o.has(e))return o.get(e);let r=t[e];return r?(r=O.getChild(r),n&&o.set(e,r),r):null},a=e.val(),u=s(a);return u&&r.appendChild(u),e.subscribe(e=>{const t=s(e);r.remove(),t&&r.appendChild(t)}),r},R=function(e,t,n){if(!p.isObservable(e))throw new i("Toggle : condition must be an Observable");return D(e,{true:t,false:n})},T=S("div"),N=S("span"),L=S("label"),P=S("p"),q=P,B=S("strong"),M=S("h1"),j=S("h2"),V=S("h3"),H=S("h4"),W=S("h5"),z=S("h6"),_=S("br"),U=S("a"),J=S("pre"),K=S("code"),Q=S("blockquote"),G=S("hr"),X=S("em"),Y=S("small"),Z=S("mark"),ee=S("del"),te=S("ins"),ne=S("sub"),re=S("sup"),oe=S("abbr"),ie=S("cite"),se=S("q"),ae=S("dl"),ue=S("dt"),le=S("dd"),ce=S("form",function(e){return e.submit=function(t){return"function"==typeof t?(e.onSubmit(e=>{e.preventDefault(),t(e)}),e):(this.setAttribute("action",t),e)},e.multipartFormData=function(){return this.setAttribute("enctype","multipart/form-data"),e},e.post=function(t){return this.setAttribute("method","post"),this.setAttribute("action",t),e},e.get=function(e){this.setAttribute("method","get"),this.setAttribute("action",e)},e}),de=S("input"),he=S("textarea"),pe=he,fe=S("select"),me=S("fieldset"),be=S("option"),ge=S("legend"),ve=S("datalist"),ye=S("output"),we=S("progress"),$e=S("meter"),Ce=S("button"),Oe=S("main"),Se=S("section"),Ee=S("article"),ke=S("aside"),Ae=S("nav"),Ie=S("figure"),Fe=S("figcaption"),xe=S("header"),De=S("footer"),Re=S("img"),Te=function(e,t){return Re({src:e,...t})},Ne=S("details"),Le=S("summary"),Pe=S("dialog"),qe=S("menu"),Be=S("ol"),Me=S("ul"),je=S("li"),Ve=je,He=Be,We=Me,ze=S("audio"),_e=S("video"),Ue=S("source"),Je=S("track"),Ke=S("canvas"),Qe=S("svg"),Ge=S("time"),Xe=S("data"),Ye=S("address"),Ze=S("kbd"),et=S("samp"),tt=S("var"),nt=S("wbr"),rt=S("caption"),ot=S("table"),it=S("thead"),st=S("tfoot"),at=S("tbody"),ut=S("tr"),lt=ut,ct=S("th"),dt=ct,ht=ct,pt=S("td"),ft=pt,mt=S("");var bt=Object.freeze({__proto__:null,Abbr:oe,Address:Ye,Anchor:f,Article:Ee,Aside:ke,AsyncImg:function(e,t,n,r){const o=Te(t||e,n),s=new Image;return s.onload=()=>{p.isFunction(r)&&r(null,o),o.src=e},s.onerror=()=>{p.isFunction(r)&&r(new i("Image not found"))},p.isObservable(e)&&e.subscribe(e=>{s.src=e}),s.src=e,o},Audio:ze,BaseImage:Re,Blockquote:Q,Br:_,Button:Ce,Canvas:Ke,Caption:rt,Checkbox:e=>de({type:"checkbox",...e}),Cite:ie,Code:K,ColorInput:e=>de({type:"color",...e}),Data:Xe,Datalist:ve,DateInput:e=>de({type:"date",...e}),DateTimeInput:e=>de({type:"datetime-local",...e}),Dd:le,Del:ee,Details:Ne,Dialog:Pe,Div:T,Dl:ae,Dt:ue,Em:X,EmailInput:e=>de({type:"email",...e}),FieldSet:me,FigCaption:Fe,Figure:Ie,FileInput:e=>de({type:"file",...e}),Footer:De,ForEach:function(e,t,n){const o=new f("ForEach"),i=o.endElement();o.startElement();let s=new Map,a=null;const l=new Set,c=e=>{for(const[t,n]of s.entries()){if(l.has(t))continue;const r=n.child?.deref();e&&r&&e.removeChild(r),n.indexObserver?.cleanup(),n.child=null,n.indexObserver=null,s.delete(n.keyId),a&&a.delete(n.keyId)}},d=(e,o)=>{const i=u(e,o,n);if(s.has(i)){const e=s.get(i);if(e.indexObserver?.set(o),e.isNew=!1,e.child?.deref())return i;s.delete(i)}try{const n=t.length>=2?b(o):null;let r=O.getChild(t(e,n));s.set(i,{keyId:i,isNew:!0,child:new WeakRef(r),indexObserver:n})}catch(e){throw r.error("ForEach",`Error creating element for key ${i}`,e),e}return i},h=()=>{const t=i.parentNode;if(!t)return;const n=p.isObservable(e)?e.val():e;if(l.clear(),Array.isArray(n))for(let e=0,t=n.length;e<t;e++){const t=d(n[e],e);l.add(t)}else for(const e in n){const t=d(n[e],e);l.add(t)}if(0===l.size)return o.removeChildren(),c(),void a?.clear();c(t),a&&0!==a.size?(()=>{let e=document.createDocumentFragment();const t=Array.from(l);Array.from(a);for(const n in t){const r=t[n],o=s.get(r);if(!o)continue;const i=o.child.deref();i&&e.appendChild(i)}o.replaceContent(e)})():(e=>{const t=document.createDocumentFragment();for(const e of l){const n=s.get(e);if(!n)continue;const r=n.child?.deref();r&&t.appendChild(r)}e.insertBefore(t,i)})(t),a?.clear(),a=new Set([...l])};return h(),p.isObservable(e)&&e.subscribe(h),o},ForEachArray:function(e,t,n,o={}){const i=new f("ForEach Array"),s=i.endElement(),a=i.startElement();let l=new Map,c=new WeakMap,d=0;const h=new WeakMap,m=()=>{i.removeChildren(),y(),d=0},g=(e,t)=>h.has(e)?h.get(e):u(e,t,n),v=(e,t=!0)=>{if(!e)return;const n=e.child?.deref();e.indexObserver?.deref()?.cleanup(),e.child=null,e.indexObserver=null,c.delete(e.item),h.delete(e.item),e.item=null,t&&(n?.remove(),l.delete(e.keyId))},y=()=>{for(const[e,t]of l.entries())v(t,!1);l.clear()},w=(e,n)=>{const o=g(e,n);if(l.has(o)){const e=l.get(o);e.indexObserver?.deref()?.set(n),e.isNew=!1;const t=e.child?.deref();if(t)return t;l.delete(o)}try{const r=t.length>=2?b(n):null;let i=O.getChild(t(e,r));return l.set(o,{keyId:o,isNew:!0,item:e,child:new WeakRef(i),indexObserver:r?new WeakRef(r):null}),h.set(e,o),p.isObject(e)&&c.set(e,i),i}catch(e){throw r.error("ForEach",`Error creating element for key ${o}`,e),e}},$=function(e,t){const n=l.get(e);if(!n)return null;const r=n.child?.deref();if(!r)return null;t?t.appendChild(r):r.remove()},C={toFragment(e,t=0){const n=document.createDocumentFragment();for(let t=0,r=e.length;t<r;t++)n.append(w(e[t],d)),d++;return n},add(e,t=0){setTimeout(()=>{i.appendElement(C.toFragment(e))},t)},replace(e){m(),C.add(e)},reOrder(e){let t=null;const n=document.createDocumentFragment();for(const r of e)t=c.get(r),t&&n.appendChild(t);t=null,i.appendElement(n,s)},removeOne(e,t){let n=c.get(e);n&&(n.remove(),c.delete(e),((e,t=!0)=>{v(l.get(e),t)})(g(e,t))),n=null},clear:m,merge(e){C.add(e,0)},push(e){let t=0;o.pushDelay&&(t=o.pushDelay(e)??0),C.add(e,t)},populate([e,t,n]){const r=document.createDocumentFragment();for(let o=0;o<t;o++){const t=n(o);e.push(t),r.append(w(t,o)),d++}i.appendChild(r),r.replaceChildren()},unshift(e){i.insertBefore(C.toFragment(e),a.nextSibling)},splice(e,t){const[n,r,...o]=e;let a=null;const u=document.createDocumentFragment();if(t.length>0){let e=g(t[0],n);if(1===t.length)$(e,u);else if(t.length>1){const r=function(e){const t=l.get(e);if(!t)return null;const n=t.child?.deref();return n||(v(t,!1),null)}(e);a=r?.previousSibling;for(let e=0;e<t.length;e++){const r=g(t[e],n+e);$(r,u)}}}else a=s;u.replaceChildren(),o&&o.length&&a&&i.insertBefore(C.toFragment(o),a.nextSibling)},reverse(e,t){C.reOrder(t)},sort(e,t){C.reOrder(t)},remove(e,t){C.removeOne(t)},pop(e,t){C.removeOne(t)},shift(e,t){C.removeOne(t)},swap(e,t){const n=s.parentNode;let r=c.get(t[0]),o=c.get(t[1]);if(!r||!o)return;const i=o.nextSibling;n.insertBefore(o,r),n.insertBefore(r,i),r=null,o=null}},S=(e,n,r)=>{if("populate"===r?.action)C.populate(r.args,r.result);else{if(console.log(d),"clear"===r.action||!e.length){if(0===d)return;m()}if(r?.action)C[r.action]&&C[r.action](r.args,r.result);else{if(0===d)return void C.add(e);C.replace(e)}}console.log(e),((e,n=0)=>{if(t.length<2)return;let r=n;for(let t=n,o=e?.length;t<o;t++){const n=l.get(g(e[t],t));n&&(n.indexObserver?.deref()?.set(r),r++)}})(e,0)};return S(e.val(),0,{action:null}),p.isObservable(e)&&e.subscribe(S),i},Form:ce,Fragment:mt,H1:M,H2:j,H3:V,H4:H,H5:W,H6:z,Header:xe,HiddenInput:e=>de({type:"hidden",...e}),HideIf:function(e,t,n){const r=b(!e.val());return e.subscribe(e=>r.set(!e)),x(r,t,n)},HideIfNot:function(e,t,n){return x(e,t,n)},Hr:G,Img:Te,Input:de,Ins:te,Kbd:Ze,Label:L,LazyImg:function(e,t){return Te(e,{...t,loading:"lazy"})},Legend:ge,Li:Ve,Link:U,ListItem:je,Main:Oe,Mark:Z,Match:D,Menu:qe,Meter:$e,MonthInput:e=>de({type:"month",...e}),NativeDocumentFragment:f,Nav:Ae,NumberInput:e=>de({type:"number",...e}),Ol:He,Option:be,OrderedList:Be,Output:ye,P:P,Paragraph:q,PasswordInput:e=>de({type:"password",...e}),Pre:J,Progress:we,Quote:se,Radio:e=>de({type:"radio",...e}),RangeInput:e=>de({type:"range",...e}),ReadonlyInput:e=>de({readonly:!0,...e}),Samp:et,SearchInput:e=>de({type:"search",...e}),Section:Se,Select:fe,ShowIf:x,SimpleButton:(e,t)=>Ce(e,{type:"button",...t}),Small:Y,Source:Ue,Span:N,Strong:B,Sub:ne,SubmitButton:(e,t)=>Ce(e,{type:"submit",...t}),Summary:Le,Sup:re,Svg:Qe,Switch:R,TBody:at,TBodyCell:ft,TFoot:st,TFootCell:ht,THead:it,THeadCell:dt,TRow:lt,Table:ot,Td:pt,TelInput:e=>de({type:"tel",...e}),TextArea:he,TextInput:pe,Th:ct,Time:Ge,TimeInput:e=>de({type:"time",...e}),Tr:ut,Track:Je,Ul:We,UnorderedList:Me,UrlInput:e=>de({type:"url",...e}),Var:tt,Video:_e,Wbr:nt,WeekInput:e=>de({type:"week",...e}),When:function(e){if(!p.isObservable(e))throw new i("When : condition must be an Observable");let t=null,n=null;return{show(e){return t=e,this},otherwise:r=>(n=r,R(e,t,n))}}});const gt={};function vt(e,t,n={}){e="/"+l(e,"/");let r=null,o=n.name||null;const i=n.middlewares||[],s=n.shouldRebuild||!1,a=n.with||{},u={},c=[],d=e=>{if(!e)return null;const[t,n]=e.split(":");let r=a[t];return!r&&n&&(r=gt[n]),r||(r="[^/]+"),r=r.replace("(","(?:"),{name:t,pattern:`(${r})`}},h=()=>{if(r)return r;const t=e.replace(/\{(.*?)}/gi,(e,t)=>{const n=d(t);return n&&n.pattern?(u[n.name]=n.pattern,c.push(n.name),n.pattern):e});return r=new RegExp("^"+t+"$"),r};this.name=()=>o,this.component=()=>t,this.middlewares=()=>i,this.shouldRebuild=()=>s,this.path=()=>e,this.match=function(e){e="/"+l(e,"/");if(!h().exec(e))return!1;const t={};return h().exec(e).forEach((e,n)=>{if(n<1)return;const r=c[n-1];t[r]=e}),t},this.url=function(t){const n=e.replace(/\{(.*?)}/gi,(e,n)=>{const r=d(n);if(t.params&&t.params[r.name])return t.params[r.name];throw new Error(`Missing parameter '${r.name}'`)}),r="object"==typeof t.query?new URLSearchParams(t.query).toString():null;return(t.basePath?t.basePath:"")+(r?`${n}?${r}`:n)}}class yt extends Error{constructor(e,t){super(e),this.context=t}}const wt=(e,t)=>{const n=[];return e.forEach(e=>{n.push(l(e.suffix,"/"))}),n.push(l(t,"/")),n.join("/")},$t=(e,t)=>{const n=[];return e.forEach(e=>{e.options.middlewares&&n.push(...e.options.middlewares)}),t&&n.push(...t),n},Ct=(e,t)=>{const n=[];return e.forEach(e=>{e.options?.name&&n.push(e.options.name)}),t&&n.push(t),n.join(".")};function Ot(){const e=[];let t=0;const n=n=>{const o=t+n;if(!e[o])return;t=o;const{route:i,params:s,query:a,path:u}=e[o];r(u)},r=e=>{window.location.replace(`${window.location.pathname}${window.location.search}#${e}`)},o=()=>window.location.hash.slice(1);this.push=function(n){const{route:i,params:s,query:a,path:u}=this.resolve(n);u!==o()&&(e.splice(t+1),e.push({route:i,params:s,query:a,path:u}),t++,r(u))},this.replace=function(n){const{route:r,params:i,query:s,path:a}=this.resolve(n);a!==o()&&(e[t]={route:r,params:i,query:s,path:a})},this.forward=function(){return t<e.length-1&&n(1)},this.back=function(){return t>0&&n(-1)},this.init=function(n){window.addEventListener("hashchange",()=>{const{route:e,params:t,query:n,path:r}=this.resolve(o());this.handleRouteChange(e,t,n,r)});const{route:r,params:i,query:s,path:a}=this.resolve(n||o());e.push({route:r,params:i,query:s,path:a}),t=0,this.handleRouteChange(r,i,s,a)}}function St(){this.push=function(e){try{const{route:t,path:n,params:r,query:o}=this.resolve(e);if(window.history.state&&window.history.state.path===n)return;window.history.pushState({name:t.name(),params:r,path:n},t.name()||n,n),this.handleRouteChange(t,r,o,n)}catch(e){r.error("HistoryRouter","Error in pushState",e)}},this.replace=function(e){const{route:t,path:n,params:o}=this.resolve(e);try{window.history.replaceState({name:t.name(),params:o,path:n},t.name()||n,n),this.handleRouteChange(t,o,{},n)}catch(e){r.error("HistoryRouter","Error in replaceState",e)}},this.forward=function(){window.history.forward()},this.back=function(){window.history.back()},this.init=function(e){window.addEventListener("popstate",e=>{try{if(!e.state||!e.state.path)return;const t=e.state.path,{route:n,params:r,query:o,path:i}=this.resolve(t);if(!n)return;this.handleRouteChange(n,r,o,i)}catch(e){r.error("HistoryRouter","Error in popstate event",e)}});const{route:t,params:n,query:o,path:i}=this.resolve(e||window.location.pathname+window.location.search);this.handleRouteChange(t,n,o,i)}}function Et(){const e=[];let t=0;const n=n=>{const r=t+n;if(!e[r])return;t=r;const{route:o,params:i,query:s,path:a}=e[r];this.handleRouteChange(o,i,s,a)};this.push=function(n){const{route:r,params:o,query:i,path:s}=this.resolve(n);e[t]&&e[t].path===s||(e.splice(t+1),e.push({route:r,params:o,query:i,path:s}),t++,this.handleRouteChange(r,o,i,s))},this.replace=function(n){const{route:r,params:o,query:i,path:s}=this.resolve(n);e[t]={route:r,params:o,query:i,path:s},this.handleRouteChange(r,o,i,s)},this.forward=function(){return t<e.length-1&&n(1)},this.back=function(){return t>0&&n(-1)},this.init=function(n){const r=n||window.location.pathname+window.location.search,{route:o,params:i,query:s,path:a}=this.resolve(r);e.push({route:o,params:i,query:s,path:a}),t=0,this.handleRouteChange(o,i,s,a)}}const kt="default";function At(e={}){const t=[],n={},o=[],i=[],s={route:null,params:null,query:null,path:null,hash:null};if("hash"===e.mode)Ot.apply(this,[]);else if("history"===e.mode)St.apply(this,[]);else{if("memory"!==e.mode)throw new yt("Invalid router mode "+e.mode);Et.apply(this,[])}const a=function(e,t){for(const n of i)try{n(e),t&&t(e)}catch(e){r.warn("Route Listener","Error in listener:",e)}};this.routes=()=>[...t],this.currentState=()=>({...s}),this.add=function(e,r,i){const s=new vt(wt(o,e),r,{...i,middlewares:$t(o,i?.middlewares||[]),name:i?.name?Ct(o,i.name):null});return t.push(s),s.name()&&(n[s.name()]=s),this},this.group=function(e,t,n){if(!p.isFunction(n))throw new yt("Callback must be a function");return o.push({suffix:e,options:t}),n(),o.pop(),this},this.generateUrl=function(e,t={},r={}){const o=n[e];if(!o)throw new yt(`Route not found for name: ${e}`);return o.url({params:t,query:r})},this.resolve=function(e){if(p.isJson(e)){const t=n[e.name];if(!t)throw new yt(`Route not found for name: ${e.name}`);return{route:t,params:e.params,query:e.query,path:t.url({...e})}}const[r,o]=e.split("?"),i="/"+l(r,"/");let s,a=null;for(const e of t)if(s=e.match(i),s){a=e;break}if(!a)throw new yt(`Route not found for url: ${r}`);const u={};if(o){const e=new URLSearchParams(o).entries();for(const[t,n]of e)u[t]=n}return{route:a,params:s,query:u,path:e}},this.subscribe=function(e){if(!p.isFunction(e))throw new yt("Listener must be a function");return i.push(e),()=>{i.splice(i.indexOf(e),1)}},this.handleRouteChange=function(e,t,n,r){s.route=e,s.params=t,s.query=n,s.path=r;const o=[...e.middlewares(),a];let i=0;const u={...s},l=e=>{if(i++,!(i>=o.length))return o[i](e||u,l)};return o[i](u,l)}}function It(e,t){const{to:n,href:r,...o}=e,i=n||r;if(p.isString(i)){const e=At.get();return U({...o,href:i},t).nd.onPreventClick(()=>{e.push(i)})}const s=i.router||kt,a=At.get(s);if(console.log(s),!a)throw new yt('Router not found "'+s+'" for link "'+i.name+'"');const u=a.generateUrl(i.name,i.params,i.query);return U({...o,href:u},t).nd.onPreventClick(()=>{a.push(u)})}At.routers={},At.create=function(t,n){if(!p.isFunction(n))throw r.error("Router","Callback must be a function",e),new yt("Callback must be a function");const o=new At(t);return At.routers[t.name||kt]=o,n(o),o.init(t.entry),o.mount=function(e){if(p.isString(e)){const t=document.querySelector(e);if(!t)throw new yt(`Container not found for selector: ${e}`);e=t}else if(!p.isElement(e))throw new yt("Container must be a string or an Element");return function(e,t){const n=new Map,r=function(e){t.innerHTML="",t.appendChild(e)},o=function(e){if(!e.route)return;const{route:t,params:o,query:i,path:s}=e;if(n.has(s)){const e=n.get(s);return void r(e)}const a=t.component()({params:o,query:i});n.set(s,a),r(a)};return e.subscribe(o),o(e.currentState()),t}(o,e)},o},At.get=function(e){const t=At.routers[e||kt];if(!t)throw new yt(`Router not found for name: ${e}`);return t},At.push=function(e,t=null){return At.get(t).push(e)},At.replace=function(e,t=null){return At.get(t).replace(e)},At.forward=function(e=null){return At.get(e).forward()},At.back=function(e=null){return At.get(e).back()},It.blank=function(e,t){return U({...e,target:"_blank"},t)};var Ft=Object.freeze({__proto__:null,Link:It,RouteParamPatterns:gt,Router:At});return t.ArgTypes=k,t.ElementCreator=O,t.HtmlElementWrapper=S,t.NDElement=h,t.Observable=b,t.Store=F,t.elements=bt,t.router=Ft,t.withValidation=A,t}({});
|
package/docs/anchor.md
CHANGED
|
@@ -372,4 +372,7 @@ anchor.replaceContent(content2);
|
|
|
372
372
|
- **[List Rendering](list-rendering.md)** - (ForEach | ForEachArray) and dynamic lists
|
|
373
373
|
- **[Routing](routing.md)** - Navigation and URL management
|
|
374
374
|
- **[State Management](state-management.md)** - Global state patterns
|
|
375
|
+
- **[NDElement](native-document-element.md)** - Native Document Element
|
|
376
|
+
- **[Extending NDElement](extending-native-document-element.md)** - Custom Methods Guide
|
|
377
|
+
- **[Args Validation](validation.md)** - Function Argument Validation
|
|
375
378
|
- **[Memory Management](memory-management.md)** - Memory management
|
|
@@ -625,5 +625,8 @@ Now that you understand conditional rendering, explore these related topics:
|
|
|
625
625
|
- **[Routing](routing.md)** - Navigation and URL management
|
|
626
626
|
- **[State Management](state-management.md)** - Global state patterns
|
|
627
627
|
- **[Lifecycle Events](lifecycle-events.md)** - Lifecycle events
|
|
628
|
+
- **[NDElement](native-document-element.md)** - Native Document Element
|
|
629
|
+
- **[Extending NDElement](extending-native-document-element.md)** - Custom Methods Guide
|
|
630
|
+
- **[Args Validation](validation.md)** - Function Argument Validation
|
|
628
631
|
- **[Memory Management](memory-management.md)** - Memory management
|
|
629
632
|
- **[Anchor](anchor.md)** - Anchor
|
package/docs/core-concepts.md
CHANGED
|
@@ -510,5 +510,8 @@ Now that you understand NativeDocument's core concepts, explore these advanced t
|
|
|
510
510
|
- **[Routing](routing.md)** - Navigation and URL management
|
|
511
511
|
- **[State Management](state-management.md)** - Global state patterns
|
|
512
512
|
- **[Lifecycle Events](lifecycle-events.md)** - Lifecycle events
|
|
513
|
+
- **[NDElement](native-document-element.md)** - Native Document Element
|
|
514
|
+
- **[Extending NDElement](extending-native-document-element.md)** - Custom Methods Guide
|
|
515
|
+
- **[Args Validation](validation.md)** - Function Argument Validation
|
|
513
516
|
- **[Memory Management](memory-management.md)** - Memory management
|
|
514
517
|
- **[Anchor](anchor.md)** - Anchor
|
package/docs/elements.md
CHANGED
|
@@ -380,5 +380,8 @@ Now that you understand NativeDocument's elements, explore these advanced topics
|
|
|
380
380
|
- **[Routing](routing.md)** - Navigation and URL management
|
|
381
381
|
- **[State Management](state-management.md)** - Global state patterns
|
|
382
382
|
- **[Lifecycle Events](lifecycle-events.md)** - Lifecycle events
|
|
383
|
+
- **[NDElement](native-document-element.md)** - Native Document Element
|
|
384
|
+
- **[Extending NDElement](extending-native-document-element.md)** - Custom Methods Guide
|
|
385
|
+
- **[Args Validation](validation.md)** - Function Argument Validation
|
|
383
386
|
- **[Memory Management](memory-management.md)** - Memory management
|
|
384
387
|
- **[Anchor](anchor.md)** - Anchor
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
# Extending NDElement - Custom Methods Guide
|
|
2
|
+
|
|
3
|
+
NDElement is designed to be extensible, allowing developers to add custom methods that make their code more readable and maintainable. This guide shows how to create custom NDElement extensions for common patterns.
|
|
4
|
+
|
|
5
|
+
## Why Extend NDElement?
|
|
6
|
+
|
|
7
|
+
Extending NDElement allows you to:
|
|
8
|
+
- **Encapsulate common patterns** into reusable methods
|
|
9
|
+
- **Improve code readability** with domain-specific method names
|
|
10
|
+
- **Reduce boilerplate** by abstracting complex event handling
|
|
11
|
+
- **Create a consistent API** across your application
|
|
12
|
+
|
|
13
|
+
## Basic Extension Pattern
|
|
14
|
+
|
|
15
|
+
The simplest way to extend NDElement is by adding methods to its prototype:
|
|
16
|
+
|
|
17
|
+
```javascript
|
|
18
|
+
// Basic extension
|
|
19
|
+
NDElement.prototype.customMethod = function(/* parameters */) {
|
|
20
|
+
// Your logic here
|
|
21
|
+
return this; // Return 'this' for method chaining
|
|
22
|
+
};
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Common Extension Examples
|
|
26
|
+
|
|
27
|
+
### 1. Keyboard Event Shortcuts
|
|
28
|
+
|
|
29
|
+
Instead of writing complex keyboard event handlers, create semantic shortcuts:
|
|
30
|
+
|
|
31
|
+
```javascript
|
|
32
|
+
// Enter key handler
|
|
33
|
+
NDElement.prototype.onEnter = function(callback) {
|
|
34
|
+
this.$element.addEventListener('keyup', e => {
|
|
35
|
+
if (e.key === 'Enter') {
|
|
36
|
+
callback(e);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
return this;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// Escape key handler
|
|
43
|
+
NDElement.prototype.onEscape = function(callback) {
|
|
44
|
+
this.$element.addEventListener('keyup', e => {
|
|
45
|
+
if (e.key === 'Escape') {
|
|
46
|
+
callback(e);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
return this;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// Arrow keys handler
|
|
53
|
+
NDElement.prototype.onArrowKey = function(callback) {
|
|
54
|
+
this.$element.addEventListener('keydown', e => {
|
|
55
|
+
if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(e.key)) {
|
|
56
|
+
callback(e, e.key);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
return this;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// Usage
|
|
63
|
+
Input({ type: 'text' })
|
|
64
|
+
.nd.onEnter(e => console.log('Form submitted'))
|
|
65
|
+
.onEscape(e => e.target.blur())
|
|
66
|
+
.onArrowKey((e, direction) => console.log('Arrow pressed:', direction));
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 2. Form Validation Extensions
|
|
70
|
+
|
|
71
|
+
Create semantic validation methods:
|
|
72
|
+
|
|
73
|
+
```javascript
|
|
74
|
+
// Required field validation
|
|
75
|
+
NDElement.prototype.required = function(message = 'This field is required') {
|
|
76
|
+
this.$element.addEventListener('blur', e => {
|
|
77
|
+
const value = e.target.value.trim();
|
|
78
|
+
if (!value) {
|
|
79
|
+
this.showError(message);
|
|
80
|
+
} else {
|
|
81
|
+
this.clearError();
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
return this;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// Email validation
|
|
88
|
+
NDElement.prototype.email = function(message = 'Please enter a valid email') {
|
|
89
|
+
this.$element.addEventListener('blur', e => {
|
|
90
|
+
const email = e.target.value.trim();
|
|
91
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
92
|
+
if (email && !emailRegex.test(email)) {
|
|
93
|
+
this.showError(message);
|
|
94
|
+
} else {
|
|
95
|
+
this.clearError();
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
return this;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// Min length validation
|
|
102
|
+
NDElement.prototype.minLength = function(length, message) {
|
|
103
|
+
message = message || `Minimum ${length} characters required`;
|
|
104
|
+
this.$element.addEventListener('input', e => {
|
|
105
|
+
if (e.target.value.length < length && e.target.value.length > 0) {
|
|
106
|
+
this.showError(message);
|
|
107
|
+
} else {
|
|
108
|
+
this.clearError();
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
return this;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
// Error display helpers
|
|
115
|
+
NDElement.prototype.showError = function(message) {
|
|
116
|
+
this.clearError();
|
|
117
|
+
const errorElement = Span({
|
|
118
|
+
class: 'error-message',
|
|
119
|
+
style: 'color: red; font-size: 0.8rem'
|
|
120
|
+
}, message);
|
|
121
|
+
|
|
122
|
+
this.$element.parentNode.appendChild(errorElement);
|
|
123
|
+
this.$element.classList.add('error');
|
|
124
|
+
return this;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
NDElement.prototype.clearError = function() {
|
|
128
|
+
const parent = this.$element.parentNode;
|
|
129
|
+
const existingError = parent.querySelector('.error-message');
|
|
130
|
+
if (existingError) {
|
|
131
|
+
existingError.remove();
|
|
132
|
+
}
|
|
133
|
+
this.$element.classList.remove('error');
|
|
134
|
+
return this;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
// Usage
|
|
138
|
+
Input({ type: 'email', placeholder: 'Email' })
|
|
139
|
+
.nd.required()
|
|
140
|
+
.email();
|
|
141
|
+
|
|
142
|
+
Input({ type: 'password', placeholder: 'Password' })
|
|
143
|
+
.nd.required()
|
|
144
|
+
.minLength(8, 'Password must be at least 8 characters');
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### 3. Animation Extensions
|
|
148
|
+
|
|
149
|
+
Create smooth animation helpers:
|
|
150
|
+
|
|
151
|
+
```javascript
|
|
152
|
+
// Fade in animation
|
|
153
|
+
NDElement.prototype.fadeIn = function(duration = 300) {
|
|
154
|
+
this.$element.style.opacity = '0';
|
|
155
|
+
this.$element.style.transition = `opacity ${duration}ms ease-in-out`;
|
|
156
|
+
|
|
157
|
+
requestAnimationFrame(() => {
|
|
158
|
+
this.$element.style.opacity = '1';
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
return this;
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
// Fade out animation
|
|
165
|
+
NDElement.prototype.fadeOut = function(duration = 300, callback) {
|
|
166
|
+
this.$element.style.transition = `opacity ${duration}ms ease-in-out`;
|
|
167
|
+
this.$element.style.opacity = '0';
|
|
168
|
+
|
|
169
|
+
setTimeout(() => {
|
|
170
|
+
if (callback) callback();
|
|
171
|
+
}, duration);
|
|
172
|
+
|
|
173
|
+
return this;
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
// Slide down animation
|
|
177
|
+
NDElement.prototype.slideDown = function(duration = 300) {
|
|
178
|
+
const element = this.$element;
|
|
179
|
+
element.style.maxHeight = '0';
|
|
180
|
+
element.style.overflow = 'hidden';
|
|
181
|
+
element.style.transition = `max-height ${duration}ms ease-in-out`;
|
|
182
|
+
|
|
183
|
+
requestAnimationFrame(() => {
|
|
184
|
+
element.style.maxHeight = element.scrollHeight + 'px';
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
return this;
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
// Usage
|
|
191
|
+
Div("Animated content")
|
|
192
|
+
.nd.onClick(function() {
|
|
193
|
+
this.nd.fadeOut(300, () => this.remove());
|
|
194
|
+
});
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Best Practices
|
|
198
|
+
|
|
199
|
+
### 1. Always Return `this`
|
|
200
|
+
Enable method chaining by returning the NDElement instance:
|
|
201
|
+
|
|
202
|
+
```javascript
|
|
203
|
+
NDElement.prototype.myMethod = function() {
|
|
204
|
+
// Your logic here
|
|
205
|
+
return this; // Enable chaining
|
|
206
|
+
};
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### 2. Use Descriptive Method Names
|
|
210
|
+
Choose names that clearly describe what the method does:
|
|
211
|
+
|
|
212
|
+
```javascript
|
|
213
|
+
// Good
|
|
214
|
+
NDElement.prototype.onEnter = function(callback) { /* ... */ };
|
|
215
|
+
NDElement.prototype.fadeIn = function(duration) { /* ... */ };
|
|
216
|
+
|
|
217
|
+
// Avoid
|
|
218
|
+
NDElement.prototype.ke = function(callback) { /* ... */ }; // Unclear
|
|
219
|
+
NDElement.prototype.doStuff = function() { /* ... */ }; // Too vague
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### 3. Handle Edge Cases
|
|
223
|
+
Always consider edge cases and provide sensible defaults:
|
|
224
|
+
|
|
225
|
+
```javascript
|
|
226
|
+
NDElement.prototype.fadeIn = function(duration = 300) {
|
|
227
|
+
// Ensure duration is valid
|
|
228
|
+
duration = Math.max(0, parseInt(duration) || 300);
|
|
229
|
+
|
|
230
|
+
// Check if element exists
|
|
231
|
+
if (!this.$element) return this;
|
|
232
|
+
|
|
233
|
+
// Your animation logic
|
|
234
|
+
return this;
|
|
235
|
+
};
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### 4. Document Your Extensions
|
|
239
|
+
|
|
240
|
+
Always document your custom methods:
|
|
241
|
+
|
|
242
|
+
```javascript
|
|
243
|
+
/**
|
|
244
|
+
* Handles Enter key press events
|
|
245
|
+
* @param {Function} callback - Function to call when Enter is pressed
|
|
246
|
+
* @returns {NDElement} Returns this for method chaining
|
|
247
|
+
* @example
|
|
248
|
+
* Input().nd.onEnter(e => console.log('Enter pressed'));
|
|
249
|
+
*/
|
|
250
|
+
NDElement.prototype.onEnter = function(callback) {
|
|
251
|
+
this.$element.addEventListener('keyup', e => {
|
|
252
|
+
if (e.key === 'Enter') {
|
|
253
|
+
callback(e);
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
return this;
|
|
257
|
+
};
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
By extending NDElement thoughtfully, you can create a powerful, domain-specific API that makes your code more readable, maintainable, and enjoyable to work with.
|
|
261
|
+
|
|
262
|
+
## Next Steps
|
|
263
|
+
|
|
264
|
+
Explore these related topics to build complete applications:
|
|
265
|
+
|
|
266
|
+
- **[Args Validation](validation.md)** - Function Argument Validation
|
|
267
|
+
- **[Memory Management](memory-management.md)** - Memory management
|
|
268
|
+
- **[Anchor](anchor.md)** - Anchor
|
package/docs/getting-started.md
CHANGED
|
@@ -358,6 +358,9 @@ Now that you've built your first NativeDocument applications, explore these topi
|
|
|
358
358
|
- **[Routing](routing.md)** - Navigation and URL management
|
|
359
359
|
- **[State Management](state-management.md)** - Global state patterns
|
|
360
360
|
- **[Lifecycle Events](lifecycle-events.md)** - Lifecycle events
|
|
361
|
+
- **[NDElement](native-document-element.md)** - Native Document Element
|
|
362
|
+
- **[Extending NDElement](extending-native-document-element.md)** - Custom Methods Guide
|
|
363
|
+
- **[Args Validation](validation.md)** - Function Argument Validation
|
|
361
364
|
- **[Memory Management](memory-management.md)** - Memory management
|
|
362
365
|
- **[Anchor](anchor.md)** - Anchor
|
|
363
366
|
|
package/docs/lifecycle-events.md
CHANGED
|
@@ -98,6 +98,9 @@ document.body.appendChild(reusableComponent);
|
|
|
98
98
|
|
|
99
99
|
Now that you understand lifecycle events, explore these related topics:
|
|
100
100
|
|
|
101
|
+
- **[NDElement](native-document-element.md)** - Native Document Element
|
|
102
|
+
- **[Extending NDElement](extending-native-document-element.md)** - Custom Methods Guide
|
|
103
|
+
- **[Args Validation](validation.md)** - Function Argument Validation
|
|
101
104
|
- **[Memory Management](memory-management.md)** - Memory management
|
|
102
105
|
- **[Anchor](anchor.md)** - Anchor
|
|
103
106
|
|
package/docs/list-rendering.md
CHANGED
|
@@ -603,5 +603,11 @@ const DebugList = ForEachArray(items, (item, index) => {
|
|
|
603
603
|
Now that you understand list rendering, explore these related topics:
|
|
604
604
|
|
|
605
605
|
- **[Conditional Rendering](conditional-rendering.md)** - Show/hide content dynamically
|
|
606
|
+
- **[Routing](routing.md)** - Navigation and URL management
|
|
607
|
+
- **[State Management](state-management.md)** - Global state patterns
|
|
608
|
+
- **[Lifecycle Events](lifecycle-events.md)** - Lifecycle events
|
|
609
|
+
- **[NDElement](native-document-element.md)** - Native Document Element
|
|
610
|
+
- **[Extending NDElement](extending-native-document-element.md)** - Custom Methods Guide
|
|
611
|
+
- **[Args Validation](validation.md)** - Function Argument Validation
|
|
606
612
|
- **[State Management](state-management.md)** - Managing application state
|
|
607
613
|
- **[Memory Management](memory-management.md)** - Understanding cleanup and memory
|