juxscript 1.1.11 → 1.1.13

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.
@@ -29,6 +29,12 @@ export declare abstract class BaseComponent<TState extends Record<string, any>>
29
29
  protected abstract getTriggerEvents(): readonly string[];
30
30
  protected abstract getCallbackEvents(): readonly string[];
31
31
  abstract render(targetId?: string): this;
32
+ /**
33
+ * REACTIVE UPDATE HOOK
34
+ * Called automatically when this.state[prop] changes.
35
+ * Override this in components to update the DOM without full re-render.
36
+ */
37
+ protected update(prop: string, value: any): void;
32
38
  /**
33
39
  * Set component style
34
40
  */
@@ -127,15 +133,6 @@ export declare abstract class BaseComponent<TState extends Record<string, any>>
127
133
  renderTo(juxComponent: any): this;
128
134
  /**
129
135
  * ✅ Read-only accessor for component state
130
- * Provides clear separation between setters (fluent methods) and getters
131
- *
132
- * @example
133
- * const myCard = card('example')
134
- * .title('Hello') // ✅ SETTER (fluent)
135
- * .content('World'); // ✅ SETTER (fluent)
136
- *
137
- * console.log(myCard.props.title); // ✅ GETTER: 'Hello'
138
- * console.log(myCard.props.content); // ✅ GETTER: 'World'
139
136
  */
140
137
  get props(): Readonly<TState>;
141
138
  }
@@ -1 +1 @@
1
- {"version":3,"file":"BaseComponent.d.ts","sourceRoot":"","sources":["BaseComponent.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"BaseComponent.d.ts","sourceRoot":"","sources":["BaseComponent.ts"],"names":[],"mappings":"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"}
@@ -18,7 +18,26 @@ export class BaseComponent {
18
18
  this._callbackHandlers = new Map();
19
19
  this._id = id;
20
20
  this.id = id;
21
- this.state = initialState;
21
+ // ✨ REACTIVE PROXY: Intercept state changes to trigger view updates automatically
22
+ this.state = new Proxy(initialState, {
23
+ set: (target, prop, value) => {
24
+ const key = prop;
25
+ if (target[key] !== value) {
26
+ target[key] = value;
27
+ this.update(prop, value);
28
+ }
29
+ return true;
30
+ }
31
+ });
32
+ }
33
+ /**
34
+ * REACTIVE UPDATE HOOK
35
+ * Called automatically when this.state[prop] changes.
36
+ * Override this in components to update the DOM without full re-render.
37
+ */
38
+ update(prop, value) {
39
+ // Default no-op. Children implement granular DOM updates here.
40
+ // Example: if (prop === 'title') document.getElementById(...).textContent = value;
22
41
  }
23
42
  /* ═════════════════════════════════════════════════════════════════
24
43
  * COMMON FLUENT API (Inherited by all components)
@@ -277,7 +296,7 @@ export class BaseComponent {
277
296
  handler(...args);
278
297
  }
279
298
  else {
280
- console.warn(`🔍 No handler found for "${eventName}"`);
299
+ // console.warn(`🔍 No handler found for "${eventName}"`);
281
300
  }
282
301
  }
283
302
  /* ═════════════════════════════════════════════════════════════════
@@ -347,15 +366,6 @@ export class BaseComponent {
347
366
  * ═════════════════════════════════════════════════════════════════ */
348
367
  /**
349
368
  * ✅ Read-only accessor for component state
350
- * Provides clear separation between setters (fluent methods) and getters
351
- *
352
- * @example
353
- * const myCard = card('example')
354
- * .title('Hello') // ✅ SETTER (fluent)
355
- * .content('World'); // ✅ SETTER (fluent)
356
- *
357
- * console.log(myCard.props.title); // ✅ GETTER: 'Hello'
358
- * console.log(myCard.props.content); // ✅ GETTER: 'World'
359
369
  */
360
370
  get props() {
361
371
  return this.state;
@@ -31,7 +31,18 @@ export abstract class BaseComponent<TState extends Record<string, any>> {
31
31
  constructor(id: string, initialState: TState) {
32
32
  this._id = id;
33
33
  this.id = id;
34
- this.state = initialState;
34
+
35
+ // ✨ REACTIVE PROXY: Intercept state changes to trigger view updates automatically
36
+ this.state = new Proxy(initialState, {
37
+ set: (target, prop, value) => {
38
+ const key = prop as keyof TState;
39
+ if (target[key] !== value) {
40
+ target[key] = value;
41
+ this.update(prop as string, value);
42
+ }
43
+ return true;
44
+ }
45
+ });
35
46
  }
36
47
 
37
48
  /* ═════════════════════════════════════════════════════════════════
@@ -42,6 +53,16 @@ export abstract class BaseComponent<TState extends Record<string, any>> {
42
53
  protected abstract getCallbackEvents(): readonly string[];
43
54
  abstract render(targetId?: string): this;
44
55
 
56
+ /**
57
+ * REACTIVE UPDATE HOOK
58
+ * Called automatically when this.state[prop] changes.
59
+ * Override this in components to update the DOM without full re-render.
60
+ */
61
+ protected update(prop: string, value: any): void {
62
+ // Default no-op. Children implement granular DOM updates here.
63
+ // Example: if (prop === 'title') document.getElementById(...).textContent = value;
64
+ }
65
+
45
66
  /* ═════════════════════════════════════════════════════════════════
46
67
  * COMMON FLUENT API (Inherited by all components)
47
68
  * ═════════════════════════════════════════════════════════════════ */
@@ -324,7 +345,7 @@ export abstract class BaseComponent<TState extends Record<string, any>> {
324
345
  const handler = this._callbackHandlers.get(eventName)!;
325
346
  handler(...args);
326
347
  } else {
327
- console.warn(`🔍 No handler found for "${eventName}"`);
348
+ // console.warn(`🔍 No handler found for "${eventName}"`);
328
349
  }
329
350
  }
330
351
 
@@ -405,15 +426,6 @@ export abstract class BaseComponent<TState extends Record<string, any>> {
405
426
 
406
427
  /**
407
428
  * ✅ Read-only accessor for component state
408
- * Provides clear separation between setters (fluent methods) and getters
409
- *
410
- * @example
411
- * const myCard = card('example')
412
- * .title('Hello') // ✅ SETTER (fluent)
413
- * .content('World'); // ✅ SETTER (fluent)
414
- *
415
- * console.log(myCard.props.title); // ✅ GETTER: 'Hello'
416
- * console.log(myCard.props.content); // ✅ GETTER: 'World'
417
429
  */
418
430
  get props(): Readonly<TState> {
419
431
  return this.state as Readonly<TState>;
@@ -32,7 +32,10 @@ export declare class ChartComponent extends BaseComponent<ChartState> {
32
32
  title(text: string, display?: boolean): this;
33
33
  legend(display?: boolean, position?: 'top' | 'bottom' | 'left' | 'right'): this;
34
34
  tooltip(enabled?: boolean): this;
35
- update(mode?: 'resize' | 'reset' | 'none' | 'hide' | 'show' | 'default'): this;
35
+ /**
36
+ * Update chart with new data or configuration
37
+ */
38
+ updateChart(mode?: 'resize' | 'reset' | 'none' | 'hide' | 'show' | 'default'): this;
36
39
  reset(): this;
37
40
  destroy(): this;
38
41
  getChart(): Chart | null;
@@ -1 +1 @@
1
- {"version":3,"file":"chart.d.ts","sourceRoot":"","sources":["chart.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,KAAK,EAAsB,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAI9F,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,YAAY,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;GAGG;AACH,qBAAa,cAAe,SAAQ,aAAa,CAAC,UAAU,CAAC;IACzD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAyB;IAC/D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAsD;IAC7F,OAAO,CAAC,aAAa,CAAsB;gBAE/B,EAAE,EAAE,MAAM,EAAE,IAAI,GAAE,SAAiB,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC;IAS9E,SAAS,CAAC,gBAAgB,IAAI,SAAS,MAAM,EAAE;IAI/C,SAAS,CAAC,iBAAiB,IAAI,SAAS,MAAM,EAAE;IAQhD,IAAI,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAoB5B,IAAI,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAS5B,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IAS7B,QAAQ,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,IAAI;IAS5B,UAAU,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI;IAa9B,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI;IASlC,UAAU,CAAC,KAAK,GAAE,OAAc,GAAG,IAAI;IAIvC,mBAAmB,CAAC,KAAK,GAAE,OAAc,GAAG,IAAI;IAIhD,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,OAAc,GAAG,IAAI;IASlD,MAAM,CAAC,OAAO,GAAE,OAAc,EAAE,QAAQ,GAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAe,GAAG,IAAI;IAS5F,OAAO,CAAC,OAAO,GAAE,OAAc,GAAG,IAAI;IAatC,MAAM,CAAC,IAAI,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,IAAI;IAQ9E,KAAK,IAAI,IAAI;IAOb,OAAO,IAAI,IAAI;IASf,QAAQ,IAAI,KAAK,GAAG,IAAI;IAQxB,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;CAqClC;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,GAAE,SAAiB,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,cAAc,CAExG"}
1
+ {"version":3,"file":"chart.d.ts","sourceRoot":"","sources":["chart.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,KAAK,EAAsB,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAI9F,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,YAAY,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;GAGG;AACH,qBAAa,cAAe,SAAQ,aAAa,CAAC,UAAU,CAAC;IACzD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAyB;IAC/D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAsD;IAC7F,OAAO,CAAC,aAAa,CAAsB;gBAE/B,EAAE,EAAE,MAAM,EAAE,IAAI,GAAE,SAAiB,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC;IAS9E,SAAS,CAAC,gBAAgB,IAAI,SAAS,MAAM,EAAE;IAI/C,SAAS,CAAC,iBAAiB,IAAI,SAAS,MAAM,EAAE;IAQhD,IAAI,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAoB5B,IAAI,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAS5B,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IAS7B,QAAQ,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,IAAI;IAS5B,UAAU,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI;IAa9B,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI;IASlC,UAAU,CAAC,KAAK,GAAE,OAAc,GAAG,IAAI;IAIvC,mBAAmB,CAAC,KAAK,GAAE,OAAc,GAAG,IAAI;IAIhD,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,OAAc,GAAG,IAAI;IASlD,MAAM,CAAC,OAAO,GAAE,OAAc,EAAE,QAAQ,GAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAe,GAAG,IAAI;IAS5F,OAAO,CAAC,OAAO,GAAE,OAAc,GAAG,IAAI;IAatC;;OAEG;IACH,WAAW,CAAC,IAAI,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,IAAI;IAOnF,KAAK,IAAI,IAAI;IAOb,OAAO,IAAI,IAAI;IASf,QAAQ,IAAI,KAAK,GAAG,IAAI;IAQxB,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;CAsDlC;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,GAAE,SAAiB,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,cAAc,CAExG"}
@@ -117,10 +117,12 @@ export class ChartComponent extends BaseComponent {
117
117
  /* ═════════════════════════════════════════════════════════════════
118
118
  * CHART OPERATIONS
119
119
  * ═════════════════════════════════════════════════════════════════ */
120
- update(mode) {
120
+ /**
121
+ * Update chart with new data or configuration
122
+ */
123
+ updateChart(mode) {
121
124
  if (this.chartInstance) {
122
125
  this.chartInstance.update(mode);
123
- this._triggerCallback('update', this.chartInstance);
124
126
  }
125
127
  return this;
126
128
  }
@@ -169,6 +171,20 @@ export class ChartComponent extends BaseComponent {
169
171
  options: this.state.options
170
172
  };
171
173
  this.chartInstance = new Chart(canvas, config);
174
+ // Wire sync for data
175
+ this._syncBindings.forEach(({ property, stateObj, toState, toComponent }) => {
176
+ if (property === 'data') {
177
+ const transform = toComponent || ((v) => v);
178
+ stateObj.subscribe((val) => {
179
+ const transformed = transform(val);
180
+ this.state.data = transformed;
181
+ if (this.chartInstance) {
182
+ this.chartInstance.data = transformed;
183
+ this.chartInstance.update();
184
+ }
185
+ });
186
+ }
187
+ });
172
188
  // Wire events and syncs
173
189
  this._wireStandardEvents(container);
174
190
  this._wireAllSyncs();
@@ -152,10 +152,12 @@ export class ChartComponent extends BaseComponent<ChartState> {
152
152
  * CHART OPERATIONS
153
153
  * ═════════════════════════════════════════════════════════════════ */
154
154
 
155
- update(mode?: 'resize' | 'reset' | 'none' | 'hide' | 'show' | 'default'): this {
155
+ /**
156
+ * Update chart with new data or configuration
157
+ */
158
+ updateChart(mode?: 'resize' | 'reset' | 'none' | 'hide' | 'show' | 'default'): this {
156
159
  if (this.chartInstance) {
157
160
  this.chartInstance.update(mode);
158
- this._triggerCallback('update', this.chartInstance);
159
161
  }
160
162
  return this;
161
163
  }
@@ -213,6 +215,23 @@ export class ChartComponent extends BaseComponent<ChartState> {
213
215
 
214
216
  this.chartInstance = new Chart(canvas, config);
215
217
 
218
+ // Wire sync for data
219
+ this._syncBindings.forEach(({ property, stateObj, toState, toComponent }) => {
220
+ if (property === 'data') {
221
+ const transform = toComponent || ((v: any) => v);
222
+
223
+ stateObj.subscribe((val: any) => {
224
+ const transformed = transform(val);
225
+ this.state.data = transformed;
226
+
227
+ if (this.chartInstance) {
228
+ this.chartInstance.data = transformed;
229
+ this.chartInstance.update();
230
+ }
231
+ });
232
+ }
233
+ });
234
+
216
235
  // Wire events and syncs
217
236
  this._wireStandardEvents(container);
218
237
  this._wireAllSyncs();
@@ -37,6 +37,11 @@ export declare class Hero extends BaseComponent<HeroState> {
37
37
  constructor(id: string, options?: HeroOptions);
38
38
  protected getTriggerEvents(): readonly string[];
39
39
  protected getCallbackEvents(): readonly string[];
40
+ /**
41
+ * Called automatically by BaseComponent when state changes.
42
+ * Centralizes DOM manipulation so setters don't have to drill/repeat logic.
43
+ */
44
+ protected update(prop: string, value: any): void;
40
45
  title(value: string): this;
41
46
  subtitle(value: string): this;
42
47
  content(value: string): this;
@@ -1 +1 @@
1
- {"version":3,"file":"hero.d.ts","sourceRoot":"","sources":["hero.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAMxD,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,GAAG;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3E,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,OAAO,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,OAAO,CAAC;IAC3C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,KAAK,SAAS,GAAG;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/D,iBAAiB,EAAE,OAAO,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,qBAAa,IAAK,SAAQ,aAAa,CAAC,SAAS,CAAC;gBACpC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB;IAqBjD,SAAS,CAAC,gBAAgB,IAAI,SAAS,MAAM,EAAE;IAI/C,SAAS,CAAC,iBAAiB,IAAI,SAAS,MAAM,EAAE;IAQhD,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK1B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK7B,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK5B,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAKxB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK5B,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAatF,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAKvC,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK5B,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAS9B,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;CA6GhC;AAED,wBAAgB,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,IAAI,CAEhE"}
1
+ {"version":3,"file":"hero.d.ts","sourceRoot":"","sources":["hero.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAMxD,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,GAAG;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3E,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,OAAO,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,OAAO,CAAC;IAC3C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,KAAK,SAAS,GAAG;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/D,iBAAiB,EAAE,OAAO,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,qBAAa,IAAK,SAAQ,aAAa,CAAC,SAAS,CAAC;gBACpC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB;IAoBjD,SAAS,CAAC,gBAAgB,IAAI,SAAS,MAAM,EAAE;IAI/C,SAAS,CAAC,iBAAiB,IAAI,SAAS,MAAM,EAAE;IAQhD;;;OAGG;IACH,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,IAAI;IA+ChD,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK1B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK7B,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK5B,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAKxB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK5B,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAatF,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAKvC,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK5B,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAS9B,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;CAuEhC;AAED,wBAAgB,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,IAAI,CAEhE"}
@@ -1,23 +1,22 @@
1
1
  import { BaseComponent } from './base/BaseComponent.js';
2
2
  // Event definitions - Hero is display-only, but CTA button can trigger actions
3
3
  const TRIGGER_EVENTS = [];
4
- const CALLBACK_EVENTS = ['ctaClick']; // ✅ When CTA button is clicked
4
+ const CALLBACK_EVENTS = ['ctaClick'];
5
5
  export class Hero extends BaseComponent {
6
6
  constructor(id, options = {}) {
7
- // Normalize backgroundImage to object format
8
7
  const bgImage = typeof options.backgroundImage === 'string'
9
8
  ? { url: options.backgroundImage, size: 'cover', repeat: 'no-repeat' }
10
9
  : options.backgroundImage || { url: '', size: 'cover', repeat: 'no-repeat' };
11
10
  super(id, {
12
11
  title: options.title ?? '',
13
12
  subtitle: options.subtitle ?? '',
14
- content: options.content ?? '', // ✅ ADD
13
+ content: options.content ?? '',
15
14
  cta: options.cta ?? '',
16
15
  ctaLink: options.ctaLink ?? '#',
17
16
  backgroundImage: { url: bgImage.url, size: bgImage.size || 'cover', repeat: bgImage.repeat || 'no-repeat' },
18
- backgroundOverlay: options.backgroundOverlay ?? false, // ✅ ADD
17
+ backgroundOverlay: options.backgroundOverlay ?? false,
19
18
  variant: options.variant ?? 'default',
20
- centered: options.centered ?? false, // ✅ ADD
19
+ centered: options.centered ?? false,
21
20
  style: options.style ?? '',
22
21
  class: options.class ?? ''
23
22
  });
@@ -29,10 +28,60 @@ export class Hero extends BaseComponent {
29
28
  return CALLBACK_EVENTS;
30
29
  }
31
30
  /* ═════════════════════════════════════════════════════════════════
32
- * FLUENT API
31
+ * REACTIVE DOM UPDATES
32
+ * ═════════════════════════════════════════════════════════════════ */
33
+ /**
34
+ * Called automatically by BaseComponent when state changes.
35
+ * Centralizes DOM manipulation so setters don't have to drill/repeat logic.
36
+ */
37
+ update(prop, value) {
38
+ const hero = document.getElementById(this._id);
39
+ if (!hero)
40
+ return; // Component not mounted/rendered yet
41
+ switch (prop) {
42
+ case 'title':
43
+ const titleEl = document.getElementById(`${this._id}-title`);
44
+ if (titleEl)
45
+ titleEl.textContent = value;
46
+ break;
47
+ case 'subtitle':
48
+ const subtitleEl = document.getElementById(`${this._id}-subtitle`);
49
+ if (subtitleEl)
50
+ subtitleEl.textContent = value;
51
+ break;
52
+ case 'content':
53
+ const contentEl = hero.querySelector('.jux-hero-body');
54
+ if (contentEl)
55
+ contentEl.innerHTML = value;
56
+ break;
57
+ case 'cta':
58
+ const ctaEl = hero.querySelector('.jux-hero-cta');
59
+ if (ctaEl)
60
+ ctaEl.textContent = value;
61
+ break;
62
+ case 'ctaLink':
63
+ const ctaLinkEl = hero.querySelector('.jux-hero-cta');
64
+ if (ctaLinkEl)
65
+ ctaLinkEl.href = value;
66
+ break;
67
+ case 'backgroundImage':
68
+ hero.style.backgroundImage = `url(${value.url})`;
69
+ hero.style.backgroundSize = value.size;
70
+ hero.style.backgroundRepeat = value.repeat;
71
+ break;
72
+ case 'centered':
73
+ if (value)
74
+ hero.classList.add('jux-hero-centered');
75
+ else
76
+ hero.classList.remove('jux-hero-centered');
77
+ break;
78
+ }
79
+ }
80
+ /* ═════════════════════════════════════════════════════════════════
81
+ * FLUENT API (Simplified - just updates state)
33
82
  * ═════════════════════════════════════════════════════════════════ */
34
83
  title(value) {
35
- this.state.title = value;
84
+ this.state.title = value; // Triggers update('title', value) via Proxy
36
85
  return this;
37
86
  }
38
87
  subtitle(value) {
@@ -136,41 +185,7 @@ export class Hero extends BaseComponent {
136
185
  }
137
186
  hero.appendChild(contentContainer);
138
187
  this._wireStandardEvents(hero);
139
- this._syncBindings.forEach(({ property, stateObj, toState, toComponent }) => {
140
- if (property === 'title') {
141
- const transform = toComponent || ((v) => String(v));
142
- stateObj.subscribe((val) => {
143
- const transformed = transform(val);
144
- const titleEl = document.getElementById(`${this._id}-title`);
145
- if (titleEl) {
146
- titleEl.textContent = transformed;
147
- }
148
- this.state.title = transformed;
149
- });
150
- }
151
- else if (property === 'subtitle') {
152
- const transform = toComponent || ((v) => String(v));
153
- stateObj.subscribe((val) => {
154
- const transformed = transform(val);
155
- const subtitleEl = document.getElementById(`${this._id}-subtitle`);
156
- if (subtitleEl) {
157
- subtitleEl.textContent = transformed;
158
- }
159
- this.state.subtitle = transformed;
160
- });
161
- }
162
- else if (property === 'content') {
163
- const transform = toComponent || ((v) => String(v));
164
- stateObj.subscribe((val) => {
165
- const transformed = transform(val);
166
- const contentEl = hero.querySelector('.jux-hero-body');
167
- if (contentEl) {
168
- contentEl.innerHTML = transformed;
169
- }
170
- this.state.content = transformed;
171
- });
172
- }
173
- });
188
+ this._wireAllSyncs(); // Use base method
174
189
  container.appendChild(hero);
175
190
  return this;
176
191
  }
@@ -178,13 +193,3 @@ export class Hero extends BaseComponent {
178
193
  export function hero(id, options = {}) {
179
194
  return new Hero(id, options);
180
195
  }
181
- // String format (backward compatible)
182
- hero('h1').backgroundImage('/hero.jpg');
183
- // Object format with defaults
184
- hero('h2').backgroundImage({ url: '/hero.jpg' });
185
- // Object format with custom values
186
- hero('h3').backgroundImage({
187
- url: '/pattern.png',
188
- size: 'contain',
189
- repeat: 'repeat'
190
- });
@@ -2,18 +2,18 @@ import { BaseComponent } from './base/BaseComponent.js';
2
2
 
3
3
  // Event definitions - Hero is display-only, but CTA button can trigger actions
4
4
  const TRIGGER_EVENTS = [] as const;
5
- const CALLBACK_EVENTS = ['ctaClick'] as const; // ✅ When CTA button is clicked
5
+ const CALLBACK_EVENTS = ['ctaClick'] as const;
6
6
 
7
7
  export interface HeroOptions {
8
8
  title?: string;
9
9
  subtitle?: string;
10
- content?: string; // ✅ ADD: Generates jux-hero-body div
11
- cta?: string; // ✅ KEEP: Generates jux-hero-cta anchor
10
+ content?: string;
11
+ cta?: string;
12
12
  ctaLink?: string;
13
13
  backgroundImage?: string | { url: string; size?: string; repeat?: string };
14
- backgroundOverlay?: boolean; // ✅ ADD: Generates jux-hero-overlay div
14
+ backgroundOverlay?: boolean;
15
15
  variant?: 'default' | 'centered' | 'split';
16
- centered?: boolean; // ✅ ADD: Affects container class
16
+ centered?: boolean;
17
17
  style?: string;
18
18
  class?: string;
19
19
  }
@@ -21,20 +21,19 @@ export interface HeroOptions {
21
21
  type HeroState = {
22
22
  title: string;
23
23
  subtitle: string;
24
- content: string; // ✅ ADD: For jux-hero-body
24
+ content: string;
25
25
  cta: string;
26
26
  ctaLink: string;
27
27
  backgroundImage: { url: string; size: string; repeat: string };
28
- backgroundOverlay: boolean; // ✅ ADD: For overlay div
28
+ backgroundOverlay: boolean;
29
29
  variant: string;
30
- centered: boolean; // ✅ ADD: For layout variant
30
+ centered: boolean;
31
31
  style: string;
32
32
  class: string;
33
33
  };
34
34
 
35
35
  export class Hero extends BaseComponent<HeroState> {
36
36
  constructor(id: string, options: HeroOptions = {}) {
37
- // Normalize backgroundImage to object format
38
37
  const bgImage = typeof options.backgroundImage === 'string'
39
38
  ? { url: options.backgroundImage, size: 'cover', repeat: 'no-repeat' }
40
39
  : options.backgroundImage || { url: '', size: 'cover', repeat: 'no-repeat' };
@@ -42,13 +41,13 @@ export class Hero extends BaseComponent<HeroState> {
42
41
  super(id, {
43
42
  title: options.title ?? '',
44
43
  subtitle: options.subtitle ?? '',
45
- content: options.content ?? '', // ✅ ADD
44
+ content: options.content ?? '',
46
45
  cta: options.cta ?? '',
47
46
  ctaLink: options.ctaLink ?? '#',
48
47
  backgroundImage: { url: bgImage.url, size: bgImage.size || 'cover', repeat: bgImage.repeat || 'no-repeat' },
49
- backgroundOverlay: options.backgroundOverlay ?? false, // ✅ ADD
48
+ backgroundOverlay: options.backgroundOverlay ?? false,
50
49
  variant: options.variant ?? 'default',
51
- centered: options.centered ?? false, // ✅ ADD
50
+ centered: options.centered ?? false,
52
51
  style: options.style ?? '',
53
52
  class: options.class ?? ''
54
53
  });
@@ -63,11 +62,62 @@ export class Hero extends BaseComponent<HeroState> {
63
62
  }
64
63
 
65
64
  /* ═════════════════════════════════════════════════════════════════
66
- * FLUENT API
65
+ * REACTIVE DOM UPDATES
66
+ * ═════════════════════════════════════════════════════════════════ */
67
+
68
+ /**
69
+ * Called automatically by BaseComponent when state changes.
70
+ * Centralizes DOM manipulation so setters don't have to drill/repeat logic.
71
+ */
72
+ protected update(prop: string, value: any): void {
73
+ const hero = document.getElementById(this._id);
74
+ if (!hero) return; // Component not mounted/rendered yet
75
+
76
+ switch (prop) {
77
+ case 'title':
78
+ const titleEl = document.getElementById(`${this._id}-title`);
79
+ if (titleEl) titleEl.textContent = value;
80
+ break;
81
+
82
+ case 'subtitle':
83
+ const subtitleEl = document.getElementById(`${this._id}-subtitle`);
84
+ if (subtitleEl) subtitleEl.textContent = value;
85
+ break;
86
+
87
+ case 'content':
88
+ const contentEl = hero.querySelector('.jux-hero-body');
89
+ if (contentEl) contentEl.innerHTML = value;
90
+ break;
91
+
92
+ case 'cta':
93
+ const ctaEl = hero.querySelector('.jux-hero-cta') as HTMLElement;
94
+ if (ctaEl) ctaEl.textContent = value;
95
+ break;
96
+
97
+ case 'ctaLink':
98
+ const ctaLinkEl = hero.querySelector('.jux-hero-cta') as HTMLAnchorElement;
99
+ if (ctaLinkEl) ctaLinkEl.href = value;
100
+ break;
101
+
102
+ case 'backgroundImage':
103
+ hero.style.backgroundImage = `url(${value.url})`;
104
+ hero.style.backgroundSize = value.size;
105
+ hero.style.backgroundRepeat = value.repeat;
106
+ break;
107
+
108
+ case 'centered':
109
+ if (value) hero.classList.add('jux-hero-centered');
110
+ else hero.classList.remove('jux-hero-centered');
111
+ break;
112
+ }
113
+ }
114
+
115
+ /* ═════════════════════════════════════════════════════════════════
116
+ * FLUENT API (Simplified - just updates state)
67
117
  * ═════════════════════════════════════════════════════════════════ */
68
118
 
69
119
  title(value: string): this {
70
- this.state.title = value;
120
+ this.state.title = value; // Triggers update('title', value) via Proxy
71
121
  return this;
72
122
  }
73
123
 
@@ -76,7 +126,7 @@ export class Hero extends BaseComponent<HeroState> {
76
126
  return this;
77
127
  }
78
128
 
79
- content(value: string): this { // ✅ ADD: Fluent method for content
129
+ content(value: string): this {
80
130
  this.state.content = value;
81
131
  return this;
82
132
  }
@@ -104,7 +154,7 @@ export class Hero extends BaseComponent<HeroState> {
104
154
  return this;
105
155
  }
106
156
 
107
- backgroundOverlay(value: boolean): this { // ✅ ADD: Fluent method for overlay
157
+ backgroundOverlay(value: boolean): this {
108
158
  this.state.backgroundOverlay = value;
109
159
  return this;
110
160
  }
@@ -114,7 +164,7 @@ export class Hero extends BaseComponent<HeroState> {
114
164
  return this;
115
165
  }
116
166
 
117
- centered(value: boolean): this { // ✅ ADD: Fluent method for centered
167
+ centered(value: boolean): this {
118
168
  this.state.centered = value;
119
169
  return this;
120
170
  }
@@ -189,45 +239,7 @@ export class Hero extends BaseComponent<HeroState> {
189
239
  hero.appendChild(contentContainer);
190
240
 
191
241
  this._wireStandardEvents(hero);
192
-
193
- this._syncBindings.forEach(({ property, stateObj, toState, toComponent }) => {
194
- if (property === 'title') {
195
- const transform = toComponent || ((v: any) => String(v));
196
-
197
- stateObj.subscribe((val: any) => {
198
- const transformed = transform(val);
199
- const titleEl = document.getElementById(`${this._id}-title`);
200
- if (titleEl) {
201
- titleEl.textContent = transformed;
202
- }
203
- this.state.title = transformed;
204
- });
205
- }
206
- else if (property === 'subtitle') {
207
- const transform = toComponent || ((v: any) => String(v));
208
-
209
- stateObj.subscribe((val: any) => {
210
- const transformed = transform(val);
211
- const subtitleEl = document.getElementById(`${this._id}-subtitle`);
212
- if (subtitleEl) {
213
- subtitleEl.textContent = transformed;
214
- }
215
- this.state.subtitle = transformed;
216
- });
217
- }
218
- else if (property === 'content') {
219
- const transform = toComponent || ((v: any) => String(v));
220
-
221
- stateObj.subscribe((val: any) => {
222
- const transformed = transform(val);
223
- const contentEl = hero.querySelector('.jux-hero-body');
224
- if (contentEl) {
225
- contentEl.innerHTML = transformed;
226
- }
227
- this.state.content = transformed;
228
- });
229
- }
230
- });
242
+ this._wireAllSyncs(); // Use base method
231
243
 
232
244
  container.appendChild(hero);
233
245
  return this;
@@ -238,15 +250,3 @@ export function hero(id: string, options: HeroOptions = {}): Hero {
238
250
  return new Hero(id, options);
239
251
  }
240
252
 
241
- // String format (backward compatible)
242
- hero('h1').backgroundImage('/hero.jpg')
243
-
244
- // Object format with defaults
245
- hero('h2').backgroundImage({ url: '/hero.jpg' })
246
-
247
- // Object format with custom values
248
- hero('h3').backgroundImage({
249
- url: '/pattern.png',
250
- size: 'contain',
251
- repeat: 'repeat'
252
- })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "juxscript",
3
- "version": "1.1.11",
3
+ "version": "1.1.13",
4
4
  "type": "module",
5
5
  "description": "A JavaScript UX authorship platform",
6
6
  "main": "index.js",