juxscript 1.0.20 → 1.0.21
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/bin/cli.js +121 -72
- package/lib/components/alert.ts +143 -92
- package/lib/components/badge.ts +93 -94
- package/lib/components/base/BaseComponent.ts +397 -0
- package/lib/components/base/FormInput.ts +322 -0
- package/lib/components/button.ts +40 -131
- package/lib/components/card.ts +57 -79
- package/lib/components/charts/areachart.ts +315 -0
- package/lib/components/charts/barchart.ts +421 -0
- package/lib/components/charts/doughnutchart.ts +263 -0
- package/lib/components/charts/lib/BaseChart.ts +402 -0
- package/lib/components/{chart-types.ts → charts/lib/chart-types.ts} +1 -1
- package/lib/components/{chart-utils.ts → charts/lib/chart-utils.ts} +1 -1
- package/lib/components/{chart.ts → charts/lib/chart.ts} +3 -3
- package/lib/components/checkbox.ts +255 -204
- package/lib/components/code.ts +31 -78
- package/lib/components/container.ts +113 -130
- package/lib/components/data.ts +37 -5
- package/lib/components/datepicker.ts +180 -147
- package/lib/components/dialog.ts +218 -221
- package/lib/components/divider.ts +63 -87
- package/lib/components/docs-data.json +498 -2404
- package/lib/components/dropdown.ts +191 -236
- package/lib/components/element.ts +196 -145
- package/lib/components/fileupload.ts +253 -167
- package/lib/components/guard.ts +92 -0
- package/lib/components/heading.ts +31 -97
- package/lib/components/helpers.ts +13 -6
- package/lib/components/hero.ts +51 -114
- package/lib/components/icon.ts +33 -120
- package/lib/components/icons.ts +2 -1
- package/lib/components/include.ts +76 -3
- package/lib/components/input.ts +155 -407
- package/lib/components/kpicard.ts +16 -16
- package/lib/components/list.ts +358 -261
- package/lib/components/loading.ts +142 -211
- package/lib/components/menu.ts +63 -152
- package/lib/components/modal.ts +42 -129
- package/lib/components/nav.ts +79 -101
- package/lib/components/paragraph.ts +38 -102
- package/lib/components/progress.ts +108 -166
- package/lib/components/radio.ts +283 -234
- package/lib/components/script.ts +19 -87
- package/lib/components/select.ts +189 -199
- package/lib/components/sidebar.ts +110 -141
- package/lib/components/style.ts +19 -82
- package/lib/components/switch.ts +254 -183
- package/lib/components/table.ts +1078 -208
- package/lib/components/tabs.ts +42 -106
- package/lib/components/theme-toggle.ts +73 -165
- package/lib/components/tooltip.ts +85 -316
- package/lib/components/write.ts +108 -127
- package/lib/jux.ts +67 -41
- package/machinery/build.js +466 -0
- package/machinery/compiler.js +354 -105
- package/machinery/server.js +23 -100
- package/machinery/watcher.js +153 -130
- package/package.json +1 -1
- package/presets/base.css +1166 -0
- package/presets/notion.css +2 -1975
- package/lib/adapters/base-adapter.js +0 -35
- package/lib/adapters/index.js +0 -33
- package/lib/adapters/mysql-adapter.js +0 -65
- package/lib/adapters/postgres-adapter.js +0 -70
- package/lib/adapters/sqlite-adapter.js +0 -56
- package/lib/components/areachart.ts +0 -1128
- package/lib/components/areachartsmooth.ts +0 -1380
- package/lib/components/barchart.ts +0 -1322
- package/lib/components/doughnutchart.ts +0 -1259
- package/lib/components/footer.ts +0 -165
- package/lib/components/header.ts +0 -187
- package/lib/components/layout.ts +0 -239
- package/lib/components/main.ts +0 -137
- package/lib/layouts/default.jux +0 -8
- package/lib/layouts/figma.jux +0 -0
- /package/lib/{themes → components/charts/lib}/charts.js +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { BaseComponent } from './base/BaseComponent.js';
|
|
2
|
+
|
|
3
|
+
// Event definitions
|
|
4
|
+
const TRIGGER_EVENTS = [] as const;
|
|
5
|
+
const CALLBACK_EVENTS = [] as const; // Headings are display-only, no events
|
|
3
6
|
|
|
4
|
-
/**
|
|
5
|
-
* Heading options
|
|
6
|
-
*/
|
|
7
7
|
export interface HeadingOptions {
|
|
8
8
|
level?: 1 | 2 | 3 | 4 | 5 | 6;
|
|
9
9
|
text?: string;
|
|
@@ -11,9 +11,6 @@ export interface HeadingOptions {
|
|
|
11
11
|
style?: string;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
/**
|
|
15
|
-
* Heading state
|
|
16
|
-
*/
|
|
17
14
|
type HeadingState = {
|
|
18
15
|
level: 1 | 2 | 3 | 4 | 5 | 6;
|
|
19
16
|
text: string;
|
|
@@ -21,99 +18,52 @@ type HeadingState = {
|
|
|
21
18
|
style: string;
|
|
22
19
|
};
|
|
23
20
|
|
|
24
|
-
|
|
25
|
-
* Heading component - semantic heading elements (h1-h6)
|
|
26
|
-
*
|
|
27
|
-
* Usage:
|
|
28
|
-
* jux.heading('title', { level: 1, text: 'Welcome' }).render('#app');
|
|
29
|
-
* jux.heading('subtitle').level(2).text('Getting Started').render('#app');
|
|
30
|
-
*/
|
|
31
|
-
export class Heading {
|
|
32
|
-
state: HeadingState;
|
|
33
|
-
container: HTMLElement | null = null;
|
|
34
|
-
_id: string;
|
|
35
|
-
id: string;
|
|
36
|
-
|
|
37
|
-
// CRITICAL: Store bind/sync instructions for deferred wiring
|
|
38
|
-
private _bindings: Array<{ event: string, handler: Function }> = [];
|
|
39
|
-
private _syncBindings: Array<{
|
|
40
|
-
property: string,
|
|
41
|
-
stateObj: State<any>,
|
|
42
|
-
toState?: Function,
|
|
43
|
-
toComponent?: Function
|
|
44
|
-
}> = [];
|
|
45
|
-
|
|
21
|
+
export class Heading extends BaseComponent<HeadingState> {
|
|
46
22
|
constructor(id: string, options: HeadingOptions = {}) {
|
|
47
|
-
|
|
48
|
-
this.id = id;
|
|
49
|
-
|
|
50
|
-
this.state = {
|
|
23
|
+
super(id, {
|
|
51
24
|
level: options.level ?? 1,
|
|
52
25
|
text: options.text ?? '',
|
|
53
26
|
class: options.class ?? '',
|
|
54
27
|
style: options.style ?? ''
|
|
55
|
-
};
|
|
28
|
+
});
|
|
56
29
|
}
|
|
57
30
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
* ------------------------- */
|
|
61
|
-
|
|
62
|
-
level(value: 1 | 2 | 3 | 4 | 5 | 6): this {
|
|
63
|
-
this.state.level = value;
|
|
64
|
-
return this;
|
|
31
|
+
protected getTriggerEvents(): readonly string[] {
|
|
32
|
+
return TRIGGER_EVENTS;
|
|
65
33
|
}
|
|
66
34
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
return this;
|
|
35
|
+
protected getCallbackEvents(): readonly string[] {
|
|
36
|
+
return CALLBACK_EVENTS;
|
|
70
37
|
}
|
|
71
38
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
39
|
+
/* ═════════════════════════════════════════════════════════════════
|
|
40
|
+
* FLUENT API
|
|
41
|
+
* ═════════════════════════════════════════════════════════════════ */
|
|
76
42
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
43
|
+
// ✅ Inherited from BaseComponent:
|
|
44
|
+
// - style(), class()
|
|
45
|
+
// - bind(), sync(), renderTo()
|
|
46
|
+
// - All other base methods
|
|
81
47
|
|
|
82
|
-
|
|
83
|
-
this.
|
|
48
|
+
level(value: 1 | 2 | 3 | 4 | 5 | 6): this {
|
|
49
|
+
this.state.level = value;
|
|
84
50
|
return this;
|
|
85
51
|
}
|
|
86
52
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
throw new Error(`Heading.sync: Expected a State object for property "${property}"`);
|
|
90
|
-
}
|
|
91
|
-
this._syncBindings.push({ property, stateObj, toState, toComponent });
|
|
53
|
+
text(value: string): this {
|
|
54
|
+
this.state.text = value;
|
|
92
55
|
return this;
|
|
93
56
|
}
|
|
94
57
|
|
|
95
|
-
/*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
58
|
+
/* ═════════════════════════════════════════════════════════════════
|
|
59
|
+
* RENDER
|
|
60
|
+
* ═════════════════════════════════════════════════════════════════ */
|
|
98
61
|
|
|
99
62
|
render(targetId?: string): this {
|
|
100
|
-
|
|
101
|
-
let container: HTMLElement;
|
|
102
|
-
if (targetId) {
|
|
103
|
-
const target = document.querySelector(targetId);
|
|
104
|
-
if (!target || !(target instanceof HTMLElement)) {
|
|
105
|
-
throw new Error(`Heading: Target "${targetId}" not found`);
|
|
106
|
-
}
|
|
107
|
-
container = target;
|
|
108
|
-
} else {
|
|
109
|
-
container = getOrCreateContainer(this._id);
|
|
110
|
-
}
|
|
111
|
-
this.container = container;
|
|
63
|
+
const container = this._setupContainer(targetId);
|
|
112
64
|
|
|
113
|
-
// === 2. PREPARE: Destructure state ===
|
|
114
65
|
const { text, level, style, class: className } = this.state;
|
|
115
66
|
|
|
116
|
-
// === 3. BUILD: Create DOM elements ===
|
|
117
67
|
const heading = document.createElement(`h${level}`) as HTMLHeadingElement;
|
|
118
68
|
heading.className = `jux-heading jux-heading-${level}`;
|
|
119
69
|
heading.id = this._id;
|
|
@@ -121,42 +71,26 @@ export class Heading {
|
|
|
121
71
|
if (className) heading.className += ` ${className}`;
|
|
122
72
|
if (style) heading.setAttribute('style', style);
|
|
123
73
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
// Wire custom bindings from .bind() calls
|
|
127
|
-
this._bindings.forEach(({ event, handler }) => {
|
|
128
|
-
heading.addEventListener(event, handler as EventListener);
|
|
129
|
-
});
|
|
74
|
+
this._wireStandardEvents(heading);
|
|
130
75
|
|
|
131
|
-
// Wire sync bindings
|
|
76
|
+
// Wire sync bindings
|
|
132
77
|
this._syncBindings.forEach(({ property, stateObj, toState, toComponent }) => {
|
|
133
78
|
if (property === 'text') {
|
|
134
|
-
const
|
|
79
|
+
const transform = toComponent || ((v: any) => String(v));
|
|
135
80
|
|
|
136
81
|
stateObj.subscribe((val: any) => {
|
|
137
|
-
const transformed =
|
|
82
|
+
const transformed = transform(val);
|
|
138
83
|
heading.textContent = transformed;
|
|
139
84
|
this.state.text = transformed;
|
|
140
85
|
});
|
|
141
86
|
}
|
|
142
87
|
});
|
|
143
88
|
|
|
144
|
-
// === 5. RENDER: Append to DOM and finalize ===
|
|
145
89
|
container.appendChild(heading);
|
|
146
90
|
return this;
|
|
147
91
|
}
|
|
148
|
-
|
|
149
|
-
renderTo(juxComponent: any): this {
|
|
150
|
-
if (!juxComponent?._id) {
|
|
151
|
-
throw new Error('Heading.renderTo: Invalid component');
|
|
152
|
-
}
|
|
153
|
-
return this.render(`#${juxComponent._id}`);
|
|
154
|
-
}
|
|
155
92
|
}
|
|
156
93
|
|
|
157
|
-
/**
|
|
158
|
-
* Factory helper
|
|
159
|
-
*/
|
|
160
94
|
export function heading(id: string, options: HeadingOptions = {}): Heading {
|
|
161
95
|
return new Heading(id, options);
|
|
162
96
|
}
|
|
@@ -22,12 +22,19 @@ export function getOrCreateContainer(id: string): HTMLElement {
|
|
|
22
22
|
container = document.createElement('div');
|
|
23
23
|
container.id = id;
|
|
24
24
|
|
|
25
|
-
// Find appropriate parent
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const
|
|
30
|
-
|
|
25
|
+
// Find appropriate parent - [data-jux-page] takes precedence, then #app, then body
|
|
26
|
+
const dataJuxPage = document.querySelector('[data-jux-page]') as HTMLElement;
|
|
27
|
+
const app = document.getElementById('app');
|
|
28
|
+
|
|
29
|
+
const parent: HTMLElement = (dataJuxPage || app || document.body) as HTMLElement;
|
|
30
|
+
|
|
31
|
+
// Log warning if falling back to body
|
|
32
|
+
if (!dataJuxPage && !app) {
|
|
33
|
+
console.warn(
|
|
34
|
+
`[Jux] Preferred container targets "[data-jux-page]" or "#app" not found. Creating container "#${id}" in fallback parent: body`,
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
31
38
|
parent.appendChild(container);
|
|
32
39
|
|
|
33
40
|
return container;
|
package/lib/components/hero.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { BaseComponent } from './base/BaseComponent.js';
|
|
2
|
+
|
|
3
|
+
// Event definitions - Hero is display-only, but CTA button can trigger actions
|
|
4
|
+
const TRIGGER_EVENTS = [] as const;
|
|
5
|
+
const CALLBACK_EVENTS = ['ctaClick'] as const; // ✅ When CTA button is clicked
|
|
3
6
|
|
|
4
|
-
/**
|
|
5
|
-
* Hero component options
|
|
6
|
-
*/
|
|
7
7
|
export interface HeroOptions {
|
|
8
8
|
title?: string;
|
|
9
9
|
subtitle?: string;
|
|
@@ -15,9 +15,6 @@ export interface HeroOptions {
|
|
|
15
15
|
class?: string;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
/**
|
|
19
|
-
* Hero component state
|
|
20
|
-
*/
|
|
21
18
|
type HeroState = {
|
|
22
19
|
title: string;
|
|
23
20
|
subtitle: string;
|
|
@@ -25,61 +22,43 @@ type HeroState = {
|
|
|
25
22
|
ctaLink: string;
|
|
26
23
|
backgroundImage: string;
|
|
27
24
|
variant: string;
|
|
28
|
-
style: string;
|
|
29
|
-
class: string;
|
|
30
25
|
content: string;
|
|
31
26
|
backgroundOverlay: boolean;
|
|
32
27
|
centered: boolean;
|
|
28
|
+
style: string;
|
|
29
|
+
class: string;
|
|
33
30
|
};
|
|
34
31
|
|
|
35
|
-
|
|
36
|
-
* Hero component
|
|
37
|
-
*
|
|
38
|
-
* Usage:
|
|
39
|
-
* const hero = jux.hero('myHero', {
|
|
40
|
-
* title: 'Welcome',
|
|
41
|
-
* subtitle: 'Get started today',
|
|
42
|
-
* cta: 'Learn More'
|
|
43
|
-
* });
|
|
44
|
-
* hero.render();
|
|
45
|
-
*/
|
|
46
|
-
export class Hero {
|
|
47
|
-
state: HeroState;
|
|
48
|
-
container: HTMLElement | null = null;
|
|
49
|
-
_id: string;
|
|
50
|
-
id: string;
|
|
51
|
-
|
|
52
|
-
// CRITICAL: Store bind/sync instructions for deferred wiring
|
|
53
|
-
private _bindings: Array<{ event: string, handler: Function }> = [];
|
|
54
|
-
private _syncBindings: Array<{
|
|
55
|
-
property: string,
|
|
56
|
-
stateObj: State<any>,
|
|
57
|
-
toState?: Function,
|
|
58
|
-
toComponent?: Function
|
|
59
|
-
}> = [];
|
|
60
|
-
|
|
32
|
+
export class Hero extends BaseComponent<HeroState> {
|
|
61
33
|
constructor(id: string, options: HeroOptions = {}) {
|
|
62
|
-
|
|
63
|
-
this.id = id;
|
|
64
|
-
|
|
65
|
-
this.state = {
|
|
34
|
+
super(id, {
|
|
66
35
|
title: options.title ?? '',
|
|
67
36
|
subtitle: options.subtitle ?? '',
|
|
68
37
|
cta: options.cta ?? '',
|
|
69
38
|
ctaLink: options.ctaLink ?? '#',
|
|
70
39
|
backgroundImage: options.backgroundImage ?? '',
|
|
71
40
|
variant: options.variant ?? 'default',
|
|
72
|
-
style: options.style ?? '',
|
|
73
|
-
class: options.class ?? '',
|
|
74
41
|
content: '',
|
|
75
42
|
backgroundOverlay: false,
|
|
76
|
-
centered: false
|
|
77
|
-
|
|
43
|
+
centered: false,
|
|
44
|
+
style: options.style ?? '',
|
|
45
|
+
class: options.class ?? ''
|
|
46
|
+
});
|
|
78
47
|
}
|
|
79
48
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
49
|
+
protected getTriggerEvents(): readonly string[] {
|
|
50
|
+
return TRIGGER_EVENTS;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
protected getCallbackEvents(): readonly string[] {
|
|
54
|
+
return CALLBACK_EVENTS;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/* ═════════════════════════════════════════════════════════════════
|
|
58
|
+
* FLUENT API
|
|
59
|
+
* ═════════════════════════════════════════════════════════════════ */
|
|
60
|
+
|
|
61
|
+
// ✅ Inherited from BaseComponent
|
|
83
62
|
|
|
84
63
|
title(value: string): this {
|
|
85
64
|
this.state.title = value;
|
|
@@ -111,51 +90,15 @@ export class Hero {
|
|
|
111
90
|
return this;
|
|
112
91
|
}
|
|
113
92
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
class(value: string): this {
|
|
120
|
-
this.state.class = value;
|
|
121
|
-
return this;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
bind(event: string, handler: Function): this {
|
|
125
|
-
this._bindings.push({ event, handler });
|
|
126
|
-
return this;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
sync(property: string, stateObj: State<any>, toState?: Function, toComponent?: Function): this {
|
|
130
|
-
if (!stateObj || typeof stateObj.subscribe !== 'function') {
|
|
131
|
-
throw new Error(`Hero.sync: Expected a State object for property "${property}"`);
|
|
132
|
-
}
|
|
133
|
-
this._syncBindings.push({ property, stateObj, toState, toComponent });
|
|
134
|
-
return this;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/* -------------------------
|
|
138
|
-
* Render
|
|
139
|
-
* ------------------------- */
|
|
93
|
+
/* ═════════════════════════════════════════════════════════════════
|
|
94
|
+
* RENDER
|
|
95
|
+
* ═════════════════════════════════════════════════════════════════ */
|
|
140
96
|
|
|
141
97
|
render(targetId?: string): this {
|
|
142
|
-
|
|
143
|
-
let container: HTMLElement;
|
|
144
|
-
if (targetId) {
|
|
145
|
-
const target = document.querySelector(targetId);
|
|
146
|
-
if (!target || !(target instanceof HTMLElement)) {
|
|
147
|
-
throw new Error(`Hero: Target "${targetId}" not found`);
|
|
148
|
-
}
|
|
149
|
-
container = target;
|
|
150
|
-
} else {
|
|
151
|
-
container = getOrCreateContainer(this._id);
|
|
152
|
-
}
|
|
153
|
-
this.container = container;
|
|
98
|
+
const container = this._setupContainer(targetId);
|
|
154
99
|
|
|
155
|
-
// === 2. PREPARE: Destructure state ===
|
|
156
100
|
const { title, subtitle, content, backgroundImage, backgroundOverlay, centered, style, class: className } = this.state;
|
|
157
101
|
|
|
158
|
-
// === 3. BUILD: Create DOM elements ===
|
|
159
102
|
const hero = document.createElement('section');
|
|
160
103
|
hero.className = 'jux-hero';
|
|
161
104
|
hero.id = this._id;
|
|
@@ -198,22 +141,30 @@ export class Hero {
|
|
|
198
141
|
contentContainer.appendChild(contentEl);
|
|
199
142
|
}
|
|
200
143
|
|
|
201
|
-
|
|
144
|
+
if (this.state.cta) {
|
|
145
|
+
const ctaButton = document.createElement('a');
|
|
146
|
+
ctaButton.className = 'jux-hero-cta';
|
|
147
|
+
ctaButton.href = this.state.ctaLink;
|
|
148
|
+
ctaButton.textContent = this.state.cta;
|
|
202
149
|
|
|
203
|
-
|
|
150
|
+
// ✅ Fire callback when CTA is clicked
|
|
151
|
+
ctaButton.addEventListener('click', (e) => {
|
|
152
|
+
this._triggerCallback('ctaClick', e);
|
|
153
|
+
});
|
|
204
154
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
155
|
+
contentContainer.appendChild(ctaButton);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
hero.appendChild(contentContainer);
|
|
159
|
+
|
|
160
|
+
this._wireStandardEvents(hero);
|
|
209
161
|
|
|
210
|
-
// Wire sync bindings from .sync() calls
|
|
211
162
|
this._syncBindings.forEach(({ property, stateObj, toState, toComponent }) => {
|
|
212
163
|
if (property === 'title') {
|
|
213
|
-
const
|
|
164
|
+
const transform = toComponent || ((v: any) => String(v));
|
|
214
165
|
|
|
215
166
|
stateObj.subscribe((val: any) => {
|
|
216
|
-
const transformed =
|
|
167
|
+
const transformed = transform(val);
|
|
217
168
|
const titleEl = document.getElementById(`${this._id}-title`);
|
|
218
169
|
if (titleEl) {
|
|
219
170
|
titleEl.textContent = transformed;
|
|
@@ -222,10 +173,10 @@ export class Hero {
|
|
|
222
173
|
});
|
|
223
174
|
}
|
|
224
175
|
else if (property === 'subtitle') {
|
|
225
|
-
const
|
|
176
|
+
const transform = toComponent || ((v: any) => String(v));
|
|
226
177
|
|
|
227
178
|
stateObj.subscribe((val: any) => {
|
|
228
|
-
const transformed =
|
|
179
|
+
const transformed = transform(val);
|
|
229
180
|
const subtitleEl = document.getElementById(`${this._id}-subtitle`);
|
|
230
181
|
if (subtitleEl) {
|
|
231
182
|
subtitleEl.textContent = transformed;
|
|
@@ -234,10 +185,10 @@ export class Hero {
|
|
|
234
185
|
});
|
|
235
186
|
}
|
|
236
187
|
else if (property === 'content') {
|
|
237
|
-
const
|
|
188
|
+
const transform = toComponent || ((v: any) => String(v));
|
|
238
189
|
|
|
239
190
|
stateObj.subscribe((val: any) => {
|
|
240
|
-
const transformed =
|
|
191
|
+
const transformed = transform(val);
|
|
241
192
|
const contentEl = hero.querySelector('.jux-hero-body');
|
|
242
193
|
if (contentEl) {
|
|
243
194
|
contentEl.innerHTML = transformed;
|
|
@@ -247,25 +198,11 @@ export class Hero {
|
|
|
247
198
|
}
|
|
248
199
|
});
|
|
249
200
|
|
|
250
|
-
// === 5. RENDER: Append to DOM and finalize ===
|
|
251
201
|
container.appendChild(hero);
|
|
252
202
|
return this;
|
|
253
203
|
}
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* Render to another Jux component's container
|
|
257
|
-
*/
|
|
258
|
-
renderTo(juxComponent: any): this {
|
|
259
|
-
if (!juxComponent?._id) {
|
|
260
|
-
throw new Error('Hero.renderTo: Invalid component');
|
|
261
|
-
}
|
|
262
|
-
return this.render(`#${juxComponent._id}`);
|
|
263
|
-
}
|
|
264
204
|
}
|
|
265
205
|
|
|
266
|
-
/**
|
|
267
|
-
* Factory helper
|
|
268
|
-
*/
|
|
269
206
|
export function hero(id: string, options: HeroOptions = {}): Hero {
|
|
270
207
|
return new Hero(id, options);
|
|
271
208
|
}
|