@xpell/core 2.0.0-alpha.10 → 2.0.0-alpha.11

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.
@@ -42,7 +42,7 @@ export type XCommandData = {
42
42
  _object?: string;
43
43
  _op: string;
44
44
  _params?: {
45
- [k: string]: string | number | Function;
45
+ [k: string]: string | number | boolean | null | object | any[];
46
46
  };
47
47
  };
48
48
  export declare class XCommand {
@@ -62,7 +62,7 @@ export declare class XCommand {
62
62
  * command parameters array
63
63
  */
64
64
  _params?: {
65
- [k: string]: string | number | Function;
65
+ [k: string]: string | number | boolean | null | object | any[];
66
66
  };
67
67
  /**
68
68
  * XCommand create date timestamp
package/dist/XData.d.ts CHANGED
@@ -48,4 +48,5 @@ export declare class _XData {
48
48
  }
49
49
  /** Singleton */
50
50
  export declare const XData: _XData;
51
+ export declare const _xd: _XData;
51
52
  export default XData;
package/dist/XObject.d.ts CHANGED
@@ -29,7 +29,7 @@ import { XNanoCommandPack, XNanoCommand } from "./XNanoCommands";
29
29
  export type wordsList = {
30
30
  [k: string]: string;
31
31
  };
32
- export type XValue = string | number | boolean | null | undefined | Function | XValue[] | {
32
+ export type XValue = string | number | boolean | null | undefined | Function | object | any[] | XValue[] | {
33
33
  [k: string]: XValue;
34
34
  };
35
35
  export interface IXData {
@@ -52,6 +52,7 @@ export type XObjectOnEventHandler = (xObject: XObject, data?: any) => void;
52
52
  export interface XObjectOnEventIndex {
53
53
  [eventName: string]: XObjectOnEventHandler;
54
54
  }
55
+ type XObjectHandler = Function | string | XCommandData | XObjectHandler[];
55
56
  export type XObjectData = {
56
57
  [k: string]: XValue;
57
58
  _id?: string;
@@ -61,10 +62,10 @@ export type XObjectData = {
61
62
  _data_source?: string;
62
63
  _on?: XObjectOnEventIndex;
63
64
  _once?: XObjectOnEventIndex;
64
- _on_create?: string | Function;
65
- _on_mount?: string | Function;
66
- _on_frame?: string | Function;
67
- _on_data?: string | Function;
65
+ _on_create?: XObjectHandler;
66
+ _on_mount?: XObjectHandler;
67
+ _on_frame?: XObjectHandler;
68
+ _on_data?: XObjectHandler;
68
69
  _process_frame?: boolean;
69
70
  _process_data?: boolean;
70
71
  _nano_commands?: XNanoCommandPack;
@@ -85,11 +86,11 @@ export declare class XObject {
85
86
  _debug?: boolean;
86
87
  _on: XObjectOnEventIndex;
87
88
  _once: XObjectOnEventIndex;
88
- _on_create?: string | Function | undefined;
89
- _on_mount?: string | Function | undefined;
90
- _on_frame?: string | Function | undefined;
91
- _on_data?: string | Function | undefined;
92
- _on_event?: string | Function | undefined;
89
+ _on_create?: XObjectHandler | undefined;
90
+ _on_mount?: XObjectHandler | undefined;
91
+ _on_frame?: XObjectHandler | undefined;
92
+ _on_data?: XObjectHandler | undefined;
93
+ _on_event?: XObjectHandler | undefined;
93
94
  _process_frame: boolean;
94
95
  _process_data: boolean;
95
96
  protected _xem_options: XEventListenerOptions;
@@ -185,6 +186,7 @@ export declare class XObject {
185
186
  *
186
187
  */
187
188
  onCreate(): Promise<void>;
189
+ private runCmd;
188
190
  protected checkAndRunInternalFunction(func: any, ...params: any): Promise<void>;
189
191
  /**
190
192
  * Triggers when the object is being mounted to other element
package/dist/Xpell.d.ts CHANGED
@@ -128,7 +128,7 @@ export declare const Xpell: XpellEngine;
128
128
  export default Xpell;
129
129
  export { Xpell as _x };
130
130
  export { XUtils, XUtils as _xu, _XUtils, type XFrameScheduler } from "./XUtils";
131
- export { XData, XData as _xd, type XDataStore, _XData } from "./XData";
131
+ export { XData, _xd, type XDataStore, _XData } from "./XData";
132
132
  export { XParser } from "./XParser";
133
133
  export { XCommand, type XCommandData } from "./XCommand";
134
134
  export { XLogger, XLogger as _xlog, _XLogger } from "./XLogger";
@@ -1,3 +1,3 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});class x{createIgnoreList(t,e){if(!t)return e;const s=t.split(",").map(i=>i.trim()).filter(Boolean);for(const i of s)e[i]="";return e}guid(){const e=globalThis.crypto;if(e&&typeof e.randomUUID=="function")return e.randomUUID();if(e&&typeof e.getRandomValues=="function"){const r=new Uint8Array(16);e.getRandomValues(r),r[6]=r[6]&15|64,r[8]=r[8]&63|128;const a=Array.from(r,_=>_.toString(16).padStart(2,"0"));return a.slice(0,4).join("")+"-"+a.slice(4,6).join("")+"-"+a.slice(6,8).join("")+"-"+a.slice(8,10).join("")+"-"+a.slice(10,16).join("")}const s="0123456789abcdef".split(""),i=[];let n;i[8]=i[13]=i[18]=i[23]="-",i[14]="4";for(let r=0;r<36;r++)i[r]||(n=(0|Math.random()*16)>>>0,i[r]=s[r===19?n&3|8:n&15]);return i.join("")}mergeDefaultsWithData(t,e,s=!1){if(!t)return e;t._id||(t._id=t.id??this.guid());for(const i of Object.keys(e))(!(i in t)||s)&&(t[i]=e[i]);return t}encode(t){const e=globalThis;if(typeof e.btoa=="function"){const s=encodeURIComponent(String(t)).replace(/%([0-9A-F]{2})/g,(i,n)=>String.fromCharCode(parseInt(n,16)));return e.btoa(s)}if(e.Buffer&&typeof e.Buffer.from=="function")return e.Buffer.from(String(t),"utf8").toString("base64");throw new Error("Base64 encode not supported in this environment")}decode(t){const e=globalThis;if(typeof e.atob=="function"){const s=e.atob(String(t)),i=Array.prototype.map.call(s,n=>"%"+n.charCodeAt(0).toString(16).padStart(2,"0")).join("");return decodeURIComponent(i)}if(e.Buffer&&typeof e.Buffer.from=="function")return e.Buffer.from(String(t),"base64").toString("utf8");throw new Error("Base64 decode not supported in this environment")}getRandomInt(t,e){return t=Math.ceil(t),e=Math.floor(e),Math.floor(Math.random()*(e-t+1))+t}getParam(t,e,s=0){return t?._params?.[e]??s}createDefaultScheduler(t){const e=globalThis;if(typeof e.requestAnimationFrame=="function")return n=>e.requestAnimationFrame(n);const s=typeof t=="number"&&isFinite(t)&&t>0?t:60;if(typeof e.setImmediate=="function"&&(!t||t>=60))return n=>e.setImmediate(n);const i=Math.max(1,Math.round(1e3/s));return n=>e.setTimeout(n,i)}}const f=new x;class N{#t=0;#e=0;#s=0;#i;#n;constructor(t=.05,e=1){const s=Number(t);this.#i=Number.isFinite(s)?Math.min(1,Math.max(.001,s)):.05;const i=Number(e);this.#n=Number.isFinite(i)?Math.max(0,Math.floor(i)):1}now(){const t=globalThis.performance;return t&&typeof t.now=="function"?t.now():Date.now()}calc(){const t=this.now();if(this.#s===0)return this.#s=t,this.#t;const e=t-this.#s;if(this.#s=t,!Number.isFinite(e)||e<=0)return this.#t;this.#e===0?this.#e=e:this.#e=(1-this.#i)*this.#e+this.#i*e;const s=1e3/this.#e;if(!Number.isFinite(s)||s<=0)return this.#t;const i=Math.round(s);return this.#t!==0&&this.#n>0&&Math.abs(i-this.#t)<this.#n?this.#t:(this.#t=i,this.#t)}reset(){this.#t=0,this.#e=0,this.#s=0}}class E{constructor(t){this._enabled=!0,this._show_date=!1,this._show_time=!0,this._debug=!1,t&&this.configure(t)}configure(t){typeof t._enabled=="boolean"&&(this._enabled=t._enabled),typeof t._show_date=="boolean"&&(this._show_date=t._show_date),typeof t._show_time=="boolean"&&(this._show_time=t._show_time),typeof t._debug=="boolean"&&(this._debug=t._debug)}_dt(){const t=new Date,e=this._show_date?`${t.getDate()}.${t.getMonth()}.${t.getFullYear()} `:"",s=this._show_time?`${t.getHours()}:${t.getMinutes()}:${t.getSeconds()}.${t.getMilliseconds()}|`:"";return e+s}log(t,...e){this._enabled&&console.log(this._dt(),t,...e)}warn(t,...e){this._enabled&&console.warn(this._dt(),t,...e)}error(t,...e){this._enabled&&console.error(this._dt(),t,...e)}debug(t,...e){!this._enabled||!this._debug||console.debug(this._dt(),t,...e)}}const c=new E,D=typeof process<"u"&&!!process?.env&&process.env.NODE_ENV==="production";D||console.info("[Xpell] _xlog is redirected to console in development mode. Tip: enable 'Show timestamps' in DevTools → Console for timed logs.");const w=D?c:console;class k{constructor(){this._objects={},this._listeners=new Map,this._any_listeners=new Set,this._compat_writes=!0,this._warn_legacy_writes=!0,this._verbose=!1,this._compat_legacy_keys=!0,this._o_proxy=null,this._objects={}}get _o(){return!this._compat_writes&&!this._warn_legacy_writes?this._objects:(this._o_proxy||(this._o_proxy=new Proxy(this._objects,{set:(t,e,s)=>{const i=String(e);return this._warn_legacy_writes&&console.warn(`[XData] Legacy write: _o["${i}"] = ... ; prefer XData.set("${i}", value).`),this._compat_writes?this.set(i,s,{source:"legacy:_o"}):t[i]=s,!0},deleteProperty:(t,e)=>{const s=String(e);return this._warn_legacy_writes&&console.warn(`[XData] Legacy delete: delete _o["${s}"] ; prefer XData.delete("${s}").`),this._compat_writes?this.delete(s,{source:"legacy:_o"}):delete t[s],!0}})),this._o_proxy)}get(t){return this._objects[t]}set(t,e,s){const i=this._objects[t];this._objects[t]=e,this._emit({key:t,value:e,prev:i,ts:Date.now(),op:"set",meta:s})}patch(t,e,s){const i=this._objects[t],r={...i&&typeof i=="object"?i:{},...e};this._objects[t]=r,this._emit({key:t,value:r,prev:i,ts:Date.now(),op:"patch",meta:s})}touch(t,e){const s=this._objects[t];this._emit({key:t,value:s,prev:s,ts:Date.now(),op:"touch",meta:e})}has(t){return Object.prototype.hasOwnProperty.call(this._objects,t)}delete(t,e){const s=this._objects[t];delete this._objects[t],this._emit({key:t,value:void 0,prev:s,ts:Date.now(),op:"delete",meta:e})}pick(t,e){const s=this._objects[t];return this.delete(t,e),s}clean(){this._objects={}}on(t,e){let s=this._listeners.get(t);return s||this._listeners.set(t,s=new Set),s.add(e),()=>this.off(t,e)}off(t,e){const s=this._listeners.get(t);s&&(s.delete(e),s.size===0&&this._listeners.delete(t))}onAny(t){return this._any_listeners.add(t),()=>this._any_listeners.delete(t)}_emit(t){this._verbose&&t.meta?.trace&&(t.stack=new Error().stack);const e=this._listeners.get(t.key);if(e)for(const s of e)s(t);for(const s of this._any_listeners)s(t)}}const u=new k;class F{constructor(t){t&&Object.keys(t).forEach(e=>{this[e]=t[e]}),this.d||(this.d=Date.now())}getParam(t,e,s){return this._params?.hasOwnProperty(e)?this._params[e]:this._params?.hasOwnProperty(t)?this._params[t]:s}}const v={type:"_type",children:"_children"},p=class p{static addHtml2XpellMapItem(t,e){p.html2XMap.elements[t]=e}static parse(t,e){const s=t.split(" ");let i=new F;if(e?(i._module=e,i._op=s[0]):(i._module=s[0],i._op=s[1]),i._params={},s.length>1)for(let n=2;n<s.length;++n){const r=s[n];if(r.indexOf(":")>-1){const _=r.split(":");i._params[_[0]]=_[1]}else i._params[n-1]=s[n]}return i}static replaceSpacesInQuotes(t,e="_%20_"){return t.replace(/(['"])(.*?)\1/g,(s,i,n)=>{const r=String(n).replace(/\s/g,e);return`${i}${r}${i}`})}static parseObjectCommand(t,e){t=p.replaceSpacesInQuotes(t);const s=t.trim().split(/\s+/),i=e||s.shift();if(!i)throw new Error("Missing module name");let n;if(s[0]?.startsWith("#")&&(n=s.shift().slice(1),!n))throw new Error("Invalid object selector '#'. Use '#<id>'");const r=s.shift();if(!r)throw new Error("Missing operation");const a={};let _=null,h=null;if(s.forEach(l=>{if(h){if(h+=` ${l}`,l.endsWith(h[0])){const b=h.slice(1,-1).replace(/_%20_/g," ");a[_]=b,h=null}return}if(l.startsWith('"')||l.startsWith("'")){if(h=l,l.endsWith(l[0])&&l.length>1){const b=l.slice(1,-1).replace(/_%20_/g," ");a[_]=b,h=null}return}if(l.includes(":")){const b=l.split(":"),$=b[0],R=b.slice(1).join(":").replace(/_%20_/g," ");a[$]=R,_=null;return}_=l.replace(/_%20_/g," ")}),h)throw new Error("Unclosed quoted parameter value");return{_module:i,_object:n,_op:r,_params:a}}static xmlString2Xpell(t){const s=new DOMParser().parseFromString(t,"text/xml");return s.childNodes.length>0?p.xml2Xpell(s.childNodes[0]):{}}static xml2Xpell(t,e){const s=p.html2XMap;let i={};i._children=[];const n=t.nodeName,r=t.nodeName;let a=e;if(e?(i[v.type]="xhtml",i._html_ns="http://www.w3.org/2000/svg"):i._type=s.elements[n]?s.elements[n]:n,t.attributes)for(let _=0;_<t.attributes.length;++_){const h=t.attributes[_],l=s.attributes[h.name]?s.attributes[h.name]:h.name;i[l]=h.value}if(t?.firstChild?.nodeValue&&(i.text=t?.firstChild.nodeValue.trim()),i[v.type]=="xhtml"?i._html_tag=r:i[v.type]=="svg"&&(a=!0,i._html_ns="http://www.w3.org/2000/svg"),t?.childNodes.length>0)for(let _=0;_<t.childNodes.length;++_){const h=t.childNodes[_];h.nodeName.startsWith("#")||i[v.children].push(p.xml2Xpell(h,a))}return i}};p.html2XMap={elements:{div:"view",a:"link",b:"xhtml",h1:"xhtml",h2:"xhtml",h3:"xhtml",h4:"xhtml",h5:"xhtml",p:"xhtml",small:"xhtml",aside:"xhtml",span:"xhtml",table:"xhtml",th:"xhtml",td:"xhtml",tr:"xhtml",thead:"xhtml",tbody:"xhtml",ul:"xhtml",li:"xhtml",ol:"xhtml",canvas:"xhtml",img:"image"},attributes:{id:"_id"}};let m=p;class M{constructor(){this._log_rules={register:!1,remove:!1,fire:!1},this._events={},this._listener_index={}}on(t,e,s={},i){this._events[t]||(this._events[t]=[]);const n=s?._owner??i,r=f.guid(),a={_id:r,_callback:e,_options:s,_owner:n,_tag:s?._tag};return this._events[t].push(a),this._listener_index[r]=t,this._log_rules.register&&w.log("XEM Register",t,r),r}once(t,e,s){return this.on(t,e,{_once:!0,_owner:s})}async fire(t,e){const s=this._events[t];if(!s||s.length===0)return;this._log_rules.fire&&w.log("XEM Fire",t,e);const i=s.slice(),n=[];for(const r of i){try{r&&r._callback&&r._callback(e)}catch(a){w.error(a)}r?._options?._once&&n.push(r._id)}for(const r of n)this.remove(r)}remove(t){const e=this._listener_index[t];if(!e)return;const s=this._events[e];if(s&&s.length){const i=s.findIndex(n=>n?._id===t);i>=0&&s.splice(i,1),s.length===0&&delete this._events[e]}delete this._listener_index[t],this._log_rules.remove&&w.log("XEM Remove",e,t)}removeOwner(t){if(!t)return;const e=[];for(const s of Object.values(this._events))for(const i of s)(i?._owner??i?._options?._owner)===t&&e.push(i._id);e.forEach(s=>this.remove(s))}clear(){this._events={},this._listener_index={}}}const g=new M;class S{#t;#e;#s;constructor(){this.#t={},this.#e={},this.#s={}}get _objects(){return this.#e}hasObject(t){return this.#e.hasOwnProperty(t)}registerObjects(t){Object.keys(t).forEach(s=>this.registerObject(s,t[s]))}registerObject(t,e){this.#t[t]=e}hasObjectClass(t){return this.#t.hasOwnProperty(t)}getObjectClass(t){return this.#t[t]}getAllClasses(){return this.#t}get _classes(){return this.#t}addObject(t){t&&t._id?(this.#e[t._id]=t,(!t._name||t._name.length==0)&&(t._name=t._id),this.#s[t._name]=t._id):c.log("unable to add object")}removeObject(t){const e=this.#e[t];e&&(delete this.#s[e?._name],delete this.#e[t])}getObject(t){return this.#e[t]}go(t){return this.getObject(t)}getObjectByName(t){return this.#s[t]?this.getObject(this.#s[t]):null}}const U={info:(o,t)=>{c.log("XObject id "+t?._id)},log:(o,t)=>{o._params&&o._params[1]?c.log(o._params[1]):c.log(t)},fire:(o,t)=>{o._params&&o._params[1]?g.fire(o._params[1],o._params[2]):o._params&&o._params.event&&g.fire(o._params.event,o._params.data)}},j={_children:"child nodes"};class y{constructor(t,e,s){this._children=[],this._parent=null,this._on={},this._once={},this._process_frame=!0,this._process_data=!0,this._nano_commands={},this._event_listeners_ids={},this._event_parsed=!1,this._mounted=!1,this._xporter={_ignore_fields:["_to_xdata_ignore_fields","_xporter","_children","_on","_once","_on_create","_on_mount","_on_frame","_on_data","_process_frame","_process_data","_parent","_event_listeners_ids","_event_parsed","_mounted","_debug"],_instance_xporters:{}},e&&f.mergeDefaultsWithData(t,e),this._id=t&&t._id?t._id:"xo-"+f.guid(),this._type="object",this._children=[],this._nano_commands={},this.addNanoCommandPack(U),t&&t.hasOwnProperty("_nano_commands")&&t._nano_commands&&(this.addNanoCommandPack(t._nano_commands),delete t._nano_commands),this.addXporterDataIgnoreFields(["_nano_commands"]),this.addXporterInstanceXporter(y,i=>i.toXData()),this._xem_options={},!s&&t&&this.parse(t,j)}log(t,...e){this._debug&&t&&c.log(this._type+"->"+this._id+"]",t,...e)}init(t,e){!e&&t&&this.parse(t,j)}parseEvents(t){if(!this._event_parsed){t||(t=this._xem_options),Object.keys(this._on).forEach(s=>{this.addEventListener(s,this._on[s],t)});const e={};Object.assign(e,t),e._once=!0,Object.keys(this._once).forEach(s=>{this.addEventListener(s,this._once[s],e)}),this._event_parsed=!0}}addEventListener(t,e,s){s||(s=this._xem_options);let i;if(typeof e=="function")i=async r=>{e(this,r)};else if(typeof e=="string")i=async r=>{const a=this._id+" "+e+" event-data='"+JSON.stringify(r).replace(/'/g,"\\'")+"'";await this.run(a)};else throw new Error("event handler must be a function");const n=g.on(t,i,s,this);this._event_listeners_ids[t]||(this._event_listeners_ids[t]=[]),this._event_listeners_ids[t].push(n)}removeEventListener(t){const e=this._event_listeners_ids[t];e&&e.length&&(e.forEach(s=>{g.remove(s)}),delete this._event_listeners_ids[t])}removeAllEventListeners(){Object.keys(this._event_listeners_ids).forEach(e=>this.removeEventListener(e))}append(t){this._children?.push(t),t._parent=this}addNanoCommand(t,e){typeof e=="function"&&(this._nano_commands[t]=e)}addNanoCommandPack(t){t&&Object.keys(t).forEach(e=>{this.addNanoCommand(e,t[e])})}addXporterDataIgnoreFields(t){this._xporter._ignore_fields=this._xporter._ignore_fields.concat(t)}addXporterInstanceXporter(t,e){const s=f.guid();this._xporter._instance_xporters[s]={cls:t,handler:e}}parse(t,e=j){Object.keys(t).forEach(i=>{!e.hasOwnProperty(i)&&t.hasOwnProperty(i)&&(this[i]=t[i])})}parseFieldsFromXDataObject(t,e){Object.keys(e).forEach(i=>{t.hasOwnProperty(i)?this[i]=t[i]:this[i]=e[i]})}parseFields(t,e,s){e.forEach(i=>{if(t.hasOwnProperty(i))this[i]=t[i];else if(s&&i.startsWith("_")){const n=i.substring(1);t.hasOwnProperty(n)&&(this[i]=t[n],this[n]=t[n])}})}async onCreate(){this._on_create?this.checkAndRunInternalFunction(this._on_create):this._on&&this._on.create?this.checkAndRunInternalFunction(this._on.create):this._once&&this._once.create&&this.checkAndRunInternalFunction(this._once.create)}async checkAndRunInternalFunction(t,...e){if(typeof t=="function")await t(this,...e);else if(typeof t=="string")if(e.length>0){const s=e[0],i=JSON.stringify(s).replace(/'/g,"\\'");await this.run(`${this._id} ${t} data:'${i}'`)}else await this.run(`${this._id} ${t}`)}async onMount(){if(!this._mounted){this.parseEvents(this._xem_options),this._process_data&&typeof this._data_source=="string"&&this._data_source.length>0&&this.bindDataSource(this._data_source,{initial:!0}),this._on_mount?await this.checkAndRunInternalFunction(this._on_mount):this._on&&this._on.mount?await this.checkAndRunInternalFunction(this._on.mount):this._once&&this._once.mount&&await this.checkAndRunInternalFunction(this._once.mount),this._mounted=!0;for(const t of this._children)t.onMount&&typeof t.onMount=="function"&&t.onMount()}}emptyDataSource(){const t=this._data_source;if(typeof t!="string"||t.length===0)return;const e=this._type??this.constructor.name,s=this._id??"no-id";u.delete(t,{source:`${e}#${s}.emptyDataSource`})}async onData(t){this._process_data&&(this._on_data?this.checkAndRunInternalFunction(this._on_data,t):this._on&&this._on.data?this.checkAndRunInternalFunction(this._on.data,t):this._once&&this._once.data&&this.checkAndRunInternalFunction(this._once.data,t))}async onFrame(t){this._process_frame&&(this._on_frame?this.checkAndRunInternalFunction(this._on_frame,t):this._on&&this._on.frame?this.checkAndRunInternalFunction(this._on.frame,t):this._once&&this._once.frame&&this.checkAndRunInternalFunction(this._once.frame,t));for(const e of this._children)e.onFrame&&typeof e.onFrame=="function"&&e.onFrame(t)}async run(t,e=!0){let s=this._cache_cmd_txt&&this._cache_cmd_txt==t?this._cache_jcmd:m.parseObjectCommand(t);e&&(this._cache_cmd_txt=t,this._cache_jcmd=s),await this.execute(s)}async execute(t){if(t._op&&this._nano_commands[t._op])try{await this._nano_commands[t._op](t,this)}catch(e){c.error(this._id+" has error with command name "+t._op+" "+e)}else c.error(this._id+" has no command name "+t._op)}toXData(){const t={};return Object.keys(this).forEach(e=>{if(!this._xporter._ignore_fields.includes(e)&&this.hasOwnProperty(e)&&this[e]!==void 0){const s=this[e];if(typeof s=="function")return;if(typeof s=="object"){const i=Object.keys(this._xporter._instance_xporters);let n=!0;i.forEach(r=>{this._xporter._instance_xporters[r],s instanceof this._xporter._instance_xporters[r].cls&&(t[e]=this._xporter._instance_xporters[r].handler(s),n=!1)}),n&&(t[e]=s)}else t[e]=s}}),t._children=[],this._children.length>0&&this._children.forEach(e=>{typeof e.toXData=="function"&&t._children?.push(e.toXData())}),t}toString(){return JSON.stringify(this.toXData())}clearAttributes(t){t.forEach(e=>{this.hasOwnProperty(e)&&(this[e]=null,delete this[e])})}bindDataSource(t,e){const s=e?.initial??!0,i=t??this._data_source;typeof i!="string"||i.length===0||this._process_data&&(this._xd_bound_key===i&&this._xd_unsub||(this.unbindDataSource(),this._data_source=i,this._xd_bound_key=i,this._type??this.constructor.name,this._id,this._xd_unsub=u.on(i,async n=>{await this.onData(n.value)}),s&&u.has(i)&&this.onData(u.get(i))))}unbindDataSource(){this._xd_unsub?.(),this._xd_unsub=void 0,this._xd_bound_key=void 0}async dispose(){if(this.unbindDataSource(),this._parent){const t=this._parent._children.indexOf(this);t>-1&&this._parent._children.splice(t,1)}this._process_data=!1,this._process_frame=!1,this.removeAllEventListeners(),this.clearAttributes(["_cache_cmd_txt","_cache_jcmd","_nano_commands","_event_listeners_ids","_parent","_on","_once","_xem_options","_xporter"]),this._children&&this._children.forEach(t=>{typeof t.dispose=="function"&&t.dispose()}),this._children=[]}removeChild(t,e=!1){if(e)t.dispose();else{const s=this._children.indexOf(t);s>-1&&this._children.splice(s,1),t._parent=null}}addChild(t){this.append(t)}}class L{static getObjects(){return{object:y}}}const B="engine:module:num-of-objects:";class C{constructor(t){this._log_rules={createObject:!1,removeObject:!1},this.#t=new S,this._name=t._name,this._id=f.guid()}#t;load(){c.log("Module "+this._name+" loaded")}create(t){let e;if(t.hasOwnProperty("_type"))if(this.#t.hasObjectClass(t._type)){let s=this.#t.getObjectClass(t._type);s.hasOwnProperty("defaults")&&f.mergeDefaultsWithData(t,s.defaults),e=new s(t)}else throw"Xpell object '"+t._type+"' not found";else e=new y(t);return this.#t.addObject(e),t._children&&t._children.forEach(s=>{const i=this.create(s);e.append(i)}),e.onCreate(),e}remove(t){const e=this.#t.getObject(t);if(!e)return;const s=[],i=n=>{n?._id&&(s.push(n._id),(n._children??[]).forEach(r=>i(r)))};i(e),typeof e.dispose=="function"&&e.dispose(),s.reverse().forEach(n=>this.#t.removeObject(n))}_info(t){c.log("module info")}async run(t){if(t){let e=t.trim();e.startsWith(this._name)||(e=this._name+" "+e);let s=m.parse(e);return await this.execute(s)}else throw"Unable to parse Xpell Command"}async execute(t){if(!t||!t._op)throw new Error(`Invalid XCommand: missing _op (module: ${this._name})`);const e=t._object;if(e){const n=this.#t.getObject(e);if(!n)throw new Error(`Module '${this._name}' cant find object id: ${e}`);return await n.execute(t)}const s="_"+t._op.replaceAll("-","_"),i=this[s];if(typeof i=="function")return await i.call(this,t);throw new Error(`Module '${this._name}' cant find op: ${t._op}`)}async onFrame(t){const e=this.#t._objects,s=Object.keys(e);s.forEach(i=>{const n=e[i];n&&n.onFrame&&typeof n.onFrame=="function"&&n?.onFrame(t)}),u.set(B+this._id,s.length,{source:"xmodule"})}get om(){return this.#t}get _object_manager(){return this.#t}getObject(t){return this.#t.getObject(t)}get _o(){return this.#t._objects}importObjectPack(t){this.#t.registerObjects(t.getObjects())}importObjects(t){this.importObjectPack(t)}importObject(t,e){this.#t.registerObject(t,e)}async _help(t){const e=t?._params?._op??t?._params?._command??"";return this.help(e)}help(t){return{module:this._name,usage:`${this._name} help`,ops:["help"],note:"No help() implemented for this module."}}}class T{static get(t,e,s){if(!t?._params)return s;const i=t._params[e];return i!==void 0?i:s}static has(t,e){return t?._params&&t._params[e]!==void 0}static str(t,...e){for(const s of e){const i=t?._params?.[s];if(i!=null)return String(i)}}static bool(t,e,s=!1){const i=this.get(t,e,s);if(typeof i=="boolean")return i;if(typeof i=="number")return i!==0;if(typeof i=="string"){const n=i.toLowerCase();if(["1","true","yes","on"].includes(n))return!0;if(["0","false","no","off"].includes(n))return!1}return!!i}static int(t,e,s=0){const i=this.get(t,e,s),n=parseInt(String(i),10);return Number.isFinite(n)?n:s}static json(t,e,s){const i=this.get(t,e,s);if(i==null)return s;if(typeof i=="object")return i;if(typeof i=="string")try{return JSON.parse(i)}catch{return s}return s}}class O extends Error{constructor(t,e,s){super(e),this.name="XError",this._code=t,this._level=s?._level??"error",this._meta=s?._meta,this._cause=s?._cause}toXData(){return{_code:this._code,_level:this._level,_meta:this._meta,_cause:this._cause,name:this.name,message:this.message}}toJSON(){return{...this.toXData(),stack:this.stack}}}class d{constructor(t){this._ok=!1,this._ts=Date.now(),this._pt=0,t&&this.setXData(t)}static create(t){return new d(t)}static ok(t){return new d({_ok:!0,_result:t})}static error(t){if(t instanceof O)return new d({_ok:!1,_result:t.toXData()});const e=new O("E_INTERNAL",t?.message??String(t),{_cause:t});return new d({_ok:!1,_result:e.toXData()})}stopProcessTimeCounter(){this._pt=Date.now()-this._ts}toXData(){return this.stopProcessTimeCounter(),{_ok:this._ok,_ts:this._ts,_pt:this._pt,_result:this._result}}toString(){return JSON.stringify(this.toXData())}setXData(t){t&&("_ok"in t&&(this._ok=!!t._ok),"_ts"in t&&typeof t._ts=="number"&&(this._ts=t._ts),"_pt"in t&&typeof t._pt=="number"&&(this._pt=t._pt),"_result"in t&&(this._result=t._result))}}class W extends d{constructor(t){super(d.error(t).toXData())}}class J extends d{constructor(t){super({_ok:!0,_result:t})}}const I="engine:frame-number",P="engine:fps";class A{constructor(t){this._log_rules={},this._modules={},this._schedule_frame=t?._schedule_frame??f.createDefaultScheduler(t?._target_fps),this._version="0.0.1",this._engine_id=f.guid(),this._frame_number=0,this._fps_calc=new N,this.parser=m,this._modules={},g.fire("xpell-init"),c._enabled=!1}set verbose(t){c._enabled=t}set _verbose(t){c._enabled=t}log(t,...e){c.log(t,...e)}async delay(t){return new Promise(e=>setTimeout(e,t))}loadModule(t){this._modules.hasOwnProperty(t._name)?c.log("Module "+t._name+" already loaded"):(this._modules[t._name]=t,t.load())}loadModules(...t){t.forEach(e=>this.loadModule(e))}info(){c.log(`Xpell information:
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});class k{createIgnoreList(e,t){if(!e)return t;const s=e.split(",").map(i=>i.trim()).filter(Boolean);for(const i of s)t[i]="";return t}guid(){const t=globalThis.crypto;if(t&&typeof t.randomUUID=="function")return t.randomUUID();if(t&&typeof t.getRandomValues=="function"){const r=new Uint8Array(16);t.getRandomValues(r),r[6]=r[6]&15|64,r[8]=r[8]&63|128;const c=Array.from(r,_=>_.toString(16).padStart(2,"0"));return c.slice(0,4).join("")+"-"+c.slice(4,6).join("")+"-"+c.slice(6,8).join("")+"-"+c.slice(8,10).join("")+"-"+c.slice(10,16).join("")}const s="0123456789abcdef".split(""),i=[];let n;i[8]=i[13]=i[18]=i[23]="-",i[14]="4";for(let r=0;r<36;r++)i[r]||(n=(0|Math.random()*16)>>>0,i[r]=s[r===19?n&3|8:n&15]);return i.join("")}mergeDefaultsWithData(e,t,s=!1){if(!e)return t;e._id||(e._id=e.id??this.guid());for(const i of Object.keys(t))(!(i in e)||s)&&(e[i]=t[i]);return e}encode(e){const t=globalThis;if(typeof t.btoa=="function"){const s=encodeURIComponent(String(e)).replace(/%([0-9A-F]{2})/g,(i,n)=>String.fromCharCode(parseInt(n,16)));return t.btoa(s)}if(t.Buffer&&typeof t.Buffer.from=="function")return t.Buffer.from(String(e),"utf8").toString("base64");throw new Error("Base64 encode not supported in this environment")}decode(e){const t=globalThis;if(typeof t.atob=="function"){const s=t.atob(String(e)),i=Array.prototype.map.call(s,n=>"%"+n.charCodeAt(0).toString(16).padStart(2,"0")).join("");return decodeURIComponent(i)}if(t.Buffer&&typeof t.Buffer.from=="function")return t.Buffer.from(String(e),"base64").toString("utf8");throw new Error("Base64 decode not supported in this environment")}getRandomInt(e,t){return e=Math.ceil(e),t=Math.floor(t),Math.floor(Math.random()*(t-e+1))+e}getParam(e,t,s=0){return e?._params?.[t]??s}createDefaultScheduler(e){const t=globalThis;if(typeof t.requestAnimationFrame=="function")return n=>t.requestAnimationFrame(n);const s=typeof e=="number"&&isFinite(e)&&e>0?e:60;if(typeof t.setImmediate=="function"&&(!e||e>=60))return n=>t.setImmediate(n);const i=Math.max(1,Math.round(1e3/s));return n=>t.setTimeout(n,i)}}const f=new k;class L{#e=0;#t=0;#s=0;#i;#n;constructor(e=.05,t=1){const s=Number(e);this.#i=Number.isFinite(s)?Math.min(1,Math.max(.001,s)):.05;const i=Number(t);this.#n=Number.isFinite(i)?Math.max(0,Math.floor(i)):1}now(){const e=globalThis.performance;return e&&typeof e.now=="function"?e.now():Date.now()}calc(){const e=this.now();if(this.#s===0)return this.#s=e,this.#e;const t=e-this.#s;if(this.#s=e,!Number.isFinite(t)||t<=0)return this.#e;this.#t===0?this.#t=t:this.#t=(1-this.#i)*this.#t+this.#i*t;const s=1e3/this.#t;if(!Number.isFinite(s)||s<=0)return this.#e;const i=Math.round(s);return this.#e!==0&&this.#n>0&&Math.abs(i-this.#e)<this.#n?this.#e:(this.#e=i,this.#e)}reset(){this.#e=0,this.#t=0,this.#s=0}}class F{constructor(e){this._enabled=!0,this._show_date=!1,this._show_time=!0,this._debug=!1,e&&this.configure(e)}configure(e){typeof e._enabled=="boolean"&&(this._enabled=e._enabled),typeof e._show_date=="boolean"&&(this._show_date=e._show_date),typeof e._show_time=="boolean"&&(this._show_time=e._show_time),typeof e._debug=="boolean"&&(this._debug=e._debug)}_dt(){const e=new Date,t=this._show_date?`${e.getDate()}.${e.getMonth()}.${e.getFullYear()} `:"",s=this._show_time?`${e.getHours()}:${e.getMinutes()}:${e.getSeconds()}.${e.getMilliseconds()}|`:"";return t+s}log(e,...t){this._enabled&&console.log(this._dt(),e,...t)}warn(e,...t){this._enabled&&console.warn(this._dt(),e,...t)}error(e,...t){this._enabled&&console.error(this._dt(),e,...t)}debug(e,...t){!this._enabled||!this._debug||console.debug(this._dt(),e,...t)}}const a=new F,S=typeof process<"u"&&!!process?.env&&process.env.NODE_ENV==="production";S||console.info("[Xpell] _xlog is redirected to console in development mode. Tip: enable 'Show timestamps' in DevTools → Console for timed logs.");const w=S?a:console;class M{constructor(){this._objects={},this._listeners=new Map,this._any_listeners=new Set,this._compat_writes=!0,this._warn_legacy_writes=!0,this._verbose=!1,this._compat_legacy_keys=!0,this._o_proxy=null,this._objects={}}get _o(){return!this._compat_writes&&!this._warn_legacy_writes?this._objects:(this._o_proxy||(this._o_proxy=new Proxy(this._objects,{set:(e,t,s)=>{const i=String(t);return this._warn_legacy_writes&&console.warn(`[XData] Legacy write: _o["${i}"] = ... ; prefer XData.set("${i}", value).`),this._compat_writes?this.set(i,s,{source:"legacy:_o"}):e[i]=s,!0},deleteProperty:(e,t)=>{const s=String(t);return this._warn_legacy_writes&&console.warn(`[XData] Legacy delete: delete _o["${s}"] ; prefer XData.delete("${s}").`),this._compat_writes?this.delete(s,{source:"legacy:_o"}):delete e[s],!0}})),this._o_proxy)}get(e){return this._objects[e]}set(e,t,s){const i=this._objects[e];this._objects[e]=t,this._emit({key:e,value:t,prev:i,ts:Date.now(),op:"set",meta:s})}patch(e,t,s){const i=this._objects[e],r={...i&&typeof i=="object"?i:{},...t};this._objects[e]=r,this._emit({key:e,value:r,prev:i,ts:Date.now(),op:"patch",meta:s})}touch(e,t){const s=this._objects[e];this._emit({key:e,value:s,prev:s,ts:Date.now(),op:"touch",meta:t})}has(e){return Object.prototype.hasOwnProperty.call(this._objects,e)}delete(e,t){const s=this._objects[e];delete this._objects[e],this._emit({key:e,value:void 0,prev:s,ts:Date.now(),op:"delete",meta:t})}pick(e,t){const s=this._objects[e];return this.delete(e,t),s}clean(){this._objects={}}on(e,t){let s=this._listeners.get(e);return s||this._listeners.set(e,s=new Set),s.add(t),()=>this.off(e,t)}off(e,t){const s=this._listeners.get(e);s&&(s.delete(t),s.size===0&&this._listeners.delete(e))}onAny(e){return this._any_listeners.add(e),()=>this._any_listeners.delete(e)}_emit(e){this._verbose&&e.meta?.trace&&(e.stack=new Error().stack);const t=this._listeners.get(e.key);if(t)for(const s of t)s(e);for(const s of this._any_listeners)s(e)}}const u=new M,P=u;class X{constructor(e){e&&Object.keys(e).forEach(t=>{this[t]=e[t]}),this.d||(this.d=Date.now())}getParam(e,t,s){return this._params?.hasOwnProperty(t)?this._params[t]:this._params?.hasOwnProperty(e)?this._params[e]:s}}const v={type:"_type",children:"_children"},p=class p{static addHtml2XpellMapItem(e,t){p.html2XMap.elements[e]=t}static parse(e,t){const s=e.split(" ");let i=new X;if(t?(i._module=t,i._op=s[0]):(i._module=s[0],i._op=s[1]),i._params={},s.length>1)for(let n=2;n<s.length;++n){const r=s[n];if(r.indexOf(":")>-1){const _=r.split(":");i._params[_[0]]=_[1]}else i._params[n-1]=s[n]}return i}static replaceSpacesInQuotes(e,t="_%20_"){return e.replace(/(['"])(.*?)\1/g,(s,i,n)=>{const r=String(n).replace(/\s/g,t);return`${i}${r}${i}`})}static parseObjectCommand(e,t){e=p.replaceSpacesInQuotes(e);const s=e.trim().split(/\s+/),i=t||s.shift();if(!i)throw new Error("Missing module name");let n;if(s[0]?.startsWith("#")&&(n=s.shift().slice(1),!n))throw new Error("Invalid object selector '#'. Use '#<id>'");const r=s.shift();if(!r)throw new Error("Missing operation");const c={};let _=null,h=null;if(s.forEach(l=>{if(h){if(h+=` ${l}`,l.endsWith(h[0])){const b=h.slice(1,-1).replace(/_%20_/g," ");c[_]=b,h=null}return}if(l.startsWith('"')||l.startsWith("'")){if(h=l,l.endsWith(l[0])&&l.length>1){const b=l.slice(1,-1).replace(/_%20_/g," ");c[_]=b,h=null}return}if(l.includes(":")){const b=l.split(":"),U=b[0],C=b.slice(1).join(":").replace(/_%20_/g," ");c[U]=C,_=null;return}_=l.replace(/_%20_/g," ")}),h)throw new Error("Unclosed quoted parameter value");return{_module:i,_object:n,_op:r,_params:c}}static xmlString2Xpell(e){const s=new DOMParser().parseFromString(e,"text/xml");return s.childNodes.length>0?p.xml2Xpell(s.childNodes[0]):{}}static xml2Xpell(e,t){const s=p.html2XMap;let i={};i._children=[];const n=e.nodeName,r=e.nodeName;let c=t;if(t?(i[v.type]="xhtml",i._html_ns="http://www.w3.org/2000/svg"):i._type=s.elements[n]?s.elements[n]:n,e.attributes)for(let _=0;_<e.attributes.length;++_){const h=e.attributes[_],l=s.attributes[h.name]?s.attributes[h.name]:h.name;i[l]=h.value}if(e?.firstChild?.nodeValue&&(i.text=e?.firstChild.nodeValue.trim()),i[v.type]=="xhtml"?i._html_tag=r:i[v.type]=="svg"&&(c=!0,i._html_ns="http://www.w3.org/2000/svg"),e?.childNodes.length>0)for(let _=0;_<e.childNodes.length;++_){const h=e.childNodes[_];h.nodeName.startsWith("#")||i[v.children].push(p.xml2Xpell(h,c))}return i}};p.html2XMap={elements:{div:"view",a:"link",b:"xhtml",h1:"xhtml",h2:"xhtml",h3:"xhtml",h4:"xhtml",h5:"xhtml",p:"xhtml",small:"xhtml",aside:"xhtml",span:"xhtml",table:"xhtml",th:"xhtml",td:"xhtml",tr:"xhtml",thead:"xhtml",tbody:"xhtml",ul:"xhtml",li:"xhtml",ol:"xhtml",canvas:"xhtml",img:"image"},attributes:{id:"_id"}};let m=p;class I{constructor(){this._log_rules={register:!1,remove:!1,fire:!1},this._events={},this._listener_index={}}on(e,t,s={},i){this._events[e]||(this._events[e]=[]);const n=s?._owner??i,r=f.guid(),c={_id:r,_callback:t,_options:s,_owner:n,_tag:s?._tag};return this._events[e].push(c),this._listener_index[r]=e,this._log_rules.register&&w.log("XEM Register",e,r),r}once(e,t,s){return this.on(e,t,{_once:!0,_owner:s})}async fire(e,t){const s=this._events[e];if(!s||s.length===0)return;this._log_rules.fire&&w.log("XEM Fire",e,t);const i=s.slice(),n=[];for(const r of i){try{r&&r._callback&&r._callback(t)}catch(c){w.error(c)}r?._options?._once&&n.push(r._id)}for(const r of n)this.remove(r)}remove(e){const t=this._listener_index[e];if(!t)return;const s=this._events[t];if(s&&s.length){const i=s.findIndex(n=>n?._id===e);i>=0&&s.splice(i,1),s.length===0&&delete this._events[t]}delete this._listener_index[e],this._log_rules.remove&&w.log("XEM Remove",t,e)}removeOwner(e){if(!e)return;const t=[];for(const s of Object.values(this._events))for(const i of s)(i?._owner??i?._options?._owner)===e&&t.push(i._id);t.forEach(s=>this.remove(s))}clear(){this._events={},this._listener_index={}}}const g=new I;class A{#e;#t;#s;constructor(){this.#e={},this.#t={},this.#s={}}get _objects(){return this.#t}hasObject(e){return this.#t.hasOwnProperty(e)}registerObjects(e){Object.keys(e).forEach(s=>this.registerObject(s,e[s]))}registerObject(e,t){this.#e[e]=t}hasObjectClass(e){return this.#e.hasOwnProperty(e)}getObjectClass(e){return this.#e[e]}getAllClasses(){return this.#e}get _classes(){return this.#e}addObject(e){e&&e._id?(this.#t[e._id]=e,(!e._name||e._name.length==0)&&(e._name=e._id),this.#s[e._name]=e._id):a.log("unable to add object")}removeObject(e){const t=this.#t[e];t&&(delete this.#s[t?._name],delete this.#t[e])}getObject(e){return this.#t[e]}go(e){return this.getObject(e)}getObjectByName(e){return this.#s[e]?this.getObject(this.#s[e]):null}}const T=["_nano_commands","_cache_cmd_txt","_cache_jcmd","_xporter","_event_listeners_ids","_parent","_children"];function j(o){return T.includes(o)}function x(o){if(!o||typeof o!="object"||Array.isArray(o))return!1;const e=Object.getPrototypeOf(o);return e===Object.prototype||e===null}const B={info:(o,e)=>{a.log("XObject id "+e?._id)},log:(o,e)=>{o._params&&o._params[1]?a.log(o._params[1]):a.log(e)},fire:(o,e)=>{o._params&&o._params[1]?g.fire(o._params[1],o._params[2]):o._params&&o._params.event&&g.fire(o._params.event,o._params.data)},noop:()=>{},"set-field":(o,e)=>{const t=o._params?.name,s=o._params?.value;if(!(!e||typeof t!="string"||t.length===0)){if(j(t)){a.error(`set-field denied for protected field: ${t}`);return}e[t]=s}},"delete-field":(o,e)=>{const t=o._params?.name;if(!(!e||typeof t!="string"||t.length===0)){if(j(t)){a.error(`delete-field denied for protected field: ${t}`);return}delete e[t]}},"toggle-field":(o,e)=>{const t=o._params?.name;if(!e||typeof t!="string"||t.length===0)return;if(j(t)){a.error(`toggle-field denied for protected field: ${t}`);return}const s=e[t];typeof s=="boolean"?e[t]=!s:s==null?e[t]=!0:e[t]=!1},merge:(o,e)=>{const t=o._params?.name,s=o._params?.value;if(!e||typeof t!="string"||t.length===0)return;if(j(t)){a.error(`merge denied for protected field: ${t}`);return}if(!x(s)){a.error("merge expects _params.value as a plain object");return}const i=e[t];x(i)||(e[t]={}),Object.assign(e[t],s)},"run-seq":async(o,e)=>{if(!e)return;const t=o._params?.seq;if(!Array.isArray(t)){a.error("run-seq expects _params.seq as an array");return}for(const s of t){if(typeof s=="string"){await e.run(`${e._id} ${s}`);continue}if(s&&typeof s=="object"&&s._op){const i=s._object;if(!(i==null||i==="this"||i===e._id)){a.error("run-seq rejected non-self _object target");return}const r={_op:s._op,_params:s._params?{...s._params}:void 0};await e.execute(r);continue}a.error("run-seq skipped invalid step; expected string or object with _op")}}},O={_children:"child nodes"};class y{constructor(e,t,s){this._children=[],this._parent=null,this._on={},this._once={},this._process_frame=!0,this._process_data=!0,this._nano_commands={},this._event_listeners_ids={},this._event_parsed=!1,this._mounted=!1,this._xporter={_ignore_fields:["_to_xdata_ignore_fields","_xporter","_children","_on","_once","_on_create","_on_mount","_on_frame","_on_data","_process_frame","_process_data","_parent","_event_listeners_ids","_event_parsed","_mounted","_debug"],_instance_xporters:{}},t&&f.mergeDefaultsWithData(e,t),this._id=e&&e._id?e._id:"xo-"+f.guid(),this._type="object",this._children=[],this._nano_commands={},this.addNanoCommandPack(B),e&&e.hasOwnProperty("_nano_commands")&&e._nano_commands&&(this.addNanoCommandPack(e._nano_commands),delete e._nano_commands),this.addXporterDataIgnoreFields(["_nano_commands"]),this.addXporterInstanceXporter(y,i=>i.toXData()),this._xem_options={},!s&&e&&this.parse(e,O)}log(e,...t){this._debug&&e&&a.log(this._type+"->"+this._id+"]",e,...t)}init(e,t){!t&&e&&this.parse(e,O)}parseEvents(e){if(!this._event_parsed){e||(e=this._xem_options),Object.keys(this._on).forEach(s=>{this.addEventListener(s,this._on[s],e)});const t={};Object.assign(t,e),t._once=!0,Object.keys(this._once).forEach(s=>{this.addEventListener(s,this._once[s],t)}),this._event_parsed=!0}}addEventListener(e,t,s){s||(s=this._xem_options);let i;if(typeof t=="function")i=async r=>{t(this,r)};else if(typeof t=="string")i=async r=>{const c=this._id+" "+t+" event-data='"+JSON.stringify(r).replace(/'/g,"\\'")+"'";await this.run(c)};else throw new Error("event handler must be a function");const n=g.on(e,i,s,this);this._event_listeners_ids[e]||(this._event_listeners_ids[e]=[]),this._event_listeners_ids[e].push(n)}removeEventListener(e){const t=this._event_listeners_ids[e];t&&t.length&&(t.forEach(s=>{g.remove(s)}),delete this._event_listeners_ids[e])}removeAllEventListeners(){Object.keys(this._event_listeners_ids).forEach(t=>this.removeEventListener(t))}append(e){this._children?.push(e),e._parent=this}addNanoCommand(e,t){typeof t=="function"&&(this._nano_commands[e]=t)}addNanoCommandPack(e){e&&Object.keys(e).forEach(t=>{this.addNanoCommand(t,e[t])})}addXporterDataIgnoreFields(e){this._xporter._ignore_fields=this._xporter._ignore_fields.concat(e)}addXporterInstanceXporter(e,t){const s=f.guid();this._xporter._instance_xporters[s]={cls:e,handler:t}}parse(e,t=O){Object.keys(e).forEach(i=>{!t.hasOwnProperty(i)&&e.hasOwnProperty(i)&&(this[i]=e[i])})}parseFieldsFromXDataObject(e,t){Object.keys(t).forEach(i=>{e.hasOwnProperty(i)?this[i]=e[i]:this[i]=t[i]})}parseFields(e,t,s){t.forEach(i=>{if(e.hasOwnProperty(i))this[i]=e[i];else if(s&&i.startsWith("_")){const n=i.substring(1);e.hasOwnProperty(n)&&(this[i]=e[n],this[n]=e[n])}})}async onCreate(){this._on_create?this.checkAndRunInternalFunction(this._on_create):this._on&&this._on.create?this.checkAndRunInternalFunction(this._on.create):this._once&&this._once.create&&this.checkAndRunInternalFunction(this._once.create)}async runCmd(e){const t=e instanceof X?e:new X(e);await this.execute(t)}async checkAndRunInternalFunction(e,...t){if(Array.isArray(e)){for(const s of e)await this.checkAndRunInternalFunction(s,...t);return}if(typeof e=="function"){await e(this,...t);return}if(typeof e=="string"){if(t.length>0){const s=t[0],i=JSON.stringify(s).replace(/'/g,"\\'");await this.run(`${this._id} ${e} data:'${i}'`)}else await this.run(`${this._id} ${e}`);return}if(e&&typeof e=="object"&&e._op){const s=e;if((s._object===void 0||s._object===null||s._object==="this"?this._id:s._object)!==this._id){a.error("XObject JSON handler target not supported in core-only patch; expected _object omitted/'this'/"+this._id);return}const n={_op:s._op,_params:s._params?{...s._params}:void 0};t.length>0&&(n._params||(n._params={}),Object.prototype.hasOwnProperty.call(n._params,"data")||(n._params.data=t[0])),this._debug&&a.log(this._type+"->"+this._id+"]","JSON handler executed locally",n),await this.execute(n);return}}async onMount(){if(!this._mounted){this.parseEvents(this._xem_options),this._process_data&&typeof this._data_source=="string"&&this._data_source.length>0&&this.bindDataSource(this._data_source,{initial:!0}),this._on_mount?await this.checkAndRunInternalFunction(this._on_mount):this._on&&this._on.mount?await this.checkAndRunInternalFunction(this._on.mount):this._once&&this._once.mount&&await this.checkAndRunInternalFunction(this._once.mount),this._mounted=!0;for(const e of this._children)e.onMount&&typeof e.onMount=="function"&&e.onMount()}}emptyDataSource(){const e=this._data_source;if(typeof e!="string"||e.length===0)return;const t=this._type??this.constructor.name,s=this._id??"no-id";u.delete(e,{source:`${t}#${s}.emptyDataSource`})}async onData(e){this._process_data&&(this._on_data?this.checkAndRunInternalFunction(this._on_data,e):this._on&&this._on.data?this.checkAndRunInternalFunction(this._on.data,e):this._once&&this._once.data&&this.checkAndRunInternalFunction(this._once.data,e))}async onFrame(e){this._process_frame&&(this._on_frame?this.checkAndRunInternalFunction(this._on_frame,e):this._on&&this._on.frame?this.checkAndRunInternalFunction(this._on.frame,e):this._once&&this._once.frame&&this.checkAndRunInternalFunction(this._once.frame,e));for(const t of this._children)t.onFrame&&typeof t.onFrame=="function"&&t.onFrame(e)}async run(e,t=!0){let s=this._cache_cmd_txt&&this._cache_cmd_txt==e?this._cache_jcmd:m.parseObjectCommand(e);t&&(this._cache_cmd_txt=e,this._cache_jcmd=s),await this.execute(s)}async execute(e){if(e._op&&this._nano_commands[e._op])try{await this._nano_commands[e._op](e,this)}catch(t){a.error(this._id+" has error with command name "+e._op+" "+t)}else a.error(this._id+" has no command name "+e._op)}toXData(){const e={};return Object.keys(this).forEach(t=>{if(!this._xporter._ignore_fields.includes(t)&&this.hasOwnProperty(t)&&this[t]!==void 0){const s=this[t];if(typeof s=="function")return;if(typeof s=="object"){const i=Object.keys(this._xporter._instance_xporters);let n=!0;i.forEach(r=>{this._xporter._instance_xporters[r],s instanceof this._xporter._instance_xporters[r].cls&&(e[t]=this._xporter._instance_xporters[r].handler(s),n=!1)}),n&&(e[t]=s)}else e[t]=s}}),e._children=[],this._children.length>0&&this._children.forEach(t=>{typeof t.toXData=="function"&&e._children?.push(t.toXData())}),e}toString(){return JSON.stringify(this.toXData())}clearAttributes(e){e.forEach(t=>{this.hasOwnProperty(t)&&(this[t]=null,delete this[t])})}bindDataSource(e,t){const s=t?.initial??!0,i=e??this._data_source;typeof i!="string"||i.length===0||this._process_data&&(this._xd_bound_key===i&&this._xd_unsub||(this.unbindDataSource(),this._data_source=i,this._xd_bound_key=i,this._type??this.constructor.name,this._id,this._xd_unsub=u.on(i,async n=>{await this.onData(n.value)}),s&&u.has(i)&&this.onData(u.get(i))))}unbindDataSource(){this._xd_unsub?.(),this._xd_unsub=void 0,this._xd_bound_key=void 0}async dispose(){if(this.unbindDataSource(),this._parent){const e=this._parent._children.indexOf(this);e>-1&&this._parent._children.splice(e,1)}this._process_data=!1,this._process_frame=!1,this.removeAllEventListeners(),this.clearAttributes(["_cache_cmd_txt","_cache_jcmd","_nano_commands","_event_listeners_ids","_parent","_on","_once","_xem_options","_xporter"]),this._children&&this._children.forEach(e=>{typeof e.dispose=="function"&&e.dispose()}),this._children=[]}removeChild(e,t=!1){if(t)e.dispose();else{const s=this._children.indexOf(e);s>-1&&this._children.splice(s,1),e._parent=null}}addChild(e){this.append(e)}}class W{static getObjects(){return{object:y}}}const q="engine:module:num-of-objects:";class J{constructor(e){this._log_rules={createObject:!1,removeObject:!1},this.#e=new A,this._name=e._name,this._id=f.guid()}#e;load(){a.log("Module "+this._name+" loaded")}create(e){let t;if(e.hasOwnProperty("_type"))if(this.#e.hasObjectClass(e._type)){let s=this.#e.getObjectClass(e._type);s.hasOwnProperty("defaults")&&f.mergeDefaultsWithData(e,s.defaults),t=new s(e)}else throw"Xpell object '"+e._type+"' not found";else t=new y(e);return this.#e.addObject(t),e._children&&e._children.forEach(s=>{const i=this.create(s);t.append(i)}),t.onCreate(),t}remove(e){const t=this.#e.getObject(e);if(!t)return;const s=[],i=n=>{n?._id&&(s.push(n._id),(n._children??[]).forEach(r=>i(r)))};i(t),typeof t.dispose=="function"&&t.dispose(),s.reverse().forEach(n=>this.#e.removeObject(n))}_info(e){a.log("module info")}async run(e){if(e){let t=e.trim();t.startsWith(this._name)||(t=this._name+" "+t);let s=m.parse(t);return await this.execute(s)}else throw"Unable to parse Xpell Command"}async execute(e){if(!e||!e._op)throw new Error(`Invalid XCommand: missing _op (module: ${this._name})`);const t=e._object;if(t){const n=this.#e.getObject(t);if(!n)throw new Error(`Module '${this._name}' cant find object id: ${t}`);return await n.execute(e)}const s="_"+e._op.replaceAll("-","_"),i=this[s];if(typeof i=="function")return await i.call(this,e);throw new Error(`Module '${this._name}' cant find op: ${e._op}`)}async onFrame(e){const t=this.#e._objects,s=Object.keys(t);s.forEach(i=>{const n=t[i];n&&n.onFrame&&typeof n.onFrame=="function"&&n?.onFrame(e)}),P.set(q+this._id,s.length,{source:"xmodule"})}get om(){return this.#e}get _object_manager(){return this.#e}getObject(e){return this.#e.getObject(e)}get _o(){return this.#e._objects}importObjectPack(e){this.#e.registerObjects(e.getObjects())}importObjects(e){this.importObjectPack(e)}importObject(e,t){this.#e.registerObject(e,t)}async _help(e){const t=e?._params?._op??e?._params?._command??"";return this.help(t)}help(e){return{module:this._name,usage:`${this._name} help`,ops:["help"],note:"No help() implemented for this module."}}}class V{static get(e,t,s){if(!e?._params)return s;const i=e._params[t];return i!==void 0?i:s}static has(e,t){return e?._params&&e._params[t]!==void 0}static str(e,...t){for(const s of t){const i=e?._params?.[s];if(i!=null)return String(i)}}static bool(e,t,s=!1){const i=this.get(e,t,s);if(typeof i=="boolean")return i;if(typeof i=="number")return i!==0;if(typeof i=="string"){const n=i.toLowerCase();if(["1","true","yes","on"].includes(n))return!0;if(["0","false","no","off"].includes(n))return!1}return!!i}static int(e,t,s=0){const i=this.get(e,t,s),n=parseInt(String(i),10);return Number.isFinite(n)?n:s}static json(e,t,s){const i=this.get(e,t,s);if(i==null)return s;if(typeof i=="object")return i;if(typeof i=="string")try{return JSON.parse(i)}catch{return s}return s}}class E extends Error{constructor(e,t,s){super(t),this.name="XError",this._code=e,this._level=s?._level??"error",this._meta=s?._meta,this._cause=s?._cause}toXData(){return{_code:this._code,_level:this._level,_meta:this._meta,_cause:this._cause,name:this.name,message:this.message}}toJSON(){return{...this.toXData(),stack:this.stack}}}class d{constructor(e){this._ok=!1,this._ts=Date.now(),this._pt=0,e&&this.setXData(e)}static create(e){return new d(e)}static ok(e){return new d({_ok:!0,_result:e})}static error(e){if(e instanceof E)return new d({_ok:!1,_result:e.toXData()});const t=new E("E_INTERNAL",e?.message??String(e),{_cause:e});return new d({_ok:!1,_result:t.toXData()})}stopProcessTimeCounter(){this._pt=Date.now()-this._ts}toXData(){return this.stopProcessTimeCounter(),{_ok:this._ok,_ts:this._ts,_pt:this._pt,_result:this._result}}toString(){return JSON.stringify(this.toXData())}setXData(e){e&&("_ok"in e&&(this._ok=!!e._ok),"_ts"in e&&typeof e._ts=="number"&&(this._ts=e._ts),"_pt"in e&&typeof e._pt=="number"&&(this._pt=e._pt),"_result"in e&&(this._result=e._result))}}class H extends d{constructor(e){super(d.error(e).toXData())}}class K extends d{constructor(e){super({_ok:!0,_result:e})}}const $="engine:frame-number",R="engine:fps";class N{constructor(e){this._log_rules={},this._modules={},this._schedule_frame=e?._schedule_frame??f.createDefaultScheduler(e?._target_fps),this._version="0.0.1",this._engine_id=f.guid(),this._frame_number=0,this._fps_calc=new L,this.parser=m,this._modules={},g.fire("xpell-init"),a._enabled=!1}set verbose(e){a._enabled=e}set _verbose(e){a._enabled=e}log(e,...t){a.log(e,...t)}async delay(e){return new Promise(t=>setTimeout(t,e))}loadModule(e){this._modules.hasOwnProperty(e._name)?a.log("Module "+e._name+" already loaded"):(this._modules[e._name]=e,e.load())}loadModules(...e){e.forEach(t=>this.loadModule(t))}info(){a.log(`Xpell information:
2
2
  - Engine Id: `+this._engine_id+`
3
- - Version `+this._version)}run(t){if(t?.length>2){let e=m.parse(t);return this.execute(e)}else throw"Unable to parse Xpell command"}execute(t){if(t&&t._module&&this._modules[t._module])return this._modules[t._module].execute(t);throw"Xpell module "+t._module+" not loaded"}onFrame(){this._frame_number++;for(const e of Object.keys(this._modules)){const s=this._modules[e];s?.onFrame&&typeof s.onFrame=="function"&&s.onFrame(this._frame_number)}const t=this._fps_calc.calc();u.set(I,this._frame_number,{source:"engine"}),u.set(P,t,{source:"engine"}),u._compat_legacy_keys&&(u.set("frame-number",this._frame_number,{source:"engine:legacy"}),u.set("fps",t,{source:"engine:legacy"})),this._schedule_frame(()=>this.onFrame())}getModule(t){return this._modules[t]}start(){c.log("Starting Xpell"),this.onFrame()}getParam(t,e){return t in u._o?u._o[t]:e}}const X=new A;exports.XCommand=F;exports.XD_FPS=P;exports.XD_FRAME_NUMBER=I;exports.XData=u;exports.XError=O;exports.XEventManager=g;exports.XLogger=c;exports.XModule=C;exports.XObject=y;exports.XObjectManager=S;exports.XObjectPack=L;exports.XParams=T;exports.XParser=m;exports.XResponse=d;exports.XResponseError=W;exports.XResponseOK=J;exports.XUtils=f;exports.Xpell=X;exports.XpellEngine=A;exports._XData=k;exports._XEventManager=M;exports._XLogger=E;exports._XUtils=x;exports._x=X;exports._xd=u;exports._xem=g;exports._xlog=c;exports._xu=f;exports.default=X;
3
+ - Version `+this._version)}run(e){if(e?.length>2){let t=m.parse(e);return this.execute(t)}else throw"Unable to parse Xpell command"}execute(e){if(e&&e._module&&this._modules[e._module])return this._modules[e._module].execute(e);throw"Xpell module "+e._module+" not loaded"}onFrame(){this._frame_number++;for(const t of Object.keys(this._modules)){const s=this._modules[t];s?.onFrame&&typeof s.onFrame=="function"&&s.onFrame(this._frame_number)}const e=this._fps_calc.calc();u.set($,this._frame_number,{source:"engine"}),u.set(R,e,{source:"engine"}),u._compat_legacy_keys&&(u.set("frame-number",this._frame_number,{source:"engine:legacy"}),u.set("fps",e,{source:"engine:legacy"})),this._schedule_frame(()=>this.onFrame())}getModule(e){return this._modules[e]}start(){a.log("Starting Xpell"),this.onFrame()}getParam(e,t){return e in u._o?u._o[e]:t}}const D=new N;exports.XCommand=X;exports.XD_FPS=R;exports.XD_FRAME_NUMBER=$;exports.XData=u;exports.XError=E;exports.XEventManager=g;exports.XLogger=a;exports.XModule=J;exports.XObject=y;exports.XObjectManager=A;exports.XObjectPack=W;exports.XParams=V;exports.XParser=m;exports.XResponse=d;exports.XResponseError=H;exports.XResponseOK=K;exports.XUtils=f;exports.Xpell=D;exports.XpellEngine=N;exports._XData=M;exports._XEventManager=I;exports._XLogger=F;exports._XUtils=k;exports._x=D;exports._xd=P;exports._xem=g;exports._xlog=a;exports._xu=f;exports.default=D;
@@ -1,4 +1,4 @@
1
- class X {
1
+ class S {
2
2
  /**
3
3
  * Create ignore list for parser to ignore spell words
4
4
  * @param list - comma-separated list of words
@@ -25,8 +25,8 @@ class X {
25
25
  if (e && typeof e.getRandomValues == "function") {
26
26
  const r = new Uint8Array(16);
27
27
  e.getRandomValues(r), r[6] = r[6] & 15 | 64, r[8] = r[8] & 63 | 128;
28
- const a = Array.from(r, (c) => c.toString(16).padStart(2, "0"));
29
- return a.slice(0, 4).join("") + "-" + a.slice(4, 6).join("") + "-" + a.slice(6, 8).join("") + "-" + a.slice(8, 10).join("") + "-" + a.slice(10, 16).join("");
28
+ const c = Array.from(r, (_) => _.toString(16).padStart(2, "0"));
29
+ return c.slice(0, 4).join("") + "-" + c.slice(4, 6).join("") + "-" + c.slice(6, 8).join("") + "-" + c.slice(8, 10).join("") + "-" + c.slice(10, 16).join("");
30
30
  }
31
31
  const s = "0123456789abcdef".split(""), i = [];
32
32
  let n;
@@ -106,8 +106,8 @@ class X {
106
106
  return (n) => e.setTimeout(n, i);
107
107
  }
108
108
  }
109
- const p = new X();
110
- class k {
109
+ const p = new S();
110
+ class M {
111
111
  #t = 0;
112
112
  // displayed fps (stable)
113
113
  #e = 0;
@@ -143,7 +143,7 @@ class k {
143
143
  this.#t = 0, this.#e = 0, this.#s = 0;
144
144
  }
145
145
  }
146
- class F {
146
+ class I {
147
147
  constructor(t) {
148
148
  this._enabled = !0, this._show_date = !1, this._show_time = !0, this._debug = !1, t && this.configure(t);
149
149
  }
@@ -167,12 +167,12 @@ class F {
167
167
  !this._enabled || !this._debug || console.debug(this._dt(), t, ...e);
168
168
  }
169
169
  }
170
- const _ = new F(), x = typeof process < "u" && !!process?.env && process.env.NODE_ENV === "production";
171
- x || console.info(
170
+ const a = new I(), X = typeof process < "u" && !!process?.env && process.env.NODE_ENV === "production";
171
+ X || console.info(
172
172
  "[Xpell] _xlog is redirected to console in development mode. Tip: enable 'Show timestamps' in DevTools → Console for timed logs."
173
173
  );
174
- const y = x ? _ : console;
175
- class S {
174
+ const y = X ? a : console;
175
+ class A {
176
176
  constructor() {
177
177
  this._objects = {}, this._listeners = /* @__PURE__ */ new Map(), this._any_listeners = /* @__PURE__ */ new Set(), this._compat_writes = !0, this._warn_legacy_writes = !0, this._verbose = !1, this._compat_legacy_keys = !0, this._o_proxy = null, this._objects = {};
178
178
  }
@@ -254,8 +254,8 @@ class S {
254
254
  for (const s of this._any_listeners) s(t);
255
255
  }
256
256
  }
257
- const u = new S();
258
- class M {
257
+ const u = new A(), P = u;
258
+ class x {
259
259
  constructor(t) {
260
260
  t && Object.keys(t).forEach((e) => {
261
261
  this[e] = t[e];
@@ -293,13 +293,13 @@ const w = {
293
293
  */
294
294
  static parse(t, e) {
295
295
  const s = t.split(" ");
296
- let i = new M();
296
+ let i = new x();
297
297
  if (e ? (i._module = e, i._op = s[0]) : (i._module = s[0], i._op = s[1]), i._params = {}, s.length > 1)
298
298
  for (let n = 2; n < s.length; ++n) {
299
299
  const r = s[n];
300
300
  if (r.indexOf(":") > -1) {
301
- const c = r.split(":");
302
- i._params[c[0]] = c[1];
301
+ const _ = r.split(":");
302
+ i._params[_[0]] = _[1];
303
303
  } else
304
304
  i._params[n - 1] = s[n];
305
305
  }
@@ -320,35 +320,35 @@ const w = {
320
320
  throw new Error("Invalid object selector '#'. Use '#<id>'");
321
321
  const r = s.shift();
322
322
  if (!r) throw new Error("Missing operation");
323
- const a = {};
324
- let c = null, h = null;
323
+ const c = {};
324
+ let _ = null, h = null;
325
325
  if (s.forEach((l) => {
326
326
  if (h) {
327
327
  if (h += ` ${l}`, l.endsWith(h[0])) {
328
328
  const m = h.slice(1, -1).replace(/_%20_/g, " ");
329
- a[c] = m, h = null;
329
+ c[_] = m, h = null;
330
330
  }
331
331
  return;
332
332
  }
333
333
  if (l.startsWith('"') || l.startsWith("'")) {
334
334
  if (h = l, l.endsWith(l[0]) && l.length > 1) {
335
335
  const m = l.slice(1, -1).replace(/_%20_/g, " ");
336
- a[c] = m, h = null;
336
+ c[_] = m, h = null;
337
337
  }
338
338
  return;
339
339
  }
340
340
  if (l.includes(":")) {
341
- const m = l.split(":"), D = m[0], E = m.slice(1).join(":").replace(/_%20_/g, " ");
342
- a[D] = E, c = null;
341
+ const m = l.split(":"), k = m[0], F = m.slice(1).join(":").replace(/_%20_/g, " ");
342
+ c[k] = F, _ = null;
343
343
  return;
344
344
  }
345
- c = l.replace(/_%20_/g, " ");
345
+ _ = l.replace(/_%20_/g, " ");
346
346
  }), h) throw new Error("Unclosed quoted parameter value");
347
347
  return {
348
348
  _module: i,
349
349
  _object: n,
350
350
  _op: r,
351
- _params: a
351
+ _params: c
352
352
  };
353
353
  }
354
354
  /**
@@ -371,16 +371,16 @@ const w = {
371
371
  let i = {};
372
372
  i._children = [];
373
373
  const n = t.nodeName, r = t.nodeName;
374
- let a = e;
374
+ let c = e;
375
375
  if (e ? (i[w.type] = "xhtml", i._html_ns = "http://www.w3.org/2000/svg") : i._type = s.elements[n] ? s.elements[n] : n, t.attributes)
376
- for (let c = 0; c < t.attributes.length; ++c) {
377
- const h = t.attributes[c], l = s.attributes[h.name] ? s.attributes[h.name] : h.name;
376
+ for (let _ = 0; _ < t.attributes.length; ++_) {
377
+ const h = t.attributes[_], l = s.attributes[h.name] ? s.attributes[h.name] : h.name;
378
378
  i[l] = h.value;
379
379
  }
380
- if (t?.firstChild?.nodeValue && (i.text = t?.firstChild.nodeValue.trim()), i[w.type] == "xhtml" ? i._html_tag = r : i[w.type] == "svg" && (a = !0, i._html_ns = "http://www.w3.org/2000/svg"), t?.childNodes.length > 0)
381
- for (let c = 0; c < t.childNodes.length; ++c) {
382
- const h = t.childNodes[c];
383
- h.nodeName.startsWith("#") || i[w.children].push(f.xml2Xpell(h, a));
380
+ if (t?.firstChild?.nodeValue && (i.text = t?.firstChild.nodeValue.trim()), i[w.type] == "xhtml" ? i._html_tag = r : i[w.type] == "svg" && (c = !0, i._html_ns = "http://www.w3.org/2000/svg"), t?.childNodes.length > 0)
381
+ for (let _ = 0; _ < t.childNodes.length; ++_) {
382
+ const h = t.childNodes[_];
383
+ h.nodeName.startsWith("#") || i[w.children].push(f.xml2Xpell(h, c));
384
384
  }
385
385
  return i;
386
386
  }
@@ -416,7 +416,7 @@ f.html2XMap = {
416
416
  }
417
417
  };
418
418
  let g = f;
419
- class I {
419
+ class $ {
420
420
  constructor() {
421
421
  this._log_rules = {
422
422
  register: !1,
@@ -433,14 +433,14 @@ class I {
433
433
  */
434
434
  on(t, e, s = {}, i) {
435
435
  this._events[t] || (this._events[t] = []);
436
- const n = s?._owner ?? i, r = p.guid(), a = {
436
+ const n = s?._owner ?? i, r = p.guid(), c = {
437
437
  _id: r,
438
438
  _callback: e,
439
439
  _options: s,
440
440
  _owner: n,
441
441
  _tag: s?._tag
442
442
  };
443
- return this._events[t].push(a), this._listener_index[r] = t, this._log_rules.register && y.log("XEM Register", t, r), r;
443
+ return this._events[t].push(c), this._listener_index[r] = t, this._log_rules.register && y.log("XEM Register", t, r), r;
444
444
  }
445
445
  /**
446
446
  * Register a listener that will be removed after first fire.
@@ -459,8 +459,8 @@ class I {
459
459
  for (const r of i) {
460
460
  try {
461
461
  r && r._callback && r._callback(e);
462
- } catch (a) {
463
- y.error(a);
462
+ } catch (c) {
463
+ y.error(c);
464
464
  }
465
465
  r?._options?._once && n.push(r._id);
466
466
  }
@@ -497,8 +497,8 @@ class I {
497
497
  this._events = {}, this._listener_index = {};
498
498
  }
499
499
  }
500
- const b = new I();
501
- class P {
500
+ const b = new $();
501
+ class R {
502
502
  #t;
503
503
  #e;
504
504
  #s;
@@ -562,7 +562,7 @@ class P {
562
562
  * @param xObject XObject to maintain
563
563
  */
564
564
  addObject(t) {
565
- t && t._id ? (this.#e[t._id] = t, (!t._name || t._name.length == 0) && (t._name = t._id), this.#s[t._name] = t._id) : _.log("unable to add object");
565
+ t && t._id ? (this.#e[t._id] = t, (!t._name || t._name.length == 0) && (t._name = t._id), this.#s[t._name] = t._id) : a.log("unable to add object");
566
566
  }
567
567
  /**
568
568
  * Remove XObject from the manager
@@ -597,18 +597,115 @@ class P {
597
597
  return this.#s[t] ? this.getObject(this.#s[t]) : null;
598
598
  }
599
599
  }
600
- const A = {
600
+ const N = [
601
+ "_nano_commands",
602
+ "_cache_cmd_txt",
603
+ "_cache_jcmd",
604
+ "_xporter",
605
+ "_event_listeners_ids",
606
+ "_parent",
607
+ "_children"
608
+ ];
609
+ function v(o) {
610
+ return N.includes(o);
611
+ }
612
+ function D(o) {
613
+ if (!o || typeof o != "object" || Array.isArray(o)) return !1;
614
+ const t = Object.getPrototypeOf(o);
615
+ return t === Object.prototype || t === null;
616
+ }
617
+ const C = {
601
618
  info: (o, t) => {
602
- _.log("XObject id " + t?._id);
619
+ a.log("XObject id " + t?._id);
603
620
  },
604
621
  log: (o, t) => {
605
- o._params && o._params[1] ? _.log(o._params[1]) : _.log(t);
622
+ o._params && o._params[1] ? a.log(o._params[1]) : a.log(t);
606
623
  },
607
624
  fire: (o, t) => {
608
625
  o._params && o._params[1] ? b.fire(o._params[1], o._params[2]) : o._params && o._params.event && b.fire(o._params.event, o._params.data);
626
+ },
627
+ // no-op utility command for sequence placeholders and explicit "do nothing" steps.
628
+ noop: () => {
629
+ },
630
+ // set a runtime field directly on the object.
631
+ "set-field": (o, t) => {
632
+ const e = o._params?.name, s = o._params?.value;
633
+ if (!(!t || typeof e != "string" || e.length === 0)) {
634
+ if (v(e)) {
635
+ a.error(`set-field denied for protected field: ${e}`);
636
+ return;
637
+ }
638
+ t[e] = s;
639
+ }
640
+ },
641
+ // delete a runtime field from the object.
642
+ "delete-field": (o, t) => {
643
+ const e = o._params?.name;
644
+ if (!(!t || typeof e != "string" || e.length === 0)) {
645
+ if (v(e)) {
646
+ a.error(`delete-field denied for protected field: ${e}`);
647
+ return;
648
+ }
649
+ delete t[e];
650
+ }
651
+ },
652
+ // toggle a field with boolean-first semantics.
653
+ "toggle-field": (o, t) => {
654
+ const e = o._params?.name;
655
+ if (!t || typeof e != "string" || e.length === 0) return;
656
+ if (v(e)) {
657
+ a.error(`toggle-field denied for protected field: ${e}`);
658
+ return;
659
+ }
660
+ const s = t[e];
661
+ typeof s == "boolean" ? t[e] = !s : s == null ? t[e] = !0 : t[e] = !1;
662
+ },
663
+ // shallow-merge a plain object into a target object field.
664
+ merge: (o, t) => {
665
+ const e = o._params?.name, s = o._params?.value;
666
+ if (!t || typeof e != "string" || e.length === 0) return;
667
+ if (v(e)) {
668
+ a.error(`merge denied for protected field: ${e}`);
669
+ return;
670
+ }
671
+ if (!D(s)) {
672
+ a.error("merge expects _params.value as a plain object");
673
+ return;
674
+ }
675
+ const i = t[e];
676
+ D(i) || (t[e] = {}), Object.assign(t[e], s);
677
+ },
678
+ // run a sequence of steps in strict order (await each).
679
+ "run-seq": async (o, t) => {
680
+ if (!t) return;
681
+ const e = o._params?.seq;
682
+ if (!Array.isArray(e)) {
683
+ a.error("run-seq expects _params.seq as an array");
684
+ return;
685
+ }
686
+ for (const s of e) {
687
+ if (typeof s == "string") {
688
+ await t.run(`${t._id} ${s}`);
689
+ continue;
690
+ }
691
+ if (s && typeof s == "object" && s._op) {
692
+ const i = s._object;
693
+ if (!(i == null || i === "this" || i === t._id)) {
694
+ a.error("run-seq rejected non-self _object target");
695
+ return;
696
+ }
697
+ const r = {
698
+ _op: s._op,
699
+ _params: s._params ? { ...s._params } : void 0
700
+ };
701
+ await t.execute(r);
702
+ continue;
703
+ }
704
+ a.error("run-seq skipped invalid step; expected string or object with _op");
705
+ }
609
706
  }
610
- }, j = { _children: "child nodes" };
611
- class v {
707
+ }, O = { _children: "child nodes" };
708
+ class j {
612
709
  /**
613
710
  * XObject constructor is creating the object and adding all the data keys to the XObject instance
614
711
  * @param data constructor input data (object)
@@ -637,14 +734,14 @@ class v {
637
734
  "_debug"
638
735
  ],
639
736
  _instance_xporters: {}
640
- }, e && p.mergeDefaultsWithData(t, e), this._id = t && t._id ? t._id : "xo-" + p.guid(), this._type = "object", this._children = [], this._nano_commands = {}, this.addNanoCommandPack(A), t && t.hasOwnProperty("_nano_commands") && t._nano_commands && (this.addNanoCommandPack(t._nano_commands), delete t._nano_commands), this.addXporterDataIgnoreFields(["_nano_commands"]), this.addXporterInstanceXporter(v, (i) => i.toXData()), this._xem_options = {
737
+ }, e && p.mergeDefaultsWithData(t, e), this._id = t && t._id ? t._id : "xo-" + p.guid(), this._type = "object", this._children = [], this._nano_commands = {}, this.addNanoCommandPack(C), t && t.hasOwnProperty("_nano_commands") && t._nano_commands && (this.addNanoCommandPack(t._nano_commands), delete t._nano_commands), this.addXporterDataIgnoreFields(["_nano_commands"]), this.addXporterInstanceXporter(j, (i) => i.toXData()), this._xem_options = {
641
738
  // _instance:_xem
642
739
  // _object: this
643
740
  // _support_html: true
644
- }, !s && t && this.parse(t, j);
741
+ }, !s && t && this.parse(t, O);
645
742
  }
646
743
  log(t, ...e) {
647
- this._debug && t && _.log(this._type + "->" + this._id + "]", t, ...e);
744
+ this._debug && t && a.log(this._type + "->" + this._id + "]", t, ...e);
648
745
  }
649
746
  /**
650
747
  * Initialize the XObject
@@ -653,7 +750,7 @@ class v {
653
750
  * @deprecated - use parse method instead
654
751
  */
655
752
  init(t, e) {
656
- !e && t && this.parse(t, j);
753
+ !e && t && this.parse(t, O);
657
754
  }
658
755
  parseEvents(t) {
659
756
  if (!this._event_parsed) {
@@ -675,8 +772,8 @@ class v {
675
772
  };
676
773
  else if (typeof e == "string")
677
774
  i = async (r) => {
678
- const a = this._id + " " + e + " event-data='" + JSON.stringify(r).replace(/'/g, "\\'") + "'";
679
- await this.run(a);
775
+ const c = this._id + " " + e + " event-data='" + JSON.stringify(r).replace(/'/g, "\\'") + "'";
776
+ await this.run(c);
680
777
  };
681
778
  else
682
779
  throw new Error("event handler must be a function");
@@ -735,7 +832,7 @@ class v {
735
832
  * @param data data to parse
736
833
  * @param ignore - lis of words to ignore in the parse process
737
834
  */
738
- parse(t, e = j) {
835
+ parse(t, e = O) {
739
836
  Object.keys(t).forEach((i) => {
740
837
  !e.hasOwnProperty(i) && t.hasOwnProperty(i) && (this[i] = t[i]);
741
838
  });
@@ -784,15 +881,43 @@ class v {
784
881
  async onCreate() {
785
882
  this._on_create ? this.checkAndRunInternalFunction(this._on_create) : this._on && this._on.create ? this.checkAndRunInternalFunction(this._on.create) : this._once && this._once.create && this.checkAndRunInternalFunction(this._once.create);
786
883
  }
884
+ async runCmd(t) {
885
+ const e = t instanceof x ? t : new x(t);
886
+ await this.execute(e);
887
+ }
787
888
  async checkAndRunInternalFunction(t, ...e) {
788
- if (typeof t == "function")
889
+ if (Array.isArray(t)) {
890
+ for (const s of t)
891
+ await this.checkAndRunInternalFunction(s, ...e);
892
+ return;
893
+ }
894
+ if (typeof t == "function") {
789
895
  await t(this, ...e);
790
- else if (typeof t == "string")
896
+ return;
897
+ }
898
+ if (typeof t == "string") {
791
899
  if (e.length > 0) {
792
900
  const s = e[0], i = JSON.stringify(s).replace(/'/g, "\\'");
793
901
  await this.run(`${this._id} ${t} data:'${i}'`);
794
902
  } else
795
903
  await this.run(`${this._id} ${t}`);
904
+ return;
905
+ }
906
+ if (t && typeof t == "object" && t._op) {
907
+ const s = t;
908
+ if ((s._object === void 0 || s._object === null || s._object === "this" ? this._id : s._object) !== this._id) {
909
+ a.error(
910
+ "XObject JSON handler target not supported in core-only patch; expected _object omitted/'this'/" + this._id
911
+ );
912
+ return;
913
+ }
914
+ const n = {
915
+ _op: s._op,
916
+ _params: s._params ? { ...s._params } : void 0
917
+ };
918
+ e.length > 0 && (n._params || (n._params = {}), Object.prototype.hasOwnProperty.call(n._params, "data") || (n._params.data = e[0])), this._debug && a.log(this._type + "->" + this._id + "]", "JSON handler executed locally", n), await this.execute(n);
919
+ return;
920
+ }
796
921
  }
797
922
  /**
798
923
  * Triggers when the object is being mounted to other element
@@ -874,10 +999,10 @@ class v {
874
999
  try {
875
1000
  await this._nano_commands[t._op](t, this);
876
1001
  } catch (e) {
877
- _.error(this._id + " has error with command name " + t._op + " " + e);
1002
+ a.error(this._id + " has error with command name " + t._op + " " + e);
878
1003
  }
879
1004
  else
880
- _.error(this._id + " has no command name " + t._op);
1005
+ a.error(this._id + " has no command name " + t._op);
881
1006
  }
882
1007
  /**
883
1008
  * Return an IXObjectData JSON representation of the XObject
@@ -957,29 +1082,29 @@ class v {
957
1082
  this.append(t);
958
1083
  }
959
1084
  }
960
- class B {
1085
+ class W {
961
1086
  /**
962
1087
  * Get all registered object in this ObjectPack
963
1088
  * @returns XObject dictionary
964
1089
  */
965
1090
  static getObjects() {
966
1091
  return {
967
- object: v
1092
+ object: j
968
1093
  };
969
1094
  }
970
1095
  }
971
- const $ = "engine:module:num-of-objects:";
972
- class C {
1096
+ const T = "engine:module:num-of-objects:";
1097
+ class q {
973
1098
  //engine: any; //deprecated remove after spell3d
974
1099
  constructor(t) {
975
1100
  this._log_rules = {
976
1101
  createObject: !1,
977
1102
  removeObject: !1
978
- }, this.#t = new P(), this._name = t._name, this._id = p.guid();
1103
+ }, this.#t = new R(), this._name = t._name, this._id = p.guid();
979
1104
  }
980
1105
  #t;
981
1106
  load() {
982
- _.log("Module " + this._name + " loaded");
1107
+ a.log("Module " + this._name + " loaded");
983
1108
  }
984
1109
  /**
985
1110
  * Creates new XObject from data object
@@ -995,7 +1120,7 @@ class C {
995
1120
  } else
996
1121
  throw "Xpell object '" + t._type + "' not found";
997
1122
  else
998
- e = new v(t);
1123
+ e = new j(t);
999
1124
  return this.#t.addObject(e), t._children && t._children.forEach((s) => {
1000
1125
  const i = this.create(s);
1001
1126
  e.append(i);
@@ -1014,7 +1139,7 @@ class C {
1014
1139
  i(e), typeof e.dispose == "function" && e.dispose(), s.reverse().forEach((n) => this.#t.removeObject(n));
1015
1140
  }
1016
1141
  _info(t) {
1017
- _.log("module info");
1142
+ a.log("module info");
1018
1143
  }
1019
1144
  //xpell interpreter
1020
1145
  /**
@@ -1063,7 +1188,7 @@ class C {
1063
1188
  s.forEach((i) => {
1064
1189
  const n = e[i];
1065
1190
  n && n.onFrame && typeof n.onFrame == "function" && n?.onFrame(t);
1066
- }), u.set($ + this._id, s.length, {
1191
+ }), P.set(T + this._id, s.length, {
1067
1192
  source: "xmodule"
1068
1193
  });
1069
1194
  }
@@ -1142,7 +1267,7 @@ class C {
1142
1267
  };
1143
1268
  }
1144
1269
  }
1145
- class L {
1270
+ class J {
1146
1271
  /* -------------------------------------------------- */
1147
1272
  /* core helpers */
1148
1273
  /* -------------------------------------------------- */
@@ -1192,7 +1317,7 @@ class L {
1192
1317
  return s;
1193
1318
  }
1194
1319
  }
1195
- class O extends Error {
1320
+ class E extends Error {
1196
1321
  constructor(t, e, s) {
1197
1322
  super(e), this.name = "XError", this._code = t, this._level = s?._level ?? "error", this._meta = s?._meta, this._cause = s?._cause;
1198
1323
  }
@@ -1229,12 +1354,12 @@ class d {
1229
1354
  return new d({ _ok: !0, _result: t });
1230
1355
  }
1231
1356
  static error(t) {
1232
- if (t instanceof O)
1357
+ if (t instanceof E)
1233
1358
  return new d({
1234
1359
  _ok: !1,
1235
1360
  _result: t.toXData()
1236
1361
  });
1237
- const e = new O(
1362
+ const e = new E(
1238
1363
  "E_INTERNAL",
1239
1364
  t?.message ?? String(t),
1240
1365
  { _cause: t }
@@ -1272,33 +1397,33 @@ class d {
1272
1397
  t && ("_ok" in t && (this._ok = !!t._ok), "_ts" in t && typeof t._ts == "number" && (this._ts = t._ts), "_pt" in t && typeof t._pt == "number" && (this._pt = t._pt), "_result" in t && (this._result = t._result));
1273
1398
  }
1274
1399
  }
1275
- class T extends d {
1400
+ class V extends d {
1276
1401
  constructor(t) {
1277
1402
  super(d.error(t).toXData());
1278
1403
  }
1279
1404
  }
1280
- class W extends d {
1405
+ class H extends d {
1281
1406
  constructor(t) {
1282
1407
  super({ _ok: !0, _result: t });
1283
1408
  }
1284
1409
  }
1285
- const R = "engine:frame-number", N = "engine:fps";
1286
- class U {
1410
+ const U = "engine:frame-number", B = "engine:fps";
1411
+ class L {
1287
1412
  constructor(t) {
1288
- this._log_rules = {}, this._modules = {}, this._schedule_frame = t?._schedule_frame ?? p.createDefaultScheduler(t?._target_fps), this._version = "0.0.1", this._engine_id = p.guid(), this._frame_number = 0, this._fps_calc = new k(), this.parser = g, this._modules = {}, b.fire("xpell-init"), _._enabled = !1;
1413
+ this._log_rules = {}, this._modules = {}, this._schedule_frame = t?._schedule_frame ?? p.createDefaultScheduler(t?._target_fps), this._version = "0.0.1", this._engine_id = p.guid(), this._frame_number = 0, this._fps_calc = new M(), this.parser = g, this._modules = {}, b.fire("xpell-init"), a._enabled = !1;
1289
1414
  }
1290
1415
  /**
1291
1416
  * @deprecated use _verbose instead
1292
1417
  * Enable Xpell logs to console
1293
1418
  */
1294
1419
  set verbose(t) {
1295
- _._enabled = t;
1420
+ a._enabled = t;
1296
1421
  }
1297
1422
  /**
1298
1423
  * Enable Xpell logs to console
1299
1424
  */
1300
1425
  set _verbose(t) {
1301
- _._enabled = t;
1426
+ a._enabled = t;
1302
1427
  }
1303
1428
  /**
1304
1429
  * Logs message to console using Xpell logger
@@ -1308,7 +1433,7 @@ class U {
1308
1433
  * @param optionalParams
1309
1434
  */
1310
1435
  log(t, ...e) {
1311
- _.log(t, ...e);
1436
+ a.log(t, ...e);
1312
1437
  }
1313
1438
  /**
1314
1439
  * Delay the execution of the next command
@@ -1323,7 +1448,7 @@ class U {
1323
1448
  * @param {XModule} xModule
1324
1449
  */
1325
1450
  loadModule(t) {
1326
- this._modules.hasOwnProperty(t._name) ? _.log("Module " + t._name + " already loaded") : (this._modules[t._name] = t, t.load());
1451
+ this._modules.hasOwnProperty(t._name) ? a.log("Module " + t._name + " already loaded") : (this._modules[t._name] = t, t.load());
1327
1452
  }
1328
1453
  /**
1329
1454
  * Loads multiple module at ones
@@ -1336,7 +1461,7 @@ class U {
1336
1461
  * Display information about the Xpell engine to the console
1337
1462
  */
1338
1463
  info() {
1339
- _.log(`Xpell information:
1464
+ a.log(`Xpell information:
1340
1465
  - Engine Id: ` + this._engine_id + `
1341
1466
  - Version ` + this._version);
1342
1467
  }
@@ -1371,7 +1496,7 @@ class U {
1371
1496
  s?.onFrame && typeof s.onFrame == "function" && s.onFrame(this._frame_number);
1372
1497
  }
1373
1498
  const t = this._fps_calc.calc();
1374
- u.set(R, this._frame_number, { source: "engine" }), u.set(N, t, { source: "engine" }), u._compat_legacy_keys && (u.set("frame-number", this._frame_number, { source: "engine:legacy" }), u.set("fps", t, { source: "engine:legacy" })), this._schedule_frame(() => this.onFrame());
1499
+ u.set(U, this._frame_number, { source: "engine" }), u.set(B, t, { source: "engine" }), u._compat_legacy_keys && (u.set("frame-number", this._frame_number, { source: "engine:legacy" }), u.set("fps", t, { source: "engine:legacy" })), this._schedule_frame(() => this.onFrame());
1375
1500
  }
1376
1501
  /**
1377
1502
  * Gets Xpell module by name
@@ -1385,7 +1510,7 @@ class U {
1385
1510
  * Start Xpell engine for web browsers using requestAnimationFrame
1386
1511
  */
1387
1512
  start() {
1388
- _.log("Starting Xpell"), this.onFrame();
1513
+ a.log("Starting Xpell"), this.onFrame();
1389
1514
  }
1390
1515
  /**
1391
1516
  * deprecated - use XData._o directly
@@ -1394,35 +1519,35 @@ class U {
1394
1519
  return t in u._o ? u._o[t] : e;
1395
1520
  }
1396
1521
  }
1397
- const J = new U();
1522
+ const Q = new L();
1398
1523
  export {
1399
- M as XCommand,
1400
- N as XD_FPS,
1401
- R as XD_FRAME_NUMBER,
1524
+ x as XCommand,
1525
+ B as XD_FPS,
1526
+ U as XD_FRAME_NUMBER,
1402
1527
  u as XData,
1403
- O as XError,
1528
+ E as XError,
1404
1529
  b as XEventManager,
1405
- _ as XLogger,
1406
- C as XModule,
1407
- v as XObject,
1408
- P as XObjectManager,
1409
- B as XObjectPack,
1410
- L as XParams,
1530
+ a as XLogger,
1531
+ q as XModule,
1532
+ j as XObject,
1533
+ R as XObjectManager,
1534
+ W as XObjectPack,
1535
+ J as XParams,
1411
1536
  g as XParser,
1412
1537
  d as XResponse,
1413
- T as XResponseError,
1414
- W as XResponseOK,
1538
+ V as XResponseError,
1539
+ H as XResponseOK,
1415
1540
  p as XUtils,
1416
- J as Xpell,
1417
- U as XpellEngine,
1418
- S as _XData,
1419
- I as _XEventManager,
1420
- F as _XLogger,
1421
- X as _XUtils,
1422
- J as _x,
1423
- u as _xd,
1541
+ Q as Xpell,
1542
+ L as XpellEngine,
1543
+ A as _XData,
1544
+ $ as _XEventManager,
1545
+ I as _XLogger,
1546
+ S as _XUtils,
1547
+ Q as _x,
1548
+ P as _xd,
1424
1549
  b as _xem,
1425
- _ as _xlog,
1550
+ a as _xlog,
1426
1551
  p as _xu,
1427
- J as default
1552
+ Q as default
1428
1553
  };
@@ -0,0 +1,457 @@
1
+ # Nano-Commands v2 (JSON + Sequences) — Xpell 2 Contract
2
+
3
+ This document is the **canonical contract** for how Xpell 2 executes *nano-commands* from:
4
+ - **DB-stored views**
5
+ - **agent edits**
6
+ - **schema-generated UI**
7
+ - **runtime events** (`_on_click`, `_on_data`, `_on_show`, …)
8
+
9
+ Goal: **data-only intent** instead of JS functions, while keeping execution **small, deterministic, and auditable**.
10
+
11
+ ---
12
+
13
+ ## Why this matters
14
+
15
+ Historically, handlers were either:
16
+ - **Functions** (powerful, but not serializable / not DB-safe)
17
+ - **String nano-commands** (simple, but awkward for complex parameters)
18
+
19
+ Xpell 2 upgrades handlers with two capabilities:
20
+
21
+ 1) **JSON Command Handlers** — structured `XCommandData` (pure data)
22
+ 2) **Sequence Handlers** — arrays of handlers executed **in order** (awaited)
23
+
24
+ This enables **dynamic views** stored in XDB/files and real-time “vibe coding” without embedding code.
25
+
26
+ ---
27
+
28
+ ## Handler formats (what you can put in object JSON)
29
+
30
+ A “handler” field (e.g. `_on_click`, `_on_show`, `_on_hide`, `_on_data`, `_on_mount`, `_on_frame`) can be:
31
+
32
+ ### A) Function (dev-only)
33
+ Use only in developer-authored object packs.
34
+
35
+ ```ts
36
+ _on_click: async (obj, e) => {
37
+ // custom code (NOT DB-safe)
38
+ }
39
+ ```
40
+
41
+ ### B) String nano-command (legacy / shorthand)
42
+ For simple actions.
43
+
44
+ ```json
45
+ "_on_click": "hide"
46
+ ```
47
+
48
+ ### C) JSON command (canonical)
49
+ For DB-stored, agent-editable views.
50
+
51
+ ```json
52
+ "_on_click": { "_op": "hide" }
53
+ ```
54
+
55
+ Or with parameters:
56
+
57
+ ```json
58
+ "_on_click": { "_op": "set-text", "_params": { "text": "ok" } }
59
+ ```
60
+
61
+ ### D) Sequence (canonical composition)
62
+ Multi-step flows as data (no scripting language).
63
+
64
+ ```json
65
+ "_on_click": [
66
+ { "_op": "hide" },
67
+ { "_op": "set-text", "_params": { "text": "Hidden" } },
68
+ { "_op": "show" }
69
+ ]
70
+ ```
71
+
72
+ **Sequence semantics:**
73
+ - Execute **in order**
74
+ - Each item is **awaited**
75
+ - Default: **abort on thrown error** (consistent with your runtime error logging)
76
+
77
+ > If you need shared state between steps, use **XData** keys (recommended).
78
+
79
+ ---
80
+
81
+ ## JSON command format (XCommandData)
82
+
83
+ A JSON command is the canonical runtime intent shape:
84
+
85
+ ```json
86
+ {
87
+ "_op": "set-text",
88
+ "_params": { "text": "hello" }
89
+ }
90
+ ```
91
+
92
+ Optional fields (tooling + future evolution):
93
+
94
+ ```json
95
+ {
96
+ "_module": "xui",
97
+ "_object": "this",
98
+ "_op": "hide",
99
+ "_params": {}
100
+ }
101
+ ```
102
+
103
+ ### Important runtime note (today)
104
+ In current Xpell 2 runtime, command resolution is **object-local**:
105
+ - `XObject.execute()` resolves `_op` against nano-command packs registered on the **target object**
106
+ - `_module` is treated as **semantic metadata** (helpful for tools/agents), not required for execution
107
+
108
+ ### `_object` target rule
109
+ - If `_object` is omitted or `"this"`, the target is the **current object** (recommended for DB-stored handlers)
110
+ - Cross-object targeting may be constrained by policy; keep DB handlers **local by default**
111
+
112
+ ---
113
+
114
+ ## Payload injection (passing data/events into JSON handlers)
115
+
116
+ When a handler is invoked with a payload (e.g. `onData(data)` or click event `e`), the runtime may inject:
117
+
118
+ - `cmd._params.data = payload` **only if** `data` is not already provided.
119
+
120
+ This enables structured value passing without JSON-in-string escaping.
121
+
122
+ Example:
123
+
124
+ ```json
125
+ "_on_data": { "_op": "set-text-from-data", "_params": { "pattern": "FPS: $data" } }
126
+ ```
127
+
128
+ ---
129
+
130
+ ## Examples
131
+
132
+ ### 1) XUIObject — simple click hide (string)
133
+ ```json
134
+ {
135
+ "_id": "btn-close",
136
+ "_type": "button",
137
+ "_text": "Close",
138
+ "_on_click": "hide"
139
+ }
140
+ ```
141
+
142
+ ### 2) XUIObject — set text on click (JSON)
143
+ ```json
144
+ {
145
+ "_id": "btn-ok",
146
+ "_type": "button",
147
+ "_text": "OK",
148
+ "_on_click": { "_op": "set-text", "_params": { "text": "ok" } }
149
+ }
150
+ ```
151
+
152
+ ### 3) XUIObject — hide then show (sequence)
153
+ ```json
154
+ {
155
+ "_id": "panel",
156
+ "_type": "view",
157
+ "_on_click": [
158
+ { "_op": "hide" },
159
+ { "_op": "show" }
160
+ ]
161
+ }
162
+ ```
163
+
164
+ ### 4) XObject — onData drives UI (sequence)
165
+ ```json
166
+ {
167
+ "_id": "fps-label",
168
+ "_type": "label",
169
+ "_data_source": "engine:fps",
170
+ "_on_data": [
171
+ { "_op": "set-text-from-data", "_params": { "pattern": "FPS: $data" } }
172
+ ]
173
+ }
174
+ ```
175
+
176
+ ---
177
+
178
+ ## Design rule: no `run-seq` nano command
179
+
180
+ Xpell 2 **does not** introduce a `run-seq` nano command.
181
+
182
+ Sequencing is structural at the handler level:
183
+ - handlers may be arrays
184
+ - each item is executed in order
185
+
186
+ This keeps nano-commands:
187
+ - **atomic**
188
+ - **auditable**
189
+ - **non-scriptable**
190
+
191
+ ---
192
+
193
+ ## Security notes
194
+
195
+ This upgrade is explicitly designed to avoid “code in DB”:
196
+
197
+ - ✅ JSON commands are **whitelisted ops** (`_op` on a known nano-command pack)
198
+ - ✅ parameters are **data**, not executable code
199
+ - ✅ runtime can enforce:
200
+ - allowed ops
201
+ - allowed targets
202
+ - capability checks
203
+ - rate limits
204
+ - ❌ avoid `eval` / `new Function` / code-in-JSON
205
+
206
+ **Rule:** if a view is stored in DB and editable by an agent, handlers must be **data-only** (no functions).
207
+
208
+ ---
209
+
210
+ ## Recommended next steps (implementation checklist)
211
+
212
+ 1) Ensure `checkAndRunInternalFunction()` supports:
213
+ - `XCommandData` objects (`{ _op, _params }`)
214
+ - sequences (arrays of handlers)
215
+ 2) Ensure event dispatch sites call:
216
+ - `checkAndRunInternalFunction(handler, payload)`
217
+ for non-function handlers as well.
218
+ 3) Add capability/allowlist enforcement at the command runner boundary.
219
+
220
+ ---
221
+
222
+ ## Changelog (conceptual)
223
+
224
+ - **v1:** strings + dev-only functions
225
+ - **v2:** JSON commands + sequences for DB-stored realtime views
226
+
227
+
228
+ -- Commands:
229
+ ```md
230
+ # Codex Prompt — Xpell Nano Commands (Authoritative List)
231
+
232
+ Use **nano commands only** for runtime behavior.
233
+ Do NOT emit JavaScript functions for DB-stored views.
234
+ All actions must map to whitelisted nano commands.
235
+
236
+ ---
237
+
238
+ ## @xpell/core — XObject (available on ALL objects)
239
+
240
+ ### info
241
+ Logs the object id.
242
+ ```
243
+
244
+ info
245
+
246
+ ```
247
+
248
+ ### log
249
+ Logs a value or the object itself.
250
+ ```
251
+
252
+ log 'hello'
253
+ log
254
+
255
+ ```
256
+
257
+ ### fire
258
+ Fires a global event via XEventManager.
259
+ ```
260
+
261
+ fire event:'my-event' data:'payload'
262
+
263
+ ```
264
+
265
+ ### set-attr
266
+ Sets a safe attribute on the object instance.
267
+ ```
268
+
269
+ set-attr name:'_name' value:'test'
270
+
271
+ ```
272
+
273
+ ### delete-attr
274
+ Deletes a safe attribute from the object instance.
275
+ ```
276
+
277
+ delete-attr name:'_name'
278
+
279
+ ```
280
+
281
+ ---
282
+
283
+ ## @xpell/ui — XUIObject (UI-only)
284
+
285
+ ### hide
286
+ Hides the UI object.
287
+ ```
288
+
289
+ hide
290
+
291
+ ```
292
+
293
+ ### show
294
+ Shows the UI object.
295
+ ```
296
+
297
+ show
298
+
299
+ ```
300
+
301
+ ### toggle
302
+ Toggles visibility.
303
+ ```
304
+
305
+ toggle
306
+
307
+ ```
308
+
309
+ ### set-text
310
+ Sets text content.
311
+ ```
312
+
313
+ set-text text:'Hello'
314
+
315
+ ```
316
+
317
+ ### set (legacy alias)
318
+ Sets text if `text` param exists.
319
+ ```
320
+
321
+ set text:'Hello'
322
+
323
+ ```
324
+
325
+ ### set-text-from-data
326
+ Sets text from incoming data payload.
327
+ ```
328
+
329
+ set-text-from-data pattern:'Value: $data'
330
+
331
+ ```
332
+
333
+ ### set-text-from-frame
334
+ Sets text from frame counter.
335
+ ```
336
+
337
+ set-text-from-frame pattern:'Frame $data'
338
+
339
+ ```
340
+
341
+ ### add-class
342
+ Adds a CSS class.
343
+ ```
344
+
345
+ add-class class:'active'
346
+
347
+ ```
348
+
349
+ ### remove-class
350
+ Removes a CSS class.
351
+ ```
352
+
353
+ remove-class class:'active'
354
+
355
+ ```
356
+
357
+ ### toggle-class
358
+ Toggles a CSS class.
359
+ ```
360
+
361
+ toggle-class class:'active'
362
+
363
+ ```
364
+
365
+ ### set-style
366
+ Sets an inline style.
367
+ ```
368
+
369
+ set-style name:'color' value:'red'
370
+
371
+ ```
372
+
373
+ ### set-attr
374
+ Sets a DOM attribute.
375
+ ```
376
+
377
+ set-attr name:'aria-label' value:'Close'
378
+
379
+ ```
380
+
381
+ ### remove-attr
382
+ Removes a DOM attribute.
383
+ ```
384
+
385
+ remove-attr name:'aria-label'
386
+
387
+ ```
388
+
389
+ ---
390
+
391
+ ## @xpell/3d — X3DObject (3D-only)
392
+
393
+ ### rotation
394
+ Sets or increments rotation axes.
395
+ ```
396
+
397
+ rotation x:0.1 y:++0.02 z:--0.01
398
+
399
+ ```
400
+
401
+ ### spin
402
+ Applies continuous rotation via on-frame hook.
403
+ ```
404
+
405
+ spin y:0.01
406
+
407
+ ```
408
+
409
+ ### stop
410
+ Stops on-frame behavior.
411
+ ```
412
+
413
+ stop
414
+
415
+ ```
416
+
417
+ ### follow-joystick
418
+ Moves object using joystick data from XData.
419
+ ```
420
+
421
+ follow-joystick
422
+
423
+ ```
424
+
425
+ ### orbit
426
+ Moves object in an orbit.
427
+ ```
428
+
429
+ orbit radius:2 speed:0.02
430
+
431
+ ````
432
+
433
+ ---
434
+
435
+ ## Sequences (native, no extra command)
436
+
437
+ Multiple nano commands can be executed in order using arrays:
438
+
439
+ ```json
440
+ [
441
+ { "_op": "hide" },
442
+ { "_op": "set-text", "_params": { "text": "Hidden" } },
443
+ { "_op": "show" }
444
+ ]
445
+ ```
446
+
447
+ ---
448
+
449
+ ## Rules (MANDATORY)
450
+
451
+ * Prefer **JSON commands** for DB-stored views
452
+ * Use **strings only for trivial actions**
453
+ * Use **arrays instead of `;` or scripting**
454
+ * Never emit `eval`, `new Function`, or inline JS
455
+ * If output is stored → it MUST be data-only
456
+
457
+ This list is the **single source of truth** for Codex and agents.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xpell/core",
3
- "version": "2.0.0-alpha.10",
3
+ "version": "2.0.0-alpha.11",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },