juxscript 1.0.132 → 1.1.2

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 (133) hide show
  1. package/README.md +1 -32
  2. package/bin/cli.js +4 -2
  3. package/index.d.ts +200 -0
  4. package/index.js +96 -22
  5. package/juxconfig.example.js +58 -63
  6. package/lib/components/alert.ts +200 -0
  7. package/lib/components/app.ts +247 -0
  8. package/lib/components/badge.ts +101 -0
  9. package/lib/components/base/BaseComponent.ts +421 -0
  10. package/lib/components/base/FormInput.ts +227 -0
  11. package/lib/components/button.ts +178 -0
  12. package/lib/components/card.ts +173 -0
  13. package/lib/components/chart.ts +231 -0
  14. package/lib/components/checkbox.ts +242 -0
  15. package/lib/components/code.ts +123 -0
  16. package/lib/components/container.ts +140 -0
  17. package/lib/components/data.ts +135 -0
  18. package/lib/components/datepicker.ts +234 -0
  19. package/lib/components/dialog.ts +172 -0
  20. package/lib/components/divider.ts +100 -0
  21. package/lib/components/dropdown.ts +186 -0
  22. package/lib/components/element.ts +267 -0
  23. package/lib/components/fileupload.ts +309 -0
  24. package/lib/components/grid.ts +291 -0
  25. package/lib/components/guard.ts +92 -0
  26. package/lib/components/heading.ts +96 -0
  27. package/lib/components/helpers.ts +41 -0
  28. package/lib/components/hero.ts +224 -0
  29. package/lib/components/icon.ts +178 -0
  30. package/lib/components/icons.ts +464 -0
  31. package/lib/components/include.ts +410 -0
  32. package/lib/components/input.ts +457 -0
  33. package/lib/components/list.ts +419 -0
  34. package/lib/components/loading.ts +100 -0
  35. package/lib/components/menu.ts +275 -0
  36. package/lib/components/modal.ts +284 -0
  37. package/lib/components/nav.ts +257 -0
  38. package/lib/components/paragraph.ts +97 -0
  39. package/lib/components/progress.ts +159 -0
  40. package/lib/components/radio.ts +278 -0
  41. package/lib/components/req.ts +303 -0
  42. package/lib/components/script.ts +41 -0
  43. package/lib/components/select.ts +252 -0
  44. package/lib/components/sidebar.ts +275 -0
  45. package/lib/components/style.ts +41 -0
  46. package/lib/components/switch.ts +246 -0
  47. package/lib/components/table.ts +1249 -0
  48. package/lib/components/tabs.ts +250 -0
  49. package/lib/components/theme-toggle.ts +293 -0
  50. package/lib/components/tooltip.ts +144 -0
  51. package/lib/components/view.ts +190 -0
  52. package/lib/components/write.ts +272 -0
  53. package/lib/globals.d.ts +19 -5
  54. package/lib/layouts/default.css +260 -0
  55. package/lib/layouts/figma.css +334 -0
  56. package/lib/reactivity/state.ts +78 -0
  57. package/lib/utils/{fetch.js → fetch.ts} +206 -81
  58. package/machinery/ast.js +347 -0
  59. package/machinery/build.js +466 -0
  60. package/machinery/compiler3.js +6 -66
  61. package/machinery/config.js +6 -93
  62. package/machinery/doc-generator.js +136 -0
  63. package/machinery/imports.js +155 -0
  64. package/machinery/server.js +166 -0
  65. package/machinery/ts-shim.js +46 -0
  66. package/machinery/watcher.js +162 -50
  67. package/package.json +9 -30
  68. package/create/index.jux +0 -77
  69. package/create/layout.jux +0 -18
  70. package/create/style.css +0 -57
  71. package/create/themes/assets/jux.svg +0 -34
  72. package/create/themes/base.css +0 -197
  73. package/create/themes/base2.css +0 -54
  74. package/create/themes/layouts/base.jux +0 -16
  75. package/create/themes/layouts/base_marketing.jux +0 -0
  76. package/create/themes/layouts/base_saas.jux +0 -0
  77. package/lib/componentsv2/base/BaseEngine.d.ts +0 -112
  78. package/lib/componentsv2/base/BaseEngine.js +0 -279
  79. package/lib/componentsv2/base/BaseSkin.d.ts +0 -74
  80. package/lib/componentsv2/base/BaseSkin.js +0 -130
  81. package/lib/componentsv2/base/Neighborhood.d.ts +0 -22
  82. package/lib/componentsv2/base/Neighborhood.js +0 -56
  83. package/lib/componentsv2/base/OptionsContract.d.ts +0 -20
  84. package/lib/componentsv2/base/OptionsContract.js +0 -107
  85. package/lib/componentsv2/base/State.d.ts +0 -18
  86. package/lib/componentsv2/base/State.js +0 -68
  87. package/lib/componentsv2/element/Element.d.ts +0 -30
  88. package/lib/componentsv2/element/Element.js +0 -50
  89. package/lib/componentsv2/element/ElementEngine.d.ts +0 -59
  90. package/lib/componentsv2/element/ElementEngine.js +0 -118
  91. package/lib/componentsv2/element/ElementSkin.d.ts +0 -10
  92. package/lib/componentsv2/element/ElementSkin.js +0 -56
  93. package/lib/componentsv2/element/structure.css +0 -261
  94. package/lib/componentsv2/grid/Grid.d.ts +0 -13
  95. package/lib/componentsv2/grid/Grid.js +0 -27
  96. package/lib/componentsv2/grid/GridEngine.d.ts +0 -77
  97. package/lib/componentsv2/grid/GridEngine.js +0 -153
  98. package/lib/componentsv2/grid/GridSkin.d.ts +0 -11
  99. package/lib/componentsv2/grid/GridSkin.js +0 -84
  100. package/lib/componentsv2/grid/structure.css +0 -27
  101. package/lib/componentsv2/input/Input.d.ts +0 -6
  102. package/lib/componentsv2/input/Input.js +0 -21
  103. package/lib/componentsv2/input/InputEngine.d.ts +0 -70
  104. package/lib/componentsv2/input/InputEngine.js +0 -143
  105. package/lib/componentsv2/input/InputSkin.d.ts +0 -11
  106. package/lib/componentsv2/input/InputSkin.js +0 -89
  107. package/lib/componentsv2/input/structure.css +0 -47
  108. package/lib/componentsv2/list/List.d.ts +0 -49
  109. package/lib/componentsv2/list/List.js +0 -105
  110. package/lib/componentsv2/list/ListEngine.d.ts +0 -121
  111. package/lib/componentsv2/list/ListEngine.js +0 -322
  112. package/lib/componentsv2/list/ListSkin.d.ts +0 -20
  113. package/lib/componentsv2/list/ListSkin.js +0 -345
  114. package/lib/componentsv2/list/structure.css +0 -359
  115. package/lib/componentsv2/plugins/ClientSQLitePlugin.d.ts +0 -21
  116. package/lib/componentsv2/plugins/ClientSQLitePlugin.js +0 -130
  117. package/lib/componentsv2/plugins/IndexedDBPlugin.d.ts +0 -18
  118. package/lib/componentsv2/plugins/IndexedDBPlugin.js +0 -75
  119. package/lib/componentsv2/plugins/LocalStoragePlugin.d.ts +0 -20
  120. package/lib/componentsv2/plugins/LocalStoragePlugin.js +0 -65
  121. package/lib/componentsv2/plugins/ServerSQLitePlugin.d.ts +0 -25
  122. package/lib/componentsv2/plugins/ServerSQLitePlugin.js +0 -70
  123. package/lib/componentsv2/stubs/ComponentComposition.ts.stub +0 -32
  124. package/lib/componentsv2/stubs/ComponentEngine.ts.stub +0 -36
  125. package/lib/componentsv2/stubs/ComponentSkin.ts.stub +0 -35
  126. package/lib/componentsv2/stubs/ComponentStructure.css.d.ts.stub +0 -2
  127. package/lib/componentsv2/stubs/ComponentStructure.css.stub +0 -13
  128. package/lib/utils/fetch.d.ts +0 -176
  129. package/machinery/serve.js +0 -255
  130. package/types/css.d.ts +0 -10
  131. /package/{create/themes/layouts/base_blog.jux → machinery/bundleAssets.js} +0 -0
  132. /package/{create/themes/layouts/base_docs.jux → machinery/bundleJux.js} +0 -0
  133. /package/{create/themes/layouts/base_login.jux → machinery/bundleVendors.js} +0 -0
@@ -1,359 +0,0 @@
1
- .jux-list {
2
- list-style: none; /* Default reset */
3
- padding: 0;
4
- margin: 0;
5
- }
6
- .jux-list.dark{
7
- background: blue;
8
- }
9
- /* Explicit type styling based on dynamic class */
10
- .jux-list-type-ol {
11
- list-style: decimal;
12
- padding-left: 1.5rem; /* Make room for numbers */
13
- }
14
-
15
- .jux-list-type-ul {
16
- list-style: none;
17
- }
18
-
19
- .jux-list-selectable .jux-list-item {
20
- cursor: pointer;
21
- }
22
-
23
- /* Visual reflection of the disabled state */
24
- .jux-list[aria-disabled="true"] {
25
- opacity: 0.5;
26
- pointer-events: none;
27
- cursor: not-allowed;
28
- user-select: none;
29
- }
30
-
31
- .jux-list-item {
32
- padding: var(--space-md) var(--space-lg);
33
- border-bottom: var(--border-width);
34
- border-color: var(--color-border);
35
- transition: background-color var(--transition-fast);
36
- margin: var(--space-sm);
37
- cursor: default; /* Base cursor */
38
- /* ✨ Uplift: Flex layout for content <-> controls separation */
39
- display: flex;
40
- justify-content: space-between;
41
- align-items: center;
42
- }
43
- .jux-list-item-highlight{
44
-
45
- background-color: var(--color-surface-secondary-subtle, #ee76781a);
46
-
47
- }
48
- /* Standard Hover Effect (Native CSS) */
49
- /* Apply to all items that are NOT disabled */
50
- .jux-list:not([aria-disabled="true"]) .jux-list-item:not(.jux-selected):hover {
51
- background-color: var(--color-surface-hover, #f5f5f5);
52
- border-radius: var(--radius-sm);
53
- }
54
-
55
- .jux-list-item:last-child {
56
- border-bottom: none;
57
- }
58
-
59
- /* REMOVED: .jux-list-item-hoverable logic */
60
-
61
- .jux-list-item-icon {
62
- display: inline-flex;
63
- align-items: center;
64
- justify-content: center;
65
- width: 24px;
66
- min-width: 24px;
67
- height: 24px;
68
- flex-shrink: 0;
69
- margin-right: var(--space-lg);
70
- color: var(--color-text-secondary);
71
- }
72
-
73
- .jux-list-item-content {
74
- display: flex;
75
- flex-direction: row;
76
- align-items: center;
77
- gap: var(--space-lg);
78
- flex: 1; /* Take available width */
79
- }
80
-
81
- /* Selected State Styling */
82
- .jux-selected {
83
- background-color: var(--color-surface-active, #f0f7ff); /* fallback light blue */
84
- border-color: var(--color-primary, #0066cc);
85
- font-weight: 500;
86
- color: var(--color-primary, #0066cc);
87
- }
88
-
89
- /* Checkmark indicator for selected items */
90
- .jux-selected .jux-list-item-content::before {
91
- content: "✓";
92
- display: inline-flex;
93
- align-items: center;
94
- justify-content: center;
95
- width: 1.25rem;
96
- height: 1.25rem;
97
- margin-right: 0.5rem;
98
- color: inherit;
99
- font-weight: bold;
100
- }
101
-
102
- /* ═════════════════════════════════════════════════════════════════
103
- ✨ CONTROLS (Edit/Delete)
104
- ═════════════════════════════════════════════════════════════════ */
105
- .jux-item-controls {
106
- display: flex;
107
- gap: var(--space-sm);
108
- opacity: 0;
109
- transform: translateX(10px);
110
- transition: opacity 0.2s, transform 0.2s;
111
- }
112
-
113
- /* Uplift: Only show controls on hover for a cleaner UI */
114
- .jux-list-item:hover .jux-item-controls {
115
- opacity: 1;
116
- transform: translateX(0);
117
- }
118
-
119
- .jux-control {
120
- background: transparent;
121
- border: none;
122
- cursor: pointer;
123
- opacity: 0.5;
124
- transition: opacity 0.2s, background-color 0.2s;
125
- font-size: 1.1rem;
126
- padding: 4px 8px;
127
- border-radius: var(--radius-sm);
128
- display: flex;
129
- align-items: center;
130
- justify-content: center;
131
- }
132
-
133
- .jux-control:hover { opacity: 1; background-color: var(--color-surface-hover); }
134
- .jux-action-delete:hover { color: #d32f2f; background-color: #fee2e2; }
135
- .jux-action-edit:hover { color: var(--color-primary, #0066cc); background-color: #e0f2fe; }
136
-
137
- /* ═════════════════════════════════════════════════════════════════
138
- ✨ MODAL (Uplifted with Animations & Tokens)
139
- ═════════════════════════════════════════════════════════════════ */
140
- .jux-modal-overlay {
141
- position: fixed;
142
- top: 0; left: 0; right: 0; bottom: 0;
143
- background: rgba(0, 0, 0, 0.4);
144
- backdrop-filter: blur(4px); /* Glass effect */
145
- display: flex;
146
- align-items: center;
147
- justify-content: center;
148
- z-index: 1000;
149
- opacity: 0;
150
- animation: jux-fade-in 0.2s forwards;
151
- }
152
-
153
- .jux-modal {
154
- background: var(--color-surface-elevated, #fff);
155
- padding: var(--space-xl);
156
- border-radius: var(--radius-sm);
157
- box-shadow: 0 10px 40px rgba(0,0,0,0.2);
158
- min-width: 360px;
159
- display: flex;
160
- flex-direction: column;
161
- gap: var(--space-lg);
162
- transform: scale(0.95);
163
- opacity: 0;
164
- animation: jux-scale-in 0.25s cubic-bezier(0.16, 1, 0.3, 1) forwards;
165
- }
166
-
167
- .jux-modal h3 {
168
- margin: 0;
169
- font-size: var(--font-size-lg);
170
- font-weight: 600;
171
- color: var(--color-text-primary);
172
- }
173
-
174
- .jux-modal input {
175
- padding: var(--space-md);
176
- border: 1px solid var(--color-border);
177
- border-radius: var(--radius-md);
178
- font-size: var(--font-size-base);
179
- width: 100%;
180
- outline: none;
181
- transition: border-color 0.2s, box-shadow 0.2s;
182
- background: var(--color-surface-base);
183
- }
184
-
185
- .jux-modal input:focus {
186
- border-color: var(--color-brand, #085156);
187
- box-shadow: 0 0 0 3px var(--color-brand-subtle);
188
- background: var(--color-background);
189
- }
190
-
191
- .jux-modal-actions {
192
- display: flex;
193
- justify-content: flex-end;
194
- gap: var(--space-md);
195
- margin-top: var(--space-sm);
196
- }
197
-
198
- .jux-modal-btn {
199
- padding: 0.6rem 1.25rem;
200
- cursor: pointer;
201
- border: none;
202
- border-radius: var(--radius-sm);
203
- font-weight: 500;
204
- font-size: var(--font-size-sm);
205
- transition: all 0.2s;
206
- }
207
-
208
- .jux-btn-cancel {
209
- background: transparent;
210
- color: var(--color-text-secondary);
211
- }
212
- .jux-btn-cancel:hover {
213
- background: var(--color-surface-hover);
214
- color: var(--color-text-primary);
215
- }
216
-
217
- .jux-btn-save {
218
- background: var(--color-brand, #085156);
219
- color: #fff;
220
- box-shadow: 0 2px 5px rgba(0,0,0,0.1);
221
- }
222
- .jux-btn-save:hover {
223
- background: var(--color-brand-hover, #066666);
224
- transform: translateY(-1px);
225
- box-shadow: 0 4px 8px rgba(0,0,0,0.15);
226
- }
227
-
228
- @keyframes jux-fade-in { from { opacity: 0; } to { opacity: 1; } }
229
- @keyframes jux-scale-in { from { transform: scale(0.95); opacity: 0; } to { transform: scale(1); opacity: 1; } }
230
-
231
- /* ═════════════════════════════════════════════════════════════════
232
- ✨ TOOLBAR (Search & Actions)
233
- ═════════════════════════════════════════════════════════════════ */
234
- .jux-list-toolbar {
235
- display: flex;
236
- gap: var(--space-sm);
237
- padding: var(--space-md);
238
- background-color: var(--color-surface-base);
239
- border-bottom: var(--border-width);
240
- border-color: var(--color-border);
241
- border-radius: var(--radius-sm) var(--radius-sm) 0 0;
242
- }
243
-
244
- .jux-search-input {
245
- flex: 1;
246
- padding: var(--space-sm) var(--space-md);
247
- border: 1px solid var(--color-border);
248
- border-radius: var(--radius-sm);
249
- font-family: inherit;
250
- font-size: var(--font-size-sm);
251
- outline: none;
252
- transition: box-shadow 0.2s, border-color 0.2s;
253
- }
254
-
255
- .jux-search-input:focus {
256
- border-color: var(--color-brand, #085156);
257
- box-shadow: 0 0 0 2px var(--color-brand-subtle);
258
- }
259
-
260
- .jux-action-add {
261
- display: inline-flex;
262
- align-items: center;
263
- justify-content: center;
264
- width: 36px;
265
- height: 36px;
266
- background-color: var(--color-surface-elevated, #fff);
267
- border: 1px solid var(--color-border);
268
- border-radius: var(--radius-sm);
269
- cursor: pointer;
270
- font-size: 1.25rem;
271
- line-height: 1;
272
- color: var(--color-text-secondary);
273
- transition: all 0.2s;
274
- }
275
-
276
- .jux-action-add:hover {
277
- background-color: var(--color-surface-hover);
278
- color: var(--color-brand);
279
- border-color: var(--color-brand-subtle);
280
- }
281
-
282
- .jux-action-add:active {
283
- transform: translateY(1px);
284
- }
285
-
286
- .jux-action-sort {
287
- display: inline-flex;
288
- align-items: center;
289
- justify-content: center;
290
- width: 36px;
291
- height: 36px;
292
- background-color: var(--color-surface-elevated, #fff);
293
- border: 1px solid var(--color-border);
294
- border-radius: var(--radius-sm);
295
- cursor: pointer;
296
- font-size: 1.1rem;
297
- line-height: 1;
298
- color: var(--color-text-secondary);
299
- transition: all 0.2s;
300
- }
301
-
302
- .jux-action-sort:hover {
303
- background-color: var(--color-surface-hover);
304
- color: var(--color-brand);
305
- border-color: var(--color-brand-subtle);
306
- }
307
-
308
- .jux-action-sort:active {
309
- transform: translateY(1px);
310
- }
311
-
312
- /* ═════════════════════════════════════════════════════════════════
313
- ✨ DRAG & DROP
314
- ═════════════════════════════════════════════════════════════════ */
315
- .jux-list-item[draggable="true"] {
316
- cursor: grab;
317
- }
318
- .jux-list-item[draggable="true"]:active {
319
- cursor: grabbing;
320
- }
321
-
322
- /* Aspect of the item currently being dragged (in the list, not the ghost) */
323
- .jux-list-item.jux-dragging {
324
- opacity: 0.4;
325
- background-color: var(--color-surface-secondary);
326
- border: 1px dashed var(--color-brand);
327
- }
328
-
329
- /* Aspect of the item under the cursor (drop target) */
330
- .jux-item-drop-target {
331
- border-top: 2px solid var(--color-brand);
332
- transition: none; /* Instant feedback */
333
- }
334
-
335
- .jux-action-drag {
336
- cursor: grab;
337
- font-size: 1.25rem;
338
- line-height: 1;
339
- color: var(--color-text-secondary);
340
- display: flex;
341
- align-items: center;
342
- }
343
- .jux-action-drag:active {
344
- cursor: grabbing;
345
- }
346
-
347
- /* ═════════════════════════════════════════════════════════════════
348
- ✨ EMPTY STATE
349
- ═════════════════════════════════════════════════════════════════ */
350
- .jux-list-empty-state {
351
- padding: var(--space-xl);
352
- text-align: center;
353
- color: var(--color-text-secondary);
354
- font-style: italic;
355
- background-color: var(--color-surface-base);
356
- border-radius: var(--radius-sm);
357
- margin: var(--space-sm);
358
- }
359
-
@@ -1,21 +0,0 @@
1
- import { JuxServiceContract, BaseEngine } from '../base/BaseEngine.js';
2
- export interface ClientSQLiteConfig {
3
- /** Key used for IndexedDB storage (the "filename") */
4
- dbName: string;
5
- /** SQL to run if creating a brand new DB (Schema) */
6
- initSql?: string;
7
- /** Main Query to bind to the Engine State */
8
- query?: string;
9
- /** State property to bind results to (e.g. 'items') */
10
- bindTo?: string;
11
- /** Transform row object to State Item shape */
12
- mapRow?: (row: any) => any;
13
- /** If true, persists to IDB after every write operation */
14
- autoSave?: boolean;
15
- }
16
- /**
17
- * Client-Side SQLite Plugin
18
- * Runs a real SQLite engine via WebAssembly (WASM) in the browser, persisted to IndexedDB.
19
- */
20
- export declare const ClientSQLitePlugin: (config: ClientSQLiteConfig) => JuxServiceContract<BaseEngine<any>>;
21
- //# sourceMappingURL=ClientSQLitePlugin.d.ts.map
@@ -1,130 +0,0 @@
1
- /**
2
- * Client-Side SQLite Plugin
3
- * Runs a real SQLite engine via WebAssembly (WASM) in the browser, persisted to IndexedDB.
4
- */
5
- export const ClientSQLitePlugin = (config) => ({
6
- name: 'client-sqlite-wasm',
7
- version: '1.0.0',
8
- targetEnv: 'client',
9
- install: (engine) => {
10
- let db = null;
11
- const IDB_NAME = 'JuxSqliteStorage';
12
- const IDB_STORE = 'files';
13
- // --- 1. IndexedDB HELPER (The "Hard Drive") ---
14
- const getFile = (key) => {
15
- return new Promise((resolve) => {
16
- const r = indexedDB.open(IDB_NAME, 1);
17
- r.onupgradeneeded = (e) => e.target.result.createObjectStore(IDB_STORE);
18
- r.onsuccess = (e) => {
19
- const t = e.target.result.transaction([IDB_STORE], 'readonly').objectStore(IDB_STORE).get(key);
20
- t.onsuccess = () => resolve(t.result);
21
- t.onerror = () => resolve(null);
22
- };
23
- });
24
- };
25
- const saveFile = (key, data) => {
26
- const r = indexedDB.open(IDB_NAME, 1);
27
- r.onsuccess = (e) => {
28
- const tx = e.target.result.transaction([IDB_STORE], 'readwrite');
29
- tx.objectStore(IDB_STORE).put(data, key);
30
- };
31
- };
32
- // --- 2. SQL Helper (Result Transformation) ---
33
- // sql.js return format: [{ columns: ['id', 'name'], values: [[1, 'Bob']] }]
34
- // We convert this to: [{ id: 1, name: 'Bob' }]
35
- const normalizeResults = (res) => {
36
- if (!res || !res.length)
37
- return [];
38
- const columns = res[0].columns;
39
- const values = res[0].values;
40
- return values.map((row) => {
41
- const obj = {};
42
- columns.forEach((col, i) => {
43
- obj[col] = row[i];
44
- });
45
- return obj;
46
- });
47
- };
48
- // --- 3. REFRESH LOGIC ---
49
- const refresh = () => {
50
- if (!db || !config.query || !config.bindTo)
51
- return;
52
- try {
53
- // @ts-ignore
54
- if (engine.loading)
55
- engine.loading(true);
56
- // Run Query
57
- const raw = db.exec(config.query);
58
- const rows = normalizeResults(raw);
59
- // Map & Update State
60
- const items = config.mapRow ? rows.map(config.mapRow) : rows;
61
- // @ts-ignore
62
- engine.updateState({ [config.bindTo]: items });
63
- // @ts-ignore
64
- if (engine.loading)
65
- engine.loading(false);
66
- // @ts-ignore
67
- if (engine.emit)
68
- engine.emit('sql:refresh', { count: items.length });
69
- }
70
- catch (e) {
71
- console.error('[ClientSQLite] Query Error:', e);
72
- // @ts-ignore
73
- if (engine.loading)
74
- engine.loading(false);
75
- }
76
- };
77
- // --- 4. INITIALIZATION ---
78
- const loadSqlJs = async () => {
79
- // Lazy load sql.js from CDN if not present
80
- if (!window.initSqlJs) {
81
- await new Promise(resolve => {
82
- const script = document.createElement('script');
83
- // sql-wasm.js is the glue code that loads the .wasm binary
84
- script.src = 'https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.8.0/sql-wasm.js';
85
- script.onload = resolve;
86
- document.head.appendChild(script);
87
- });
88
- }
89
- const SQL = await window.initSqlJs({
90
- locateFile: (file) => `https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.8.0/${file}`
91
- });
92
- // "Mount" the file from IDB
93
- const binary = await getFile(config.dbName);
94
- if (binary) {
95
- db = new SQL.Database(binary);
96
- // @ts-ignore
97
- if (engine.emit)
98
- engine.emit('sql:mounted', { size: binary.length });
99
- }
100
- else {
101
- db = new SQL.Database();
102
- if (config.initSql)
103
- db.run(config.initSql);
104
- if (config.autoSave)
105
- saveFile(config.dbName, db.export());
106
- // @ts-ignore
107
- if (engine.emit)
108
- engine.emit('sql:created');
109
- }
110
- // Expose SQL methods to Engine (Mixins)
111
- Object.assign(engine, {
112
- sqlRun: (sql) => {
113
- db.run(sql);
114
- if (config.autoSave)
115
- saveFile(config.dbName, db.export());
116
- refresh();
117
- },
118
- sqlExec: (sql) => {
119
- return normalizeResults(db.exec(sql));
120
- },
121
- sqlExport: () => {
122
- return db.export();
123
- }
124
- });
125
- refresh();
126
- };
127
- loadSqlJs();
128
- }
129
- });
130
- //# sourceMappingURL=ClientSQLitePlugin.js.map
@@ -1,18 +0,0 @@
1
- import { JuxServiceContract, BaseEngine } from '../base/BaseEngine.js';
2
- export interface IndexedDBConfig {
3
- dbName: string;
4
- storeName: string;
5
- /**
6
- * State Binding: The property key on the Engine's state to persist.
7
- * e.g., 'items'
8
- */
9
- bindTo: string;
10
- /** If true, loads data immediately on install */
11
- autoLoad?: boolean;
12
- }
13
- /**
14
- * IndexedDB Plugin
15
- * Asynchronous persistence for larger datasets.
16
- */
17
- export declare const IndexedDBPlugin: (config: IndexedDBConfig) => JuxServiceContract<BaseEngine<any>>;
18
- //# sourceMappingURL=IndexedDBPlugin.d.ts.map
@@ -1,75 +0,0 @@
1
- /**
2
- * IndexedDB Plugin
3
- * Asynchronous persistence for larger datasets.
4
- */
5
- export const IndexedDBPlugin = (config) => ({
6
- name: 'indexed-db-persist',
7
- version: '1.0.0',
8
- targetEnv: 'client',
9
- install: (engine) => {
10
- // @ts-ignore
11
- const initialState = engine.state[config.bindTo];
12
- if (initialState !== undefined && !Array.isArray(initialState)) {
13
- console.error(`[IndexedDBPlugin] 🛑 Configuration Error: bindTo='${config.bindTo}' is not an Array. This plugin is designed for List/Collection data.`);
14
- return;
15
- }
16
- let db = null;
17
- const request = indexedDB.open(config.dbName, 1);
18
- // 1. Schema Setup
19
- request.onupgradeneeded = (e) => {
20
- const d = e.target.result;
21
- if (!d.objectStoreNames.contains(config.storeName)) {
22
- d.createObjectStore(config.storeName);
23
- }
24
- };
25
- // 2. IO Operations
26
- const save = (data) => {
27
- if (!db)
28
- return;
29
- const tx = db.transaction([config.storeName], 'readwrite');
30
- const store = tx.objectStore(config.storeName);
31
- store.put(data, 'state_snapshot'); // Storing entire bound state as one blob for simplicity
32
- };
33
- const load = () => {
34
- if (!db)
35
- return;
36
- // @ts-ignore
37
- if (typeof engine.loading === 'function')
38
- engine.loading(true);
39
- const tx = db.transaction([config.storeName], 'readonly');
40
- const store = tx.objectStore(config.storeName);
41
- const req = store.get('state_snapshot');
42
- req.onsuccess = () => {
43
- if (req.result) {
44
- // @ts-ignore
45
- engine.updateState({ [config.bindTo]: req.result });
46
- // @ts-ignore
47
- if (engine.emit)
48
- engine.emit('plugin:hydrated', { source: 'IndexedDB' });
49
- }
50
- // @ts-ignore
51
- if (typeof engine.loading === 'function')
52
- engine.loading(false);
53
- };
54
- req.onerror = () => {
55
- // @ts-ignore
56
- if (typeof engine.loading === 'function')
57
- engine.loading(false);
58
- };
59
- };
60
- // 3. Initialization
61
- request.onsuccess = (e) => {
62
- db = e.target.result;
63
- if (config.autoLoad) {
64
- load();
65
- }
66
- // Auto-save subscription (debounced slightly in real world, direct here)
67
- engine.subscribe((state) => {
68
- if (db)
69
- save(state[config.bindTo]);
70
- });
71
- };
72
- request.onerror = (e) => console.error('[IndexedDBPlugin] Open Error', e);
73
- }
74
- });
75
- //# sourceMappingURL=IndexedDBPlugin.js.map
@@ -1,20 +0,0 @@
1
- import { JuxServiceContract, BaseEngine } from '../base/BaseEngine.js';
2
- export interface LocalStorageConfig {
3
- /** Unique key for storage (e.g. 'my-app-list-v1') */
4
- key: string;
5
- /**
6
- * State Binding: The property key on the Engine's state to persist.
7
- * e.g., 'items' for a ListEngine.
8
- */
9
- bindTo: string;
10
- /** If true, clears storage on install (fresh start) */
11
- clearOnInstall?: boolean;
12
- /** If true, automatically saves to storage when state changes */
13
- autoSave?: boolean;
14
- }
15
- /**
16
- * LocalStorage Plugin
17
- * Persists a slice of Engine State to Browser LocalStorage.
18
- */
19
- export declare const LocalStoragePlugin: (config: LocalStorageConfig) => JuxServiceContract<BaseEngine<any>>;
20
- //# sourceMappingURL=LocalStoragePlugin.d.ts.map
@@ -1,65 +0,0 @@
1
- /**
2
- * LocalStorage Plugin
3
- * Persists a slice of Engine State to Browser LocalStorage.
4
- */
5
- export const LocalStoragePlugin = (config) => ({
6
- name: 'local-storage-persist',
7
- version: '1.0.0',
8
- targetEnv: 'client',
9
- install: (engine) => {
10
- // @ts-ignore
11
- const initialState = engine.state[config.bindTo];
12
- if (initialState !== undefined && !Array.isArray(initialState)) {
13
- console.error(`[LocalStoragePlugin] 🛑 Configuration Error: bindTo='${config.bindTo}' is not an Array. This plugin is designed for List/Collection data.`);
14
- return;
15
- }
16
- const storageKey = `jux:${config.key}`;
17
- // 1. Hydrate (Load from Storage)
18
- const load = () => {
19
- try {
20
- const raw = localStorage.getItem(storageKey);
21
- if (raw) {
22
- const data = JSON.parse(raw);
23
- // @ts-ignore - Generic update
24
- engine.updateState({ [config.bindTo]: data });
25
- // @ts-ignore
26
- if (engine.emit)
27
- engine.emit('plugin:hydrated', { source: 'localStorage', count: Array.isArray(data) ? data.length : 1 });
28
- }
29
- }
30
- catch (e) {
31
- console.error('[LocalStoragePlugin] Load Failed', e);
32
- }
33
- };
34
- // 2. Persist (Save to Storage)
35
- const save = (state) => {
36
- try {
37
- const value = state[config.bindTo];
38
- localStorage.setItem(storageKey, JSON.stringify(value));
39
- }
40
- catch (e) {
41
- console.error('[LocalStoragePlugin] Save Failed', e);
42
- }
43
- };
44
- // Logic
45
- if (config.clearOnInstall) {
46
- localStorage.removeItem(storageKey);
47
- }
48
- else {
49
- load();
50
- }
51
- if (config.autoSave !== false) {
52
- engine.subscribe((state) => save(state));
53
- }
54
- // Expose manual triggers
55
- engine.on('storage:save', () => save(engine.state));
56
- engine.on('storage:load', load);
57
- engine.on('storage:clear', () => {
58
- localStorage.removeItem(storageKey);
59
- // @ts-ignore
60
- if (engine.emit)
61
- engine.emit('plugin:cleared', { source: 'localStorage' });
62
- });
63
- }
64
- });
65
- //# sourceMappingURL=LocalStoragePlugin.js.map