juxscript 1.1.28 → 1.1.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -27,6 +27,7 @@ import { menu } from './lib/components/menu.js';
27
27
  import { modal } from './lib/components/modal.js';
28
28
  import { nav } from './lib/components/nav.js';
29
29
  import { paragraph } from './lib/components/paragraph.js';
30
+ import { pen } from './lib/components/pen.js';
30
31
  import { progress } from './lib/components/progress.js';
31
32
  import { radio } from './lib/components/radio.js';
32
33
  import { script } from './lib/components/script.js';
@@ -43,7 +44,8 @@ import { write } from './lib/components/write.js';
43
44
  import { renderIcon, renderEmoji } from './lib/components/icons.js';
44
45
  import { state } from './lib/reactivity/state.js';
45
46
  import { registry } from './lib/components/registry.js';
46
- export { state, registry };
47
+ import { stateHistory } from './lib/components/history/StateHistory.js';
48
+ export { state, registry, stateHistory };
47
49
  export declare const jux: {
48
50
  alert: typeof alert;
49
51
  app: typeof app;
@@ -73,6 +75,7 @@ export declare const jux: {
73
75
  modal: typeof modal;
74
76
  nav: typeof nav;
75
77
  paragraph: typeof paragraph;
78
+ pen: typeof pen;
76
79
  progress: typeof progress;
77
80
  radio: typeof radio;
78
81
  req: import("./lib/components/req.js").Req;
package/index.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAClD,OAAO,EAAE,GAAG,EAAE,MAAM,yBAAyB,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC1D,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAC5D,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAEhD,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AACtD,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AACtD,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAClD,OAAO,EAAE,GAAG,EAAE,MAAM,yBAAyB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC1D,OAAO,EAAE,GAAG,EAAE,MAAM,yBAAyB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACxD,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAElD,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AACtD,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AACtD,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAElD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,0CAA0C,CAAC;AAExE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC;AAGzC,eAAO,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkDf,CAAC"}
package/index.js CHANGED
@@ -27,6 +27,7 @@ import { menu } from './lib/components/menu.js';
27
27
  import { modal } from './lib/components/modal.js';
28
28
  import { nav } from './lib/components/nav.js';
29
29
  import { paragraph } from './lib/components/paragraph.js';
30
+ import { pen } from './lib/components/pen.js'; // ✅ Import pen
30
31
  import { progress } from './lib/components/progress.js';
31
32
  import { radio } from './lib/components/radio.js';
32
33
  import { req } from './lib/components/req.js';
@@ -45,7 +46,8 @@ import { fetchAPI } from './lib/utils/fetch.js';
45
46
  import { renderIcon, renderEmoji } from './lib/components/icons.js';
46
47
  import { state } from './lib/reactivity/state.js';
47
48
  import { registry } from './lib/components/registry.js'; // ✅ Import registry
48
- export { state, registry }; // ✅ Export registry
49
+ import { stateHistory } from './lib/components/history/StateHistory.js'; // ✅ Import history
50
+ export { state, registry, stateHistory }; // ✅ Export history
49
51
  // Utilities
50
52
  export const jux = {
51
53
  alert,
@@ -76,6 +78,7 @@ export const jux = {
76
78
  modal,
77
79
  nav,
78
80
  paragraph,
81
+ pen,
79
82
  progress,
80
83
  radio,
81
84
  req,
@@ -131,17 +131,30 @@ export declare abstract class BaseComponent<TState extends BaseState = BaseState
131
131
  */
132
132
  remove(): this;
133
133
  bind(event: string, handler: Function): this;
134
- /**
135
- * Sync a component property with a State object
136
- * @param property - The property to sync
137
- * @param stateObj - The State object to sync with
138
- * @param toStateOrTransform - Either toState function OR a simple transform function
139
- * @param toComponent - Optional toComponent function (if toState was provided)
140
- */
141
134
  sync(property: string, stateObj: State<any>, toStateOrTransform?: Function, toComponent?: Function): this;
142
135
  protected _isTriggerEvent(event: string): boolean;
143
136
  protected _isCallbackEvent(event: string): boolean;
144
137
  protected _triggerCallback(eventName: string, ...args: any[]): void;
138
+ /**
139
+ * Roll back to previous state
140
+ */
141
+ rollback(): this;
142
+ /**
143
+ * Roll forward to next state
144
+ */
145
+ rollforward(): this;
146
+ /**
147
+ * Get complete timeline of this component's changes
148
+ */
149
+ timeline(): Array<any>;
150
+ /**
151
+ * Get only state changes for this component
152
+ */
153
+ stateHistory(): import("../history/StateHistory.js").StateSnapshot<any>[];
154
+ /**
155
+ * Get only events for this component
156
+ */
157
+ eventHistory(): import("../history/StateHistory.js").EventSnapshot[];
145
158
  protected _setupContainer(targetId?: string): HTMLElement;
146
159
  protected _wireStandardEvents(element: HTMLElement): void;
147
160
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"BaseComponent.d.ts","sourceRoot":"","sources":["BaseComponent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAIlD;;;GAGG;AACH,MAAM,WAAW,SAAS;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACvC;AAED;;;;;;;;GAQG;AACH,8BAAsB,aAAa,CAAC,MAAM,SAAS,SAAS,GAAG,SAAS;IAEpE,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,WAAW,GAAG,IAAI,CAAQ;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,EAAE,EAAE,MAAM,CAAC;IAGX,SAAS,CAAC,SAAS,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,QAAQ,CAAA;KAAE,CAAC,CAAM;IACtE,SAAS,CAAC,aAAa,EAAE,KAAK,CAAC;QAC3B,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;QACrB,OAAO,CAAC,EAAE,QAAQ,CAAC;QACnB,WAAW,CAAC,EAAE,QAAQ,CAAA;KACzB,CAAC,CAAM;IACR,SAAS,CAAC,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAa;IAC9D,SAAS,CAAC,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAa;IAC/D,SAAS,CAAC,eAAe,EAAE,OAAO,CAAS;gBAE/B,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM;IAqC5C,SAAS,CAAC,QAAQ,CAAC,gBAAgB,IAAI,SAAS,MAAM,EAAE;IACxD,SAAS,CAAC,QAAQ,CAAC,iBAAiB,IAAI,SAAS,MAAM,EAAE;IACzD,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAExC;;;;;OAKG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,IAAI;IAqCtC;;;OAGG;IACH,SAAS,CAAC,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,IAAI;IAuB5D;;OAEG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK1B;;OAEG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAS1B;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAQ7B;;OAEG;IACH,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAOhC;;OAEG;IACH,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAUhC;;OAEG;IACH,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAK7B;;OAEG;IACH,IAAI,IAAI,IAAI;IAIZ;;OAEG;IACH,IAAI,IAAI,IAAI;IAIZ;;OAEG;IACH,gBAAgB,IAAI,IAAI;IASxB;;OAEG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAOvC;;OAEG;IACH,KAAK,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAO/C;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAW9B;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAK9B;;OAEG;IACH,MAAM,IAAI,IAAI;IAId;;OAEG;IACH,OAAO,IAAI,IAAI;IAQf;;OAEG;IACH,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAS7B;;OAEG;IACH,KAAK,IAAI,IAAI;IAQb;;OAEG;IACH,IAAI,IAAI,IAAI;IAYZ;;OAEG;IACH,MAAM,IAAI,IAAI;IAed,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,GAAG,IAAI;IAW5C;;;;;;OAMG;IACH,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,kBAAkB,CAAC,EAAE,QAAQ,EAAE,WAAW,CAAC,EAAE,QAAQ,GAAG,IAAI;IAkBzG,SAAS,CAAC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAIjD,SAAS,CAAC,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAIlD,SAAS,CAAC,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAcnE,SAAS,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,WAAW;IAuBzD,SAAS,CAAC,mBAAmB,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAMzD;;OAEG;IACH,SAAS,CAAC,aAAa,IAAI,IAAI;IA+B/B,QAAQ,CAAC,YAAY,EAAE,GAAG,GAAG,IAAI;IAWjC;;;;;;OAMG;IACH,IAAI,KAAK,IAAI,QAAQ,CAAC,MAAM,CAAC,CAE5B;CACJ"}
1
+ {"version":3,"file":"BaseComponent.d.ts","sourceRoot":"","sources":["BaseComponent.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { getOrCreateContainer } from '../helpers.js';
2
- import { registry } from '../registry.js'; // ✅ Import registry
2
+ import { registry } from '../registry.js';
3
+ import { stateHistory } from '../history/StateHistory.js'; // ✅ Import history
3
4
  /**
4
5
  * Abstract base class for all JUX components
5
6
  * Provides common storage, event routing, and lifecycle methods
@@ -32,11 +33,14 @@ export class BaseComponent {
32
33
  this.state = new Proxy(stateWithDefaults, {
33
34
  set: (target, prop, value) => {
34
35
  const key = prop;
35
- if (target[key] !== value) {
36
+ const oldValue = target[key];
37
+ if (oldValue !== value) {
38
+ // ✅ Record state change in history
39
+ stateHistory.recordStateChange(this._id, prop, oldValue, value);
36
40
  target[key] = value;
37
41
  // 1️⃣ Update DOM via update()
38
42
  this.update(prop, value);
39
- // 2️⃣ Notify synced State<T> objects (with guard)
43
+ // 2️⃣ Notify synced State<T> objects (with guard)
40
44
  if (!this._isUpdatingSync) {
41
45
  this._notifySyncedState(prop, value);
42
46
  }
@@ -287,6 +291,8 @@ export class BaseComponent {
287
291
  * EVENT BINDING (Shared logic)
288
292
  * ═════════════════════════════════════════════════════════════════ */
289
293
  bind(event, handler) {
294
+ // ✅ Record bind event
295
+ stateHistory.recordEvent(this._id, 'bind', event, { handlerName: handler.name });
290
296
  if (this._isTriggerEvent(event)) {
291
297
  this._triggerHandlers.set(event, handler);
292
298
  }
@@ -298,20 +304,17 @@ export class BaseComponent {
298
304
  }
299
305
  return this;
300
306
  }
301
- /**
302
- * Sync a component property with a State object
303
- * @param property - The property to sync
304
- * @param stateObj - The State object to sync with
305
- * @param toStateOrTransform - Either toState function OR a simple transform function
306
- * @param toComponent - Optional toComponent function (if toState was provided)
307
- */
308
307
  sync(property, stateObj, toStateOrTransform, toComponent) {
309
308
  if (!stateObj || typeof stateObj.subscribe !== 'function') {
310
309
  throw new Error(`${this.constructor.name}.sync: Expected a State object for property "${property}"`);
311
310
  }
312
- // If only 3 args provided, treat the function as toComponent (the common case)
313
311
  const actualToState = (toComponent !== undefined) ? toStateOrTransform : undefined;
314
312
  const actualToComponent = (toComponent !== undefined) ? toComponent : toStateOrTransform;
313
+ // ✅ Record sync event
314
+ stateHistory.recordEvent(this._id, 'sync', property, {
315
+ hasToState: !!actualToState,
316
+ hasToComponent: !!actualToComponent
317
+ });
315
318
  this._syncBindings.push({
316
319
  property,
317
320
  stateObj,
@@ -327,13 +330,59 @@ export class BaseComponent {
327
330
  return this.getCallbackEvents().includes(event);
328
331
  }
329
332
  _triggerCallback(eventName, ...args) {
333
+ // ✅ Record callback event
334
+ stateHistory.recordEvent(this._id, 'callback', eventName, { argsCount: args.length });
330
335
  if (this._callbackHandlers.has(eventName)) {
331
336
  const handler = this._callbackHandlers.get(eventName);
332
337
  handler(...args);
333
338
  }
334
- else {
335
- // console.warn(`🔍 No handler found for "${eventName}"`);
339
+ }
340
+ /* ═════════════════════════════════════════════════════════════════
341
+ * TIME-TRAVEL DEBUGGING (PUBLIC API)
342
+ * ═════════════════════════════════════════════════════════════════ */
343
+ /**
344
+ * Roll back to previous state
345
+ */
346
+ rollback() {
347
+ const snapshot = stateHistory.moveBack();
348
+ if (snapshot && snapshot.componentId === this._id) {
349
+ stateHistory.startReplay();
350
+ this.state[snapshot.property] = snapshot.oldValue;
351
+ stateHistory.endReplay();
352
+ }
353
+ return this;
354
+ }
355
+ /**
356
+ * Roll forward to next state
357
+ */
358
+ rollforward() {
359
+ const snapshot = stateHistory.moveForward();
360
+ if (snapshot && snapshot.componentId === this._id) {
361
+ stateHistory.startReplay();
362
+ this.state[snapshot.property] = snapshot.newValue;
363
+ stateHistory.endReplay();
336
364
  }
365
+ return this;
366
+ }
367
+ /**
368
+ * Get complete timeline of this component's changes
369
+ */
370
+ timeline() {
371
+ const stateChanges = stateHistory.getComponentHistory(this._id);
372
+ const events = stateHistory.getComponentEvents(this._id);
373
+ return [...stateChanges, ...events].sort((a, b) => a.timestamp - b.timestamp);
374
+ }
375
+ /**
376
+ * Get only state changes for this component
377
+ */
378
+ stateHistory() {
379
+ return stateHistory.getComponentHistory(this._id);
380
+ }
381
+ /**
382
+ * Get only events for this component
383
+ */
384
+ eventHistory() {
385
+ return stateHistory.getComponentEvents(this._id);
337
386
  }
338
387
  /* ═════════════════════════════════════════════════════════════════
339
388
  * COMMON RENDER HELPERS
@@ -374,13 +423,13 @@ export class BaseComponent {
374
423
  if (typeof method === 'function') {
375
424
  // Set initial value
376
425
  const initialValue = transform(stateObj.value);
377
- this._isUpdatingSync = true; // ✅ Guard during initial set
426
+ this._isUpdatingSync = true;
378
427
  method.call(this, initialValue);
379
428
  this._isUpdatingSync = false;
380
429
  // Subscribe to changes with guard
381
430
  stateObj.subscribe((val) => {
382
431
  if (this._isUpdatingSync)
383
- return; // ✅ Skip if updating
432
+ return;
384
433
  const transformed = transform(val);
385
434
  this._isUpdatingSync = true;
386
435
  method.call(this, transformed);
@@ -1,6 +1,7 @@
1
1
  import { State } from '../../reactivity/state.js';
2
2
  import { getOrCreateContainer } from '../helpers.js';
3
- import { registry } from '../registry.js'; // ✅ Import registry
3
+ import { registry } from '../registry.js';
4
+ import { stateHistory } from '../history/StateHistory.js'; // ✅ Import history
4
5
 
5
6
  /**
6
7
  * Base state interface that ALL component states must extend
@@ -60,13 +61,18 @@ export abstract class BaseComponent<TState extends BaseState = BaseState> {
60
61
  this.state = new Proxy(stateWithDefaults, {
61
62
  set: (target, prop, value) => {
62
63
  const key = prop as keyof TState;
63
- if (target[key] !== value) {
64
+ const oldValue = target[key];
65
+
66
+ if (oldValue !== value) {
67
+ // ✅ Record state change in history
68
+ stateHistory.recordStateChange(this._id, prop as string, oldValue, value);
69
+
64
70
  target[key] = value;
65
71
 
66
72
  // 1️⃣ Update DOM via update()
67
73
  this.update(prop as string, value);
68
74
 
69
- // 2️⃣ Notify synced State<T> objects (with guard)
75
+ // 2️⃣ Notify synced State<T> objects (with guard)
70
76
  if (!this._isUpdatingSync) {
71
77
  this._notifySyncedState(prop as string, value);
72
78
  }
@@ -359,6 +365,9 @@ export abstract class BaseComponent<TState extends BaseState = BaseState> {
359
365
  * ═════════════════════════════════════════════════════════════════ */
360
366
 
361
367
  bind(event: string, handler: Function): this {
368
+ // ✅ Record bind event
369
+ stateHistory.recordEvent(this._id, 'bind', event, { handlerName: handler.name });
370
+
362
371
  if (this._isTriggerEvent(event)) {
363
372
  this._triggerHandlers.set(event, handler);
364
373
  } else if (this._isCallbackEvent(event)) {
@@ -369,22 +378,20 @@ export abstract class BaseComponent<TState extends BaseState = BaseState> {
369
378
  return this;
370
379
  }
371
380
 
372
- /**
373
- * Sync a component property with a State object
374
- * @param property - The property to sync
375
- * @param stateObj - The State object to sync with
376
- * @param toStateOrTransform - Either toState function OR a simple transform function
377
- * @param toComponent - Optional toComponent function (if toState was provided)
378
- */
379
381
  sync(property: string, stateObj: State<any>, toStateOrTransform?: Function, toComponent?: Function): this {
380
382
  if (!stateObj || typeof stateObj.subscribe !== 'function') {
381
383
  throw new Error(`${this.constructor.name}.sync: Expected a State object for property "${property}"`);
382
384
  }
383
385
 
384
- // If only 3 args provided, treat the function as toComponent (the common case)
385
386
  const actualToState = (toComponent !== undefined) ? toStateOrTransform : undefined;
386
387
  const actualToComponent = (toComponent !== undefined) ? toComponent : toStateOrTransform;
387
388
 
389
+ // ✅ Record sync event
390
+ stateHistory.recordEvent(this._id, 'sync', property, {
391
+ hasToState: !!actualToState,
392
+ hasToComponent: !!actualToComponent
393
+ });
394
+
388
395
  this._syncBindings.push({
389
396
  property,
390
397
  stateObj,
@@ -403,15 +410,68 @@ export abstract class BaseComponent<TState extends BaseState = BaseState> {
403
410
  }
404
411
 
405
412
  protected _triggerCallback(eventName: string, ...args: any[]): void {
413
+ // ✅ Record callback event
414
+ stateHistory.recordEvent(this._id, 'callback', eventName, { argsCount: args.length });
406
415
 
407
416
  if (this._callbackHandlers.has(eventName)) {
408
417
  const handler = this._callbackHandlers.get(eventName)!;
409
418
  handler(...args);
410
- } else {
411
- // console.warn(`🔍 No handler found for "${eventName}"`);
412
419
  }
413
420
  }
414
421
 
422
+ /* ═════════════════════════════════════════════════════════════════
423
+ * TIME-TRAVEL DEBUGGING (PUBLIC API)
424
+ * ═════════════════════════════════════════════════════════════════ */
425
+
426
+ /**
427
+ * Roll back to previous state
428
+ */
429
+ rollback(): this {
430
+ const snapshot = stateHistory.moveBack();
431
+ if (snapshot && snapshot.componentId === this._id) {
432
+ stateHistory.startReplay();
433
+ (this.state as any)[snapshot.property] = snapshot.oldValue;
434
+ stateHistory.endReplay();
435
+ }
436
+ return this;
437
+ }
438
+
439
+ /**
440
+ * Roll forward to next state
441
+ */
442
+ rollforward(): this {
443
+ const snapshot = stateHistory.moveForward();
444
+ if (snapshot && snapshot.componentId === this._id) {
445
+ stateHistory.startReplay();
446
+ (this.state as any)[snapshot.property] = snapshot.newValue;
447
+ stateHistory.endReplay();
448
+ }
449
+ return this;
450
+ }
451
+
452
+ /**
453
+ * Get complete timeline of this component's changes
454
+ */
455
+ timeline(): Array<any> {
456
+ const stateChanges = stateHistory.getComponentHistory(this._id);
457
+ const events = stateHistory.getComponentEvents(this._id);
458
+ return [...stateChanges, ...events].sort((a, b) => a.timestamp - b.timestamp);
459
+ }
460
+
461
+ /**
462
+ * Get only state changes for this component
463
+ */
464
+ stateHistory() {
465
+ return stateHistory.getComponentHistory(this._id);
466
+ }
467
+
468
+ /**
469
+ * Get only events for this component
470
+ */
471
+ eventHistory() {
472
+ return stateHistory.getComponentEvents(this._id);
473
+ }
474
+
415
475
  /* ═════════════════════════════════════════════════════════════════
416
476
  * COMMON RENDER HELPERS
417
477
  * ═════════════════════════════════════════════════════════════════ */
@@ -457,13 +517,13 @@ export abstract class BaseComponent<TState extends BaseState = BaseState> {
457
517
  if (typeof method === 'function') {
458
518
  // Set initial value
459
519
  const initialValue = transform(stateObj.value);
460
- this._isUpdatingSync = true; // ✅ Guard during initial set
520
+ this._isUpdatingSync = true;
461
521
  method.call(this, initialValue);
462
522
  this._isUpdatingSync = false;
463
523
 
464
524
  // Subscribe to changes with guard
465
525
  stateObj.subscribe((val: any) => {
466
- if (this._isUpdatingSync) return; // ✅ Skip if updating
526
+ if (this._isUpdatingSync) return;
467
527
 
468
528
  const transformed = transform(val);
469
529
  this._isUpdatingSync = true;
@@ -0,0 +1,91 @@
1
+ /**
2
+ * State History Tracker
3
+ * Tracks all state mutations for time-travel debugging and undo/redo
4
+ */
5
+ export interface StateSnapshot<T = any> {
6
+ timestamp: number;
7
+ componentId: string;
8
+ property: string;
9
+ oldValue: T;
10
+ newValue: T;
11
+ stackTrace?: string;
12
+ }
13
+ export interface EventSnapshot {
14
+ timestamp: number;
15
+ componentId: string;
16
+ eventType: 'bind' | 'sync' | 'callback' | 'trigger';
17
+ eventName: string;
18
+ details: Record<string, any>;
19
+ }
20
+ export declare class StateHistory {
21
+ private stateSnapshots;
22
+ private eventSnapshots;
23
+ private maxHistory;
24
+ private currentIndex;
25
+ private isReplaying;
26
+ /**
27
+ * Record a state change
28
+ */
29
+ recordStateChange<T>(componentId: string, property: string, oldValue: T, newValue: T): void;
30
+ /**
31
+ * Record an event (bind, sync, callback, trigger)
32
+ */
33
+ recordEvent(componentId: string, eventType: 'bind' | 'sync' | 'callback' | 'trigger', eventName: string, details?: Record<string, any>): void;
34
+ /**
35
+ * Get timeline of all changes and events
36
+ */
37
+ getTimeline(): Array<StateSnapshot | EventSnapshot>;
38
+ /**
39
+ * Get state snapshots for a specific component
40
+ */
41
+ getComponentHistory(componentId: string): StateSnapshot[];
42
+ /**
43
+ * Get event snapshots for a specific component
44
+ */
45
+ getComponentEvents(componentId: string): EventSnapshot[];
46
+ /**
47
+ * Check if we can roll back
48
+ */
49
+ canRollback(): boolean;
50
+ /**
51
+ * Check if we can roll forward
52
+ */
53
+ canRollforward(): boolean;
54
+ /**
55
+ * Get the current snapshot (for rollback)
56
+ */
57
+ getCurrentSnapshot(): StateSnapshot | null;
58
+ /**
59
+ * Move index for rollback
60
+ */
61
+ moveBack(): StateSnapshot | null;
62
+ /**
63
+ * Move index for rollforward
64
+ */
65
+ moveForward(): StateSnapshot | null;
66
+ /**
67
+ * Mark as replaying to prevent recursive recording
68
+ */
69
+ startReplay(): void;
70
+ /**
71
+ * End replay mode
72
+ */
73
+ endReplay(): void;
74
+ /**
75
+ * Clear all history
76
+ */
77
+ clear(): void;
78
+ /**
79
+ * Get summary statistics
80
+ */
81
+ getStats(): {
82
+ totalStateChanges: number;
83
+ totalEvents: number;
84
+ currentIndex: number;
85
+ canRollback: boolean;
86
+ canRollforward: boolean;
87
+ components: number;
88
+ };
89
+ }
90
+ export declare const stateHistory: StateHistory;
91
+ //# sourceMappingURL=StateHistory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StateHistory.d.ts","sourceRoot":"","sources":["StateHistory.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,aAAa,CAAC,CAAC,GAAG,GAAG;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,CAAC,CAAC;IACZ,QAAQ,EAAE,CAAC,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IACpD,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAChC;AAED,qBAAa,YAAY;IACrB,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,UAAU,CAAe;IACjC,OAAO,CAAC,YAAY,CAAc;IAClC,OAAO,CAAC,WAAW,CAAkB;IAErC;;OAEG;IACH,iBAAiB,CAAC,CAAC,EACf,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,CAAC,EACX,QAAQ,EAAE,CAAC,GACZ,IAAI;IA2BP;;OAEG;IACH,WAAW,CACP,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,EACnD,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,GAClC,IAAI;IAiBP;;OAEG;IACH,WAAW,IAAI,KAAK,CAAC,aAAa,GAAG,aAAa,CAAC;IAKnD;;OAEG;IACH,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,aAAa,EAAE;IAIzD;;OAEG;IACH,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,aAAa,EAAE;IAIxD;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACH,cAAc,IAAI,OAAO;IAIzB;;OAEG;IACH,kBAAkB,IAAI,aAAa,GAAG,IAAI;IAO1C;;OAEG;IACH,QAAQ,IAAI,aAAa,GAAG,IAAI;IAQhC;;OAEG;IACH,WAAW,IAAI,aAAa,GAAG,IAAI;IAQnC;;OAEG;IACH,WAAW,IAAI,IAAI;IAInB;;OAEG;IACH,SAAS,IAAI,IAAI;IAIjB;;OAEG;IACH,KAAK,IAAI,IAAI;IAMb;;OAEG;IACH,QAAQ;;;;;;;;CAaX;AAGD,eAAO,MAAM,YAAY,cAAqB,CAAC"}
@@ -0,0 +1,154 @@
1
+ /**
2
+ * State History Tracker
3
+ * Tracks all state mutations for time-travel debugging and undo/redo
4
+ */
5
+ export class StateHistory {
6
+ constructor() {
7
+ this.stateSnapshots = [];
8
+ this.eventSnapshots = [];
9
+ this.maxHistory = 100;
10
+ this.currentIndex = -1;
11
+ this.isReplaying = false;
12
+ }
13
+ /**
14
+ * Record a state change
15
+ */
16
+ recordStateChange(componentId, property, oldValue, newValue) {
17
+ if (this.isReplaying)
18
+ return; // Don't record during replay
19
+ const snapshot = {
20
+ timestamp: Date.now(),
21
+ componentId,
22
+ property,
23
+ oldValue,
24
+ newValue,
25
+ stackTrace: new Error().stack
26
+ };
27
+ // Trim future history if we're not at the end
28
+ if (this.currentIndex < this.stateSnapshots.length - 1) {
29
+ this.stateSnapshots = this.stateSnapshots.slice(0, this.currentIndex + 1);
30
+ }
31
+ this.stateSnapshots.push(snapshot);
32
+ this.currentIndex = this.stateSnapshots.length - 1;
33
+ // Trim if exceeds max
34
+ if (this.stateSnapshots.length > this.maxHistory) {
35
+ this.stateSnapshots.shift();
36
+ this.currentIndex--;
37
+ }
38
+ }
39
+ /**
40
+ * Record an event (bind, sync, callback, trigger)
41
+ */
42
+ recordEvent(componentId, eventType, eventName, details = {}) {
43
+ const snapshot = {
44
+ timestamp: Date.now(),
45
+ componentId,
46
+ eventType,
47
+ eventName,
48
+ details
49
+ };
50
+ this.eventSnapshots.push(snapshot);
51
+ // Trim if exceeds max
52
+ if (this.eventSnapshots.length > this.maxHistory) {
53
+ this.eventSnapshots.shift();
54
+ }
55
+ }
56
+ /**
57
+ * Get timeline of all changes and events
58
+ */
59
+ getTimeline() {
60
+ return [...this.stateSnapshots, ...this.eventSnapshots]
61
+ .sort((a, b) => a.timestamp - b.timestamp);
62
+ }
63
+ /**
64
+ * Get state snapshots for a specific component
65
+ */
66
+ getComponentHistory(componentId) {
67
+ return this.stateSnapshots.filter(s => s.componentId === componentId);
68
+ }
69
+ /**
70
+ * Get event snapshots for a specific component
71
+ */
72
+ getComponentEvents(componentId) {
73
+ return this.eventSnapshots.filter(s => s.componentId === componentId);
74
+ }
75
+ /**
76
+ * Check if we can roll back
77
+ */
78
+ canRollback() {
79
+ return this.currentIndex > 0;
80
+ }
81
+ /**
82
+ * Check if we can roll forward
83
+ */
84
+ canRollforward() {
85
+ return this.currentIndex < this.stateSnapshots.length - 1;
86
+ }
87
+ /**
88
+ * Get the current snapshot (for rollback)
89
+ */
90
+ getCurrentSnapshot() {
91
+ if (this.currentIndex >= 0 && this.currentIndex < this.stateSnapshots.length) {
92
+ return this.stateSnapshots[this.currentIndex];
93
+ }
94
+ return null;
95
+ }
96
+ /**
97
+ * Move index for rollback
98
+ */
99
+ moveBack() {
100
+ if (this.canRollback()) {
101
+ this.currentIndex--;
102
+ return this.stateSnapshots[this.currentIndex];
103
+ }
104
+ return null;
105
+ }
106
+ /**
107
+ * Move index for rollforward
108
+ */
109
+ moveForward() {
110
+ if (this.canRollforward()) {
111
+ this.currentIndex++;
112
+ return this.stateSnapshots[this.currentIndex];
113
+ }
114
+ return null;
115
+ }
116
+ /**
117
+ * Mark as replaying to prevent recursive recording
118
+ */
119
+ startReplay() {
120
+ this.isReplaying = true;
121
+ }
122
+ /**
123
+ * End replay mode
124
+ */
125
+ endReplay() {
126
+ this.isReplaying = false;
127
+ }
128
+ /**
129
+ * Clear all history
130
+ */
131
+ clear() {
132
+ this.stateSnapshots = [];
133
+ this.eventSnapshots = [];
134
+ this.currentIndex = -1;
135
+ }
136
+ /**
137
+ * Get summary statistics
138
+ */
139
+ getStats() {
140
+ return {
141
+ totalStateChanges: this.stateSnapshots.length,
142
+ totalEvents: this.eventSnapshots.length,
143
+ currentIndex: this.currentIndex,
144
+ canRollback: this.canRollback(),
145
+ canRollforward: this.canRollforward(),
146
+ components: new Set([
147
+ ...this.stateSnapshots.map(s => s.componentId),
148
+ ...this.eventSnapshots.map(s => s.componentId)
149
+ ]).size
150
+ };
151
+ }
152
+ }
153
+ // Global singleton
154
+ export const stateHistory = new StateHistory();