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.
- package/lib/components/base/BaseComponent.d.ts +6 -9
- package/lib/components/base/BaseComponent.d.ts.map +1 -1
- package/lib/components/base/BaseComponent.js +21 -11
- package/lib/components/base/BaseComponent.ts +23 -11
- package/lib/components/chart.d.ts +4 -1
- package/lib/components/chart.d.ts.map +1 -1
- package/lib/components/chart.js +18 -2
- package/lib/components/chart.ts +21 -2
- package/lib/components/hero.d.ts +5 -0
- package/lib/components/hero.d.ts.map +1 -1
- package/lib/components/hero.js +57 -52
- package/lib/components/hero.ts +68 -68
- package/package.json +1 -1
|
@@ -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":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAGlD;;;;;;;;GAQG;AACH,8BAAsB,aAAa,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAElE,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;gBAEnD,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM;
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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"}
|
package/lib/components/chart.js
CHANGED
|
@@ -117,10 +117,12 @@ export class ChartComponent extends BaseComponent {
|
|
|
117
117
|
/* ═════════════════════════════════════════════════════════════════
|
|
118
118
|
* CHART OPERATIONS
|
|
119
119
|
* ═════════════════════════════════════════════════════════════════ */
|
|
120
|
-
|
|
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();
|
package/lib/components/chart.ts
CHANGED
|
@@ -152,10 +152,12 @@ export class ChartComponent extends BaseComponent<ChartState> {
|
|
|
152
152
|
* CHART OPERATIONS
|
|
153
153
|
* ═════════════════════════════════════════════════════════════════ */
|
|
154
154
|
|
|
155
|
-
|
|
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();
|
package/lib/components/hero.d.ts
CHANGED
|
@@ -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;
|
|
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"}
|
package/lib/components/hero.js
CHANGED
|
@@ -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'];
|
|
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 ?? '',
|
|
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,
|
|
17
|
+
backgroundOverlay: options.backgroundOverlay ?? false,
|
|
19
18
|
variant: options.variant ?? 'default',
|
|
20
|
-
centered: options.centered ?? false,
|
|
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
|
-
*
|
|
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.
|
|
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
|
-
});
|
package/lib/components/hero.ts
CHANGED
|
@@ -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;
|
|
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;
|
|
11
|
-
cta?: string;
|
|
10
|
+
content?: string;
|
|
11
|
+
cta?: string;
|
|
12
12
|
ctaLink?: string;
|
|
13
13
|
backgroundImage?: string | { url: string; size?: string; repeat?: string };
|
|
14
|
-
backgroundOverlay?: boolean;
|
|
14
|
+
backgroundOverlay?: boolean;
|
|
15
15
|
variant?: 'default' | 'centered' | 'split';
|
|
16
|
-
centered?: boolean;
|
|
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;
|
|
24
|
+
content: string;
|
|
25
25
|
cta: string;
|
|
26
26
|
ctaLink: string;
|
|
27
27
|
backgroundImage: { url: string; size: string; repeat: string };
|
|
28
|
-
backgroundOverlay: boolean;
|
|
28
|
+
backgroundOverlay: boolean;
|
|
29
29
|
variant: string;
|
|
30
|
-
centered: boolean;
|
|
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 ?? '',
|
|
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,
|
|
48
|
+
backgroundOverlay: options.backgroundOverlay ?? false,
|
|
50
49
|
variant: options.variant ?? 'default',
|
|
51
|
-
centered: options.centered ?? false,
|
|
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
|
-
*
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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
|
-
})
|