sigpro 1.0.14 → 1.2.40

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.
Files changed (112) hide show
  1. package/Readme.md +164 -1008
  2. package/dist/sigpro.db.js +1 -0
  3. package/dist/sigpro.editor.js +1 -0
  4. package/dist/sigpro.grid.js +78 -0
  5. package/dist/sigpro.js +1 -0
  6. package/dist/sigpro.locale.js +1 -0
  7. package/dist/sigpro.router.js +1 -0
  8. package/dist/sigpro.ui.css +2 -0
  9. package/dist/sigpro.ui.js +1 -0
  10. package/dist/sigpro.vite.js +4 -0
  11. package/package.json +94 -13
  12. package/sigpro.d.ts +395 -0
  13. package/sigpro.ui.d.ts +308 -0
  14. package/.github/workflows/publish.yml +0 -25
  15. package/bun.lock +0 -385
  16. package/docs/404.html +0 -22
  17. package/docs/api/components.html +0 -595
  18. package/docs/api/effects.html +0 -787
  19. package/docs/api/fetch.html +0 -873
  20. package/docs/api/pages.html +0 -405
  21. package/docs/api/quick.html +0 -217
  22. package/docs/api/routing.html +0 -628
  23. package/docs/api/signals.html +0 -683
  24. package/docs/api/storage.html +0 -820
  25. package/docs/assets/api_components.md.BlFwj17l.js +0 -571
  26. package/docs/assets/api_components.md.BlFwj17l.lean.js +0 -1
  27. package/docs/assets/api_effects.md.Br_yStBS.js +0 -763
  28. package/docs/assets/api_effects.md.Br_yStBS.lean.js +0 -1
  29. package/docs/assets/api_fetch.md.DQLBJSoq.js +0 -849
  30. package/docs/assets/api_fetch.md.DQLBJSoq.lean.js +0 -1
  31. package/docs/assets/api_pages.md.BP19nHXw.js +0 -381
  32. package/docs/assets/api_pages.md.BP19nHXw.lean.js +0 -1
  33. package/docs/assets/api_quick.md.BDS3ttnt.js +0 -193
  34. package/docs/assets/api_quick.md.BDS3ttnt.lean.js +0 -1
  35. package/docs/assets/api_routing.md.7SNAZXtp.js +0 -604
  36. package/docs/assets/api_routing.md.7SNAZXtp.lean.js +0 -1
  37. package/docs/assets/api_signals.md.CrW68-BA.js +0 -659
  38. package/docs/assets/api_signals.md.CrW68-BA.lean.js +0 -1
  39. package/docs/assets/api_storage.md.COEWBXHk.js +0 -796
  40. package/docs/assets/api_storage.md.COEWBXHk.lean.js +0 -1
  41. package/docs/assets/app.DtmzNmNl.js +0 -1
  42. package/docs/assets/chunks/framework.C8AWLET_.js +0 -19
  43. package/docs/assets/chunks/theme.yfWKMLQM.js +0 -1
  44. package/docs/assets/guide_getting-started.md.BeQpK3vd.js +0 -172
  45. package/docs/assets/guide_getting-started.md.BeQpK3vd.lean.js +0 -1
  46. package/docs/assets/guide_why.md.DXchYMN-.js +0 -23
  47. package/docs/assets/guide_why.md.DXchYMN-.lean.js +0 -1
  48. package/docs/assets/index.md.uvMJmU4o.js +0 -1
  49. package/docs/assets/index.md.uvMJmU4o.lean.js +0 -1
  50. package/docs/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 +0 -0
  51. package/docs/assets/inter-italic-cyrillic.By2_1cv3.woff2 +0 -0
  52. package/docs/assets/inter-italic-greek-ext.1u6EdAuj.woff2 +0 -0
  53. package/docs/assets/inter-italic-greek.DJ8dCoTZ.woff2 +0 -0
  54. package/docs/assets/inter-italic-latin-ext.CN1xVJS-.woff2 +0 -0
  55. package/docs/assets/inter-italic-latin.C2AdPX0b.woff2 +0 -0
  56. package/docs/assets/inter-italic-vietnamese.BSbpV94h.woff2 +0 -0
  57. package/docs/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 +0 -0
  58. package/docs/assets/inter-roman-cyrillic.C5lxZ8CY.woff2 +0 -0
  59. package/docs/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 +0 -0
  60. package/docs/assets/inter-roman-greek.BBVDIX6e.woff2 +0 -0
  61. package/docs/assets/inter-roman-latin-ext.4ZJIpNVo.woff2 +0 -0
  62. package/docs/assets/inter-roman-latin.Di8DUHzh.woff2 +0 -0
  63. package/docs/assets/inter-roman-vietnamese.BjW4sHH5.woff2 +0 -0
  64. package/docs/assets/style.DJRheFKp.css +0 -1
  65. package/docs/assets/ui_intro.md.gZ21GFqo.js +0 -1
  66. package/docs/assets/ui_intro.md.gZ21GFqo.lean.js +0 -1
  67. package/docs/assets/vite_plugin.md.gDWEi8f0.js +0 -225
  68. package/docs/assets/vite_plugin.md.gDWEi8f0.lean.js +0 -1
  69. package/docs/guide/getting-started.html +0 -196
  70. package/docs/guide/why.html +0 -47
  71. package/docs/hashmap.json +0 -1
  72. package/docs/index.html +0 -25
  73. package/docs/logo.svg +0 -118
  74. package/docs/ui/intro.html +0 -25
  75. package/docs/vite/plugin.html +0 -249
  76. package/docs/vp-icons.css +0 -1
  77. package/index.js +0 -3
  78. package/packages/docs/.vitepress/cache/deps/@theme_index.js +0 -275
  79. package/packages/docs/.vitepress/cache/deps/@theme_index.js.map +0 -7
  80. package/packages/docs/.vitepress/cache/deps/_metadata.json +0 -40
  81. package/packages/docs/.vitepress/cache/deps/chunk-3S55Y3P7.js +0 -12951
  82. package/packages/docs/.vitepress/cache/deps/chunk-3S55Y3P7.js.map +0 -7
  83. package/packages/docs/.vitepress/cache/deps/chunk-RLEUDPPB.js +0 -9719
  84. package/packages/docs/.vitepress/cache/deps/chunk-RLEUDPPB.js.map +0 -7
  85. package/packages/docs/.vitepress/cache/deps/package.json +0 -3
  86. package/packages/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js +0 -4505
  87. package/packages/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js.map +0 -7
  88. package/packages/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js +0 -583
  89. package/packages/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js.map +0 -7
  90. package/packages/docs/.vitepress/cache/deps/vue.js +0 -347
  91. package/packages/docs/.vitepress/cache/deps/vue.js.map +0 -7
  92. package/packages/docs/.vitepress/config.js +0 -68
  93. package/packages/docs/api/components.md +0 -760
  94. package/packages/docs/api/effects.md +0 -1039
  95. package/packages/docs/api/fetch.md +0 -998
  96. package/packages/docs/api/pages.md +0 -497
  97. package/packages/docs/api/quick.md +0 -436
  98. package/packages/docs/api/routing.md +0 -784
  99. package/packages/docs/api/signals.md +0 -899
  100. package/packages/docs/api/storage.md +0 -952
  101. package/packages/docs/guide/getting-started.md +0 -308
  102. package/packages/docs/guide/why.md +0 -135
  103. package/packages/docs/index.md +0 -84
  104. package/packages/docs/logo.svg +0 -118
  105. package/packages/docs/public/logo.svg +0 -118
  106. package/packages/docs/ui/intro.md +0 -16
  107. package/packages/docs/vite/plugin.md +0 -423
  108. package/packages/sigpro/plugin.js +0 -91
  109. package/packages/sigpro/plugin.min.js +0 -1
  110. package/packages/sigpro/sigpro.js +0 -631
  111. package/packages/sigpro/sigpro.min.js +0 -1
  112. package/vite.config.js +0 -24
@@ -1,631 +0,0 @@
1
- // Global state for tracking the current reactive effect
2
- let activeEffect = null;
3
- const effectQueue = new Set();
4
- let isFlushScheduled = false;
5
- let flushCount = 0;
6
-
7
- const flushEffectQueue = () => {
8
- isFlushScheduled = false;
9
- flushCount++;
10
-
11
- if (flushCount > 100) {
12
- effectQueue.clear();
13
- flushCount = 0;
14
- throw new Error("SigPro: Infinite reactive loop detected.");
15
- }
16
-
17
- try {
18
- const effects = Array.from(effectQueue);
19
- effectQueue.clear();
20
- for (const effect of effects) effect.run();
21
- } catch (error) {
22
- console.error("SigPro Flush Error:", error);
23
- } finally {
24
- setTimeout(() => {
25
- flushCount = 0;
26
- }, 0);
27
- }
28
- };
29
-
30
- /**
31
- * Creates a reactive signal
32
- * @param {any} initialValue - Initial value or getter function
33
- * @returns {Function} Signal getter/setter function
34
- */
35
- const $ = (initialValue) => {
36
- const subscribers = new Set();
37
- let signal;
38
-
39
- if (typeof initialValue === "function") {
40
- let isDirty = true;
41
- let cachedValue;
42
-
43
- const computedEffect = {
44
- dependencies: new Set(),
45
- markDirty: () => {
46
- if (!isDirty) {
47
- isDirty = true;
48
- subscribers.forEach((sub) => {
49
- if (sub.markDirty) sub.markDirty();
50
- effectQueue.add(sub);
51
- });
52
- if (!isFlushScheduled && effectQueue.size) {
53
- isFlushScheduled = true;
54
- queueMicrotask(flushEffectQueue);
55
- }
56
- }
57
- },
58
- run: () => {
59
- computedEffect.dependencies.forEach((dep) => dep.delete(computedEffect));
60
- computedEffect.dependencies.clear();
61
- const prev = activeEffect;
62
- activeEffect = computedEffect;
63
- try {
64
- cachedValue = initialValue();
65
- } finally {
66
- activeEffect = prev;
67
- isDirty = false;
68
- }
69
- },
70
- };
71
-
72
- signal = () => {
73
- if (activeEffect) {
74
- subscribers.add(activeEffect);
75
- activeEffect.dependencies.add(subscribers);
76
- }
77
- if (isDirty) computedEffect.run();
78
- return cachedValue;
79
- };
80
- } else {
81
- signal = (...args) => {
82
- if (args.length) {
83
- const next = typeof args[0] === "function" ? args[0](initialValue) : args[0];
84
- if (!Object.is(initialValue, next)) {
85
- initialValue = next;
86
- subscribers.forEach((sub) => {
87
- if (sub.markDirty) sub.markDirty();
88
- effectQueue.add(sub);
89
- });
90
- if (!isFlushScheduled && effectQueue.size) {
91
- isFlushScheduled = true;
92
- queueMicrotask(flushEffectQueue);
93
- }
94
- }
95
- }
96
- if (activeEffect) {
97
- subscribers.add(activeEffect);
98
- activeEffect.dependencies.add(subscribers);
99
- }
100
- return initialValue;
101
- };
102
- }
103
- return signal;
104
- };
105
-
106
- let currentPageCleanups = null;
107
-
108
- /**
109
- * Creates a reactive effect that runs when dependencies change
110
- * @param {Function} effectFn - The effect function to run
111
- * @returns {Function} Cleanup function to stop the effect
112
- */
113
- const $e = (effectFn) => {
114
- const effect = {
115
- dependencies: new Set(),
116
- cleanupHandlers: new Set(),
117
- run() {
118
- this.cleanupHandlers.forEach((h) => h());
119
- this.cleanupHandlers.clear();
120
- this.dependencies.forEach((dep) => dep.delete(this));
121
- this.dependencies.clear();
122
-
123
- const prev = activeEffect;
124
- activeEffect = this;
125
- try {
126
- const res = effectFn();
127
- if (typeof res === "function") this.cleanupHandlers.add(res);
128
- } finally {
129
- activeEffect = prev;
130
- }
131
- },
132
- stop() {
133
- this.cleanupHandlers.forEach((h) => h());
134
- this.dependencies.forEach((dep) => dep.delete(this));
135
- },
136
- };
137
-
138
- if (currentPageCleanups) currentPageCleanups.push(() => effect.stop());
139
- if (activeEffect) activeEffect.cleanupHandlers.add(() => effect.stop());
140
-
141
- effect.run();
142
- return () => effect.stop();
143
- };
144
-
145
- /**
146
- * Persistent signal with localStorage
147
- * @param {string} key - Storage key
148
- * @param {any} initialValue - Default value if none stored
149
- * @param {Storage} [storage=localStorage] - Storage type (localStorage/sessionStorage)
150
- * @returns {Function} Signal that persists to storage
151
- */
152
- const $s = (key, initialValue, storage = localStorage) => {
153
- let initial;
154
- try {
155
- const saved = storage.getItem(key);
156
- if (saved !== null) {
157
- initial = JSON.parse(saved);
158
- } else {
159
- initial = initialValue;
160
- }
161
- } catch (e) {
162
- console.warn(`Error reading ${key} from storage:`, e);
163
- initial = initialValue;
164
- storage.removeItem(key);
165
- }
166
-
167
- const signal = $(initial);
168
-
169
- $e(() => {
170
- try {
171
- const value = signal();
172
- if (value === undefined || value === null) {
173
- storage.removeItem(key);
174
- } else {
175
- storage.setItem(key, JSON.stringify(value));
176
- }
177
- } catch (e) {
178
- console.warn(`Error saving ${key} to storage:`, e);
179
- }
180
- });
181
-
182
- return signal;
183
- };
184
-
185
- /**
186
- * Tagged template literal for creating reactive HTML
187
- * @param {string[]} strings - Template strings
188
- * @param {...any} values - Dynamic values
189
- * @returns {DocumentFragment} Reactive document fragment
190
- * @see {@link https://developer.mozilla.org/es/docs/Glossary/Cross-site_scripting}
191
- */
192
- const html = (strings, ...values) => {
193
- const templateCache = html._templateCache ?? (html._templateCache = new WeakMap());
194
-
195
- const getNodeByPath = (root, path) => path.reduce((node, index) => node?.childNodes?.[index], root);
196
-
197
- const applyTextContent = (node, values) => {
198
- const parts = node.textContent.split("{{part}}");
199
- const parent = node.parentNode;
200
- let valueIndex = 0;
201
-
202
- parts.forEach((part, index) => {
203
- if (part) parent.insertBefore(document.createTextNode(part), node);
204
- if (index < parts.length - 1) {
205
- const currentValue = values[valueIndex++];
206
- const startMarker = document.createComment("s");
207
- const endMarker = document.createComment("e");
208
- parent.insertBefore(startMarker, node);
209
- parent.insertBefore(endMarker, node);
210
-
211
- if (typeof currentValue === "function") {
212
- let lastResult;
213
- $e(() => {
214
- const result = currentValue();
215
- if (result === lastResult) return;
216
- lastResult = result;
217
- updateContent(result);
218
- });
219
- } else {
220
- updateContent(currentValue);
221
- }
222
-
223
- function updateContent(result) {
224
- if (typeof result !== "object" && !Array.isArray(result)) {
225
- const textNode = startMarker.nextSibling;
226
- const safeText = String(result ?? "");
227
-
228
- if (textNode !== endMarker && textNode?.nodeType === 3) {
229
- textNode.textContent = safeText;
230
- } else {
231
- while (startMarker.nextSibling !== endMarker) parent.removeChild(startMarker.nextSibling);
232
- parent.insertBefore(document.createTextNode(safeText), endMarker);
233
- }
234
- } else {
235
- while (startMarker.nextSibling !== endMarker) parent.removeChild(startMarker.nextSibling);
236
-
237
- const items = Array.isArray(result) ? result : [result];
238
- const fragment = document.createDocumentFragment();
239
- items.forEach((item) => {
240
- if (item == null || item === false) return;
241
- const nodeItem = item instanceof Node ? item : document.createTextNode(item);
242
- fragment.appendChild(nodeItem);
243
- });
244
- parent.insertBefore(fragment, endMarker);
245
- }
246
- }
247
- }
248
- });
249
- node.remove();
250
- };
251
-
252
- let cachedTemplate = templateCache.get(strings);
253
- if (!cachedTemplate) {
254
- const template = document.createElement("template");
255
- template.innerHTML = strings.join("{{part}}");
256
-
257
- const dynamicNodes = [];
258
- const treeWalker = document.createTreeWalker(template.content, 133);
259
-
260
- const getNodePath = (node) => {
261
- const path = [];
262
- while (node && node !== template.content) {
263
- let index = 0;
264
- for (let sibling = node.previousSibling; sibling; sibling = sibling.previousSibling) index++;
265
- path.push(index);
266
- node = node.parentNode;
267
- }
268
- return path.reverse();
269
- };
270
-
271
- let currentNode;
272
- while ((currentNode = treeWalker.nextNode())) {
273
- let isDynamic = false;
274
- const nodeInfo = {
275
- type: currentNode.nodeType,
276
- path: getNodePath(currentNode),
277
- parts: [],
278
- };
279
-
280
- if (currentNode.nodeType === 1) {
281
- for (let i = 0; i < currentNode.attributes.length; i++) {
282
- const attribute = currentNode.attributes[i];
283
- if (attribute.value.includes("{{part}}")) {
284
- nodeInfo.parts.push({ name: attribute.name });
285
- isDynamic = true;
286
- }
287
- }
288
- } else if (currentNode.nodeType === 3 && currentNode.textContent.includes("{{part}}")) {
289
- isDynamic = true;
290
- }
291
-
292
- if (isDynamic) dynamicNodes.push(nodeInfo);
293
- }
294
-
295
- templateCache.set(strings, (cachedTemplate = { template, dynamicNodes }));
296
- }
297
-
298
- const fragment = cachedTemplate.template.content.cloneNode(true);
299
- let valueIndex = 0;
300
-
301
- const targets = cachedTemplate.dynamicNodes.map((nodeInfo) => ({
302
- node: getNodeByPath(fragment, nodeInfo.path),
303
- info: nodeInfo,
304
- }));
305
-
306
- targets.forEach(({ node, info }) => {
307
- if (!node) return;
308
-
309
- if (info.type === 1) {
310
- info.parts.forEach((part) => {
311
- const currentValue = values[valueIndex++];
312
- const attributeName = part.name;
313
- const firstChar = attributeName[0];
314
-
315
- if (firstChar === "@") {
316
- const [eventName, ...modifiers] = attributeName.slice(1).split(".");
317
-
318
- const handlerWrapper = (e) => {
319
- if (modifiers.includes("prevent")) e.preventDefault();
320
- if (modifiers.includes("stop")) e.stopPropagation();
321
- if (modifiers.includes("self") && e.target !== node) return;
322
-
323
- if (modifiers.some((m) => m.startsWith("debounce"))) {
324
- const ms = modifiers.find((m) => m.startsWith("debounce"))?.split(":")[1] || 300;
325
- clearTimeout(node._debounceTimer);
326
- node._debounceTimer = setTimeout(() => currentValue(e), ms);
327
- return;
328
- }
329
-
330
- if (modifiers.includes("once")) {
331
- node.removeEventListener(eventName, handlerWrapper);
332
- }
333
-
334
- currentValue(e);
335
- };
336
-
337
- node.addEventListener(eventName, handlerWrapper, {
338
- passive: modifiers.includes("passive"),
339
- capture: modifiers.includes("capture"),
340
- });
341
- } else if (firstChar === ":") {
342
- const propertyName = attributeName.slice(1);
343
- const eventType = node.type === "checkbox" || node.type === "radio" ? "change" : "input";
344
-
345
- if (typeof currentValue === "function") {
346
- $e(() => {
347
- const value = currentValue();
348
- if (node[propertyName] !== value) node[propertyName] = value;
349
- });
350
- } else {
351
- node[propertyName] = currentValue;
352
- }
353
-
354
- node.addEventListener(eventType, () => {
355
- const value = eventType === "change" ? node.checked : node.value;
356
- if (typeof currentValue === "function") currentValue(value);
357
- });
358
- } else if (firstChar === "?") {
359
- const attrName = attributeName.slice(1);
360
-
361
- if (typeof currentValue === "function") {
362
- $e(() => {
363
- const result = currentValue();
364
- node.toggleAttribute(attrName, !!result);
365
- });
366
- } else {
367
- node.toggleAttribute(attrName, !!currentValue);
368
- }
369
- } else if (firstChar === ".") {
370
- const propertyName = attributeName.slice(1);
371
-
372
- if (typeof currentValue === "function") {
373
- $e(() => {
374
- const result = currentValue();
375
- node[propertyName] = result;
376
- if (result != null && typeof result !== "object" && typeof result !== "boolean") {
377
- node.setAttribute(propertyName, result);
378
- }
379
- });
380
- } else {
381
- node[propertyName] = currentValue;
382
- if (currentValue != null && typeof currentValue !== "object" && typeof currentValue !== "boolean") {
383
- node.setAttribute(propertyName, currentValue);
384
- }
385
- }
386
- } else {
387
- if (typeof currentValue === "function") {
388
- $e(() => node.setAttribute(attributeName, currentValue()));
389
- } else {
390
- node.setAttribute(attributeName, currentValue);
391
- }
392
- }
393
- });
394
- } else if (info.type === 3) {
395
- const placeholderCount = node.textContent.split("{{part}}").length - 1;
396
- applyTextContent(node, values.slice(valueIndex, valueIndex + placeholderCount));
397
- valueIndex += placeholderCount;
398
- }
399
- });
400
-
401
- return fragment;
402
- };
403
-
404
- /**
405
- * Creates a page with automatic cleanup
406
- * @param {Function} setupFunction - Page setup function that receives props
407
- * @returns {Function} A function that creates page instances with props
408
- */
409
- const $p = (setupFunction) => {
410
- const tagName = "page-" + Math.random().toString(36).substring(2, 9);
411
-
412
- customElements.define(
413
- tagName,
414
- class extends HTMLElement {
415
- connectedCallback() {
416
- this.style.display = "contents";
417
- this._cleanups = [];
418
- currentPageCleanups = this._cleanups;
419
-
420
- try {
421
- const result = setupFunction({
422
- params: JSON.parse(this.getAttribute("params") || "{}"),
423
- onUnmount: (fn) => this._cleanups.push(fn),
424
- });
425
- this.appendChild(result instanceof Node ? result : document.createTextNode(String(result)));
426
- } finally {
427
- currentPageCleanups = null;
428
- }
429
- }
430
-
431
- disconnectedCallback() {
432
- this._cleanups.forEach((fn) => fn());
433
- this._cleanups = [];
434
- this.innerHTML = "";
435
- }
436
- },
437
- );
438
-
439
- return (props = {}) => {
440
- const el = document.createElement(tagName);
441
- el.setAttribute("params", JSON.stringify(props));
442
- return el;
443
- };
444
- };
445
-
446
- /**
447
- * Creates a custom web component with reactive properties
448
- * @param {string} tagName - Custom element tag name
449
- * @param {Function} setupFunction - Component setup function
450
- * @param {string[]} observedAttributes - Array of observed attributes
451
- * @param {boolean} useShadowDOM - Enable Shadow DOM (default: false)
452
- */
453
- const $c = (tagName, setupFunction, observedAttributes = [], useShadowDOM = false) => {
454
- if (customElements.get(tagName)) return;
455
-
456
- customElements.define(
457
- tagName,
458
- class extends HTMLElement {
459
- static get observedAttributes() {
460
- return observedAttributes;
461
- }
462
-
463
- constructor() {
464
- super();
465
- this._propertySignals = {};
466
- this.cleanupFunctions = [];
467
-
468
- if (useShadowDOM) {
469
- this._root = this.attachShadow({ mode: "open" });
470
- } else {
471
- this._root = this;
472
- }
473
-
474
- observedAttributes.forEach((attr) => (this._propertySignals[attr] = $(undefined)));
475
- }
476
-
477
- connectedCallback() {
478
- const frozenChildren = [...this.childNodes];
479
- this._root.innerHTML = "";
480
-
481
- observedAttributes.forEach((attr) => {
482
- const initialValue = this.hasOwnProperty(attr) ? this[attr] : this.getAttribute(attr);
483
-
484
- Object.defineProperty(this, attr, {
485
- get: () => this._propertySignals[attr](),
486
- set: (value) => {
487
- const processedValue = value === "false" ? false : value === "" && attr !== "value" ? true : value;
488
- this._propertySignals[attr](processedValue);
489
- },
490
- configurable: true,
491
- });
492
-
493
- if (initialValue !== null && initialValue !== undefined) this[attr] = initialValue;
494
- });
495
-
496
- const context = {
497
- select: (selector) => this._root.querySelector(selector),
498
- selectAll: (selector) => this._root.querySelectorAll(selector),
499
- slot: (name) =>
500
- frozenChildren.filter((node) => {
501
- const slotName = node.nodeType === 1 ? node.getAttribute("slot") : null;
502
- return name ? slotName === name : !slotName;
503
- }),
504
- emit: (name, detail) => this.dispatchEvent(new CustomEvent(name, { detail, bubbles: true, composed: true })),
505
- host: this,
506
- root: this._root,
507
- onUnmount: (cleanupFn) => this.cleanupFunctions.push(cleanupFn),
508
- };
509
-
510
- const result = setupFunction(this._propertySignals, context);
511
- if (result instanceof Node) this._root.appendChild(result);
512
- }
513
-
514
- attributeChangedCallback(name, oldValue, newValue) {
515
- if (this[name] !== newValue) this[name] = newValue;
516
- }
517
-
518
- disconnectedCallback() {
519
- this.cleanupFunctions.forEach((cleanupFn) => cleanupFn());
520
- this.cleanupFunctions = [];
521
- }
522
- },
523
- );
524
- };
525
-
526
- /**
527
- * Ultra-simple fetch wrapper with optional loading signal
528
- * @param {string} url - Endpoint URL
529
- * @param {Object} data - Data to send (automatically JSON.stringify'd)
530
- * @param {Function} [loading] - Optional signal function to track loading state
531
- * @returns {Promise<Object|null>} Parsed JSON response or null on error
532
- */
533
- const $f = async (url, data, loading) => {
534
- if (loading) loading(true);
535
-
536
- try {
537
- const res = await fetch(url, {
538
- method: "POST",
539
- headers: { "Content-Type": "application/json" },
540
- body: JSON.stringify(data),
541
- });
542
-
543
- const text = await res.text();
544
- try {
545
- return JSON.parse(text);
546
- } catch (e) {
547
- console.warn("Invalid JSON response");
548
- return null;
549
- }
550
- } catch (e) {
551
- return null;
552
- } finally {
553
- if (loading) loading(false);
554
- }
555
- };
556
-
557
- /**
558
- * Creates a router for hash-based navigation
559
- * @param {Array<{path: string|RegExp, component: Function}>} routes - Route configurations
560
- * @returns {HTMLDivElement} Router container element
561
- */
562
- const $r = (routes) => {
563
- const getCurrentPath = () => window.location.hash.replace(/^#/, "") || "/";
564
- const container = document.createElement("div");
565
- container.style.display = "contents";
566
-
567
- const matchRoute = (path, routePath) => {
568
- if (!routePath.includes(":")) {
569
- return routePath === path ? {} : null;
570
- }
571
-
572
- const parts = routePath.split("/");
573
- const pathParts = path.split("/");
574
-
575
- if (parts.length !== pathParts.length) return null;
576
-
577
- const params = {};
578
- for (let i = 0; i < parts.length; i++) {
579
- if (parts[i].startsWith(":")) {
580
- params[parts[i].slice(1)] = pathParts[i];
581
- } else if (parts[i] !== pathParts[i]) {
582
- return null;
583
- }
584
- }
585
- return params;
586
- };
587
-
588
- const render = () => {
589
- const path = getCurrentPath();
590
- let matchedRoute = null;
591
- let routeParams = {};
592
-
593
- for (const route of routes) {
594
- const params = matchRoute(path, route.path);
595
- if (params !== null) {
596
- matchedRoute = route;
597
- routeParams = params;
598
- break;
599
- }
600
- }
601
-
602
- const view = matchedRoute ? matchedRoute.component(routeParams) : Object.assign(document.createElement("h1"), { textContent: "404" });
603
-
604
- container.replaceChildren(view instanceof Node ? view : document.createTextNode(String(view ?? "")));
605
- };
606
-
607
- window.addEventListener("hashchange", render);
608
- render();
609
- return container;
610
- };
611
-
612
- $r.go = (path) => {
613
- const targetPath = path.startsWith("/") ? path : `/${path}`;
614
- if (window.location.hash !== `#${targetPath}`) {
615
- window.location.hash = targetPath;
616
- }
617
- };
618
-
619
- /* Can customize the name of your functions */
620
-
621
- $.effect = $e;
622
- $.page = $p;
623
- $.component = $c;
624
- $.fetch = $f;
625
- $.router = $r;
626
- $.storage = $s;
627
-
628
- if (typeof window !== "undefined") {
629
- window.$ = $;
630
- }
631
- export { $, html };
@@ -1 +0,0 @@
1
- let activeEffect=null;const effectQueue=new Set;let isFlushScheduled=!1,flushCount=0;const flushEffectQueue=()=>{if(isFlushScheduled=!1,flushCount++,flushCount>100)throw effectQueue.clear(),flushCount=0,new Error("SigPro: Infinite reactive loop detected.");try{const e=Array.from(effectQueue);effectQueue.clear();for(const t of e)t.run()}catch(e){console.error("SigPro Flush Error:",e)}finally{setTimeout(()=>{flushCount=0},0)}},$=e=>{const t=new Set;let n;if("function"==typeof e){let s,o=!0;const c={dependencies:new Set,markDirty:()=>{o||(o=!0,t.forEach(e=>{e.markDirty&&e.markDirty(),effectQueue.add(e)}),!isFlushScheduled&&effectQueue.size&&(isFlushScheduled=!0,queueMicrotask(flushEffectQueue)))},run:()=>{c.dependencies.forEach(e=>e.delete(c)),c.dependencies.clear();const t=activeEffect;activeEffect=c;try{s=e()}finally{activeEffect=t,o=!1}}};n=()=>(activeEffect&&(t.add(activeEffect),activeEffect.dependencies.add(t)),o&&c.run(),s)}else n=(...n)=>{if(n.length){const s="function"==typeof n[0]?n[0](e):n[0];Object.is(e,s)||(e=s,t.forEach(e=>{e.markDirty&&e.markDirty(),effectQueue.add(e)}),!isFlushScheduled&&effectQueue.size&&(isFlushScheduled=!0,queueMicrotask(flushEffectQueue)))}return activeEffect&&(t.add(activeEffect),activeEffect.dependencies.add(t)),e};return n};let currentPageCleanups=null;const $e=e=>{const t={dependencies:new Set,cleanupHandlers:new Set,run(){this.cleanupHandlers.forEach(e=>e()),this.cleanupHandlers.clear(),this.dependencies.forEach(e=>e.delete(this)),this.dependencies.clear();const t=activeEffect;activeEffect=this;try{const t=e();"function"==typeof t&&this.cleanupHandlers.add(t)}finally{activeEffect=t}},stop(){this.cleanupHandlers.forEach(e=>e()),this.dependencies.forEach(e=>e.delete(this))}};return currentPageCleanups&&currentPageCleanups.push(()=>t.stop()),activeEffect&&activeEffect.cleanupHandlers.add(()=>t.stop()),t.run(),()=>t.stop()},$s=(e,t,n=localStorage)=>{let s;try{const o=n.getItem(e);s=null!==o?JSON.parse(o):t}catch(o){console.warn(`Error reading ${e} from storage:`,o),s=t,n.removeItem(e)}const o=$(s);return $e(()=>{try{const t=o();null==t?n.removeItem(e):n.setItem(e,JSON.stringify(t))}catch(t){console.warn(`Error saving ${e} to storage:`,t)}}),o},html=(e,...t)=>{const n=html._templateCache??(html._templateCache=new WeakMap);let s=n.get(e);if(!s){const t=document.createElement("template");t.innerHTML=e.join("{{part}}");const o=[],c=document.createTreeWalker(t.content,133),r=e=>{const n=[];for(;e&&e!==t.content;){let t=0;for(let n=e.previousSibling;n;n=n.previousSibling)t++;n.push(t),e=e.parentNode}return n.reverse()};let i;for(;i=c.nextNode();){let e=!1;const t={type:i.nodeType,path:r(i),parts:[]};if(1===i.nodeType)for(let n=0;n<i.attributes.length;n++){const s=i.attributes[n];s.value.includes("{{part}}")&&(t.parts.push({name:s.name}),e=!0)}else 3===i.nodeType&&i.textContent.includes("{{part}}")&&(e=!0);e&&o.push(t)}n.set(e,s={template:t,dynamicNodes:o})}const o=s.template.content.cloneNode(!0);let c=0;return s.dynamicNodes.map(e=>{return{node:(t=o,n=e.path,n.reduce((e,t)=>e?.childNodes?.[t],t)),info:e};var t,n}).forEach(({node:e,info:n})=>{if(e)if(1===n.type)n.parts.forEach(n=>{const s=t[c++],o=n.name,r=o[0];if("@"===r){const[t,...n]=o.slice(1).split("."),c=o=>{if(n.includes("prevent")&&o.preventDefault(),n.includes("stop")&&o.stopPropagation(),!n.includes("self")||o.target===e){if(n.some(e=>e.startsWith("debounce"))){const t=n.find(e=>e.startsWith("debounce"))?.split(":")[1]||300;return clearTimeout(e._debounceTimer),void(e._debounceTimer=setTimeout(()=>s(o),t))}n.includes("once")&&e.removeEventListener(t,c),s(o)}};e.addEventListener(t,c,{passive:n.includes("passive"),capture:n.includes("capture")})}else if(":"===r){const t=o.slice(1),n="checkbox"===e.type||"radio"===e.type?"change":"input";"function"==typeof s?$e(()=>{const n=s();e[t]!==n&&(e[t]=n)}):e[t]=s,e.addEventListener(n,()=>{const t="change"===n?e.checked:e.value;"function"==typeof s&&s(t)})}else if("?"===r){const t=o.slice(1);"function"==typeof s?$e(()=>{const n=s();e.toggleAttribute(t,!!n)}):e.toggleAttribute(t,!!s)}else if("."===r){const t=o.slice(1);"function"==typeof s?$e(()=>{const n=s();e[t]=n,null!=n&&"object"!=typeof n&&"boolean"!=typeof n&&e.setAttribute(t,n)}):(e[t]=s,null!=s&&"object"!=typeof s&&"boolean"!=typeof s&&e.setAttribute(t,s))}else"function"==typeof s?$e(()=>e.setAttribute(o,s())):e.setAttribute(o,s)});else if(3===n.type){const n=e.textContent.split("{{part}}").length-1;((e,t)=>{const n=e.textContent.split("{{part}}"),s=e.parentNode;let o=0;n.forEach((c,r)=>{if(c&&s.insertBefore(document.createTextNode(c),e),r<n.length-1){const l=t[o++],a=document.createComment("s"),u=document.createComment("e");if(s.insertBefore(a,e),s.insertBefore(u,e),"function"==typeof l){let f;$e(()=>{const e=l();e!==f&&(f=e,i(e))})}else i(l);function i(e){if("object"==typeof e||Array.isArray(e)){for(;a.nextSibling!==u;)s.removeChild(a.nextSibling);const t=Array.isArray(e)?e:[e],n=document.createDocumentFragment();t.forEach(e=>{if(null==e||!1===e)return;const t=e instanceof Node?e:document.createTextNode(e);n.appendChild(t)}),s.insertBefore(n,u)}else{const t=a.nextSibling,n=String(e??"");if(t!==u&&3===t?.nodeType)t.textContent=n;else{for(;a.nextSibling!==u;)s.removeChild(a.nextSibling);s.insertBefore(document.createTextNode(n),u)}}}}}),e.remove()})(e,t.slice(c,c+n)),c+=n}}),o},$p=e=>{const t="page-"+Math.random().toString(36).substring(2,9);return customElements.define(t,class extends HTMLElement{connectedCallback(){this.style.display="contents",this._cleanups=[],currentPageCleanups=this._cleanups;try{const t=e({params:JSON.parse(this.getAttribute("params")||"{}"),onUnmount:e=>this._cleanups.push(e)});this.appendChild(t instanceof Node?t:document.createTextNode(String(t)))}finally{currentPageCleanups=null}}disconnectedCallback(){this._cleanups.forEach(e=>e()),this._cleanups=[],this.innerHTML=""}}),(e={})=>{const n=document.createElement(t);return n.setAttribute("params",JSON.stringify(e)),n}},$c=(e,t,n=[],s=!1)=>{customElements.get(e)||customElements.define(e,class extends HTMLElement{static get observedAttributes(){return n}constructor(){super(),this._propertySignals={},this.cleanupFunctions=[],this._root=s?this.attachShadow({mode:"open"}):this,n.forEach(e=>this._propertySignals[e]=$(void 0))}connectedCallback(){const e=[...this.childNodes];this._root.innerHTML="",n.forEach(e=>{const t=this.hasOwnProperty(e)?this[e]:this.getAttribute(e);Object.defineProperty(this,e,{get:()=>this._propertySignals[e](),set:t=>{const n="false"!==t&&(""===t&&"value"!==e||t);this._propertySignals[e](n)},configurable:!0}),null!=t&&(this[e]=t)});const s={select:e=>this._root.querySelector(e),selectAll:e=>this._root.querySelectorAll(e),slot:t=>e.filter(e=>{const n=1===e.nodeType?e.getAttribute("slot"):null;return t?n===t:!n}),emit:(e,t)=>this.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0,composed:!0})),host:this,root:this._root,onUnmount:e=>this.cleanupFunctions.push(e)},o=t(this._propertySignals,s);o instanceof Node&&this._root.appendChild(o)}attributeChangedCallback(e,t,n){this[e]!==n&&(this[e]=n)}disconnectedCallback(){this.cleanupFunctions.forEach(e=>e()),this.cleanupFunctions=[]}})},$f=async(e,t,n)=>{n&&n(!0);try{const n=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}),s=await n.text();try{return JSON.parse(s)}catch(e){return console.warn("Invalid JSON response"),null}}catch(e){return null}finally{n&&n(!1)}},$r=e=>{const t=document.createElement("div");t.style.display="contents";const n=(e,t)=>{if(!t.includes(":"))return t===e?{}:null;const n=t.split("/"),s=e.split("/");if(n.length!==s.length)return null;const o={};for(let e=0;e<n.length;e++)if(n[e].startsWith(":"))o[n[e].slice(1)]=s[e];else if(n[e]!==s[e])return null;return o},s=()=>{const s=window.location.hash.replace(/^#/,"")||"/";let o=null,c={};for(const t of e){const e=n(s,t.path);if(null!==e){o=t,c=e;break}}const r=o?o.component(c):Object.assign(document.createElement("h1"),{textContent:"404"});t.replaceChildren(r instanceof Node?r:document.createTextNode(String(r??"")))};return window.addEventListener("hashchange",s),s(),t};$r.go=e=>{const t=e.startsWith("/")?e:`/${e}`;window.location.hash!==`#${t}`&&(window.location.hash=t)},$.effect=$e,$.page=$p,$.component=$c,$.fetch=$f,$.router=$r,$.storage=$s,"undefined"!=typeof window&&(window.$=$);export{$,html};
package/vite.config.js DELETED
@@ -1,24 +0,0 @@
1
- import { defineConfig } from 'vite';
2
- import tailwindcss from '@tailwindcss/vite';
3
- const isDev = process.env.NODE_ENV === 'development';
4
-
5
- export default defineConfig({
6
- base: isDev ? '/absproxy/5175/' : '/',
7
- plugins: [
8
- tailwindcss(),
9
- ],
10
- root: 'UI',
11
- build: {
12
- outDir: '../dist',
13
- },
14
- resolve: {
15
- alias: {
16
- 'sigpro': './sigpro.js',
17
- },
18
- },
19
- server: {
20
- port: 5175,
21
- open: true,
22
- allowedHosts: true,
23
- },
24
- });