@twobirds/microcomponents 0.1.19 → 0.1.21

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.
@@ -0,0 +1 @@
1
+ var t={d:(e,n)=>{for(var r in n)t.o(n,r)&&!t.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:n[r]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e)},e={};function n(){return!!window}function r(t){return t&&t.constructor&&t.constructor===Object}function s(t){let e={};return[...Object.keys(t)].sort().forEach((n=>{r(t[n])?e[n]=s(t[n]):e[n]=t[n]})),e}function a(t,e=!0){let n={};return[...Object.getOwnPropertyNames(t)].forEach((e=>{if(t[e]instanceof Object){const r=a(t[e],!1);n[e]={};for(const t in r)n[e+"."+t]=r[t]}else n[e]=t[e]})),e?s(n):n}function c(t,e){return JSON.stringify(a(t))===JSON.stringify(a(e))}function o(t,e={}){let n=t.constructor===String?t.split("."):t;if(e&&n[0]&&e[n[0]])return e[n[0]].constructor===Object&&n.length>1?o(n.splice(1),e[n[0]]):e[n[0]];console.warn("ns",n[0],"not in",e)}function i(t,e){var n=Array.from(arguments);if(n.length>2){for(;n.length>1;)n[0]=i(n[0],n[1]),n.splice(1,1);return n[0]}if("string"==typeof t)t.match(/\{[^\{\}]*\}/g)?.forEach((function(n){var r=o(n.substring(1,n.length-1),e);void 0!==r&&(t=t.replace(n,r))}));else if(r(t))switch(t.constructor){case Object:Object.keys(t).forEach((function(n){t.hasOwnProperty(n)&&(t[n]=i(t[n],e))}));break;case Array:t.forEach((function(n,r,s){s[r]=i(t[r],e)}))}return t}function l(t){return t.split("-").map((t=>t.charAt(0).toUpperCase()+t.slice(1))).join("")}function u(t,e){let n;return()=>{clearTimeout(n),n=setTimeout((function(){t(...arguments)}),e)}}function d(t){let e=document.createElement("template");return t=t.replace(/<([A-Za-z0-9\-]*)([^>\/]*)(\/>)/gi,"<$1$2></$1>"),e.innerHTML=t,e.content.normalize(),Array.from(e.content.childNodes)}function f(t,e){const n=Object.getOwnPropertyDescriptors(t);for(const[t,r]of Object.entries(n))("get"in r||"set"in r)&&Object.defineProperty(e,t,r)}function h(t){return"_mc"+t[0].toUpperCase()+t.substring(1)}function m(t,e,n,r=!1){return t.addEventListener(h(e),n,{capture:!1,once:r}),n}t.d(e,{DC:()=>O,MC:()=>v,Oc:()=>E,E_:()=>_,IT:()=>f,sg:()=>u,bD:()=>c,c2:()=>S,YO:()=>a,Rc:()=>F,tn:()=>N,qS:()=>d,Bd:()=>n,nz:()=>r,TK:()=>l,k5:()=>o,lB:()=>P,qg:()=>i,mf:()=>s});class p{stopped=!1;constructor(){}stop(){this.stopped=!0}}function b(t,e,n={},r="l",s){const a=/^_mc/.test(e)?e:h(e),c=s||new p,o=new CustomEvent(a,{detail:{data:n,control:c},bubbles:!1});c.stopped||/l/.test(r)&&(t.dispatchEvent(o),o.stopImmediatePropagation(),c.stopped)||/[ud]/.test(r)&&(-1===r.indexOf("l")&&(r+="l"),setTimeout((()=>{if(r.indexOf("u")>-1){let e=t.parentElement?.closest("[data-mc]");e&&e?._mc.trigger(a,n,r,c)}if(r.indexOf("d")>-1){let e=t._mc.children();e&&e.forEach((t=>t.trigger(a,n,r)))}}),0))}const g=new Function("try {return this===window;}catch(e){ return false;}");function y(t){return t&&t instanceof HTMLElement}class E{_target;constructor(t){var e;this._target=new WeakRef(t||{}),function(t){if(!g()||t.constructor===O)return;const e=t.target;if(e instanceof HTMLElement){let n=t;Object.getOwnPropertyNames(n.constructor.prototype).filter((t=>/^(on[A-Z]|one[A-Z])/.test(t)&&"function"==typeof n.constructor.prototype[t])).forEach((t=>{let r=/^one/.test(t),s=t.replace(/^on[e]{0,1}/,""),a=s.toLowerCase();if("on"+a in e){let r=e=>{n[t](e)};e.addEventListener(a,r)}else m(e,s,(e=>{n[t](e)}),r)}))}}(this),e=this,setTimeout((()=>{e.constructor!==O&&e.trigger("Init")}),0)}get target(){return this._target.deref()}}class v extends E{constructor(t){super(t)}}class O extends E{constructor(t){super(t)}static add(t,e,n={}){return function(t,e,n={}){let r=t;r._mc||(r._mc=new O(t));const s=r._mc;return e.length&&!s[e]&&(s[e]=n,t instanceof HTMLElement&&!t.getAttribute("data-mc")&&t.setAttribute("data-mc","")),r}(t,e,n)}static remove(t,e){!function(t,e){if(!e)return;const n=t?._mc||{};n&&n[e]&&delete n[e],!Object.keys(n).length&&t instanceof HTMLElement&&t.hasAttribute("data-mc")&&t.removeAttribute("data-mc")}(t,e)}off(t,e){!function(t,e,n){t.removeEventListener(h(e),n)}(this.target,t,e)}on(t,e){return m(this.target,t,e)}one(t,e){return function(t,e,n){return m(t,e,n,!0),n}(this.target,t,e)}trigger(t,e={},n="l",r){b(this.target,t,e,n,r)}ancestors(){let t=this?.target,e=[];if(!y(t))return[];for(;t=t.closest("[data-mc]");)t?._mc&&e.push(t?._mc);return e.length?e:null}closest(){let t=this.target;return y(t)&&t.closest("[data-mc]")?._mc||null}children(){let t=this?.target;return y(t)?function(t){const e=Math.random().toString().replace(".",""),n='[data-mc]:not([temp_id="'+e+'"] [data-mc] [data-mc])';t.setAttribute("temp_id",e);const r=[...t.querySelectorAll(n)].filter((t=>!!t._mc)).map((t=>t._mc));return t.removeAttribute("temp_id"),r.length?r:null}(t):null}descendants(){const t=this?.target;if(!y(t))return[];const e=[...t.querySelectorAll("[data-mc]")].filter((t=>!!t._mc)).map((t=>t._mc));return e.length?e:null}}const w=new Set;function A(t){return()=>{const e=Array.from(document.querySelectorAll(`[data-mc*="${t}"]`)).filter((t=>t instanceof HTMLElement));if(0===e.length)return;const n=customElements.get(t);e.forEach((e=>{try{O.add(e,n.name,new n(e))}catch(t){if(!n.create)throw`Class ${n.name} doesn't have a callable constructor AND class doesn't have a static .create() method.`;{let t=n.create(e);t.setAttribute("data-mc",e.getAttribute("data-mc")),e.replaceWith(t),e=t}}const r=e.getAttribute("data-mc").split(" ").filter((e=>e!==t&&""!==e)).join(" ").trim();e.setAttribute("data-mc",r)}))}}function C(t){if(w.has(t))return;w.add(t);const e="./"+t.split("-").join("/")+".js",n=document.createElement("script");n.setAttribute("src",e),n.setAttribute("blocking","render"),n.async=!0,n.setAttribute("type","module"),n.setAttribute("data-name",t),n.setAttribute("loading",""),customElements.whenDefined(t).then(A(t)),n.addEventListener("load",(e=>{w.delete(t),document.head.querySelector(`script[data-name="${t}"]`)?.remove()})),n.addEventListener("error",(t=>{console.error("could not load DC code from",e)})),document.head.append(n)}function k(){[...document.querySelectorAll(":not(:defined)")].filter((t=>!!t&&!customElements.get(t.tagName.toLowerCase())&&!w.has(t.tagName.toLowerCase()))).forEach((t=>{C(t.tagName.toLowerCase())})),[...document.querySelectorAll('[data-mc]:not([data-mc=""]')].filter((t=>!!t)).forEach((t=>{const e=t.getAttribute("data-mc")?.split(" ").filter((t=>""!==t));e?.forEach((t=>{const e=customElements.get(t);w.has(t)||e?e&&A(t)():C(t)}))}))}let j=null;function _(t=!0){return t?(j||(j=new MutationObserver(k),setTimeout((()=>{j.observe(document.body,{childList:!0,subtree:!0}),k()}),5),window.autoload=window.autoload||_),!0):(j&&(j.disconnect(),j=null),!1)}function S(t,e,n=[]){if(customElements.get(t))return void console.warn(`IGNORED: Custom element "${t}" is already defined!`);if(!t.includes("-"))throw new Error('createCustomElement: tagName must contain at least one hyphen ("-").');let r=l(t);e.prototype instanceof E?customElements.define(t,function(t,e){return Object.defineProperty(e,"name",{value:t})}(r,class extends HTMLElement{constructor(t){super(),O.add(this,r,new e(this,t))}connectedCallback(){this.dispatchEvent(new CustomEvent("_mcConnected"))}connectedMoveCallback(){this.dispatchEvent(new CustomEvent("_mcConnectedMove"))}disconnectedCallback(){this.dispatchEvent(new CustomEvent("_mcDisconnected"))}adoptedCallback(){this.dispatchEvent(new CustomEvent("_mcAdopted"))}attributeChangedCallback(t,e,n){this.dispatchEvent(new CustomEvent("_mcAttributeChanged",{detail:{name:t,oldValue:e,newValue:n}}))}formResetCallback(){this.dispatchEvent(new CustomEvent("_mcFormReset"))}static get observedAttributes(){return n}})):customElements.define(t,e)}function N(t){return customElements.get(t)}function T(t){return null!=t&&"object"==typeof t}function L(t){let e=new Set,n=/\{[^\{\}]*\}/g;return(t.getAttributeNames?t.getAttributeNames():[]).filter((e=>t.getAttribute(e)?.match(n))).forEach((r=>{new Set(t.getAttribute(r)?.match(n)).forEach((t=>e.add(t.replace(/[\{\}]/g,""))))})),[...t.childNodes].filter((t=>3===t.nodeType&&(t.nodeValue||"").match(n))).forEach((t=>{(t?.nodeValue||"").match(n).forEach((t=>e.add(t.replace(/[\{\}]/g,""))))})),[...e]}_.state=w;const D=[HTMLInputElement,HTMLSelectElement,HTMLTextAreaElement];class x extends O{data={};oldDisplay="";constructor(t){super(t),L(t).forEach((t=>this.data[t]="")),P(this),this.#t()}#t(){let t=this.target,e=!1;(t.getAttributeNames?t.getAttributeNames():[]).filter((e=>t.getAttribute(e)?.match(/\{[^\{\}]*\}/g))).forEach((e=>{let n=new Set(t.getAttribute(e)?.match(/\{[^\{\}]*\}/g));var r;this.data.subscribe((r=t.getAttribute(e),s=>{let a=r;n.forEach((t=>{a=a.replace(t,s[t.replace(/[\{\}]/g,"")])})),t.setAttribute(e,a)}))})),[...t.childNodes].filter((t=>3===t.nodeType&&(t.nodeValue||"").match(/\{[^\{\}]*\}/g))).forEach((n=>{e=!0;let r=new Set(n.nodeValue.match(/\{[^\{\}]*\}/g));this.data.subscribe((e=>s=>{let a=e;r.forEach((t=>{a=a.replace(t,s[t.replace(/[\{\}]/g,"")])})),this.oldDisplay?t.style=this.oldDisplay:t.removeAttribute("style"),delete this.oldDisplay,n.nodeValue=a})(n.nodeValue)),this.oldDisplay=t.getAttribute("style")||"",e&&!D.includes(t.constructor)&&"FIELDSET"!==t.tagName&&(t.style.display="none")}))}onData(t){let e={};Object.keys(t.detail.data).forEach((n=>{this.data.hasOwnProperty(n)&&(e[n]=t.detail.data[n])})),JSON.stringify(e)!==JSON.stringify(this.data)&&Object.assign(this.data,e)}}const M={};function q(t){let e=t.constructor.name;return M[e]||function(t){const e=t.constructor,n=e.name;let r=class extends e{#e=!0;#n=[];constructor(t){super(t),this.constructor.callbacks=[],T(t)&&Object.getOwnPropertyNames(t).forEach((e=>{this[e]=t[e]}))}get callbacks(){return this.#n}set callbacks(t){this.#n=t}subscribe(t){return this.#n.push(t),this}bind(t){if(T(this.valueOf())){!function(t){var e;(e=t,[e].concat([...e.querySelectorAll("*")]).filter((t=>!!L(t).length)).filter((t=>"STYLE"!==t?.tagName)).reverse()).forEach((t=>{t?._mc?._placeholders||O.add(t,"_placeholders",new x(t))}))}(t);const e=[t,...t.querySelectorAll("[data-mc]")].filter((t=>!!t?._mc?._placeholders)),n=function(t){let n=a(t);e.forEach((t=>{t&&b(t,"data",n)}))};this.#n.push(n),this.notify()}else console.warn("IGNORED - cannot bind a non-Object to the dom, IS:",typeof this.valueOf(),this);return this}notify(t){let e=T(this.valueOf())&&this.valueOf()instanceof Array==0?structuredClone(Object.assign({},this)):this.valueOf();return void 0!==t&&(this.#e=t),this.#e&&this.#n.forEach((t=>{t(e)})),this}};return M[n]=r,r}(t)}const P=(t,e)=>((e?[e]:[...Object.getOwnPropertyNames(t)]).forEach((e=>{if(t.hasOwnProperty(e)&&"function"!=typeof t[e]&&!t?.[e]?.constructor?.prototype?.subscribe){if("_"===e[0]||void 0===t?.[e])return t;let n=t[e],r=new(q(n))(n),s=u((function(){r.notify()}),0);Object.defineProperty(t,e,{enumerable:!0,get(){if(T(r.valueOf())){let t=structuredClone(Object.assign({},r));setTimeout((function(){c(structuredClone(Object.assign({},r)),t)||s()}),0)}return r},set(t){if(typeof t==typeof r.valueOf())if(T(r.valueOf())&&r.valueOf()instanceof Array==0)void 0===r?.constructor?.prototype?.subscribe&&(r=new(q(t))(structuredClone(Object.assign({},t))),f(t,r)),Object.assign(r,t),r.notify();else{let e=r.valueOf(),n=r.callbacks;t!==e&&(r=new(q(t))(t),r.callbacks=n,s())}else console.warn("IGNORED - cannot change observable types, IS:",typeof r.valueOf(),r,"- CANNOT BECOME:",typeof t)}}),t[e]=n}})),t);class I{constructor(t){}}class H extends I{#r;constructor(t){super(t),this.#r=t}get val(){return new FormData(this.#r.form).get(this.#r.name)}set val(t){[...this.#r.form.querySelectorAll(`input[type="radio"][name="${this.#r.name}"]`)].filter((e=>e.getAttribute("value")===t)).shift().checked=!0}}class V extends I{#r;constructor(t){super(t),this.#r=t}get val(){return this.#r.checked}set val(t){this.#r.checked=t}}class R extends I{#r;constructor(t){super(t),this.#r=t}get val(){return this.#r.value}set val(t){this.#r.value=t}}class $ extends I{#r;#s=!1;constructor(t){super(t),this.#r=t,this.#s=t.multiple}get val(){const t=[];return[...this.#r.querySelectorAll("option")].filter((t=>t.selected)).forEach((e=>{t.push(e.value)})),this.#s?t:t.length?t[0]:""}set val(t){t="string"==typeof t?[t]:t,[...this.#r.querySelectorAll("option")].forEach((e=>{t.indexOf(e.value)>-1?e.selected=!0:e.selected=!1}))}}class B extends I{#r;constructor(t){super(t),this.#r=t}get val(){return this.#r.value||""}set val(t){this.#r.value=t}}const z=t=>{let e=[...(t||document).querySelectorAll("input,select,textarea")],n={};return e.forEach((t=>{const e=t.getAttribute("name");if(e){let r=!1;switch((t=>t.tagName.toLowerCase())(t)){case"input":switch(t.type){case"radio":r=new H(t);break;case"checkbox":r=new V(t);break;default:r=new R(t)}break;case"select":r=new $(t);break;case"textarea":r=new B(t);break;default:console.warn("handler missing:",e,"for",t.tagName.toLowerCase(),t)}r&&(O.add(t,e,r),Object.defineProperty(n,e,{enumerable:!0,configurable:!0,get:()=>r.val,set:t=>{r.val!==t&&(r.val=t)}}))}})),n};function F(t,e,n){let r=z(n);t[e]=Object.assign({},r),P(t,e),f(r,t[e]),[...n.querySelectorAll("input, textarea, select")].forEach((n=>{n.addEventListener("input",(n=>{t[e].notify()}))}))}var G=e.DC,J=e.MC,Y=e.Oc,Z=e.E_,K=e.IT,U=e.sg,W=e.bD,Q=e.c2,X=e.YO,tt=e.Rc,et=e.tn,nt=e.qS,rt=e.Bd,st=e.nz,at=e.TK,ct=e.k5,ot=e.lB,it=e.qg,lt=e.mf;export{G as DC,J as MC,Y as McBase,Z as autoload,K as copyGettersSetters,U as debounce,W as deepEqual,Q as defineCE,X as flattenObject,tt as formValues,et as getCE,nt as htmlToElements,rt as isBrowser,st as isNativeObject,at as kebabToPascal,ct as nameSpace,ot as observe,it as parse,lt as sortObject};
@@ -0,0 +1,11 @@
1
+ import { LooseObject } from './helpers.js';
2
+ type Callback = (value: any) => void;
3
+ export type Observable = {
4
+ subscribe: (cb: Callback) => void;
5
+ notify: () => void;
6
+ bind: (target: HTMLElement | DocumentFragment | ShadowRoot) => void;
7
+ callbacks: Array<Function>;
8
+ };
9
+ export declare const observe: (target: LooseObject, propertyName?: string) => LooseObject;
10
+ export {};
11
+ //# sourceMappingURL=observables.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observables.d.ts","sourceRoot":"","sources":["../src/observables.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAA0D,MAAM,cAAc,CAAC;AAcnG,KAAK,QAAQ,GAAG,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;AA0MrC,MAAM,MAAM,UAAU,GAAG;IACxB,SAAS,EAAE,CAAC,EAAE,EAAE,QAAQ,KAAK,IAAI,CAAC;IAClC,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,IAAI,EAAE,CAAC,MAAM,EAAE,WAAW,GAAG,gBAAgB,GAAG,UAAU,KAAK,IAAI,CAAC;IACpE,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;CAC3B,CAAC;AAwJF,eAAO,MAAM,OAAO,WAAY,WAAW,iBAAiB,MAAM,KAAG,WA2EpE,CAAC"}
@@ -0,0 +1,228 @@
1
+ import { flattenObject, debounce, deepEqual, copyGettersSetters } from './helpers.js';
2
+ import { DC } from './MC.js';
3
+ import { trigger } from './events.js';
4
+ function isObservableObject(value) {
5
+ return value != null && typeof value === 'object';
6
+ }
7
+ function getPlaceholders(target) {
8
+ let placeholders = new Set(), regEx = /\{[^\{\}]*\}/g;
9
+ (target.getAttributeNames ? target.getAttributeNames() : [])
10
+ .filter((attr) => target.getAttribute(attr)?.match(regEx))
11
+ .forEach((attr) => {
12
+ let attrPlaceholders = new Set(target.getAttribute(attr)?.match(regEx));
13
+ attrPlaceholders.forEach((attrPlaceholder) => placeholders.add(attrPlaceholder.replace(/[\{\}]/g, '')));
14
+ });
15
+ [...target.childNodes]
16
+ .filter((childNode) => {
17
+ return (childNode.nodeType === 3 && (childNode.nodeValue || '').match(regEx));
18
+ })
19
+ .forEach((childNode) => {
20
+ let textContent = childNode?.nodeValue || '';
21
+ let contentPlaceholders = textContent.match(regEx);
22
+ contentPlaceholders.forEach((textNodePlaceholder) => placeholders.add(textNodePlaceholder.replace(/[\{\}]/g, '')));
23
+ });
24
+ return [...placeholders];
25
+ }
26
+ const inputs = [HTMLInputElement, HTMLSelectElement, HTMLTextAreaElement];
27
+ class Placeholders extends DC {
28
+ data = {};
29
+ oldDisplay = '';
30
+ constructor(target) {
31
+ super(target);
32
+ getPlaceholders(target).forEach((property) => (this.data[property] = ''));
33
+ observe(this);
34
+ this.#attachCallbacks();
35
+ }
36
+ #attachCallbacks() {
37
+ let target = this.target, hide = false;
38
+ (target.getAttributeNames ? target.getAttributeNames() : [])
39
+ .filter((attr) => target.getAttribute(attr)?.match(/\{[^\{\}]*\}/g))
40
+ .forEach((attr) => {
41
+ let placeholders = new Set(target.getAttribute(attr)?.match(/\{[^\{\}]*\}/g));
42
+ this.data.subscribe(((template) => (data) => {
43
+ let result = template;
44
+ placeholders.forEach((placeholder) => {
45
+ result = result.replace(placeholder, data[placeholder.replace(/[\{\}]/g, '')]);
46
+ });
47
+ target.setAttribute(attr, result);
48
+ })(target.getAttribute(attr)));
49
+ });
50
+ [...target.childNodes]
51
+ .filter((childNode) => {
52
+ return (childNode.nodeType === 3 && (childNode.nodeValue || '').match(/\{[^\{\}]*\}/g));
53
+ })
54
+ .forEach((childNode) => {
55
+ hide = true;
56
+ let placeholders = new Set(childNode.nodeValue.match(/\{[^\{\}]*\}/g));
57
+ this.data.subscribe(((template) => (data) => {
58
+ let result = template;
59
+ placeholders.forEach((placeholder) => {
60
+ result = result.replace(placeholder, data[placeholder.replace(/[\{\}]/g, '')]);
61
+ });
62
+ if (this.oldDisplay) {
63
+ target.style = this.oldDisplay;
64
+ }
65
+ else {
66
+ target.removeAttribute('style');
67
+ }
68
+ delete this.oldDisplay;
69
+ childNode.nodeValue = result;
70
+ })(childNode.nodeValue));
71
+ this.oldDisplay = target.getAttribute('style') || '';
72
+ if (hide &&
73
+ !inputs.includes(target.constructor) &&
74
+ target.tagName !== 'FIELDSET') {
75
+ target.style.display = 'none';
76
+ }
77
+ });
78
+ }
79
+ onData(ev) {
80
+ let data = {};
81
+ Object.keys(ev.detail.data).forEach((key) => {
82
+ if (this.data.hasOwnProperty(key))
83
+ data[key] = ev.detail.data[key];
84
+ });
85
+ if (JSON.stringify(data) !== JSON.stringify(this.data))
86
+ Object.assign(this.data, data);
87
+ }
88
+ }
89
+ function getPlaceholderElements(target) {
90
+ let elements = [target]
91
+ .concat([...target.querySelectorAll('*')])
92
+ .filter((e) => !!getPlaceholders(e).length)
93
+ .filter((e) => e?.tagName !== 'STYLE')
94
+ .reverse();
95
+ return elements;
96
+ }
97
+ function makePlaceholders(element) {
98
+ getPlaceholderElements(element).forEach((e) => {
99
+ if (e?._mc?._placeholders)
100
+ return;
101
+ DC.add(e, '_placeholders', new Placeholders(e));
102
+ });
103
+ }
104
+ const classRepo = {};
105
+ function makeObservable(val) {
106
+ const Constructor = val.constructor, ConstructorName = Constructor.name;
107
+ let ObservableClass = class extends Constructor {
108
+ #notify = true;
109
+ #callbacks = [];
110
+ constructor(val) {
111
+ super(val);
112
+ this.constructor.callbacks = [];
113
+ if (isObservableObject(val)) {
114
+ Object.getOwnPropertyNames(val).forEach((key) => {
115
+ this[key] = val[key];
116
+ });
117
+ }
118
+ }
119
+ get callbacks() {
120
+ return this.#callbacks;
121
+ }
122
+ set callbacks(callbacks) {
123
+ this.#callbacks = callbacks;
124
+ }
125
+ subscribe(callback) {
126
+ this.#callbacks.push(callback);
127
+ return this;
128
+ }
129
+ bind(target) {
130
+ const iso = isObservableObject(this.valueOf());
131
+ if (iso) {
132
+ makePlaceholders(target);
133
+ const placeholders = [target, ...target.querySelectorAll('[data-mc]')].filter((e) => !!e?._mc?._placeholders);
134
+ const func = function callback(data) {
135
+ let flattenedData = flattenObject(data);
136
+ placeholders.forEach((node) => {
137
+ if (!node)
138
+ return;
139
+ trigger(node, 'data', flattenedData);
140
+ });
141
+ };
142
+ this.#callbacks.push(func);
143
+ this.notify();
144
+ }
145
+ else {
146
+ console.warn('IGNORED - cannot bind a non-Object to the dom, IS:', typeof this.valueOf(), this);
147
+ }
148
+ return this;
149
+ }
150
+ notify(notify) {
151
+ let data = isObservableObject(this.valueOf()) && this.valueOf() instanceof Array === false
152
+ ? structuredClone(Object.assign({}, this))
153
+ : this.valueOf();
154
+ if (notify !== undefined) {
155
+ this.#notify = notify;
156
+ }
157
+ if (this.#notify) {
158
+ this.#callbacks.forEach((f) => {
159
+ f(data);
160
+ });
161
+ }
162
+ return this;
163
+ }
164
+ };
165
+ classRepo[ConstructorName] = ObservableClass;
166
+ return ObservableClass;
167
+ }
168
+ function getConstructor(val) {
169
+ let key = val.constructor.name;
170
+ return classRepo[key] || makeObservable(val);
171
+ }
172
+ export const observe = (target, propertyName) => {
173
+ let keys = !propertyName ? [...Object.getOwnPropertyNames(target)] : [propertyName];
174
+ keys.forEach((key) => {
175
+ if (target.hasOwnProperty(key) &&
176
+ typeof target[key] !== 'function' &&
177
+ !target?.[key]?.constructor?.prototype?.subscribe) {
178
+ if (key[0] === '_' || target?.[key] === undefined)
179
+ return target;
180
+ let val = target[key];
181
+ let o = new (getConstructor(val))(val);
182
+ let debouncedNotify = debounce(function debouncedNotify() {
183
+ o.notify();
184
+ }, 0);
185
+ Object.defineProperty(target, key, {
186
+ enumerable: true,
187
+ get() {
188
+ if (isObservableObject(o.valueOf())) {
189
+ let check = structuredClone(Object.assign({}, o));
190
+ setTimeout(function checkChanges() {
191
+ let state = structuredClone(Object.assign({}, o));
192
+ if (!deepEqual(state, check)) {
193
+ debouncedNotify();
194
+ }
195
+ }, 0);
196
+ }
197
+ return o;
198
+ },
199
+ set(val) {
200
+ if (typeof val === typeof o.valueOf()) {
201
+ let iso = isObservableObject(o.valueOf()) && o.valueOf() instanceof Array === false;
202
+ if (iso) {
203
+ if (o?.constructor?.prototype?.subscribe === undefined) {
204
+ o = new (getConstructor(val))(structuredClone(Object.assign({}, val)));
205
+ copyGettersSetters(val, o);
206
+ }
207
+ Object.assign(o, val);
208
+ o.notify();
209
+ }
210
+ else {
211
+ let old = o.valueOf(), callbacks = o.callbacks;
212
+ if (val !== old) {
213
+ o = new (getConstructor(val))(val);
214
+ o.callbacks = callbacks;
215
+ debouncedNotify();
216
+ }
217
+ }
218
+ }
219
+ else {
220
+ console.warn('IGNORED - cannot change observable types, IS:', typeof o.valueOf(), o, '- CANNOT BECOME:', typeof val);
221
+ }
222
+ },
223
+ });
224
+ target[key] = val;
225
+ }
226
+ });
227
+ return target;
228
+ };
@@ -0,0 +1 @@
1
+ var t={d:(e,r)=>{for(var n in r)t.o(r,n)&&!t.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:r[n]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e)},e={};function r(t){let e={};return[...Object.keys(t)].sort().forEach((n=>{var c;(c=t[n])&&c.constructor&&c.constructor===Object?e[n]=r(t[n]):e[n]=t[n]})),e}function n(t,e=!0){let c={};return[...Object.getOwnPropertyNames(t)].forEach((e=>{if(t[e]instanceof Object){const r=n(t[e],!1);c[e]={};for(const t in r)c[e+"."+t]=r[t]}else c[e]=t[e]})),e?r(c):c}function c(t){return"_mc"+t[0].toUpperCase()+t.substring(1)}function s(t,e,r,n=!1){return t.addEventListener(c(e),r,{capture:!1,once:n}),r}t.d(e,{l:()=>y});class a{stopped=!1;constructor(){}stop(){this.stopped=!0}}function o(t,e,r={},n="l",s){const o=/^_mc/.test(e)?e:c(e),i=s||new a,l=new CustomEvent(o,{detail:{data:r,control:i},bubbles:!1});i.stopped||/l/.test(n)&&(t.dispatchEvent(l),l.stopImmediatePropagation(),i.stopped)||/[ud]/.test(n)&&(-1===n.indexOf("l")&&(n+="l"),setTimeout((()=>{if(n.indexOf("u")>-1){let e=t.parentElement?.closest("[data-mc]");e&&e?._mc.trigger(o,r,n,i)}if(n.indexOf("d")>-1){let e=t._mc.children();e&&e.forEach((t=>t.trigger(o,r,n)))}}),0))}const i=new Function("try {return this===window;}catch(e){ return false;}");function l(t){return t&&t instanceof HTMLElement}class u{_target;constructor(t){var e;this._target=new WeakRef(t||{}),function(t){if(!i()||t.constructor===f)return;const e=t.target;if(e instanceof HTMLElement){let r=t;Object.getOwnPropertyNames(r.constructor.prototype).filter((t=>/^(on[A-Z]|one[A-Z])/.test(t)&&"function"==typeof r.constructor.prototype[t])).forEach((t=>{let n=/^one/.test(t),c=t.replace(/^on[e]{0,1}/,""),a=c.toLowerCase();if("on"+a in e){let n=e=>{r[t](e)};e.addEventListener(a,n)}else s(e,c,(e=>{r[t](e)}),n)}))}}(this),e=this,setTimeout((()=>{e.constructor!==f&&e.trigger("Init")}),0)}get target(){return this._target.deref()}}class f extends u{constructor(t){super(t)}static add(t,e,r={}){return function(t,e,r={}){let n=t;n._mc||(n._mc=new f(t));const c=n._mc;return e.length&&!c[e]&&(c[e]=r,t instanceof HTMLElement&&!t.getAttribute("data-mc")&&t.setAttribute("data-mc","")),n}(t,e,r)}static remove(t,e){!function(t,e){if(!e)return;const r=t?._mc||{};r&&r[e]&&delete r[e],!Object.keys(r).length&&t instanceof HTMLElement&&t.hasAttribute("data-mc")&&t.removeAttribute("data-mc")}(t,e)}off(t,e){!function(t,e,r){t.removeEventListener(c(e),r)}(this.target,t,e)}on(t,e){return s(this.target,t,e)}one(t,e){return function(t,e,r){return s(t,e,r,!0),r}(this.target,t,e)}trigger(t,e={},r="l",n){o(this.target,t,e,r,n)}ancestors(){let t=this?.target,e=[];if(!l(t))return[];for(;t=t.closest("[data-mc]");)t?._mc&&e.push(t?._mc);return e.length?e:null}closest(){let t=this.target;return l(t)&&t.closest("[data-mc]")?._mc||null}children(){let t=this?.target;return l(t)?function(t){const e=Math.random().toString().replace(".",""),r='[data-mc]:not([temp_id="'+e+'"] [data-mc] [data-mc])';t.setAttribute("temp_id",e);const n=[...t.querySelectorAll(r)].filter((t=>!!t._mc)).map((t=>t._mc));return t.removeAttribute("temp_id"),n.length?n:null}(t):null}descendants(){const t=this?.target;if(!l(t))return[];const e=[...t.querySelectorAll("[data-mc]")].filter((t=>!!t._mc)).map((t=>t._mc));return e.length?e:null}}function d(t){return null!=t&&"object"==typeof t}function h(t){let e=new Set,r=/\{[^\{\}]*\}/g;return(t.getAttributeNames?t.getAttributeNames():[]).filter((e=>t.getAttribute(e)?.match(r))).forEach((n=>{new Set(t.getAttribute(n)?.match(r)).forEach((t=>e.add(t.replace(/[\{\}]/g,""))))})),[...t.childNodes].filter((t=>3===t.nodeType&&(t.nodeValue||"").match(r))).forEach((t=>{(t?.nodeValue||"").match(r).forEach((t=>e.add(t.replace(/[\{\}]/g,""))))})),[...e]}new Set;const m=[HTMLInputElement,HTMLSelectElement,HTMLTextAreaElement];class p extends f{data={};oldDisplay="";constructor(t){super(t),h(t).forEach((t=>this.data[t]="")),y(this),this.#t()}#t(){let t=this.target,e=!1;(t.getAttributeNames?t.getAttributeNames():[]).filter((e=>t.getAttribute(e)?.match(/\{[^\{\}]*\}/g))).forEach((e=>{let r=new Set(t.getAttribute(e)?.match(/\{[^\{\}]*\}/g));var n;this.data.subscribe((n=t.getAttribute(e),c=>{let s=n;r.forEach((t=>{s=s.replace(t,c[t.replace(/[\{\}]/g,"")])})),t.setAttribute(e,s)}))})),[...t.childNodes].filter((t=>3===t.nodeType&&(t.nodeValue||"").match(/\{[^\{\}]*\}/g))).forEach((r=>{e=!0;let n=new Set(r.nodeValue.match(/\{[^\{\}]*\}/g));this.data.subscribe((e=>c=>{let s=e;n.forEach((t=>{s=s.replace(t,c[t.replace(/[\{\}]/g,"")])})),this.oldDisplay?t.style=this.oldDisplay:t.removeAttribute("style"),delete this.oldDisplay,r.nodeValue=s})(r.nodeValue)),this.oldDisplay=t.getAttribute("style")||"",e&&!m.includes(t.constructor)&&"FIELDSET"!==t.tagName&&(t.style.display="none")}))}onData(t){let e={};Object.keys(t.detail.data).forEach((r=>{this.data.hasOwnProperty(r)&&(e[r]=t.detail.data[r])})),JSON.stringify(e)!==JSON.stringify(this.data)&&Object.assign(this.data,e)}}const b={};function g(t){let e=t.constructor.name;return b[e]||function(t){const e=t.constructor,r=e.name;let c=class extends e{#e=!0;#r=[];constructor(t){super(t),this.constructor.callbacks=[],d(t)&&Object.getOwnPropertyNames(t).forEach((e=>{this[e]=t[e]}))}get callbacks(){return this.#r}set callbacks(t){this.#r=t}subscribe(t){return this.#r.push(t),this}bind(t){if(d(this.valueOf())){!function(t){var e;(e=t,[e].concat([...e.querySelectorAll("*")]).filter((t=>!!h(t).length)).filter((t=>"STYLE"!==t?.tagName)).reverse()).forEach((t=>{t?._mc?._placeholders||f.add(t,"_placeholders",new p(t))}))}(t);const e=[t,...t.querySelectorAll("[data-mc]")].filter((t=>!!t?._mc?._placeholders)),r=function(t){let r=n(t);e.forEach((t=>{t&&o(t,"data",r)}))};this.#r.push(r),this.notify()}else console.warn("IGNORED - cannot bind a non-Object to the dom, IS:",typeof this.valueOf(),this);return this}notify(t){let e=d(this.valueOf())&&this.valueOf()instanceof Array==0?structuredClone(Object.assign({},this)):this.valueOf();return void 0!==t&&(this.#e=t),this.#e&&this.#r.forEach((t=>{t(e)})),this}};return b[r]=c,c}(t)}const y=(t,e)=>((e?[e]:[...Object.getOwnPropertyNames(t)]).forEach((e=>{if(t.hasOwnProperty(e)&&"function"!=typeof t[e]&&!t?.[e]?.constructor?.prototype?.subscribe){if("_"===e[0]||void 0===t?.[e])return t;let r=t[e],c=new(g(r))(r),s=function(){let t;return()=>{clearTimeout(t),t=setTimeout((function(){!function(){c.notify()}(...arguments)}),0)}}();Object.defineProperty(t,e,{enumerable:!0,get(){if(d(c.valueOf())){let t=structuredClone(Object.assign({},c));setTimeout((function(){var e,r;e=structuredClone(Object.assign({},c)),r=t,JSON.stringify(n(e))!==JSON.stringify(n(r))&&s()}),0)}return c},set(t){if(typeof t==typeof c.valueOf())if(d(c.valueOf())&&c.valueOf()instanceof Array==0)void 0===c?.constructor?.prototype?.subscribe&&(c=new(g(t))(structuredClone(Object.assign({},t))),function(t,e){const r=Object.getOwnPropertyDescriptors(t);for(const[t,n]of Object.entries(r))("get"in n||"set"in n)&&Object.defineProperty(e,t,n)}(t,c)),Object.assign(c,t),c.notify();else{let e=c.valueOf(),r=c.callbacks;t!==e&&(c=new(g(t))(t),c.callbacks=r,s())}else console.warn("IGNORED - cannot change observable types, IS:",typeof c.valueOf(),c,"- CANNOT BECOME:",typeof t)}}),t[e]=r}})),t);var O=e.l;export{O as observe};
@@ -1,15 +1,29 @@
1
- 'use strict';
1
+ import { LooseObject, flattenObject, debounce, deepEqual, copyGettersSetters } from './helpers.js';
2
+ import { HTMLMcElement, DC } from './MC.js';
3
+ import { trigger } from './events.js';
2
4
 
3
- import { LooseObject, debounce, deepEqual, flattenObject, copyGettersSetters } from './helpers.js';
4
-
5
- import { DC, HTMLMcElement, trigger } from './MC.js';
5
+ /**
6
+ Determines if a value is an observable object.
6
7
 
8
+ @param value - The value to check.
9
+ @returns `true` if the value is a non-null object, otherwise `false`.
10
+ */
7
11
  function isObservableObject(value: any): boolean {
8
12
  return value != null && typeof value === 'object';
9
13
  }
10
14
 
11
15
  type Callback = (value: any) => void;
12
16
 
17
+ /**
18
+ Extracts placeholder names from an HTML element's attributes and text content.
19
+
20
+ Placeholders are strings enclosed in curly braces `{}`. This function scans
21
+ all attributes and direct child text nodes of the target element for placeholders
22
+ and returns them as an array of unique names (without braces).
23
+
24
+ @param target - The HTMLElement to scan for placeholders.
25
+ @returns An array of placeholder names found within the element's attributes and text content.
26
+ */
13
27
  function getPlaceholders(target: HTMLElement): string[] {
14
28
  let placeholders: Set<string> = new Set(),
15
29
  regEx = /\{[^\{\}]*\}/g;
@@ -18,8 +32,10 @@ function getPlaceholders(target: HTMLElement): string[] {
18
32
  (target.getAttributeNames ? target.getAttributeNames() : [])
19
33
  .filter((attr) => target.getAttribute(attr)?.match(regEx)) // extract placeholder(s)
20
34
  .forEach((attr) => {
21
- let placeholders: Set<string> = new Set(target.getAttribute(attr)?.match(regEx));
22
- placeholders.forEach((placeholder) => placeholders.add(placeholder.replace(/[\{\}]/g, '')));
35
+ let attrPlaceholders: Set<string> = new Set(target.getAttribute(attr)?.match(regEx));
36
+ attrPlaceholders.forEach((attrPlaceholder: string) =>
37
+ placeholders.add(attrPlaceholder.replace(/[\{\}]/g, ''))
38
+ );
23
39
  });
24
40
 
25
41
  // scan children text nodes
@@ -31,21 +47,38 @@ function getPlaceholders(target: HTMLElement): string[] {
31
47
  );
32
48
  })
33
49
  .forEach((childNode) => {
34
- ((childNode as any).nodeValue || '').match(regEx).forEach((placeholder: string) => {
35
- placeholders.add(placeholder.replace(/[\{\}]/g, ''));
36
- });
50
+ let textContent: string = childNode?.nodeValue || '';
51
+ let contentPlaceholders = textContent.match(regEx) as string[];
52
+ contentPlaceholders.forEach((textNodePlaceholder) =>
53
+ placeholders.add(textNodePlaceholder.replace(/[\{\}]/g, ''))
54
+ );
37
55
  });
38
56
 
39
- // extract {} and return result
40
- return [...placeholders].map((placeholder) => placeholder.replace(/[\{\}]/g, ''));
57
+ return [...placeholders];
41
58
  }
42
59
 
43
60
  const inputs = [HTMLInputElement, HTMLSelectElement, HTMLTextAreaElement];
44
61
 
62
+ /**
63
+ A class that manages placeholders within an HTML element and updates them dynamically.
64
+
65
+ This class extends `DC` (Data Controller) and processes the target element to identify
66
+ placeholder patterns in attributes and text nodes. It then observes changes on its internal
67
+ data object and updates the corresponding DOM locations when notified of changes.
68
+ */
45
69
  class Placeholders extends DC {
46
70
  data: LooseObject = {};
47
71
  oldDisplay?: string = '';
48
72
 
73
+ /**
74
+ Creates a new `Placeholders` instance for the given HTML element.
75
+
76
+ Initializes the internal data with empty strings for each placeholder
77
+ found in the target and starts observing the data object. Attaches
78
+ callbacks to update placeholders as needed.
79
+
80
+ @param target - The HTMLElement to process for placeholders.
81
+ */
49
82
  constructor(target: HTMLElement) {
50
83
  super(target);
51
84
  getPlaceholders(target).forEach((property) => (this.data[property] = ''));
@@ -63,7 +96,7 @@ class Placeholders extends DC {
63
96
  .forEach((attr: string) => {
64
97
  let placeholders: Set<string> = new Set(target.getAttribute(attr)?.match(/\{[^\{\}]*\}/g));
65
98
  // attach callback
66
- this.data.observe(
99
+ this.data.subscribe(
67
100
  ((template: string) => (data: LooseObject) => {
68
101
  let result: string = template;
69
102
  placeholders.forEach((placeholder) => {
@@ -91,7 +124,7 @@ class Placeholders extends DC {
91
124
  let placeholders: Set<string> = new Set(childNode.nodeValue.match(/\{[^\{\}]*\}/g));
92
125
 
93
126
  // attach callback
94
- this.data.observe(
127
+ this.data.subscribe(
95
128
  ((template: string) => (data: LooseObject) => {
96
129
  let result: string = template;
97
130
  placeholders.forEach((placeholder) => {
@@ -126,6 +159,14 @@ class Placeholders extends DC {
126
159
  });
127
160
  }
128
161
 
162
+ /**
163
+ Handles a `data` custom event to update the internal placeholder data.
164
+
165
+ Extracts matching keys from the event's detail data and updates only those
166
+ properties in the internal `data` object that were previously defined as placeholders.
167
+
168
+ @param ev - The CustomEvent containing new data to merge into the placeholders.
169
+ */
129
170
  onData(ev: CustomEvent) {
130
171
  let data: LooseObject = {};
131
172
  Object.keys(ev.detail.data).forEach((key) => {
@@ -135,6 +176,12 @@ class Placeholders extends DC {
135
176
  }
136
177
  }
137
178
 
179
+ /**
180
+ Finds all elements within a given scope that contain placeholders.
181
+
182
+ @param target - The HTMLElement, DocumentFragment, or ShadowRoot to search.
183
+ @returns An array of HTMLElements containing placeholder patterns.
184
+ */
138
185
  function getPlaceholderElements(
139
186
  target: HTMLElement | DocumentFragment | ShadowRoot
140
187
  ): HTMLElement[] {
@@ -146,6 +193,14 @@ function getPlaceholderElements(
146
193
  return elements as HTMLElement[];
147
194
  }
148
195
 
196
+ /**
197
+ Applies placeholder support to an element and its descendants.
198
+
199
+ This function scans the provided target for elements containing placeholders
200
+ and attaches a `Placeholders` controller instance to each one if not already present.
201
+
202
+ @param element - The HTMLElement, DocumentFragment, or ShadowRoot to process.
203
+ */
149
204
  function makePlaceholders(element: HTMLElement | DocumentFragment | ShadowRoot): void {
150
205
  getPlaceholderElements(element).forEach((e: HTMLElement) => {
151
206
  if ((e as HTMLMcElement)?._mc?._placeholders) return;
@@ -153,11 +208,17 @@ function makePlaceholders(element: HTMLElement | DocumentFragment | ShadowRoot):
153
208
  });
154
209
  }
155
210
 
211
+ /**
212
+ Interface representing an observable object that supports subscription, notification, and DOM binding.
213
+
214
+ Observable objects track registered callbacks and invoke them when their internal state changes.
215
+ They can also be bound to a DOM target to automatically update placeholder values in the view layer.
216
+ */
156
217
  export type Observable = {
157
- observe: (cb: Callback) => void;
158
- notify: () => void;
159
- bind: (target: HTMLElement | DocumentFragment | ShadowRoot) => void;
160
- callbacks: Array<Function>;
218
+ subscribe: (cb: Callback) => void; // Registers a callback function to be invoked when the observable is notified.
219
+ notify: () => void; // Notifies all registered callbacks with the current observable data.
220
+ bind: (target: HTMLElement | DocumentFragment | ShadowRoot) => void; // Binds the observable to a DOM target, setting up placeholder updates.
221
+ callbacks: Array<Function>; // Array of registered callback functions.
161
222
  };
162
223
 
163
224
  type Class<T> = new (...args: any[]) => T;
@@ -165,7 +226,15 @@ type Class<T> = new (...args: any[]) => T;
165
226
  // repository for observable class wrappers
166
227
  const classRepo: LooseObject = {};
167
228
 
168
- // creates a new observable class wrapper
229
+ /**
230
+ Creates a new observable wrapper class for the given value's constructor.
231
+
232
+ Returns a subclass of the original constructor that implements the Observable interface,
233
+ allowing observation and notification of changes. The new class is cached in `classRepo`.
234
+
235
+ @param val - The value whose constructor should be wrapped with observable behavior.
236
+ @returns A new Observable class that wraps the original constructor.
237
+ */
169
238
  function makeObservable(val: any): Class<typeof val> {
170
239
  const Constructor = val.constructor,
171
240
  ConstructorName: string = Constructor.name;
@@ -193,11 +262,27 @@ function makeObservable(val: any): Class<typeof val> {
193
262
  this.#callbacks = callbacks;
194
263
  }
195
264
 
196
- observe(callback: Function) {
265
+ /**
266
+ Registers a callback function to be invoked when the observable object is notified.
267
+
268
+ @param callback - The function to invoke on notification.
269
+ @returns This instance for chaining.
270
+ */
271
+ subscribe(callback: Function) {
197
272
  this.#callbacks.push(callback);
198
273
  return this;
199
274
  }
200
275
 
276
+ /**
277
+ Binds the observable to a DOM target, setting up placeholder updates and
278
+ triggering initial callbacks.
279
+
280
+ Scans the target and its descendants for placeholders and registers handlers
281
+ to update them with flattened data on notification.
282
+
283
+ @param target - The HTMLElement, DocumentFragment, or ShadowRoot to bind.
284
+ @returns This instance for chaining.
285
+ */
201
286
  bind(target: HTMLElement | DocumentFragment | ShadowRoot) {
202
287
  const iso = isObservableObject(this.valueOf());
203
288
 
@@ -229,6 +314,15 @@ function makeObservable(val: any): Class<typeof val> {
229
314
  return this;
230
315
  }
231
316
 
317
+ /**
318
+ Notifies registered callbacks with the current observable data.
319
+
320
+ Clones the internal value (if it's an object and not an array) before passing
321
+ to callbacks. Respects the internal `#notify` flag that can suppress notifications.
322
+
323
+ @param notify - Optional boolean override for the notification state.
324
+ @returns This instance for chaining.
325
+ */
232
326
  notify(notify?: boolean) {
233
327
  let data =
234
328
  isObservableObject(this.valueOf()) && this.valueOf() instanceof Array === false
@@ -255,11 +349,28 @@ function makeObservable(val: any): Class<typeof val> {
255
349
  return ObservableClass;
256
350
  }
257
351
 
352
+ /**
353
+ Retrieves or creates an observable wrapper class for the given value.
354
+
355
+ @param val - The value whose constructor should be wrapped with observable behavior.
356
+ @returns A class that wraps the original constructor and implements observable functionality.
357
+ */
258
358
  function getConstructor(val: any): Class<typeof val> {
259
359
  let key: string = val.constructor.name;
260
360
  return classRepo[key] || makeObservable(val);
261
361
  }
262
362
 
363
+ /**
364
+ Makes a target object's properties observable by replacing them with wrapped values.
365
+
366
+ Wraps each property of `target` that is not already observable (and meets criteria)
367
+ in an observable wrapper. Also sets up deep change detection for objects and
368
+ debounced notifications when the data changes.
369
+
370
+ @param target - The LooseObject whose properties should be made observable.
371
+ @param propertyName - Optional specific property name to make one property observable instead of all properties.
372
+ @returns The original target object, now with observable properties.
373
+ */
263
374
  export const observe = (target: LooseObject, propertyName?: string): LooseObject => {
264
375
  let keys = !propertyName ? [...Object.getOwnPropertyNames(target)] : [propertyName];
265
376
 
@@ -267,7 +378,7 @@ export const observe = (target: LooseObject, propertyName?: string): LooseObject
267
378
  if (
268
379
  target.hasOwnProperty(key) &&
269
380
  typeof target[key] !== 'function' &&
270
- !target?.[key]?.constructor?.prototype?.observe
381
+ !target?.[key]?.constructor?.prototype?.subscribe
271
382
  ) {
272
383
  if (key[0] === '_' || target?.[key] === undefined) return target;
273
384
  let val: any = target[key];
@@ -297,7 +408,7 @@ export const observe = (target: LooseObject, propertyName?: string): LooseObject
297
408
  let iso = isObservableObject(o.valueOf()) && o.valueOf() instanceof Array === false;
298
409
  if (iso) {
299
410
  // is observable object
300
- if (o?.constructor?.prototype?.observe === undefined) {
411
+ if (o?.constructor?.prototype?.subscribe === undefined) {
301
412
  // not observed yet
302
413
  o = new (getConstructor(val) as Class<typeof val>)(
303
414
  structuredClone(Object.assign({}, val))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twobirds/microcomponents",
3
- "version": "0.1.19",
3
+ "version": "0.1.21",
4
4
  "description": "Micro Components Organization Class",
5
5
  "main": "./dist/microcomponents.ts",
6
6
  "types": "./dist/microcomponents.d.ts",
@@ -16,14 +16,14 @@
16
16
  "sideEffects": false,
17
17
  "scripts": {
18
18
  "format": "prettier --write \"src/**/*.{ts,js}\"",
19
- "lint": "eslint \"src/**/*.{ts,js}\" --fix > eslint.log",
20
- "typedoc": "typedoc",
19
+ "lint": "eslint \"src/**/*.ts\" --fix > eslint.log",
20
+ "typedoc": "typedoc || true",
21
21
  "webpack": "webpack",
22
22
  "clean": "rm -rf build/*; rm -rf dist/*; rm -rf public/*;",
23
- "prep": "cp -R src/* build || true; mkdir public || true; npm run typedoc; npm run format; npm run lint;",
24
- "copyToDist": "cp build/*.js dist; cp public/microcomponents.min.js public/test; cp -R build/*.ts* dist; cp *.svg dist;",
25
- "copyToPublic1": "cp dist/*.* public; cp dist/*.* public/test;",
26
- "copyToPublic2": "cp -R assets/* public || true; cp -R build/src/* public/; cp dist/MicroComponents.svg public; cp public/MicroComponents.svg public/test;",
23
+ "prep": " mkdir build || true; cp -r src/* build/ || true; mkdir public || true; npm run format; npm run lint;",
24
+ "copyToDist": "cp build/*.js dist; cp -r build/*.ts* dist; cp *.svg dist;",
25
+ "copyToPublic1": "cp -r build/test public; cp build/* public/test/; cp build/* public; cp -r assets/* public || true; cp -r build/src/test/* public/test || true;",
26
+ "copyToPublic2": "cp dist/MicroComponents.svg public; cp public/MicroComponents.svg public/test;",
27
27
  "build": "npm run clean; npm run prep; tsc; npm run webpack; npm run copyToDist; npm run copyToPublic1; npm run copyToPublic2;",
28
28
  "dev": "cd public; php -S 0.0.0.0:10000; cd ..",
29
29
  "doc": "cd public/typedoc; php -S 0.0.0.0:11000; cd ../..",