-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDomKit.min.js
More file actions
5 lines (5 loc) · 9.95 KB
/
Copy pathDomKit.min.js
File metadata and controls
5 lines (5 loc) · 9.95 KB
1
2
3
4
5
/**
* DomKit - A minimalist front-end renderer with component support
* Version: v1.1.0
*/
const DomKit=function(){let e=new Map,t=new Map,n=new Map,r="",o="/components/";function i(t){return e.has(t)&&(e.delete(t),console.log(`Component unloaded: ${t}`)),!0}function s(){let t=Array.from(e.keys());return t.forEach(e=>i(e)),t}function l(i){if(e.has(i))return Promise.resolve(e.get(i));if(n.has(i))return n.get(i);if(!t.has(i))return Promise.reject(Error(`Component "${i}" is not registered.`));let s=new Promise((s,l)=>{let a=t.get(i),p=`${r}${o}${a}`,d=document.createElement("script");d.src=p,d.onload=()=>{if(window.__domkitComponents&&window.__domkitComponents[i]){let t=window.__domkitComponents[i];e.set(i,t),n.delete(i),s(t)}else n.delete(i),l(Error(`Component "${i}" was not properly exported.`))},d.onerror=()=>{n.delete(i),l(Error(`Failed to load component: ${i} from ${p}`))},document.head.appendChild(d)});return n.set(i,s),s}function a(t){return e.has(t)}function p(e,n){return t.set(e,n),!0}let d=(n,r={},o=[])=>{if("function"==typeof n)try{return n({...r,children:o})}catch(i){return console.error("Component render error:",i),d("div",{className:"error"},["Component error"])}if("string"==typeof n&&t.has(n)){if(e.has(n)){let s=e.get(n);return d(s,r,o)}{let l={},a={};Object.keys(r).forEach(e=>{e.startsWith("on")&&"function"==typeof r[e]?l[e]=r[e]:a[e]=r[e]});let p={tag:"div",props:{className:"component-loading","data-component-name":n,"data-component-props":JSON.stringify(a),"data-component-children":JSON.stringify(o),"data-component-events":JSON.stringify(Object.keys(l))},children:[`Loading ${n}...`],_eventHandlers:l};return p}}null==n&&(console.error("Tag cannot be null/undefined"),n="div");let f=Array.isArray(o)?o.filter(e=>null!=e):null!=o?[o]:[];return{tag:n,props:r,children:f}},f=(e,t)=>{if(e.props?.key!==t.props?.key)return!0;if(null===e||null===t)return e!==t;if(typeof e!=typeof t)return!0;if("string"==typeof e||"number"==typeof e)return e!==t;if(!e.tag||!t.tag||e.tag!==t.tag)return!0;let n=Object.keys(e.props||{}),r=Object.keys(t.props||{});if(n.length!==r.length)return!0;for(let o of n)if(!o.startsWith("on")){if("style"===o&&"object"==typeof e.props[o]&&"object"==typeof t.props[o]){let i=Object.keys(e.props[o]),s=Object.keys(t.props[o]);if(i.length!==s.length)return!0;for(let l of i)if(e.props[o][l]!==t.props[o][l])return!0}else if(e.props[o]!==t.props[o])return!0}return!1},c=(e,t,n)=>{if(!e||!(e instanceof HTMLElement)){console.error("Invalid element passed to updateProps");return}t.ref&&"function"==typeof t.ref&&t.ref(e),Object.keys(n).forEach(r=>{if(r.startsWith("on")&&(!t[r]||n[r]!==t[r])){let o=r.substring(2).toLowerCase();e._events&&e._events[o]&&(e.removeEventListener(o,e._events[o]),delete e._events[o])}}),Object.keys(t).forEach(r=>{if(r.startsWith("on")||n[r]!==t[r]){if(r.startsWith("on")){let o=r.substring(2).toLowerCase();e._events||(e._events={}),e._events[o]&&e.removeEventListener(o,e._events[o]),e._events[o]=t[r],e.addEventListener(o,t[r])}else if("style"===r&&"object"==typeof t[r]){let i=t[r],s=n[r]||{};Object.keys(s).forEach(t=>{i[t]||(e.style[t]="")}),Object.keys(i).forEach(t=>{s[t]!==i[t]&&(e.style[t]=i[t])})}else"className"===r?e.setAttribute("class",t[r]):e.setAttribute(r,t[r])}}),Object.keys(n).forEach(n=>{t[n]||n.startsWith("on")||"style"===n||e.removeAttribute(n)})},u=(e,t,n,r=0)=>{if(!e||!(e instanceof Node)){console.error("Invalid parent node");return}let o=null;if(t&&"object"==typeof t&&t._customRender&&(o=t._customRender(n)),!n){e.appendChild(m(t)),o&&o();return}if(!t){e.removeChild(e.childNodes[r]);return}if(f(t,n)){e.replaceChild(m(t),e.childNodes[r]),o&&o();return}if("string"==typeof t||"number"==typeof t){o&&o();return}c(e.childNodes[r],t.props||{},n.props||{});let i=t.children?t.children.length:0,s=n.children?n.children.length:0;for(let l=0;l<Math.max(i,s);l++)u(e.childNodes[r],t.children&&l<i?t.children[l]:null,n.children&&l<s?n.children[l]:null,l);o&&o()},m=e=>{try{if(null==e)return document.createTextNode("");if("string"==typeof e||"number"==typeof e)return document.createTextNode(e);if("function"==typeof e.tag){let t=e.tag(e.props||{});return m(t)}let n;n=e.props&&e.props.xmlns?document.createElementNS(e.props.xmlns,e.tag):document.createElement(e.tag),e.props&&(c(n,e.props,{}),e.props.ref&&"function"==typeof e.props.ref&&e.props.ref(n));let r=Array.isArray(e.children)?e.children:e.children?[e.children]:[];return r.forEach(e=>{null!=e&&n.appendChild(m(e))}),n}catch(o){return console.error("Failed to create DOM element:",o,e),document.createTextNode("")}},h=async(n,r)=>{if(!r){console.error("Render failed: no container provided");return}if("string"==typeof r){let o=document.querySelector(r);if(!o){console.error(`Container not found: ${r}`);return}r=o}let i=function n(r){let o=new Set;return!function n(r){if(r){if(r.props&&r.props["data-component-name"]){let i=r.props["data-component-name"];e.has(i)||o.add(i)}"string"==typeof r.tag&&t.has(r.tag)&&!e.has(r.tag)&&o.add(r.tag),r.children&&r.children.forEach(n)}}(r),Array.from(o)}(n);if(i.length>0)try{await Promise.all(i.map(e=>l(e))),n=function t(n){if(!n||"string"==typeof n||"number"==typeof n)return n;if(n.props&&n.props["data-component-name"]){let r=n.props["data-component-name"];if(e.has(r)){let o=e.get(r),i=JSON.parse(n.props["data-component-props"]||"{}");n._eventHandlers&&Object.assign(i,n._eventHandlers);let s=JSON.parse(n.props["data-component-children"]||"[]");return d(o,i,s)}}let l=n.children?n.children.map(t):[];return{tag:n.tag,props:{...n.props},children:l}}(n),g(n,r)}catch(s){console.error("Failed to load components:",s),r.innerHTML=`<div class="error">Failed to load components: ${s.message}</div>`}else g(n,r)};function g(e,t){if("undefined"!=typeof MutationObserver&&!t._observer)try{t._observer=new MutationObserver(()=>{t._externallyModified=!0}),t._observer.observe(t,{childList:!0,subtree:!1,attributes:!1,characterData:!1})}catch(n){console.warn("MutationObserver setup failed:",n)}if(t._externallyModified&&(t._vdom=null,t._externallyModified=!1),t._vdom)u(t,e,t._vdom,0),t._vdom=e;else{for(;t.firstChild;)t.removeChild(t.firstChild);t.appendChild(m(e)),t._vdom=e}let r=DomKit.getComponentConfig();console.log("Components after render:",r.loadedComponents)}let y=(e,t,n)=>{let r="string"==typeof n?document.querySelector(n):n;if(!r){console.error(`Container not found: ${n}`);return}let o=DomKit.createState(t),i=()=>{let t=e(o.getState(),o.setState.bind(o));DomKit.render(t,r)};return o.subscribe(i),i(),{getState:o.getState,setState:o.setState}},C=e=>t=>{try{return e(t)}catch(n){return console.error("Component render error:",n),d("div",{className:"error"},["Component error"])}},v=(e,t,n="replace")=>{"string"==typeof t&&(t=document.querySelector(t));let r="function"==typeof e?d(e):e,o=m(r);switch(t._injected||(t._injected=[]),n){case"append":t.appendChild(o),t._injected.push(r);break;case"prepend":t.insertBefore(o,t.firstChild),t._injected.unshift(r);break;default:for(;t.firstChild;)t.removeChild(t.firstChild);t.appendChild(o),t._injected=[r]}return o},b=(e,t,n=0)=>{"string"==typeof t&&(t=document.querySelector(t));let r="function"==typeof e?d(e):e;if(!t._injected||!t._injected[n])return v(r,t,"append");let o=t._injected[n];if(o&&!f(r,o))return t.children[n];let i=t.children[n];if(!i)return v(r,t,"append");let s=document.createElement("div"),l=m(r);return s.appendChild(l),t.replaceChild(l,i),t._injected[n]=r,l},k=(e={})=>{let t=[],n={...e},r=[],o=()=>{t.length>0&&(n={...n,...Object.assign({},...t)},t=[],r.forEach(e=>e(n)))},i=e=>{t.push(e),requestAnimationFrame(o)},s=()=>({...n}),l=e=>(r.push(e),()=>{let t=r.indexOf(e);t>-1&&r.splice(t,1)}),a=()=>{r.length=0};return{getState:s,setState:i,subscribe:l,cleanup:a}},$=(e,t={})=>{let n=k(t),r=null,o=t=>{let{getState:o,setState:i}=n,s=e({...t,state:o(),setState:i});return r=s,s};return o.getState=n.getState,o.setState=n.setState,o.subscribe=n.subscribe,o.forceUpdate=e=>{e&&r&&DomKit.render(r,e)},o},S=(e,t,n)=>{let r=k(e),o=null,i=()=>{o=t(r.getState(),r.setState),DomKit.render(o,n)};return r.subscribe(i),i(),r},E=(e={})=>{void 0===e.value&&(e.value=""),"function"!=typeof e.onChange&&(e.onChange=()=>{});let{value:t,onChange:n,...r}=e,o=null,i=e=>{n&&n(e.target.value,e)},s=DomKit.h("input",{...r,value:t||"",onChange:i,ref(e){o=e}});return s._customRender=()=>{let e=document.activeElement===o,t={start:o?o.selectionStart:0,end:o?o.selectionEnd:0};return()=>{e&&o&&(o.focus(),o.setSelectionRange(t.start,t.end))}},s},j=(e,t)=>{if("function"!=typeof e)return console.error("DomKit.memo: First argument must be a component function"),e;let n=null,r=null;return (o={})=>{let i=!t||t(n,o);if(!r||i)try{r=e(o),n=o}catch(s){return console.error("DomKit.memo: Component render error:",s),d("div",{className:"error"},["Component error"])}return r}};return{h:d,render:h,createComponent:C,createApp:y,createState:k,createStatefulComponent:$,useState:S,createInputField:E,memo:j,configureComponentLoader:function e(t={}){t.domain&&(r=t.domain),t.componentPath&&(o=t.componentPath),t.components&&Object.entries(t.components).forEach(([e,t])=>{p(e,t)}),console.log(`Component loader configured: ${r}${o}`)},loadComponent:l,preloadComponents:function e(t){return Promise.all(t.map(e=>l(e)))},isComponentLoaded:a,getComponent:function t(n){if(!a(n))throw Error(`Component "${n}" is not loaded. Call loadComponent() first.`);return e.get(n)},registerComponent:p,getComponentConfig:function n(){return{domain:r,path:o,registeredComponents:Array.from(t.entries()),loadedComponents:Array.from(e.keys())}},unloadComponent:i,unloadAllComponents:s,cleanupComponentLoader:function e(){s(),t.clear(),n.clear()},isComponentRegistered:e=>t.has(e),getLoadingComponents:()=>Array.from(n.keys()),mount(e,t){h(d(e),t)},inject:(e,t,n)=>v("function"==typeof e?d(e):e,t,n),updateInjected:(e,t,n)=>b("function"==typeof e?d(e):e,t,n),append:(e,t)=>v("function"==typeof e?d(e):e,t,"append"),prepend:(e,t)=>v("function"==typeof e?d(e):e,t,"prepend")}}();window.registerDomKitComponent=function(e,t){window.__domkitComponents||(window.__domkitComponents={}),window.__domkitComponents[e]=t,console.log(`Component registered: ${e}`)};