@apigo.cc/state 1.0.16 → 1.0.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/state.js CHANGED
@@ -1,673 +1,692 @@
1
- (function(global, factory) {
2
- typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define(["exports"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.ApigoState = {}));
3
- })(this, function(exports2) {
1
+ (function(factory) {
2
+ typeof define === "function" && define.amd ? define(factory) : factory();
3
+ })(function() {
4
4
  "use strict";
5
- var _a;
6
- let __activeBinding = null;
7
- let __noWriteBack = null;
8
- const _setActiveBinding = (val) => __activeBinding = val;
9
- const _setNoWriteBack = (val) => __noWriteBack = val;
10
- const _notifiers = /* @__PURE__ */ new Set();
11
- const _onNotifyUpdate = (fn) => _notifiers.add(fn);
12
- function NewState(defaults = {}, getter = null, setter = null) {
13
- const _defaults = {};
14
- const _stateMappings = /* @__PURE__ */ new Map();
15
- const _watchers = /* @__PURE__ */ new Map();
16
- const _watchFunc = (k, cb) => {
17
- if (!_watchers.has(k)) _watchers.set(k, /* @__PURE__ */ new Set());
18
- !cb ? _watchers.get(k).clear() : _watchers.get(k).add(cb);
19
- return () => _watchers.get(k).delete(cb);
20
- };
21
- const _unwatchFunc = (k, cb) => {
22
- if (_watchers.has(k)) _watchers.set(k, /* @__PURE__ */ new Set());
23
- _watchers.get(k).delete(cb);
24
- };
25
- const __getter = getter || ((k) => _defaults[k]);
26
- const __setter = setter || ((k, v) => _defaults[k] = v);
27
- Object.assign(_defaults, defaults);
28
- return new Proxy(_defaults, {
29
- get(target, key) {
30
- if (key === "__watch") return _watchFunc;
31
- if (key === "__unwatch") return _unwatchFunc;
32
- if (key === "__isProxy") return true;
33
- if (__activeBinding) {
34
- if (!_stateMappings.has(key)) _stateMappings.set(key, /* @__PURE__ */ new Set());
35
- _stateMappings.get(key).add(__activeBinding);
36
- if (!__activeBinding.node._states) __activeBinding.node._states = /* @__PURE__ */ new Set();
37
- __activeBinding.node._states.add(_stateMappings);
5
+ (function(global) {
6
+ const Util = {
7
+ clone: window.structuredClone || ((obj) => JSON.parse(JSON.stringify(obj))),
8
+ base64: (str) => btoa(String.fromCharCode(...new TextEncoder().encode(str))),
9
+ unbase64: (str) => new TextDecoder().decode(Uint8Array.from(atob(str), (c) => c.charCodeAt(0))),
10
+ urlbase64: (str) => Util.base64(str).replace(/[+/=]/g, (m) => ({ "+": "-", "/": "", "=": "" })[m]),
11
+ unurlbase64: (str) => Util.unbase64(str.replace(/[-_.]/g, (m) => ({ "-": "+", "_": "/", ".": "=" })[m]).padEnd(Math.ceil(str.length / 4) * 4, "=")),
12
+ safeJson: (str) => {
13
+ try {
14
+ return JSON.parse(str);
15
+ } catch {
16
+ return null;
38
17
  }
39
- return __getter(key);
40
18
  },
41
- set(target, key, value) {
42
- if (__getter(key) !== value) {
43
- __setter(key, value);
44
- }
45
- if (_watchers.has(key)) {
46
- _watchers.get(key).forEach((cb) => {
47
- const r = cb(value);
48
- if (r !== void 0) {
49
- value = r;
50
- target[key] = value;
51
- }
52
- });
53
- }
54
- if (_watchers.has(null)) {
55
- _watchers.get(null).forEach((cb) => cb(value));
56
- }
57
- if (_stateMappings.has(key)) {
58
- const bindings = _stateMappings.get(key);
59
- for (const binding of bindings) {
60
- if (!binding.node.isConnected) {
61
- bindings.delete(binding);
62
- continue;
63
- }
64
- if (__noWriteBack !== binding.node) {
65
- _notifiers.forEach((fn) => fn(binding));
19
+ updateDefaults: (obj, defaults) => {
20
+ for (const k in defaults) if (obj[k] === void 0) obj[k] = defaults[k];
21
+ },
22
+ copyFunction: (toObj, fromObj, ...funcNames) => {
23
+ funcNames.forEach((name) => toObj[name] = fromObj[name].bind(fromObj));
24
+ },
25
+ getFunctionBody: (fn) => {
26
+ const code = fn.toString();
27
+ return code.slice(code.indexOf("{") + 1, code.lastIndexOf("}")).trim();
28
+ },
29
+ makeDom: (html) => {
30
+ if (html.includes(">\n")) html = html.replace(/>\s+</g, "><").trim();
31
+ const node = document.createElement("div");
32
+ node.innerHTML = html;
33
+ return node.children[0];
34
+ },
35
+ newAvg: () => {
36
+ let total = 0, count = 0, avg = 0;
37
+ return {
38
+ add: (v) => {
39
+ total += v;
40
+ count++;
41
+ return avg = total / count;
42
+ },
43
+ get: () => avg,
44
+ clear: () => {
45
+ total = 0, count = 0, avg = 0;
46
+ }
47
+ };
48
+ },
49
+ newTimeCount: () => {
50
+ let startTime = 0, total = 0, count = 0;
51
+ return {
52
+ start: () => startTime = (/* @__PURE__ */ new Date()).getTime(),
53
+ end: () => {
54
+ const endTime = (/* @__PURE__ */ new Date()).getTime();
55
+ const left = endTime - startTime;
56
+ startTime = endTime;
57
+ total += left;
58
+ count++;
59
+ return left;
60
+ },
61
+ avg: () => total / count
62
+ };
63
+ }
64
+ };
65
+ const $ = (a, b) => b ? a.querySelector(b) : document.querySelector(a);
66
+ const $$ = (a, b) => b ? a.querySelectorAll(b) : document.querySelectorAll(a);
67
+ global.Util = Util;
68
+ global.$ = $;
69
+ global.$$ = $$;
70
+ })(globalThis);
71
+ (function(global) {
72
+ var _a;
73
+ let __activeBinding = null;
74
+ let __noWriteBack = null;
75
+ const _notifiers = /* @__PURE__ */ new Set();
76
+ function NewState(defaults = {}, getter = null, setter = null) {
77
+ const _defaults = {};
78
+ const _stateMappings = /* @__PURE__ */ new Map();
79
+ const _watchers = /* @__PURE__ */ new Map();
80
+ const _watchFunc = (k, cb) => {
81
+ if (!_watchers.has(k)) _watchers.set(k, /* @__PURE__ */ new Set());
82
+ !cb ? _watchers.get(k).clear() : _watchers.get(k).add(cb);
83
+ return () => _watchers.get(k).delete(cb);
84
+ };
85
+ const _unwatchFunc = (k, cb) => {
86
+ if (_watchers.has(k)) _watchers.set(k, /* @__PURE__ */ new Set());
87
+ _watchers.get(k).delete(cb);
88
+ };
89
+ const __getter = getter || ((k) => _defaults[k]);
90
+ const __setter = setter || ((k, v) => _defaults[k] = v);
91
+ Object.assign(_defaults, defaults);
92
+ return new Proxy(_defaults, {
93
+ get(target, key) {
94
+ if (key === "__watch") return _watchFunc;
95
+ if (key === "__unwatch") return _unwatchFunc;
96
+ if (key === "__isProxy") return true;
97
+ if (__activeBinding) {
98
+ if (!_stateMappings.has(key)) _stateMappings.set(key, /* @__PURE__ */ new Set());
99
+ _stateMappings.get(key).add(__activeBinding);
100
+ if (!__activeBinding.node._states) __activeBinding.node._states = /* @__PURE__ */ new Set();
101
+ __activeBinding.node._states.add(_stateMappings);
102
+ }
103
+ return __getter(key);
104
+ },
105
+ set(target, key, value) {
106
+ if (__getter(key) !== value) {
107
+ __setter(key, value);
108
+ }
109
+ if (_watchers.has(key)) {
110
+ _watchers.get(key).forEach((cb) => {
111
+ const r = cb(value);
112
+ if (r !== void 0) {
113
+ value = r;
114
+ target[key] = value;
115
+ }
116
+ });
117
+ }
118
+ if (_watchers.has(null)) {
119
+ _watchers.get(null).forEach((cb) => cb(value));
120
+ }
121
+ if (_stateMappings.has(key)) {
122
+ const bindings = _stateMappings.get(key);
123
+ for (const binding of bindings) {
124
+ if (!binding.node.isConnected) {
125
+ bindings.delete(binding);
126
+ continue;
127
+ }
128
+ if (__noWriteBack !== binding.node) {
129
+ _notifiers.forEach((fn) => fn(binding));
130
+ }
66
131
  }
67
132
  }
133
+ return true;
68
134
  }
69
- return true;
70
- }
71
- });
72
- }
73
- const $ = (a, b) => b ? a.querySelector(b) : document.querySelector(a);
74
- const $$ = (a, b) => b ? a.querySelectorAll(b) : document.querySelectorAll(a);
75
- const _components = /* @__PURE__ */ new Map();
76
- const _pendingTemplates = [];
77
- const Component = {
78
- getTemplate: (name) => document.querySelector(`template[component="${name.toUpperCase()}"]`),
79
- register: (name, setupFunc, templateNode = null, ...globalNodes) => {
80
- console.log("Component.register:", name.toUpperCase());
81
- _components.set(name.toUpperCase(), setupFunc);
82
- if (document.readyState !== "loading") Component._addTemplate(name, templateNode, globalNodes);
83
- else _pendingTemplates.push([name, templateNode, globalNodes]);
84
- },
85
- exists: (name) => _components.has(name.toUpperCase()),
86
- getSetupFunction: (name) => _components.get(name.toUpperCase()),
87
- _addTemplate: (name, templateNode, globalNodes) => {
88
- if (templateNode) {
89
- const template = document.createElement("TEMPLATE");
90
- template.setAttribute("component", name.toUpperCase());
91
- template.content.appendChild(templateNode);
92
- document.body.appendChild(template);
93
- }
94
- if (globalNodes) globalNodes.forEach((node) => document.body.appendChild(node));
95
- },
96
- _initPending: () => {
97
- _pendingTemplates.forEach(([name, templateNode, globalNodes]) => Component._addTemplate(name, templateNode, globalNodes));
98
- _pendingTemplates.length = 0;
135
+ });
99
136
  }
100
- };
101
- function _mergeNode(from, to, scanObj, exists = {}) {
102
- if (from.attributes) {
103
- Array.from(from.attributes).forEach((attr) => {
104
- if (attr.name === "class") return;
105
- if (attr.name === "style") {
106
- if (to.hasAttribute("style")) to.setAttribute("style", `${attr.value}; ${to.getAttribute("style")}`);
107
- else to.setAttribute("style", attr.value);
108
- } else if (!to.hasAttribute(attr.name)) {
109
- to.setAttribute(attr.name, attr.value);
110
- }
137
+ let _hashParams = new URLSearchParams(((_a = window.location.hash) == null ? void 0 : _a.substring(1)) || "");
138
+ const Hash = NewState({}, (k) => global.Util.safeJson(_hashParams.get(k)), (k, v) => {
139
+ const oldStr = _hashParams.get(k);
140
+ const newStr = v === void 0 ? void 0 : JSON.stringify(v);
141
+ if (oldStr === newStr || oldStr === null && newStr === void 0) return;
142
+ v === void 0 ? _hashParams.delete(k) : _hashParams.set(k, newStr);
143
+ window.location.hash = "#" + _hashParams.toString();
144
+ });
145
+ if (typeof window !== "undefined") {
146
+ window.addEventListener("hashchange", () => {
147
+ var _a2;
148
+ const newParams = new URLSearchParams(((_a2 = window.location.hash) == null ? void 0 : _a2.substring(1)) || "");
149
+ const keys = /* @__PURE__ */ new Set([..._hashParams.keys(), ...newParams.keys()]);
150
+ _hashParams = newParams;
151
+ keys.forEach((k) => Hash[k] = Hash[k]);
111
152
  });
112
153
  }
113
- to.classList.add(...from.classList);
114
- const target = to.tagName === "TEMPLATE" ? to.content : to;
115
- const sourceNodes = from.tagName === "TEMPLATE" ? from.content.childNodes : from.childNodes;
116
- Array.from(sourceNodes).forEach((child) => target.appendChild(child));
117
- if (from.tagName && Component.exists(from.tagName)) _makeComponent(from.tagName, to, scanObj, exists);
118
- }
119
- function _makeComponent(name, node, scanObj, exists = {}) {
120
- if (exists[name]) return;
121
- exists[name] = true;
122
- if (scanObj.thisObj) {
123
- Array.from(node.attributes).forEach((attr) => {
124
- if ((attr.name.startsWith("$") || attr.name.startsWith("st-")) && attr.value.includes("this.")) {
125
- attr.value = attr.value.replace(/\bthis\./g, "this.parent.");
154
+ const LocalStorage = NewState({}, (k) => global.Util.safeJson(localStorage.getItem(k)), (k, v) => {
155
+ const oldStr = localStorage.getItem(k);
156
+ const newStr = v === void 0 ? void 0 : JSON.stringify(v);
157
+ if (oldStr === newStr || oldStr === null && newStr === void 0) return;
158
+ v === void 0 ? localStorage.removeItem(k) : localStorage.setItem(k, newStr);
159
+ });
160
+ const State = NewState({ exitBlocks: 0 });
161
+ global.NewState = NewState;
162
+ global.Hash = Hash;
163
+ global.LocalStorage = LocalStorage;
164
+ global.State = State;
165
+ global._onNotifyUpdate = (fn) => _notifiers.add(fn);
166
+ global._setActiveBinding = (val) => __activeBinding = val;
167
+ global._getActiveBinding = () => __activeBinding;
168
+ global._setNoWriteBack = (val) => __noWriteBack = val;
169
+ global._getNoWriteBack = () => __noWriteBack;
170
+ global._reactiveBridge = {
171
+ get activeBinding() {
172
+ return __activeBinding;
173
+ },
174
+ set activeBinding(v) {
175
+ __activeBinding = v;
176
+ },
177
+ get noWriteBack() {
178
+ return __noWriteBack;
179
+ },
180
+ set noWriteBack(v) {
181
+ __noWriteBack = v;
182
+ },
183
+ onNotifyUpdate: global._onNotifyUpdate
184
+ };
185
+ })(globalThis);
186
+ (function(global) {
187
+ const { Hash, LocalStorage, State, _reactiveBridge, $$ } = global;
188
+ const { onNotifyUpdate } = _reactiveBridge;
189
+ let _disableRunCodeError = false;
190
+ const _fnCache = /* @__PURE__ */ new Map();
191
+ function setDisableRunCodeError(value) {
192
+ _disableRunCodeError = value;
193
+ }
194
+ function _runCode(code, vars, thisObj, extendVars) {
195
+ if (global.__DEBUG) console.log("DEBUG _runCode:", code, "vars:", vars, "extendVars:", extendVars);
196
+ const argKeys = [...Object.keys(extendVars || {}), ...Object.keys(vars || {})];
197
+ const argValues = [...Object.values(extendVars || {}), ...Object.values(vars || {})];
198
+ const cacheKey = code + argKeys.join(",");
199
+ try {
200
+ let fn = _fnCache.get(cacheKey);
201
+ if (!fn) {
202
+ fn = new Function("Hash", "LocalStorage", "State", ...argKeys, code);
203
+ _fnCache.set(cacheKey, fn);
126
204
  }
127
- });
205
+ return fn.apply(thisObj, [Hash, LocalStorage, State, ...argValues]);
206
+ } catch (e) {
207
+ if (!_disableRunCodeError) console.error(e, extendVars, [code, extendVars, vars, thisObj]);
208
+ return null;
209
+ }
210
+ }
211
+ function _returnCode(code, vars, thisObj, extendVars) {
212
+ if (code.includes("${")) return _runCode("return `" + code + "`", vars, thisObj, extendVars);
213
+ else return _runCode("return " + code, vars, thisObj, extendVars);
128
214
  }
129
- const componentFunc = Component.getSetupFunction(name);
130
- const slots = {};
131
- Array.from(node.childNodes).forEach((child) => {
132
- if (child.nodeType === Node.ELEMENT_NODE && child.hasAttribute("slot")) {
133
- slots[child.getAttribute("slot")] = child;
134
- child.removeAttribute("slot");
215
+ const _components = /* @__PURE__ */ new Map();
216
+ const _pendingTemplates = [];
217
+ const Component = {
218
+ getTemplate: (name) => {
219
+ const sel = `template[component="${name.toUpperCase()}"]`;
220
+ const tpl = document.querySelector(sel);
221
+ if (global.__DEBUG) console.log("DEBUG getTemplate:", name, "selector:", sel, "found:", !!tpl);
222
+ return tpl;
223
+ },
224
+ register: (name, setupFunc, templateNode = null, ...globalNodes) => {
225
+ if (global.__DEBUG) console.log("DEBUG Component.register:", name);
226
+ _components.set(name.toUpperCase(), setupFunc);
227
+ if (document.readyState !== "loading") Component._addTemplate(name, templateNode, globalNodes);
228
+ else _pendingTemplates.push([name, templateNode, globalNodes]);
229
+ },
230
+ exists: (name) => _components.has(name.toUpperCase()),
231
+ getSetupFunction: (name) => _components.get(name.toUpperCase()),
232
+ _addTemplate: (name, templateNode, globalNodes) => {
233
+ if (templateNode) {
234
+ const template = document.createElement("TEMPLATE");
235
+ template.setAttribute("component", name.toUpperCase());
236
+ template.content.appendChild(templateNode);
237
+ document.head.appendChild(template);
238
+ if (global.__DEBUG) console.log("DEBUG _addTemplate added to HEAD:", name.toUpperCase());
239
+ }
240
+ if (globalNodes) globalNodes.forEach((node) => document.head.appendChild(node));
241
+ },
242
+ _initPending: () => {
243
+ _pendingTemplates.forEach(([name, templateNode, globalNodes]) => Component._addTemplate(name, templateNode, globalNodes));
244
+ _pendingTemplates.length = 0;
135
245
  }
136
- });
137
- node.innerHTML = "";
138
- node.state = NewState(node.state || {});
139
- const template = Component.getTemplate(name);
140
- if (template) {
141
- const tplnode = template.content.cloneNode(true);
142
- if (tplnode.childNodes.length) {
143
- const rootNode = tplnode.children[0];
144
- if (rootNode) _mergeNode(rootNode, node, scanObj, exists);
145
- $$(node, "[slot-id]").forEach((placeholder) => {
146
- const slotName = placeholder.getAttribute("slot-id");
147
- if (slots[slotName]) {
148
- placeholder.removeAttribute("slot-id");
149
- placeholder.innerHTML = "";
150
- _mergeNode(slots[slotName], placeholder, scanObj, exists);
246
+ };
247
+ function _mergeNode(from, to, scanObj, exists = {}) {
248
+ if (global.__DEBUG) console.log("DEBUG _mergeNode from:", from.tagName, "to:", to.tagName);
249
+ if (from.attributes) {
250
+ Array.from(from.attributes).forEach((attr) => {
251
+ if (attr.name === "class") return;
252
+ if (attr.name === "style") {
253
+ if (to.hasAttribute("style")) to.setAttribute("style", `${attr.value}; ${to.getAttribute("style")}`);
254
+ else to.setAttribute("style", attr.value);
255
+ } else if (!to.hasAttribute(attr.name)) {
256
+ to.setAttribute(attr.name, attr.value);
151
257
  }
152
258
  });
153
259
  }
260
+ to.classList.add(...from.classList);
261
+ const target = to.tagName === "TEMPLATE" ? to.content : to;
262
+ const sourceNodes = from.tagName === "TEMPLATE" ? from.content.childNodes : from.childNodes;
263
+ Array.from(sourceNodes).forEach((child) => target.appendChild(child));
264
+ if (from.tagName && Component.exists(from.tagName)) _makeComponent(from.tagName, to, scanObj, exists);
154
265
  }
155
- if (componentFunc) componentFunc(node);
156
- }
157
- let _disableRunCodeError = false;
158
- function setDisableRunCodeError(value) {
159
- _disableRunCodeError = value;
160
- }
161
- const _fnCache = /* @__PURE__ */ new Map();
162
- function _runCode(code, vars, thisObj, extendVars) {
163
- const allVars = { ...extendVars || {}, ...vars || {} };
164
- const argKeys = Object.keys(allVars);
165
- const argValues = Object.values(allVars);
166
- const cacheKey = code + argKeys.join(",");
167
- try {
168
- let fn = _fnCache.get(cacheKey);
169
- if (!fn) {
170
- fn = new Function("Hash", "LocalStorage", "State", ...argKeys, code);
171
- _fnCache.set(cacheKey, fn);
266
+ function _makeComponent(name, node, scanObj, exists = {}) {
267
+ if (exists[name]) return;
268
+ exists[name] = true;
269
+ if (scanObj.thisObj) {
270
+ Array.from(node.attributes).forEach((attr) => {
271
+ if ((attr.name.startsWith("$") || attr.name.startsWith("st-")) && attr.value.includes("this.")) {
272
+ attr.value = attr.value.replace(/\bthis\./g, "this.parent.");
273
+ }
274
+ });
172
275
  }
173
- return fn.apply(thisObj, [globalThis.Hash, globalThis.LocalStorage, globalThis.State, ...argValues]);
174
- } catch (e) {
175
- if (!_disableRunCodeError) console.error(e, extendVars, [code, extendVars, vars, thisObj]);
176
- return null;
177
- }
178
- }
179
- function _returnCode(code, vars, thisObj, extendVars) {
180
- if (code.includes("${")) return _runCode("return `" + code + "`", vars, thisObj, extendVars);
181
- else return _runCode("return " + code, vars, thisObj, extendVars);
182
- }
183
- let _translator = (text, args) => {
184
- if (!text || typeof text !== "string") return text;
185
- return text.replace(/\{(.+?)\}/g, (match, key) => args.hasOwnProperty(key) ? args[key] : match);
186
- };
187
- const SetTranslator = (fn) => _translator = fn;
188
- const _translate = (text) => {
189
- if (!text || typeof text !== "string" || !text.includes("{#")) return text;
190
- return text.replace(/\{#(.+?)#\}/g, (m, content) => {
191
- const parts = content.split("||").map((s) => s.trim());
192
- const args = {};
193
- if (parts.length > 1) {
194
- const matches = parts[0].match(/\{(.+?)\}/g);
195
- if (matches) matches.forEach((match, i) => args[match.substring(1, match.length - 1)] = parts[i + 1] || "");
276
+ const componentFunc = Component.getSetupFunction(name);
277
+ const slots = {};
278
+ Array.from(node.childNodes).forEach((child) => {
279
+ if (child.nodeType === Node.ELEMENT_NODE && child.hasAttribute("slot")) {
280
+ slots[child.getAttribute("slot")] = child;
281
+ child.removeAttribute("slot");
282
+ }
283
+ });
284
+ node.innerHTML = "";
285
+ node.state = global.NewState(node.state || {});
286
+ const template = Component.getTemplate(name);
287
+ if (template) {
288
+ const tplnode = template.content.cloneNode(true);
289
+ if (tplnode.childNodes.length) {
290
+ const rootNode = tplnode.children[0];
291
+ if (rootNode) _mergeNode(rootNode, node, scanObj, exists);
292
+ $$(node, "[slot-id]").forEach((placeholder) => {
293
+ const slotName = placeholder.getAttribute("slot-id");
294
+ if (slots[slotName]) {
295
+ placeholder.removeAttribute("slot-id");
296
+ placeholder.innerHTML = "";
297
+ _mergeNode(slots[slotName], placeholder, scanObj, exists);
298
+ }
299
+ });
300
+ }
196
301
  }
197
- return _translator(parts[0], args);
198
- });
199
- };
200
- if (typeof document !== "undefined") {
201
- try {
202
- document.createElement("div").setAttribute("$t", "1");
203
- } catch (e) {
204
- const originalSetAttribute = Element.prototype.setAttribute;
205
- Element.prototype.setAttribute = function(name, value) {
206
- if (!name.startsWith("$")) return originalSetAttribute.call(this, name, value);
207
- return originalSetAttribute.call(this, "st-" + name.substring(1), value);
208
- };
302
+ if (componentFunc) componentFunc(node);
209
303
  }
210
- }
211
- _onNotifyUpdate((binding) => _updateBinding(binding));
212
- function _clearRenderedNodes(node) {
213
- if (node._renderedNodes) node._renderedNodes.forEach((nodes) => nodes.forEach((child) => {
214
- child.remove();
215
- if (child._renderedNodes) _clearRenderedNodes(child);
216
- }));
217
- }
218
- function _updateBinding(binding) {
219
- const node = binding.node;
220
- if (!node.isConnected && node.tagName !== "TEMPLATE") return;
221
- _setActiveBinding(binding);
222
- let result = binding.exp ? binding.tpl ? _returnCode(binding.tpl, { thisNode: node }, node._thisObj || node, node._ref || null) : null : binding.tpl;
223
- if (binding.exp === 2 && typeof result === "string") {
304
+ let _translator = (text, args) => {
305
+ if (!text || typeof text !== "string") return text;
306
+ return text.replace(/\{(.+?)\}/g, (match, key) => args.hasOwnProperty(key) ? args[key] : match);
307
+ };
308
+ const SetTranslator = (fn) => _translator = fn;
309
+ const _translate = (text) => {
310
+ if (!text || typeof text !== "string" || !text.includes("{#")) return text;
311
+ return text.replace(/\{#(.+?)#\}/g, (m, content) => {
312
+ const parts = content.split("||").map((s) => s.trim());
313
+ const args = {};
314
+ if (parts.length > 1) {
315
+ const matches = parts[0].match(/\{(.+?)\}/g);
316
+ if (matches) matches.forEach((match, i) => args[match.substring(1, match.length - 1)] = parts[i + 1] || "");
317
+ }
318
+ return _translator(parts[0], args);
319
+ });
320
+ };
321
+ if (typeof document !== "undefined") {
224
322
  try {
225
- result = _returnCode(result, { thisNode: node }, node._thisObj || node, node._ref || null);
323
+ document.createElement("div").setAttribute("$t", "1");
226
324
  } catch (e) {
325
+ const originalSetAttribute = Element.prototype.setAttribute;
326
+ Element.prototype.setAttribute = function(name, value) {
327
+ if (!name.startsWith("$")) return originalSetAttribute.call(this, name, value);
328
+ return originalSetAttribute.call(this, "st-" + name.substring(1), value);
329
+ };
227
330
  }
228
331
  }
229
- _setActiveBinding(null);
230
- if (binding.prop) {
231
- const prop = binding.prop;
232
- let o = node;
233
- for (let i = 0; i < prop.length - 1; i++) {
234
- if (!prop[i]) continue;
235
- if (o[prop[i]] == null) o[prop[i]] = {};
236
- o = o[prop[i]];
237
- if (typeof o !== "object") break;
238
- }
239
- if (typeof o === "object" && o !== null) {
240
- const lk = prop[prop.length - 1];
241
- if (lk) {
242
- if (typeof result === "object" && result != null && !Array.isArray(result) && o[lk] == null) o[lk] = {};
243
- const lo = o[lk];
244
- if (typeof lo === "object" && lo != null && lo.__watch) Object.assign(lo, result);
245
- else {
246
- if (o[lk] !== result) o[lk] = result;
247
- }
248
- } else if (typeof result === "object" && result != null && !Array.isArray(result)) {
249
- Object.assign(o, result);
332
+ onNotifyUpdate((binding) => _updateBinding(binding));
333
+ function _clearRenderedNodes(node) {
334
+ if (node._renderedNodes) node._renderedNodes.forEach((nodes) => nodes.forEach((child) => {
335
+ child.remove();
336
+ if (child._renderedNodes) _clearRenderedNodes(child);
337
+ }));
338
+ }
339
+ function _updateBinding(binding) {
340
+ const node = binding.node;
341
+ if (!node.isConnected && node.tagName !== "TEMPLATE") return;
342
+ _reactiveBridge.activeBinding = binding;
343
+ let result = binding.exp ? binding.tpl ? _returnCode(binding.tpl, { thisNode: node }, node._thisObj || node, node._ref || {}) : null : binding.tpl;
344
+ if (binding.exp === 2 && typeof result === "string") {
345
+ try {
346
+ result = _returnCode(result, { thisNode: node }, node._thisObj || node, node._ref || {});
347
+ } catch (e) {
250
348
  }
251
349
  }
252
- } else if (binding.attr) {
253
- const attr = binding.attr;
254
- if (attr === "if") {
255
- if (result) {
256
- if (!node._renderedNodes || node._renderedNodes.length === 0) {
257
- node._children.forEach((child) => {
258
- node.parentNode.insertBefore(child, node);
259
- child._ref = { ...node._ref };
260
- child._thisObj = node._thisObj;
261
- });
262
- node._renderedNodes = [node._children];
350
+ _reactiveBridge.activeBinding = null;
351
+ if (binding.prop) {
352
+ const prop = binding.prop;
353
+ let o = node;
354
+ for (let i = 0; i < prop.length - 1; i++) {
355
+ if (!prop[i]) continue;
356
+ if (o[prop[i]] == null) o[prop[i]] = {};
357
+ o = o[prop[i]];
358
+ if (typeof o !== "object") break;
359
+ }
360
+ if (typeof o === "object" && o !== null) {
361
+ const lk = prop[prop.length - 1];
362
+ if (lk) {
363
+ if (typeof result === "object" && result != null && !Array.isArray(result) && o[lk] == null) o[lk] = {};
364
+ const lo = o[lk];
365
+ if (typeof lo === "object" && lo != null && lo.__watch) Object.assign(lo, result);
366
+ else {
367
+ if (o[lk] !== result) o[lk] = result;
368
+ }
369
+ } else if (typeof result === "object" && result != null && !Array.isArray(result)) {
370
+ Object.assign(o, result);
263
371
  }
264
- } else {
265
- _clearRenderedNodes(node);
266
- node._renderedNodes = [];
267
372
  }
268
- } else if (attr === "each") {
269
- if (result && typeof result === "object") {
270
- const asName = node.getAttribute("as") || "item";
271
- const indexName = node.getAttribute("index") || "index";
272
- const keyName = node.getAttribute("key");
273
- let keys, getVal;
274
- if (result instanceof Map) {
275
- keys = Array.from(result.keys());
276
- getVal = (k) => result.get(k);
277
- } else if (typeof result[Symbol.iterator] === "function") {
278
- const arr = Array.isArray(result) ? result : Array.from(result);
279
- keys = new Array(arr.length);
280
- for (let i = 0; i < arr.length; i++) keys[i] = i;
281
- getVal = (k) => arr[k];
373
+ } else if (binding.attr) {
374
+ const attr = binding.attr;
375
+ if (attr === "if") {
376
+ if (result) {
377
+ if (!node._renderedNodes || node._renderedNodes.length === 0) {
378
+ node._children.forEach((child) => {
379
+ node.parentNode.insertBefore(child, node);
380
+ child._ref = { ...node._ref };
381
+ child._thisObj = node._thisObj;
382
+ });
383
+ node._renderedNodes = [node._children];
384
+ }
282
385
  } else {
283
- keys = Object.keys(result);
284
- getVal = (k) => result[k];
386
+ _clearRenderedNodes(node);
387
+ node._renderedNodes = [];
285
388
  }
286
- if (!node._keyedNodes) node._keyedNodes = /* @__PURE__ */ new Map();
287
- const newKeyedNodes = /* @__PURE__ */ new Map();
288
- const currentRenderedNodes = [];
289
- keys.forEach((k, i) => {
290
- const item = getVal(k);
291
- const rawKey = keyName ? item && typeof item === "object" ? item[keyName] : item : k;
292
- const keyVal = rawKey === void 0 || rawKey === null || newKeyedNodes.has(rawKey) ? `st_key_${i}` : rawKey;
293
- let existingNodes = node._keyedNodes.get(keyVal);
294
- if (existingNodes) {
295
- node._keyedNodes.delete(keyVal);
296
- existingNodes.forEach((child) => {
297
- child._ref[indexName] = k;
298
- child._ref[asName] = item;
299
- _scanTree(child);
300
- });
389
+ } else if (attr === "each") {
390
+ if (result && typeof result === "object") {
391
+ const asName = node.getAttribute("as") || "item";
392
+ const indexName = node.getAttribute("index") || "index";
393
+ const keyName = node.getAttribute("key");
394
+ let keys, getVal;
395
+ if (result instanceof Map) {
396
+ keys = Array.from(result.keys());
397
+ getVal = (k) => result.get(k);
398
+ } else if (typeof result[Symbol.iterator] === "function") {
399
+ const arr = Array.isArray(result) ? result : Array.from(result);
400
+ keys = new Array(arr.length);
401
+ for (let i = 0; i < arr.length; i++) keys[i] = i;
402
+ getVal = (k) => arr[k];
301
403
  } else {
302
- existingNodes = [];
303
- node._children.forEach((child) => {
304
- const cloned = child.cloneNode(true);
305
- cloned._ref = { ...node._ref, [indexName]: k, [asName]: item };
306
- cloned._thisObj = node._thisObj;
307
- node.parentNode.insertBefore(cloned, node);
308
- existingNodes.push(cloned);
309
- });
404
+ keys = Object.keys(result);
405
+ getVal = (k) => result[k];
310
406
  }
311
- newKeyedNodes.set(keyVal, existingNodes);
312
- currentRenderedNodes.push(existingNodes);
313
- });
314
- node._keyedNodes.forEach((nodes) => nodes.forEach((child) => {
315
- _clearRenderedNodes(child);
316
- child.remove();
317
- }));
318
- node._keyedNodes = newKeyedNodes;
319
- node._renderedNodes = currentRenderedNodes;
407
+ if (!node._keyedNodes) node._keyedNodes = /* @__PURE__ */ new Map();
408
+ const newKeyedNodes = /* @__PURE__ */ new Map();
409
+ const currentRenderedNodes = [];
410
+ keys.forEach((k, i) => {
411
+ const item = getVal(k);
412
+ const rawKey = keyName ? item && typeof item === "object" ? item[keyName] : item : k;
413
+ const keyVal = rawKey === void 0 || rawKey === null || newKeyedNodes.has(rawKey) ? `st_key_${i}` : rawKey;
414
+ let existingNodes = node._keyedNodes.get(keyVal);
415
+ if (existingNodes) {
416
+ node._keyedNodes.delete(keyVal);
417
+ existingNodes.forEach((child) => {
418
+ child._ref[indexName] = k;
419
+ child._ref[asName] = item;
420
+ _scanTree(child);
421
+ });
422
+ } else {
423
+ existingNodes = [];
424
+ node._children.forEach((child) => {
425
+ const cloned = child.cloneNode(true);
426
+ cloned._ref = { ...node._ref, [indexName]: k, [asName]: item };
427
+ cloned._thisObj = node._thisObj;
428
+ node.parentNode.insertBefore(cloned, node);
429
+ existingNodes.push(cloned);
430
+ });
431
+ }
432
+ newKeyedNodes.set(keyVal, existingNodes);
433
+ currentRenderedNodes.push(existingNodes);
434
+ });
435
+ node._keyedNodes.forEach((nodes) => nodes.forEach((child) => {
436
+ _clearRenderedNodes(child);
437
+ child.remove();
438
+ }));
439
+ node._keyedNodes = newKeyedNodes;
440
+ node._renderedNodes = currentRenderedNodes;
441
+ } else {
442
+ _clearRenderedNodes(node);
443
+ node._renderedNodes = [];
444
+ }
445
+ } else if (attr === "bind") {
446
+ if (["INPUT", "SELECT", "TEXTAREA"].includes(node.tagName) && !node.hasAttribute("autocomplete")) node.setAttribute("autocomplete", "off");
447
+ if (node.type === "checkbox") {
448
+ if (node.value !== "on" && !result) {
449
+ _runCode(`${binding.tpl} = []`, { thisNode: node }, node._thisObj || node, node._ref || {});
450
+ result = [];
451
+ }
452
+ node._checkboxMultiMode = result instanceof Array;
453
+ const isChecked = result instanceof Array ? result.includes(node.value) : !!result;
454
+ if (node.checked !== isChecked) node.checked = isChecked;
455
+ } else if (node.type === "radio") {
456
+ if (node.checked !== (node.value === String(result ?? ""))) node.checked = node.value === String(result ?? "");
457
+ } else if ("value" in node && node.type !== "file") {
458
+ Promise.resolve().then(() => {
459
+ if (node.value !== String(result ?? "")) node.value = result;
460
+ });
461
+ } else if (node.isContentEditable) {
462
+ if (node.innerHTML !== String(result ?? "")) node.innerHTML = result;
463
+ }
464
+ node.dispatchEvent(new CustomEvent("bind", { bubbles: false, detail: result }));
320
465
  } else {
321
- _clearRenderedNodes(node);
322
- node._renderedNodes = [];
323
- }
324
- } else if (attr === "bind") {
325
- if (["INPUT", "SELECT", "TEXTAREA"].includes(node.tagName) && !node.hasAttribute("autocomplete")) node.setAttribute("autocomplete", "off");
326
- if (node.type === "checkbox") {
327
- if (node.value !== "on" && !result) {
328
- _runCode(`${binding.tpl} = []`, { thisNode: node }, node._thisObj || node, node._ref || {});
329
- result = [];
466
+ if (["checked", "disabled", "readonly"].includes(attr)) result = !!result;
467
+ if (typeof result === "boolean") result ? node.setAttribute(attr, "") : node.removeAttribute(attr);
468
+ else if (result !== void 0) {
469
+ if (typeof result !== "string") result = JSON.stringify(result);
470
+ if (attr === "text") node.textContent = result ?? "";
471
+ else if (attr === "html") node.innerHTML = result ?? "";
472
+ else if (attr === "class") {
473
+ if (node._staticClass === void 0) node._staticClass = node.className;
474
+ node.className = (node._staticClass ? node._staticClass + " " : "") + (result || "");
475
+ } else if (attr === "style") {
476
+ if (node._staticStyle === void 0) node._staticStyle = node.getAttribute("style") || "";
477
+ node.setAttribute("style", (node._staticStyle ? node._staticStyle + "; " : "") + (result || ""));
478
+ } else if (node.tagName === "IMG" && attr === "src" && result.includes(".svg")) node.setAttribute("_src", result ?? "");
479
+ else node.setAttribute(attr, result ?? "");
330
480
  }
331
- node._checkboxMultiMode = result instanceof Array;
332
- const isChecked = result instanceof Array ? result.includes(node.value) : !!result;
333
- if (node.checked !== isChecked) node.checked = isChecked;
334
- } else if (node.type === "radio") {
335
- if (node.checked !== (node.value === String(result ?? ""))) node.checked = node.value === String(result ?? "");
336
- } else if ("value" in node && node.type !== "file") {
337
- Promise.resolve().then(() => {
338
- if (node.value !== String(result ?? "")) node.value = result;
339
- });
340
- } else if (node.isContentEditable) {
341
- if (node.innerHTML !== String(result ?? "")) node.innerHTML = result;
342
- }
343
- node.dispatchEvent(new CustomEvent("bind", { bubbles: false, detail: result }));
344
- } else {
345
- if (["checked", "disabled", "readonly"].includes(attr)) result = !!result;
346
- if (typeof result === "boolean") result ? node.setAttribute(attr, "") : node.removeAttribute(attr);
347
- else if (result !== void 0) {
348
- if (typeof result !== "string") result = JSON.stringify(result);
349
- if (attr === "text") node.textContent = result ?? "";
350
- else if (attr === "html") node.innerHTML = result ?? "";
351
- else if (node.tagName === "IMG" && attr === "src" && result.includes(".svg")) node.setAttribute("_src", result ?? "");
352
- else node.setAttribute(attr, result ?? "");
353
481
  }
354
482
  }
355
483
  }
356
- }
357
- const _initBinding = (binding) => {
358
- if (!binding.node._bindings) binding.node._bindings = [];
359
- binding.node._bindings.push({ attr: binding.attr, prop: binding.prop, tpl: binding.tpl, exp: binding.exp });
360
- _updateBinding(binding);
361
- };
362
- const _parseNode = (node, scanObj) => {
363
- if (node._bindings) {
364
- node._states = /* @__PURE__ */ new Set();
365
- node._bindings.forEach((b) => _updateBinding({ node, ...b }));
366
- if (node._hasOnUpdate) node.dispatchEvent(new Event("update", { bubbles: false }));
367
- return;
484
+ function _initBinding(binding) {
485
+ if (!binding.node._bindings) binding.node._bindings = [];
486
+ binding.node._bindings.push({ attr: binding.attr, prop: binding.prop, tpl: binding.tpl, exp: binding.exp });
487
+ _updateBinding(binding);
368
488
  }
369
- if (Component.exists(node.tagName) && !node._componentInitialized) {
370
- Array.from(node.attributes).forEach((attr) => {
371
- var _a2;
372
- if (attr.name.startsWith("$.")) {
373
- const realAttrName = attr.name.slice(2);
374
- let tpl = _translate(attr.value);
375
- if (tpl.includes("this.")) tpl = tpl.replace(/\bthis\./g, "this.parent.");
376
- const result = _returnCode(tpl, { thisNode: node }, { parent: scanObj.thisObj || node }, node._ref || {});
377
- let o = node;
378
- const prop = realAttrName.split(".");
379
- for (let i = 0; i < prop.length - 1; i++) {
380
- if (prop[i]) o = o[_a2 = prop[i]] ?? (o[_a2] = {});
489
+ function _parseNode(node, scanObj) {
490
+ if (node._bindings) {
491
+ node._states = /* @__PURE__ */ new Set();
492
+ node._bindings.forEach((b) => _updateBinding({ node, ...b }));
493
+ if (node._hasOnUpdate) node.dispatchEvent(new Event("update", { bubbles: false }));
494
+ return;
495
+ }
496
+ if (Component.exists(node.tagName) && !node._componentInitialized) {
497
+ Array.from(node.attributes).forEach((attr) => {
498
+ var _a;
499
+ if (attr.name.startsWith("$.")) {
500
+ const realAttrName = attr.name.slice(2);
501
+ let tpl = _translate(attr.value);
502
+ if (tpl.includes("this.")) tpl = tpl.replace(/\bthis\./g, "this.parent.");
503
+ const result = _returnCode(tpl, { thisNode: node }, { parent: scanObj.thisObj || node }, node._ref || {});
504
+ let o = node;
505
+ const prop = realAttrName.split(".");
506
+ for (let i = 0; i < prop.length - 1; i++) {
507
+ if (prop[i]) o = o[_a = prop[i]] ?? (o[_a] = {});
508
+ }
509
+ o[prop[prop.length - 1]] = result;
510
+ node.removeAttribute(attr.name);
381
511
  }
382
- o[prop[prop.length - 1]] = result;
383
- node.removeAttribute(attr.name);
384
- }
385
- });
386
- _makeComponent(node.tagName, node, scanObj);
387
- $$(node, "[slot-id]").forEach((p) => p.removeAttribute("slot-id"));
388
- node._componentInitialized = true;
389
- if (!node._thisObj) node._thisObj = node;
390
- }
391
- if (node.tagName === "TEMPLATE") {
392
- node._children = [...node.content.childNodes];
393
- if (!node._renderedNodes) node._renderedNodes = [];
394
- }
395
- let attrs = [];
396
- if (node.tagName === "TEMPLATE") {
397
- ["$if", "$each", "st-if", "st-each"].forEach((n) => node.hasAttribute(n) && attrs.push(node.getAttributeNode(n)));
398
- } else {
399
- attrs = Array.from(node.attributes).filter((a) => (a.name.startsWith("$") || a.name.startsWith("st-")) && !["$if", "$each", "st-if", "st-each"].includes(a.name) || a.name.includes("."));
400
- }
401
- if (node._thisObj && scanObj.thisObj) node._thisObj.parent = scanObj.thisObj;
402
- if (!node._thisObj) node._thisObj = scanObj.thisObj || null;
403
- if (!node._ref) node._ref = scanObj.extendVars || {};
404
- node._states = /* @__PURE__ */ new Set();
405
- attrs.forEach((attr) => {
406
- let exp = 0;
407
- if (attr.name.startsWith("$$") || attr.name.startsWith("st-st-")) exp = 2;
408
- else if (attr.name.startsWith("$") || attr.name.startsWith("st-")) exp = 1;
409
- const realAttrName = exp === 2 ? attr.name.startsWith("$$") ? attr.name.slice(2) : attr.name.slice(6) : exp === 1 ? attr.name.startsWith("$") ? attr.name.slice(1) : attr.name.slice(3) : attr.name;
410
- let tpl = attr.value;
411
- node.removeAttribute(attr.name);
412
- if (realAttrName.startsWith(".")) _initBinding({ node, prop: realAttrName.split("."), tpl, exp });
413
- else if (realAttrName.startsWith("on")) {
414
- const eventName = realAttrName.slice(2);
415
- if (eventName === "update") node._hasOnUpdate = true;
416
- if (eventName === "load" && !["BODY", "IMG", "IFRAME"].includes(node.tagName)) node._hasOnLoad = true;
417
- if (eventName === "unload" && !["BODY", "IMG", "IFRAME"].includes(node.tagName)) node._hasOnUnload = true;
418
- node.addEventListener(eventName, (e) => _runCode(tpl, { event: e, thisNode: node, ...e.detail || {} }, scanObj.thisObj || node, node._ref || {}));
512
+ });
513
+ _makeComponent(node.tagName, node, scanObj);
514
+ $$(node, "[slot-id]").forEach((p) => p.removeAttribute("slot-id"));
515
+ node._componentInitialized = true;
516
+ if (!node._thisObj) node._thisObj = node;
517
+ }
518
+ if (node.tagName === "TEMPLATE") {
519
+ node._children = [...node.content.childNodes];
520
+ if (!node._renderedNodes) node._renderedNodes = [];
521
+ }
522
+ let attrs = [];
523
+ if (node.tagName === "TEMPLATE") {
524
+ ["$if", "$each", "st-if", "st-each", "$$if", "$$each", "st-st-if", "st-st-each"].forEach((n) => node.hasAttribute(n) && attrs.push(node.getAttributeNode(n)));
419
525
  } else {
420
- if (realAttrName === "bind") {
421
- node.addEventListener(["textarea", "text", "password"].includes(node.type || "text") || node.isContentEditable ? "input" : "change", (e) => {
422
- let newVal = node.isContentEditable ? e.target.innerHTML : node.type === "checkbox" ? e.target.checked : e.target.files || e.target.value || e.detail;
423
- _setNoWriteBack(node);
424
- setDisableRunCodeError(true);
425
- if (node.type === "checkbox" && node._checkboxMultiMode) _runCode(`!!checked ? (!${tpl}.includes(val) && ${tpl}.push(val)) : (index = ${tpl}.indexOf(val), index > -1 && ${tpl}.splice(index, 1))`, { val: node.value, checked: newVal, thisNode: node }, scanObj.thisObj || node, node._ref || {});
426
- else _runCode(`${tpl} = val`, { val: newVal, thisNode: node }, scanObj.thisObj || node, node._ref || {});
427
- setDisableRunCodeError(false);
428
- _setNoWriteBack(null);
429
- });
430
- } else if (realAttrName === "text" && !tpl) {
431
- tpl = node.textContent;
432
- node.textContent = "";
433
- }
434
- if (tpl) {
435
- tpl = _translate(tpl);
436
- _initBinding({ node, attr: realAttrName, tpl, exp });
437
- }
526
+ attrs = Array.from(node.attributes).filter((a) => (a.name.startsWith("$") || a.name.startsWith("st-")) && !["$if", "$each", "st-if", "st-each", "$$if", "$$each", "st-st-if", "st-st-each"].includes(a.name) || a.name.includes("."));
438
527
  }
439
- });
440
- if (node._hasOnLoad || node._componentInitialized) Promise.resolve().then(() => node.dispatchEvent(new Event("load", { bubbles: false })));
441
- if (node._hasOnUpdate) node.dispatchEvent(new Event("update", { bubbles: false }));
442
- if (node._thisObj) scanObj.thisObj = node._thisObj;
443
- };
444
- const _scanTree = (node, scanObj = {}) => {
445
- if (node.nodeType === 3) {
446
- if (node._stTranslated) return;
447
- const translated = _translate(node.textContent);
448
- if (translated !== node.textContent) node.textContent = translated;
449
- node._stTranslated = true;
450
- return;
451
- }
452
- if (node.nodeType !== 1) return;
453
- if (!node._stTranslated) {
454
- Array.from(node.attributes).forEach((attr) => {
455
- if (!attr.name.startsWith("$") && !attr.name.startsWith("st-") && !attr.name.startsWith(".")) {
456
- const translated = _translate(attr.value);
457
- if (translated !== attr.value) attr.value = translated;
528
+ if (node._thisObj && scanObj.thisObj) node._thisObj.parent = scanObj.thisObj;
529
+ if (!node._thisObj) node._thisObj = scanObj.thisObj || null;
530
+ if (!node._ref) node._ref = scanObj.extendVars || {};
531
+ node._states = /* @__PURE__ */ new Set();
532
+ attrs.forEach((attr) => {
533
+ let exp = 0;
534
+ if (attr.name.startsWith("$$") || attr.name.startsWith("st-st-")) exp = 2;
535
+ else if (attr.name.startsWith("$") || attr.name.startsWith("st-")) exp = 1;
536
+ const realAttrName = exp === 2 ? attr.name.startsWith("$$") ? attr.name.slice(2) : attr.name.slice(6) : exp === 1 ? attr.name.startsWith("$") ? attr.name.slice(1) : attr.name.slice(3) : attr.name;
537
+ let tpl = attr.value;
538
+ node.removeAttribute(attr.name);
539
+ if (realAttrName.startsWith(".")) _initBinding({ node, prop: realAttrName.split("."), tpl, exp });
540
+ else if (realAttrName.startsWith("on")) {
541
+ const eventName = realAttrName.slice(2);
542
+ if (eventName === "update") node._hasOnUpdate = true;
543
+ if (eventName === "load" && !["BODY", "IMG", "IFRAME"].includes(node.tagName)) node._hasOnLoad = true;
544
+ if (eventName === "unload" && !["BODY", "IMG", "IFRAME"].includes(node.tagName)) node._hasOnUnload = true;
545
+ node.addEventListener(eventName, (e) => _runCode(tpl, { event: e, thisNode: node, ...e.detail || {} }, scanObj.thisObj || node, node._ref || {}));
546
+ } else {
547
+ if (realAttrName === "bind") {
548
+ node.addEventListener(["textarea", "text", "password"].includes(node.type || "text") || node.isContentEditable ? "input" : "change", (e) => {
549
+ let newVal = node.isContentEditable ? e.target.innerHTML : node.type === "checkbox" ? e.target.checked : e.target.files || e.target.value || e.detail;
550
+ _reactiveBridge.noWriteBack = node;
551
+ setDisableRunCodeError(true);
552
+ if (node.type === "checkbox" && node._checkboxMultiMode) _runCode(`!!checked ? (!${tpl}.includes(val) && ${tpl}.push(val)) : (index = ${tpl}.indexOf(val), index > -1 && ${tpl}.splice(index, 1))`, { val: node.value, checked: newVal, thisNode: node }, scanObj.thisObj || node, node._ref || {});
553
+ else _runCode(`${tpl} = val`, { val: newVal, thisNode: node }, scanObj.thisObj || node, node._ref || {});
554
+ setDisableRunCodeError(false);
555
+ _reactiveBridge.noWriteBack = null;
556
+ });
557
+ } else if (realAttrName === "text" && !tpl) {
558
+ tpl = node.textContent;
559
+ node.textContent = "";
560
+ }
561
+ if (tpl) {
562
+ tpl = _translate(tpl);
563
+ _initBinding({ node, attr: realAttrName, tpl, exp });
564
+ }
458
565
  }
459
566
  });
460
- node._stTranslated = true;
567
+ if (node._hasOnLoad || node._componentInitialized) Promise.resolve().then(() => node.dispatchEvent(new Event("load", { bubbles: false })));
568
+ if (node._hasOnUpdate) node.dispatchEvent(new Event("update", { bubbles: false }));
569
+ if (node._thisObj) scanObj.thisObj = node._thisObj;
461
570
  }
462
- if (node.tagName !== "TEMPLATE" && (node.hasAttribute("$if") || node.hasAttribute("$each") || node.hasAttribute("st-if") || node.hasAttribute("st-each"))) {
463
- const template = document.createElement("TEMPLATE");
464
- const attrs = Array.from(node.attributes).filter((attr) => ["$if", "$each", "st-if", "st-each"].includes(attr.name) || (node.hasAttribute("$each") || node.hasAttribute("st-each")) && ["as", "index"].includes(attr.name));
465
- attrs.forEach((attr) => {
571
+ function _scanTree(node, scanObj = {}) {
572
+ if (node.nodeType === 3) {
573
+ if (node._stTranslated) return;
574
+ const translated = _translate(node.textContent);
575
+ if (translated !== node.textContent) node.textContent = translated;
576
+ node._stTranslated = true;
577
+ return;
578
+ }
579
+ if (node.nodeType !== 1) return;
580
+ if (!node._stTranslated) {
581
+ Array.from(node.attributes).forEach((attr) => {
582
+ if (!attr.name.startsWith("$") && !attr.name.startsWith("st-") && !attr.name.startsWith(".")) {
583
+ const translated = _translate(attr.value);
584
+ if (translated !== attr.value) attr.value = translated;
585
+ }
586
+ });
587
+ node._stTranslated = true;
588
+ }
589
+ if (node.tagName !== "TEMPLATE" && (node.hasAttribute("$if") || node.hasAttribute("$each") || node.hasAttribute("st-if") || node.hasAttribute("st-each") || node.hasAttribute("$$if") || node.hasAttribute("$$each") || node.hasAttribute("st-st-if") || node.hasAttribute("st-st-each"))) {
590
+ const template = document.createElement("TEMPLATE");
591
+ const attrs = Array.from(node.attributes).filter((attr) => ["$if", "$each", "st-if", "st-each", "$$if", "$$each", "st-st-if", "st-st-each"].includes(attr.name) || (node.hasAttribute("$each") || node.hasAttribute("st-each") || node.hasAttribute("$$each") || node.hasAttribute("st-st-each")) && ["as", "index", "key"].includes(attr.name));
592
+ attrs.forEach((attr) => {
593
+ template.setAttribute(attr.name, attr.value);
594
+ node.removeAttribute(attr.name);
595
+ });
596
+ node.parentNode.insertBefore(template, node);
597
+ template.content.appendChild(node);
598
+ template._ref = node._ref;
599
+ return;
600
+ }
601
+ if (node.tagName === "TEMPLATE" && (node.hasAttribute("$if") || node.hasAttribute("st-if") || node.hasAttribute("$$if") || node.hasAttribute("st-st-if")) && (node.hasAttribute("$each") || node.hasAttribute("st-each") || node.hasAttribute("$$each") || node.hasAttribute("st-st-each"))) {
602
+ const template = document.createElement("TEMPLATE");
603
+ const attrs = Array.from(node.attributes).filter((attr2) => ["$if", "$each", "st-if", "st-each", "$$if", "$$each", "st-st-if", "st-st-each"].includes(attr2.name));
604
+ const attr = attrs[attrs.length - 1];
466
605
  template.setAttribute(attr.name, attr.value);
467
606
  node.removeAttribute(attr.name);
468
- });
469
- node.parentNode.insertBefore(template, node);
470
- template.content.appendChild(node);
471
- template._ref = node._ref;
472
- return;
473
- }
474
- if (node.tagName === "TEMPLATE" && (node.hasAttribute("$if") || node.hasAttribute("st-if")) && (node.hasAttribute("$each") || node.hasAttribute("st-each"))) {
475
- const template = document.createElement("TEMPLATE");
476
- const attrs = Array.from(node.attributes).filter((attr2) => ["$if", "$each", "st-if", "st-each"].includes(attr2.name));
477
- const attr = attrs[attrs.length - 1];
478
- template.setAttribute(attr.name, attr.value);
479
- node.removeAttribute(attr.name);
480
- if (attr.name === "$each" || attr.name === "st-each") {
481
- Array.from(node.attributes).filter((attr2) => ["as", "index"].includes(attr2.name)).forEach((attr2) => {
482
- template.setAttribute(attr2.name, attr2.value);
483
- node.removeAttribute(attr2.name);
607
+ if (["$each", "st-each", "$$each", "st-st-each"].includes(attr.name)) {
608
+ Array.from(node.attributes).filter((attr2) => ["as", "index", "key"].includes(attr2.name)).forEach((attr2) => {
609
+ template.setAttribute(attr2.name, attr2.value);
610
+ node.removeAttribute(attr2.name);
611
+ });
612
+ }
613
+ Array.from(node.content.childNodes).forEach((child) => template.content.appendChild(child));
614
+ node.content.appendChild(template);
615
+ template._ref = node._ref;
616
+ }
617
+ if (node.tagName === "IMG" && (node.hasAttribute("src") || node.hasAttribute("_src") || node.hasAttribute("$src"))) {
618
+ const imgNode = node;
619
+ Promise.resolve().then(() => {
620
+ const url = imgNode.getAttribute("_src") || imgNode.getAttribute("src");
621
+ if (url) fetch(url, { cache: "force-cache" }).then((r) => r.text()).then((svgText) => {
622
+ const realSvg = new DOMParser().parseFromString(svgText, "image/svg+xml").querySelector("svg");
623
+ if (realSvg) {
624
+ Array.from(imgNode.attributes).forEach((attr) => realSvg.setAttribute(attr.name, attr.value));
625
+ imgNode.replaceWith(realSvg);
626
+ }
627
+ });
484
628
  });
485
629
  }
486
- Array.from(node.content.childNodes).forEach((child) => template.content.appendChild(child));
487
- node.content.appendChild(template);
488
- template._ref = node._ref;
630
+ if (node._thisObj !== void 0) scanObj.thisObj = node._thisObj || null;
631
+ else {
632
+ let curr = node;
633
+ while (curr && curr._thisObj === void 0) curr = curr.parentNode;
634
+ scanObj.thisObj = curr ? curr._thisObj : null;
635
+ }
636
+ if (node._ref === void 0) {
637
+ let curr = node;
638
+ while (curr && curr._ref === void 0) curr = curr.parentNode;
639
+ node._ref = curr ? { ...curr._ref } : {};
640
+ }
641
+ if (node._refExt !== void 0) {
642
+ Object.assign(node._ref, node._refExt);
643
+ }
644
+ if (scanObj.extendVars) Object.assign(node._ref, scanObj.extendVars);
645
+ _parseNode(node, { ...scanObj });
646
+ const nodes = [...node.childNodes || []];
647
+ nodes.forEach((child) => _scanTree(child, { thisObj: scanObj.thisObj, extendVars: { ...node._ref } }));
489
648
  }
490
- if (node.tagName === "IMG" && (node.hasAttribute("src") || node.hasAttribute("_src") || node.hasAttribute("$src"))) {
491
- const imgNode = node;
492
- Promise.resolve().then(() => {
493
- const url = imgNode.getAttribute("_src") || imgNode.getAttribute("src");
494
- if (url) fetch(url, { cache: "force-cache" }).then((r) => r.text()).then((svgText) => {
495
- const realSvg = new DOMParser().parseFromString(svgText, "image/svg+xml").querySelector("svg");
496
- if (realSvg) {
497
- Array.from(imgNode.attributes).forEach((attr) => realSvg.setAttribute(attr.name, attr.value));
498
- imgNode.replaceWith(realSvg);
649
+ function _unbindTree(node) {
650
+ if (node.nodeType !== 1) return;
651
+ if (node._hasOnUnload) node.dispatchEvent(new Event("unload", { bubbles: false }));
652
+ if (node._states) node._states.forEach((mappings) => {
653
+ for (const [key, bindingSet] of mappings) {
654
+ for (const binding of bindingSet) {
655
+ if (binding.node === node) bindingSet.delete(binding);
499
656
  }
500
- });
657
+ }
501
658
  });
659
+ node.childNodes && node.childNodes.forEach((child) => _unbindTree(child));
502
660
  }
503
- if (node._thisObj !== void 0) scanObj.thisObj = node._thisObj || null;
504
- else {
505
- let curr = node;
506
- while (curr && curr._thisObj === void 0) curr = curr.parentNode;
507
- scanObj.thisObj = curr ? curr._thisObj : null;
508
- }
509
- if (node._ref === void 0) {
510
- let curr = node;
511
- while (curr && curr._ref === void 0) curr = curr.parentNode;
512
- node._ref = curr ? { ...curr._ref } : {};
513
- }
514
- if (scanObj.extendVars) Object.assign(node._ref, scanObj.extendVars);
515
- _parseNode(node, { ...scanObj });
516
- const nodes = [...node.childNodes || []];
517
- nodes.forEach((child) => _scanTree(child, { thisObj: scanObj.thisObj, extendVars: { ...node._ref } }));
518
- };
519
- const _unbindTree = (node) => {
520
- if (node.nodeType !== 1) return;
521
- if (node._hasOnUnload) node.dispatchEvent(new Event("unload", { bubbles: false }));
522
- if (node._states) node._states.forEach((mappings) => {
523
- for (const [key, bindingSet] of mappings) {
524
- for (const binding of bindingSet) {
525
- if (binding.node === node) bindingSet.delete(binding);
526
- }
527
- }
528
- });
529
- node.childNodes && node.childNodes.forEach((child) => _unbindTree(child));
530
- };
531
- const _unsafeRefreshState = _scanTree;
532
- const Util = {
533
- clone: window.structuredClone || ((obj) => JSON.parse(JSON.stringify(obj))),
534
- base64: (str) => btoa(String.fromCharCode(...new TextEncoder().encode(str))),
535
- unbase64: (str) => new TextDecoder().decode(Uint8Array.from(atob(str), (c) => c.charCodeAt(0))),
536
- urlbase64: (str) => Util.base64(str).replace(/[+/=]/g, (m) => ({ "+": "-", "/": "", "=": "" })[m]),
537
- unurlbase64: (str) => Util.unbase64(str.replace(/[-_.]/g, (m) => ({ "-": "+", "_": "/", ".": "=" })[m]).padEnd(Math.ceil(str.length / 4) * 4, "=")),
538
- safeJson: (str) => {
539
- try {
540
- return JSON.parse(str);
541
- } catch {
542
- return null;
543
- }
544
- },
545
- updateDefaults: (obj, defaults) => {
546
- for (const k in defaults) if (obj[k] === void 0) obj[k] = defaults[k];
547
- },
548
- copyFunction: (toObj, fromObj, ...funcNames) => {
549
- funcNames.forEach((name) => toObj[name] = fromObj[name].bind(fromObj));
550
- },
551
- getFunctionBody: (fn) => {
552
- const code = fn.toString();
553
- return code.slice(code.indexOf("{") + 1, code.lastIndexOf("}")).trim();
554
- },
555
- makeDom: (html) => {
556
- if (html.includes(">\n")) html = html.replace(/>\s+</g, "><").trim();
557
- const node = document.createElement("div");
558
- node.innerHTML = html;
559
- return node.children[0];
560
- },
561
- newAvg: () => {
562
- let total = 0, count = 0, avg = 0;
563
- return {
564
- add: (v) => {
565
- total += v;
566
- count++;
567
- return avg = total / count;
568
- },
569
- get: () => avg,
570
- clear: () => {
571
- total = 0, count = 0, avg = 0;
661
+ if (typeof document !== "undefined") {
662
+ const init = () => {
663
+ Component._initPending();
664
+ const htmlNode = document.documentElement;
665
+ if (!htmlNode.hasAttribute("$data-bs-theme") && !htmlNode.hasAttribute("data-bs-theme")) {
666
+ htmlNode.setAttribute("$data-bs-theme", "LocalStorage.darkMode?'dark':'light'");
572
667
  }
668
+ new MutationObserver((mutations) => {
669
+ mutations.forEach((mutation) => {
670
+ mutation.addedNodes.forEach((newNode) => {
671
+ if (newNode.isConnected) _scanTree(newNode);
672
+ });
673
+ mutation.removedNodes.forEach((oldNode) => {
674
+ _unbindTree(oldNode);
675
+ });
676
+ });
677
+ }).observe(document.documentElement, { childList: true, subtree: true });
678
+ _scanTree(document.documentElement);
573
679
  };
574
- },
575
- newTimeCount: () => {
576
- let startTime = 0, total = 0, count = 0;
577
- return {
578
- start: () => startTime = (/* @__PURE__ */ new Date()).getTime(),
579
- end: () => {
580
- const endTime = (/* @__PURE__ */ new Date()).getTime();
581
- const left = endTime - startTime;
582
- startTime = endTime;
583
- total += left;
584
- count++;
585
- return left;
586
- },
587
- avg: () => total / count
588
- };
680
+ if (document.readyState !== "loading") init();
681
+ else document.addEventListener("DOMContentLoaded", init, true);
589
682
  }
590
- };
591
- globalThis.Util = Util;
592
- let _hashParams = new URLSearchParams(((_a = window.location.hash) == null ? void 0 : _a.substring(1)) || "");
593
- const Hash = NewState({}, (k) => Util.safeJson(_hashParams.get(k)), (k, v) => {
594
- const oldStr = _hashParams.get(k);
595
- const newStr = v === void 0 ? void 0 : JSON.stringify(v);
596
- if (oldStr === newStr || oldStr === null && newStr === void 0) return;
597
- v === void 0 ? _hashParams.delete(k) : _hashParams.set(k, newStr);
598
- window.location.hash = "#" + _hashParams.toString();
599
- });
600
- if (typeof window !== "undefined") {
601
- window.addEventListener("hashchange", () => {
602
- var _a2;
603
- const newParams = new URLSearchParams(((_a2 = window.location.hash) == null ? void 0 : _a2.substring(1)) || "");
604
- const keys = /* @__PURE__ */ new Set([..._hashParams.keys(), ...newParams.keys()]);
605
- _hashParams = newParams;
606
- keys.forEach((k) => Hash[k] = Hash[k]);
607
- });
608
- }
609
- const LocalStorage = NewState({}, (k) => Util.safeJson(localStorage.getItem(k)), (k, v) => {
610
- const oldStr = localStorage.getItem(k);
611
- const newStr = v === void 0 ? void 0 : JSON.stringify(v);
612
- if (oldStr === newStr || oldStr === null && newStr === void 0) return;
613
- v === void 0 ? localStorage.removeItem(k) : localStorage.setItem(k, newStr);
614
- });
615
- const State = NewState({
616
- exitBlocks: 0
617
- });
618
- globalThis.Hash = Hash;
619
- globalThis.LocalStorage = LocalStorage;
620
- globalThis.State = State;
621
- const ApigoState = {
622
- NewState,
623
- Component,
624
- $,
625
- $$,
626
- RefreshState: _unsafeRefreshState,
627
- SetTranslator,
628
- _scanTree,
629
- _unbindTree,
630
- Util,
631
- Hash,
632
- LocalStorage,
633
- State
634
- };
635
- globalThis.$ = $;
636
- globalThis.$$ = $$;
637
- if (typeof window !== "undefined") {
638
- window.ApigoState = ApigoState;
639
- }
640
- if (typeof document !== "undefined") {
641
- const init = () => {
642
- Component._initPending();
643
- const htmlNode = document.documentElement;
644
- if (!htmlNode.hasAttribute("$data-bs-theme") && !htmlNode.hasAttribute("data-bs-theme")) {
645
- htmlNode.setAttribute("$data-bs-theme", "LocalStorage.darkMode?'dark':'light'");
646
- }
647
- new MutationObserver((mutations) => {
648
- mutations.forEach((mutation) => {
649
- mutation.addedNodes.forEach((newNode) => {
650
- if (newNode.isConnected) _scanTree(newNode);
651
- });
652
- mutation.removedNodes.forEach((oldNode) => _unbindTree(oldNode));
653
- });
654
- }).observe(document.documentElement, { childList: true, subtree: true });
655
- _scanTree(document.documentElement);
656
- };
657
- if (document.readyState !== "loading") init();
658
- else document.addEventListener("DOMContentLoaded", init, true);
659
- }
660
- exports2.$ = $;
661
- exports2.$$ = $$;
662
- exports2.Component = Component;
663
- exports2.Hash = Hash;
664
- exports2.LocalStorage = LocalStorage;
665
- exports2.NewState = NewState;
666
- exports2.RefreshState = _unsafeRefreshState;
667
- exports2.SetTranslator = SetTranslator;
668
- exports2.State = State;
669
- exports2.Util = Util;
670
- exports2._scanTree = _scanTree;
671
- exports2._unbindTree = _unbindTree;
672
- Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
683
+ global.Component = Component;
684
+ global.SetTranslator = SetTranslator;
685
+ global._runCode = _runCode;
686
+ global._returnCode = _returnCode;
687
+ global._scanTree = _scanTree;
688
+ global._unbindTree = _unbindTree;
689
+ global._unsafeRefreshState = _scanTree;
690
+ global.RefreshState = _scanTree;
691
+ })(globalThis);
673
692
  });