elementdrawing 1.0.0

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 (78) hide show
  1. package/LICENSE +21 -0
  2. package/dist/elementdrawing.min.js +3 -0
  3. package/dist/elementdrawing.min.js.LICENSE.txt +8 -0
  4. package/dist/elementdrawing.min.js.map +1 -0
  5. package/dist/index.html +1 -0
  6. package/package.json +127 -0
  7. package/src/core/bridge.h +855 -0
  8. package/src/core/diff.c +900 -0
  9. package/src/core/element.c +1078 -0
  10. package/src/core/event.c +813 -0
  11. package/src/core/fiber.c +1027 -0
  12. package/src/core/hooks.c +919 -0
  13. package/src/core/renderer.c +963 -0
  14. package/src/core/scheduler.c +702 -0
  15. package/src/core/state.c +803 -0
  16. package/src/css/animations.css +779 -0
  17. package/src/css/base.css +615 -0
  18. package/src/css/components.css +1311 -0
  19. package/src/css/tailwind.css +370 -0
  20. package/src/css/themes.css +517 -0
  21. package/src/css/utilities.css +475 -0
  22. package/src/index.js +746 -0
  23. package/src/js/animation.js +655 -0
  24. package/src/js/dom.js +665 -0
  25. package/src/js/events.js +585 -0
  26. package/src/js/http.js +446 -0
  27. package/src/js/index.js +26 -0
  28. package/src/js/router.js +483 -0
  29. package/src/js/store.js +539 -0
  30. package/src/js/utils.js +593 -0
  31. package/src/js/validator.js +529 -0
  32. package/src/jsx/components/Accordion.jsx +210 -0
  33. package/src/jsx/components/Alert.jsx +169 -0
  34. package/src/jsx/components/Avatar.jsx +214 -0
  35. package/src/jsx/components/Badge.jsx +136 -0
  36. package/src/jsx/components/Breadcrumb.jsx +200 -0
  37. package/src/jsx/components/Button.jsx +188 -0
  38. package/src/jsx/components/Card.jsx +192 -0
  39. package/src/jsx/components/Carousel.jsx +278 -0
  40. package/src/jsx/components/Checkbox.jsx +215 -0
  41. package/src/jsx/components/Dialog.jsx +242 -0
  42. package/src/jsx/components/Drawer.jsx +190 -0
  43. package/src/jsx/components/Dropdown.jsx +268 -0
  44. package/src/jsx/components/Form.jsx +274 -0
  45. package/src/jsx/components/Input.jsx +285 -0
  46. package/src/jsx/components/Menu.jsx +276 -0
  47. package/src/jsx/components/Modal.jsx +274 -0
  48. package/src/jsx/components/Navbar.jsx +292 -0
  49. package/src/jsx/components/Pagination.jsx +268 -0
  50. package/src/jsx/components/Progress.jsx +252 -0
  51. package/src/jsx/components/Radio.jsx +208 -0
  52. package/src/jsx/components/Select.jsx +397 -0
  53. package/src/jsx/components/Sidebar.jsx +250 -0
  54. package/src/jsx/components/Slider.jsx +310 -0
  55. package/src/jsx/components/Spinner.jsx +198 -0
  56. package/src/jsx/components/Switch.jsx +201 -0
  57. package/src/jsx/components/Table.jsx +332 -0
  58. package/src/jsx/components/Tabs.jsx +227 -0
  59. package/src/jsx/components/Textarea.jsx +212 -0
  60. package/src/jsx/components/Toast.jsx +270 -0
  61. package/src/jsx/components/Tooltip.jsx +178 -0
  62. package/src/jsx/components/Typography.jsx +299 -0
  63. package/src/jsx/components/index.jsx +70 -0
  64. package/src/jsx/core/element.js +3 -0
  65. package/src/jsx/hooks/index.js +356 -0
  66. package/src/jsx/hooks/useCallback.js +472 -0
  67. package/src/jsx/hooks/useContext.js +586 -0
  68. package/src/jsx/hooks/useEffect.js +704 -0
  69. package/src/jsx/hooks/useLayoutEffect.js +508 -0
  70. package/src/jsx/hooks/useMemo.js +689 -0
  71. package/src/jsx/hooks/useReducer.js +729 -0
  72. package/src/jsx/hooks/useRef.js +542 -0
  73. package/src/jsx/hooks/useState.js +854 -0
  74. package/src/jsx/runtime/commit.js +903 -0
  75. package/src/jsx/runtime/createElement.js +860 -0
  76. package/src/jsx/runtime/index.js +356 -0
  77. package/src/jsx/runtime/reconcile.js +687 -0
  78. package/src/jsx/runtime/render.js +914 -0
@@ -0,0 +1,539 @@
1
+ /**
2
+ * State Management Store
3
+ * ElementDrawing Framework - Store with state, getters, mutations, actions,
4
+ * subscriptions, middleware, persistence, snapshots, modules, and undo/redo.
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ // ─── Store Class ──────────────────────────────────────────────────────────────
10
+
11
+ function Store(options) {
12
+ options = options || {};
13
+
14
+ // ─── Core State ────────────────────────────────────────────────────────
15
+ this._state = options.state ? deepClone(options.state) : {};
16
+ this._getters = {};
17
+ this._mutations = {};
18
+ this._actions = {};
19
+ this._modules = {};
20
+ this._subscribers = [];
21
+ this._middleware = [];
22
+ this._watchers = {};
23
+ this._strict = options.strict || false;
24
+ this._history = [];
25
+ this._historyIndex = -1;
26
+ this._maxHistory = options.maxHistory || 50;
27
+ this._isCommitting = false;
28
+
29
+ // ─── Persistence Config ────────────────────────────────────────────────
30
+ this._persistence = options.persistence || null;
31
+
32
+ // ─── Register Getters ──────────────────────────────────────────────────
33
+ if (options.getters) {
34
+ Object.keys(options.getters).forEach((key) => {
35
+ this._getters[key] = options.getters[key];
36
+ });
37
+ }
38
+
39
+ // ─── Register Mutations ────────────────────────────────────────────────
40
+ if (options.mutations) {
41
+ Object.keys(options.mutations).forEach((key) => {
42
+ this._mutations[key] = options.mutations[key];
43
+ });
44
+ }
45
+
46
+ // ─── Register Actions ──────────────────────────────────────────────────
47
+ if (options.actions) {
48
+ Object.keys(options.actions).forEach((key) => {
49
+ this._actions[key] = options.actions[key];
50
+ });
51
+ }
52
+
53
+ // ─── Register Modules ──────────────────────────────────────────────────
54
+ if (options.modules) {
55
+ Object.keys(options.modules).forEach((key) => {
56
+ this.registerModule(key, options.modules[key]);
57
+ });
58
+ }
59
+
60
+ // ─── Register Middleware ───────────────────────────────────────────────
61
+ if (options.middleware) {
62
+ options.middleware.forEach((m) => this.use(m));
63
+ }
64
+
65
+ // ─── Load Persisted State ──────────────────────────────────────────────
66
+ if (this._persistence) {
67
+ this._loadPersistedState();
68
+ }
69
+
70
+ // ─── Save Initial Snapshot ─────────────────────────────────────────────
71
+ this._saveSnapshot();
72
+ }
73
+
74
+ // ─── State Access ─────────────────────────────────────────────────────────────
75
+
76
+ /**
77
+ * Get the current state (read-only in strict mode).
78
+ * @returns {Object}
79
+ */
80
+ Store.prototype.getState = function () {
81
+ return this._state;
82
+ };
83
+
84
+ /**
85
+ * Get a nested state value by path.
86
+ * @param {string} path - Dot-notation path (e.g., 'user.profile.name')
87
+ * @returns {*}
88
+ */
89
+ Store.prototype.get = function (path) {
90
+ return path.split('.').reduce((obj, key) => obj && obj[key], this._state);
91
+ };
92
+
93
+ // ─── Getters ──────────────────────────────────────────────────────────────────
94
+
95
+ /**
96
+ * Get a computed value from a getter.
97
+ * @param {string} name
98
+ * @returns {*}
99
+ */
100
+ Store.prototype.getGetter = function (name) {
101
+ const getter = this._getters[name];
102
+ if (!getter) {
103
+ console.warn('[Store] Getter not found: ' + name);
104
+ return undefined;
105
+ }
106
+ return getter(this._state, this._getters);
107
+ };
108
+
109
+ /**
110
+ * Register a getter.
111
+ * @param {string} name
112
+ * @param {Function} getter - (state, getters) => value
113
+ */
114
+ Store.prototype.registerGetter = function (name, getter) {
115
+ this._getters[name] = getter;
116
+ };
117
+
118
+ // ─── Mutations ────────────────────────────────────────────────────────────────
119
+
120
+ /**
121
+ * Commit a mutation to synchronously change state.
122
+ * @param {string} type - Mutation type
123
+ * @param {*} [payload] - Mutation payload
124
+ */
125
+ Store.prototype.commit = function (type, payload) {
126
+ if (this._strict && !this._isCommitting) {
127
+ console.warn('[Store] Mutations must be committed inside commit() in strict mode');
128
+ }
129
+
130
+ const mutation = this._mutations[type];
131
+ if (!mutation) {
132
+ console.warn('[Store] Unknown mutation type: ' + type);
133
+ return;
134
+ }
135
+
136
+ // Apply middleware
137
+ for (const mw of this._middleware) {
138
+ if (mw.beforeMutation) {
139
+ const result = mw.beforeMutation(type, payload, this._state);
140
+ if (result === false) return; // Middleware cancelled the mutation
141
+ }
142
+ }
143
+
144
+ // Execute mutation
145
+ this._isCommitting = true;
146
+ const prevState = deepClone(this._state);
147
+ try {
148
+ mutation(this._state, payload);
149
+ } catch (error) {
150
+ console.error('[Store] Mutation error (' + type + '):', error);
151
+ this._state = prevState;
152
+ this._isCommitting = false;
153
+ return;
154
+ }
155
+ this._isCommitting = false;
156
+
157
+ // Notify subscribers
158
+ this._subscribers.forEach((sub) => {
159
+ try { sub({ type, payload }, this._state, prevState); }
160
+ catch (e) { console.error('[Store] Subscriber error:', e); }
161
+ });
162
+
163
+ // Apply middleware after
164
+ for (const mw of this._middleware) {
165
+ if (mw.afterMutation) mw.afterMutation(type, payload, this._state, prevState);
166
+ }
167
+
168
+ // Save snapshot for undo/redo
169
+ this._saveSnapshot();
170
+
171
+ // Persist state
172
+ if (this._persistence) this._persistState();
173
+
174
+ // Notify watchers
175
+ this._notifyWatchers(prevState, this._state);
176
+ };
177
+
178
+ /**
179
+ * Register a mutation.
180
+ * @param {string} type
181
+ * @param {Function} mutation - (state, payload) => void
182
+ */
183
+ Store.prototype.registerMutation = function (type, mutation) {
184
+ this._mutations[type] = mutation;
185
+ };
186
+
187
+ // ─── Actions ──────────────────────────────────────────────────────────────────
188
+
189
+ /**
190
+ * Dispatch an action (can be asynchronous).
191
+ * @param {string} type - Action type
192
+ * @param {*} [payload] - Action payload
193
+ * @returns {Promise}
194
+ */
195
+ Store.prototype.dispatch = function (type, payload) {
196
+ const action = this._actions[type];
197
+ if (!action) {
198
+ console.warn('[Store] Unknown action type: ' + type);
199
+ return Promise.reject(new Error('Unknown action: ' + type));
200
+ }
201
+
202
+ const context = {
203
+ state: this._state,
204
+ getters: this._getters,
205
+ commit: this.commit.bind(this),
206
+ dispatch: this.dispatch.bind(this),
207
+ get: this.get.bind(this),
208
+ getGetter: this.getGetter.bind(this),
209
+ };
210
+
211
+ // Apply middleware
212
+ for (const mw of this._middleware) {
213
+ if (mw.beforeAction) {
214
+ const result = mw.beforeAction(type, payload, this._state);
215
+ if (result === false) return Promise.resolve(false);
216
+ }
217
+ }
218
+
219
+ try {
220
+ const result = action(context, payload);
221
+
222
+ if (result && typeof result.then === 'function') {
223
+ return result.then((res) => {
224
+ for (const mw of this._middleware) {
225
+ if (mw.afterAction) mw.afterAction(type, payload, this._state);
226
+ }
227
+ return res;
228
+ }).catch((error) => {
229
+ for (const mw of this._middleware) {
230
+ if (mw.actionError) mw.actionError(error, type, payload);
231
+ }
232
+ throw error;
233
+ });
234
+ }
235
+
236
+ for (const mw of this._middleware) {
237
+ if (mw.afterAction) mw.afterAction(type, payload, this._state);
238
+ }
239
+ return Promise.resolve(result);
240
+ } catch (error) {
241
+ for (const mw of this._middleware) {
242
+ if (mw.actionError) mw.actionError(error, type, payload);
243
+ }
244
+ return Promise.reject(error);
245
+ }
246
+ };
247
+
248
+ /**
249
+ * Register an action.
250
+ * @param {string} type
251
+ * @param {Function} action - (context, payload) => result | Promise
252
+ */
253
+ Store.prototype.registerAction = function (type, action) {
254
+ this._actions[type] = action;
255
+ };
256
+
257
+ // ─── Subscriptions ────────────────────────────────────────────────────────────
258
+
259
+ /**
260
+ * Subscribe to state changes.
261
+ * @param {Function} subscriber - (mutation, state, prevState) => void
262
+ * @returns {Function} Unsubscribe function
263
+ */
264
+ Store.prototype.subscribe = function (subscriber) {
265
+ this._subscribers.push(subscriber);
266
+ return () => {
267
+ const idx = this._subscribers.indexOf(subscriber);
268
+ if (idx !== -1) this._subscribers.splice(idx, 1);
269
+ };
270
+ };
271
+
272
+ /**
273
+ * Watch a specific state path for changes.
274
+ * @param {string} path - Dot-notation path
275
+ * @param {Function} callback - (newValue, oldValue) => void
276
+ * @returns {Function} Unwatch function
277
+ */
278
+ Store.prototype.watch = function (path, callback) {
279
+ if (!this._watchers[path]) this._watchers[path] = [];
280
+ this._watchers[path].push(callback);
281
+ return () => {
282
+ const watchers = this._watchers[path];
283
+ if (watchers) {
284
+ const idx = watchers.indexOf(callback);
285
+ if (idx !== -1) watchers.splice(idx, 1);
286
+ }
287
+ };
288
+ };
289
+
290
+ Store.prototype._notifyWatchers = function (prevState, newState) {
291
+ Object.keys(this._watchers).forEach((path) => {
292
+ const oldVal = path.split('.').reduce((obj, key) => obj && obj[key], prevState);
293
+ const newVal = path.split('.').reduce((obj, key) => obj && obj[key], newState);
294
+ if (!Object.is(oldVal, newVal)) {
295
+ this._watchers[path].forEach((cb) => {
296
+ try { cb(newVal, oldVal); } catch (e) { console.error('[Store] Watcher error:', e); }
297
+ });
298
+ }
299
+ });
300
+ };
301
+
302
+ // ─── Middleware ────────────────────────────────────────────────────────────────
303
+
304
+ /**
305
+ * Add middleware to the store.
306
+ * @param {Object} middleware
307
+ * @param {Function} [middleware.beforeMutation]
308
+ * @param {Function} [middleware.afterMutation]
309
+ * @param {Function} [middleware.beforeAction]
310
+ * @param {Function} [middleware.afterAction]
311
+ * @param {Function} [middleware.actionError]
312
+ * @returns {Function} Remove middleware function
313
+ */
314
+ Store.prototype.use = function (middleware) {
315
+ this._middleware.push(middleware);
316
+ return () => {
317
+ const idx = this._middleware.indexOf(middleware);
318
+ if (idx !== -1) this._middleware.splice(idx, 1);
319
+ };
320
+ };
321
+
322
+ // ─── State Persistence ────────────────────────────────────────────────────────
323
+
324
+ Store.prototype._persistState = function () {
325
+ if (!this._persistence) return;
326
+ try {
327
+ const storage = window[this._persistence.storage || 'localStorage'];
328
+ const key = this._persistence.key || 'ed_store';
329
+ const serialized = (this._persistence.serialize || JSON.stringify)(this._state);
330
+ storage.setItem(key, serialized);
331
+ } catch (error) {
332
+ console.error('[Store] Persistence error:', error);
333
+ }
334
+ };
335
+
336
+ Store.prototype._loadPersistedState = function () {
337
+ if (!this._persistence) return;
338
+ try {
339
+ const storage = window[this._persistence.storage || 'localStorage'];
340
+ const key = this._persistence.key || 'ed_store';
341
+ const serialized = storage.getItem(key);
342
+ if (serialized !== null) {
343
+ const saved = (this._persistence.deserialize || JSON.parse)(serialized);
344
+ Object.assign(this._state, saved);
345
+ }
346
+ } catch (error) {
347
+ console.error('[Store] Load persistence error:', error);
348
+ }
349
+ };
350
+
351
+ // ─── State Snapshot / Restore ─────────────────────────────────────────────────
352
+
353
+ Store.prototype._saveSnapshot = function () {
354
+ // Truncate future history if we're not at the end
355
+ if (this._historyIndex < this._history.length - 1) {
356
+ this._history = this._history.slice(0, this._historyIndex + 1);
357
+ }
358
+
359
+ this._history.push(deepClone(this._state));
360
+
361
+ // Limit history size
362
+ if (this._history.length > this._maxHistory) {
363
+ this._history.shift();
364
+ }
365
+
366
+ this._historyIndex = this._history.length - 1;
367
+ };
368
+
369
+ /**
370
+ * Create a snapshot of the current state.
371
+ * @returns {Object} Snapshot object
372
+ */
373
+ Store.prototype.snapshot = function () {
374
+ return {
375
+ state: deepClone(this._state),
376
+ timestamp: Date.now(),
377
+ };
378
+ };
379
+
380
+ /**
381
+ * Restore state from a snapshot.
382
+ * @param {Object} snapshot
383
+ */
384
+ Store.prototype.restore = function (snapshot) {
385
+ if (!snapshot || !snapshot.state) {
386
+ console.warn('[Store] Invalid snapshot');
387
+ return;
388
+ }
389
+ this._state = deepClone(snapshot.state);
390
+ if (this._persistence) this._persistState();
391
+ this._notifyWatchers({}, this._state);
392
+ };
393
+
394
+ // ─── Undo/Redo ────────────────────────────────────────────────────────────────
395
+
396
+ /**
397
+ * Undo the last state change.
398
+ * @returns {boolean} True if undo was possible
399
+ */
400
+ Store.prototype.undo = function () {
401
+ if (this._historyIndex <= 0) return false;
402
+ this._historyIndex--;
403
+ this._state = deepClone(this._history[this._historyIndex]);
404
+ this._notifyWatchers({}, this._state);
405
+ if (this._persistence) this._persistState();
406
+ return true;
407
+ };
408
+
409
+ /**
410
+ * Redo the last undone state change.
411
+ * @returns {boolean} True if redo was possible
412
+ */
413
+ Store.prototype.redo = function () {
414
+ if (this._historyIndex >= this._history.length - 1) return false;
415
+ this._historyIndex++;
416
+ this._state = deepClone(this._history[this._historyIndex]);
417
+ this._notifyWatchers({}, this._state);
418
+ if (this._persistence) this._persistState();
419
+ return true;
420
+ };
421
+
422
+ /**
423
+ * Check if undo is available.
424
+ * @returns {boolean}
425
+ */
426
+ Store.prototype.canUndo = function () { return this._historyIndex > 0; };
427
+
428
+ /**
429
+ * Check if redo is available.
430
+ * @returns {boolean}
431
+ */
432
+ Store.prototype.canRedo = function () { return this._historyIndex < this._history.length - 1; };
433
+
434
+ // ─── Module System ────────────────────────────────────────────────────────────
435
+
436
+ /**
437
+ * Register a namespaced module.
438
+ * @param {string} name - Module namespace
439
+ * @param {Object} module - Module with state, getters, mutations, actions
440
+ */
441
+ Store.prototype.registerModule = function (name, module) {
442
+ const namespacedState = module.state ? deepClone(module.state) : {};
443
+ this._state[name] = namespacedState;
444
+ this._modules[name] = module;
445
+
446
+ // Register namespaced getters
447
+ if (module.getters) {
448
+ Object.keys(module.getters).forEach((key) => {
449
+ this._getters[name + '/' + key] = module.getters[key];
450
+ });
451
+ }
452
+
453
+ // Register namespaced mutations
454
+ if (module.mutations) {
455
+ Object.keys(module.mutations).forEach((key) => {
456
+ this._mutations[name + '/' + key] = (state, payload) => {
457
+ module.mutations[key](state[name], payload);
458
+ };
459
+ });
460
+ }
461
+
462
+ // Register namespaced actions
463
+ if (module.actions) {
464
+ Object.keys(module.actions).forEach((key) => {
465
+ this._actions[name + '/' + key] = (context, payload) => {
466
+ const moduleContext = Object.assign({}, context, {
467
+ state: context.state[name],
468
+ commit: (type, p) => context.commit(name + '/' + type, p),
469
+ dispatch: (type, p) => context.dispatch(name + '/' + type, p),
470
+ });
471
+ return module.actions[key](moduleContext, payload);
472
+ };
473
+ });
474
+ }
475
+ };
476
+
477
+ /**
478
+ * Unregister a namespaced module.
479
+ * @param {string} name
480
+ */
481
+ Store.prototype.unregisterModule = function (name) {
482
+ delete this._state[name];
483
+ delete this._modules[name];
484
+
485
+ // Clean up namespaced getters, mutations, actions
486
+ const prefix = name + '/';
487
+ Object.keys(this._getters).forEach((k) => { if (k.startsWith(prefix)) delete this._getters[k]; });
488
+ Object.keys(this._mutations).forEach((k) => { if (k.startsWith(prefix)) delete this._mutations[k]; });
489
+ Object.keys(this._actions).forEach((k) => { if (k.startsWith(prefix)) delete this._actions[k]; });
490
+ };
491
+
492
+ // ─── DevTools Integration ─────────────────────────────────────────────────────
493
+
494
+ /**
495
+ * Get store information for DevTools.
496
+ * @returns {Object}
497
+ */
498
+ Store.prototype.getDevToolsInfo = function () {
499
+ return {
500
+ state: deepClone(this._state),
501
+ getters: Object.keys(this._getters),
502
+ mutations: Object.keys(this._mutations),
503
+ actions: Object.keys(this._actions),
504
+ modules: Object.keys(this._modules),
505
+ history: { index: this._historyIndex, length: this._history.length },
506
+ };
507
+ };
508
+
509
+ // ─── Utility ──────────────────────────────────────────────────────────────────
510
+
511
+ function deepClone(obj, cache) {
512
+ if (obj === null || typeof obj !== 'object') return obj;
513
+ if (obj instanceof Date) return new Date(obj.getTime());
514
+ if (obj instanceof RegExp) return new RegExp(obj.source, obj.flags);
515
+ cache = cache || new WeakMap();
516
+ if (cache.has(obj)) return cache.get(obj);
517
+ const clone = Array.isArray(obj) ? [] : {};
518
+ cache.set(obj, clone);
519
+ Object.keys(obj).forEach((k) => { clone[k] = deepClone(obj[k], cache); });
520
+ return clone;
521
+ }
522
+
523
+ // ─── Factory ──────────────────────────────────────────────────────────────────
524
+
525
+ /**
526
+ * Create a new store instance.
527
+ * @param {Object} [options]
528
+ * @returns {Store}
529
+ */
530
+ function createStore(options) {
531
+ return new Store(options);
532
+ }
533
+
534
+ // ─── Exports ──────────────────────────────────────────────────────────────────
535
+
536
+ module.exports = {
537
+ Store,
538
+ createStore,
539
+ };