sigpro 1.0.14 → 1.2.39

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 (109) hide show
  1. package/Readme.md +164 -1008
  2. package/dist/sigpro.editor.js +1 -0
  3. package/dist/sigpro.grid.js +78 -0
  4. package/dist/sigpro.js +1 -0
  5. package/dist/sigpro.ui.css +2 -0
  6. package/dist/sigpro.ui.js +1 -0
  7. package/dist/sigpro.utils.js +1 -0
  8. package/dist/sigpro.vite.js +4 -0
  9. package/package.json +64 -14
  10. package/sigpro.d.ts +395 -0
  11. package/.github/workflows/publish.yml +0 -25
  12. package/bun.lock +0 -385
  13. package/docs/404.html +0 -22
  14. package/docs/api/components.html +0 -595
  15. package/docs/api/effects.html +0 -787
  16. package/docs/api/fetch.html +0 -873
  17. package/docs/api/pages.html +0 -405
  18. package/docs/api/quick.html +0 -217
  19. package/docs/api/routing.html +0 -628
  20. package/docs/api/signals.html +0 -683
  21. package/docs/api/storage.html +0 -820
  22. package/docs/assets/api_components.md.BlFwj17l.js +0 -571
  23. package/docs/assets/api_components.md.BlFwj17l.lean.js +0 -1
  24. package/docs/assets/api_effects.md.Br_yStBS.js +0 -763
  25. package/docs/assets/api_effects.md.Br_yStBS.lean.js +0 -1
  26. package/docs/assets/api_fetch.md.DQLBJSoq.js +0 -849
  27. package/docs/assets/api_fetch.md.DQLBJSoq.lean.js +0 -1
  28. package/docs/assets/api_pages.md.BP19nHXw.js +0 -381
  29. package/docs/assets/api_pages.md.BP19nHXw.lean.js +0 -1
  30. package/docs/assets/api_quick.md.BDS3ttnt.js +0 -193
  31. package/docs/assets/api_quick.md.BDS3ttnt.lean.js +0 -1
  32. package/docs/assets/api_routing.md.7SNAZXtp.js +0 -604
  33. package/docs/assets/api_routing.md.7SNAZXtp.lean.js +0 -1
  34. package/docs/assets/api_signals.md.CrW68-BA.js +0 -659
  35. package/docs/assets/api_signals.md.CrW68-BA.lean.js +0 -1
  36. package/docs/assets/api_storage.md.COEWBXHk.js +0 -796
  37. package/docs/assets/api_storage.md.COEWBXHk.lean.js +0 -1
  38. package/docs/assets/app.DtmzNmNl.js +0 -1
  39. package/docs/assets/chunks/framework.C8AWLET_.js +0 -19
  40. package/docs/assets/chunks/theme.yfWKMLQM.js +0 -1
  41. package/docs/assets/guide_getting-started.md.BeQpK3vd.js +0 -172
  42. package/docs/assets/guide_getting-started.md.BeQpK3vd.lean.js +0 -1
  43. package/docs/assets/guide_why.md.DXchYMN-.js +0 -23
  44. package/docs/assets/guide_why.md.DXchYMN-.lean.js +0 -1
  45. package/docs/assets/index.md.uvMJmU4o.js +0 -1
  46. package/docs/assets/index.md.uvMJmU4o.lean.js +0 -1
  47. package/docs/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 +0 -0
  48. package/docs/assets/inter-italic-cyrillic.By2_1cv3.woff2 +0 -0
  49. package/docs/assets/inter-italic-greek-ext.1u6EdAuj.woff2 +0 -0
  50. package/docs/assets/inter-italic-greek.DJ8dCoTZ.woff2 +0 -0
  51. package/docs/assets/inter-italic-latin-ext.CN1xVJS-.woff2 +0 -0
  52. package/docs/assets/inter-italic-latin.C2AdPX0b.woff2 +0 -0
  53. package/docs/assets/inter-italic-vietnamese.BSbpV94h.woff2 +0 -0
  54. package/docs/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 +0 -0
  55. package/docs/assets/inter-roman-cyrillic.C5lxZ8CY.woff2 +0 -0
  56. package/docs/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 +0 -0
  57. package/docs/assets/inter-roman-greek.BBVDIX6e.woff2 +0 -0
  58. package/docs/assets/inter-roman-latin-ext.4ZJIpNVo.woff2 +0 -0
  59. package/docs/assets/inter-roman-latin.Di8DUHzh.woff2 +0 -0
  60. package/docs/assets/inter-roman-vietnamese.BjW4sHH5.woff2 +0 -0
  61. package/docs/assets/style.DJRheFKp.css +0 -1
  62. package/docs/assets/ui_intro.md.gZ21GFqo.js +0 -1
  63. package/docs/assets/ui_intro.md.gZ21GFqo.lean.js +0 -1
  64. package/docs/assets/vite_plugin.md.gDWEi8f0.js +0 -225
  65. package/docs/assets/vite_plugin.md.gDWEi8f0.lean.js +0 -1
  66. package/docs/guide/getting-started.html +0 -196
  67. package/docs/guide/why.html +0 -47
  68. package/docs/hashmap.json +0 -1
  69. package/docs/index.html +0 -25
  70. package/docs/logo.svg +0 -118
  71. package/docs/ui/intro.html +0 -25
  72. package/docs/vite/plugin.html +0 -249
  73. package/docs/vp-icons.css +0 -1
  74. package/index.js +0 -3
  75. package/packages/docs/.vitepress/cache/deps/@theme_index.js +0 -275
  76. package/packages/docs/.vitepress/cache/deps/@theme_index.js.map +0 -7
  77. package/packages/docs/.vitepress/cache/deps/_metadata.json +0 -40
  78. package/packages/docs/.vitepress/cache/deps/chunk-3S55Y3P7.js +0 -12951
  79. package/packages/docs/.vitepress/cache/deps/chunk-3S55Y3P7.js.map +0 -7
  80. package/packages/docs/.vitepress/cache/deps/chunk-RLEUDPPB.js +0 -9719
  81. package/packages/docs/.vitepress/cache/deps/chunk-RLEUDPPB.js.map +0 -7
  82. package/packages/docs/.vitepress/cache/deps/package.json +0 -3
  83. package/packages/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js +0 -4505
  84. package/packages/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js.map +0 -7
  85. package/packages/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js +0 -583
  86. package/packages/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js.map +0 -7
  87. package/packages/docs/.vitepress/cache/deps/vue.js +0 -347
  88. package/packages/docs/.vitepress/cache/deps/vue.js.map +0 -7
  89. package/packages/docs/.vitepress/config.js +0 -68
  90. package/packages/docs/api/components.md +0 -760
  91. package/packages/docs/api/effects.md +0 -1039
  92. package/packages/docs/api/fetch.md +0 -998
  93. package/packages/docs/api/pages.md +0 -497
  94. package/packages/docs/api/quick.md +0 -436
  95. package/packages/docs/api/routing.md +0 -784
  96. package/packages/docs/api/signals.md +0 -899
  97. package/packages/docs/api/storage.md +0 -952
  98. package/packages/docs/guide/getting-started.md +0 -308
  99. package/packages/docs/guide/why.md +0 -135
  100. package/packages/docs/index.md +0 -84
  101. package/packages/docs/logo.svg +0 -118
  102. package/packages/docs/public/logo.svg +0 -118
  103. package/packages/docs/ui/intro.md +0 -16
  104. package/packages/docs/vite/plugin.md +0 -423
  105. package/packages/sigpro/plugin.js +0 -91
  106. package/packages/sigpro/plugin.min.js +0 -1
  107. package/packages/sigpro/sigpro.js +0 -631
  108. package/packages/sigpro/sigpro.min.js +0 -1
  109. 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
- });