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
package/lib/components/nav.ts
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { State } from '../reactivity/state.js';
|
|
1
|
+
import { BaseComponent } from './base/BaseComponent.js';
|
|
3
2
|
import { renderIcon } from './icons.js';
|
|
4
3
|
import { req } from './req.js';
|
|
5
4
|
|
|
5
|
+
// Event definitions
|
|
6
|
+
const TRIGGER_EVENTS = [] as const;
|
|
7
|
+
const CALLBACK_EVENTS = [] as const;
|
|
8
|
+
|
|
6
9
|
export interface NavItem {
|
|
7
10
|
label: string;
|
|
8
11
|
href: string;
|
|
9
12
|
active?: boolean;
|
|
13
|
+
itemClass?: string;
|
|
10
14
|
}
|
|
11
15
|
|
|
12
16
|
export interface NavBrand {
|
|
@@ -33,41 +37,30 @@ type NavState = {
|
|
|
33
37
|
class: string;
|
|
34
38
|
};
|
|
35
39
|
|
|
36
|
-
export class Nav {
|
|
37
|
-
|
|
38
|
-
container: HTMLElement | null = null;
|
|
39
|
-
_id: string;
|
|
40
|
-
id: string;
|
|
41
|
-
|
|
42
|
-
// CRITICAL: Store bind/sync instructions for deferred wiring
|
|
43
|
-
private _bindings: Array<{ event: string, handler: Function }> = [];
|
|
44
|
-
private _syncBindings: Array<{
|
|
45
|
-
property: string,
|
|
46
|
-
stateObj: State<any>,
|
|
47
|
-
toState?: Function,
|
|
48
|
-
toComponent?: Function
|
|
49
|
-
}> = [];
|
|
40
|
+
export class Nav extends BaseComponent<NavState> {
|
|
41
|
+
private _nav: HTMLElement | null = null;
|
|
50
42
|
|
|
51
43
|
constructor(id: string, options: NavOptions = {}) {
|
|
52
|
-
|
|
53
|
-
this.id = id;
|
|
54
|
-
|
|
55
|
-
this.state = {
|
|
44
|
+
super(id, {
|
|
56
45
|
items: options.items ?? [],
|
|
57
46
|
brand: options.brand,
|
|
58
47
|
variant: options.variant ?? 'default',
|
|
59
48
|
sticky: options.sticky ?? false,
|
|
60
49
|
style: options.style ?? '',
|
|
61
50
|
class: options.class ?? ''
|
|
62
|
-
};
|
|
51
|
+
});
|
|
63
52
|
|
|
64
|
-
// Auto-set active state based on current path
|
|
65
53
|
this._setActiveStates();
|
|
66
54
|
}
|
|
67
55
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
56
|
+
protected getTriggerEvents(): readonly string[] {
|
|
57
|
+
return TRIGGER_EVENTS;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
protected getCallbackEvents(): readonly string[] {
|
|
61
|
+
return CALLBACK_EVENTS;
|
|
62
|
+
}
|
|
63
|
+
|
|
71
64
|
private _setActiveStates(): void {
|
|
72
65
|
this.state.items = this.state.items.map(item => ({
|
|
73
66
|
...item,
|
|
@@ -75,9 +68,11 @@ export class Nav {
|
|
|
75
68
|
}));
|
|
76
69
|
}
|
|
77
70
|
|
|
78
|
-
/*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
71
|
+
/* ═════════════════════════════════════════════════════════════════
|
|
72
|
+
* FLUENT API
|
|
73
|
+
* ═════════════════════════════════════════════════════════════════ */
|
|
74
|
+
|
|
75
|
+
// ✅ Inherited from BaseComponent
|
|
81
76
|
|
|
82
77
|
items(value: NavItem[]): this {
|
|
83
78
|
this.state.items = value;
|
|
@@ -91,6 +86,14 @@ export class Nav {
|
|
|
91
86
|
return this;
|
|
92
87
|
}
|
|
93
88
|
|
|
89
|
+
itemClass(className: string): this {
|
|
90
|
+
this.state.items = this.state.items.map(item => ({
|
|
91
|
+
...item,
|
|
92
|
+
itemClass: className
|
|
93
|
+
}));
|
|
94
|
+
return this;
|
|
95
|
+
}
|
|
96
|
+
|
|
94
97
|
brand(value: NavBrand): this {
|
|
95
98
|
this.state.brand = value;
|
|
96
99
|
return this;
|
|
@@ -106,51 +109,15 @@ export class Nav {
|
|
|
106
109
|
return this;
|
|
107
110
|
}
|
|
108
111
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
class(value: string): this {
|
|
115
|
-
this.state.class = value;
|
|
116
|
-
return this;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
bind(event: string, handler: Function): this {
|
|
120
|
-
this._bindings.push({ event, handler });
|
|
121
|
-
return this;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
sync(property: string, stateObj: State<any>, toState?: Function, toComponent?: Function): this {
|
|
125
|
-
if (!stateObj || typeof stateObj.subscribe !== 'function') {
|
|
126
|
-
throw new Error(`Nav.sync: Expected a State object for property "${property}"`);
|
|
127
|
-
}
|
|
128
|
-
this._syncBindings.push({ property, stateObj, toState, toComponent });
|
|
129
|
-
return this;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/* -------------------------
|
|
133
|
-
* Render (5-Step Pattern)
|
|
134
|
-
* ------------------------- */
|
|
112
|
+
/* ═════════════════════════════════════════════════════════════════
|
|
113
|
+
* RENDER
|
|
114
|
+
* ═════════════════════════════════════════════════════════════════ */
|
|
135
115
|
|
|
136
116
|
render(targetId?: string): this {
|
|
137
|
-
|
|
138
|
-
let container: HTMLElement;
|
|
139
|
-
if (targetId) {
|
|
140
|
-
const target = document.querySelector(targetId);
|
|
141
|
-
if (!target || !(target instanceof HTMLElement)) {
|
|
142
|
-
throw new Error(`Nav: Target "${targetId}" not found`);
|
|
143
|
-
}
|
|
144
|
-
container = target;
|
|
145
|
-
} else {
|
|
146
|
-
container = getOrCreateContainer(this._id);
|
|
147
|
-
}
|
|
148
|
-
this.container = container;
|
|
117
|
+
const container = this._setupContainer(targetId);
|
|
149
118
|
|
|
150
|
-
// === 2. PREPARE: Destructure state ===
|
|
151
119
|
const { brand, items, variant, sticky, style, class: className } = this.state;
|
|
152
120
|
|
|
153
|
-
// === 3. BUILD: Create DOM elements ===
|
|
154
121
|
const nav = document.createElement('nav');
|
|
155
122
|
nav.className = `jux-nav jux-nav-${variant}`;
|
|
156
123
|
nav.id = this._id;
|
|
@@ -193,55 +160,73 @@ export class Nav {
|
|
|
193
160
|
nav.appendChild(brandEl);
|
|
194
161
|
}
|
|
195
162
|
|
|
196
|
-
// Nav items
|
|
163
|
+
// Nav items container
|
|
197
164
|
const itemsContainer = document.createElement('div');
|
|
198
165
|
itemsContainer.className = 'jux-nav-items';
|
|
199
166
|
|
|
200
167
|
items.forEach(item => {
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
navItem.href = item.href;
|
|
204
|
-
navItem.textContent = item.label;
|
|
205
|
-
if (item.active) navItem.classList.add('jux-nav-item-active');
|
|
206
|
-
itemsContainer.appendChild(navItem);
|
|
207
|
-
});
|
|
168
|
+
const itemWrapper = document.createElement('div');
|
|
169
|
+
itemWrapper.className = 'jux-nav-item-wrapper';
|
|
208
170
|
|
|
209
|
-
|
|
171
|
+
if (item.itemClass) {
|
|
172
|
+
itemWrapper.className += ` ${item.itemClass}`;
|
|
173
|
+
}
|
|
210
174
|
|
|
211
|
-
|
|
175
|
+
const navLink = document.createElement('a');
|
|
176
|
+
navLink.className = 'jux-nav-link';
|
|
177
|
+
navLink.href = item.href;
|
|
178
|
+
navLink.textContent = item.label;
|
|
179
|
+
if (item.active) {
|
|
180
|
+
itemWrapper.classList.add('jux-nav-item-active');
|
|
181
|
+
navLink.classList.add('jux-nav-link-active');
|
|
182
|
+
}
|
|
212
183
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
nav.addEventListener(event, handler as EventListener);
|
|
184
|
+
itemWrapper.appendChild(navLink);
|
|
185
|
+
itemsContainer.appendChild(itemWrapper);
|
|
216
186
|
});
|
|
217
187
|
|
|
218
|
-
|
|
188
|
+
nav.appendChild(itemsContainer);
|
|
189
|
+
|
|
190
|
+
this._wireStandardEvents(nav);
|
|
191
|
+
|
|
192
|
+
// Wire sync bindings
|
|
219
193
|
this._syncBindings.forEach(({ property, stateObj, toState, toComponent }) => {
|
|
220
194
|
if (property === 'items') {
|
|
221
|
-
const
|
|
195
|
+
const transform = toComponent || ((v: any) => v);
|
|
222
196
|
|
|
223
197
|
stateObj.subscribe((val: any) => {
|
|
224
|
-
const transformed =
|
|
198
|
+
const transformed = transform(val);
|
|
225
199
|
this.state.items = transformed;
|
|
226
200
|
this._setActiveStates();
|
|
227
201
|
|
|
228
|
-
// Re-render items
|
|
229
202
|
itemsContainer.innerHTML = '';
|
|
230
203
|
this.state.items.forEach((item: any) => {
|
|
231
|
-
const
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
204
|
+
const itemWrapper = document.createElement('div');
|
|
205
|
+
itemWrapper.className = 'jux-nav-item-wrapper';
|
|
206
|
+
|
|
207
|
+
if (item.itemClass) {
|
|
208
|
+
itemWrapper.className += ` ${item.itemClass}`;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const navLink = document.createElement('a');
|
|
212
|
+
navLink.className = 'jux-nav-link';
|
|
213
|
+
navLink.href = item.href;
|
|
214
|
+
navLink.textContent = item.label;
|
|
215
|
+
if (item.active) {
|
|
216
|
+
itemWrapper.classList.add('jux-nav-item-active');
|
|
217
|
+
navLink.classList.add('jux-nav-link-active');
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
itemWrapper.appendChild(navLink);
|
|
221
|
+
itemsContainer.appendChild(itemWrapper);
|
|
237
222
|
});
|
|
238
223
|
});
|
|
239
224
|
}
|
|
240
225
|
else if (property === 'brand') {
|
|
241
|
-
const
|
|
226
|
+
const transform = toComponent || ((v: any) => v);
|
|
242
227
|
|
|
243
228
|
stateObj.subscribe((val: any) => {
|
|
244
|
-
const transformed =
|
|
229
|
+
const transformed = transform(val);
|
|
245
230
|
const brandEl = nav.querySelector('.jux-nav-brand');
|
|
246
231
|
if (brandEl && transformed.text) {
|
|
247
232
|
const textEl = brandEl.querySelector('span:last-child');
|
|
@@ -254,8 +239,8 @@ export class Nav {
|
|
|
254
239
|
}
|
|
255
240
|
});
|
|
256
241
|
|
|
257
|
-
// === 5. RENDER: Append to DOM and finalize ===
|
|
258
242
|
container.appendChild(nav);
|
|
243
|
+
this._nav = nav;
|
|
259
244
|
|
|
260
245
|
requestAnimationFrame(() => {
|
|
261
246
|
if ((window as any).lucide) {
|
|
@@ -265,13 +250,6 @@ export class Nav {
|
|
|
265
250
|
|
|
266
251
|
return this;
|
|
267
252
|
}
|
|
268
|
-
|
|
269
|
-
renderTo(juxComponent: any): this {
|
|
270
|
-
if (!juxComponent?._id) {
|
|
271
|
-
throw new Error('Nav.renderTo: Invalid component');
|
|
272
|
-
}
|
|
273
|
-
return this.render(`#${juxComponent._id}`);
|
|
274
|
-
}
|
|
275
253
|
}
|
|
276
254
|
|
|
277
255
|
export function nav(id: string, options: NavOptions = {}): Nav {
|
|
@@ -1,118 +1,61 @@
|
|
|
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;
|
|
3
6
|
|
|
4
|
-
/**
|
|
5
|
-
* Paragraph options
|
|
6
|
-
*/
|
|
7
7
|
export interface ParagraphOptions {
|
|
8
8
|
text?: string;
|
|
9
9
|
class?: string;
|
|
10
10
|
style?: string;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
/**
|
|
14
|
-
* Paragraph state
|
|
15
|
-
*/
|
|
16
13
|
type ParagraphState = {
|
|
17
14
|
text: string;
|
|
18
15
|
class: string;
|
|
19
16
|
style: string;
|
|
20
17
|
};
|
|
21
18
|
|
|
22
|
-
|
|
23
|
-
* Paragraph component - semantic paragraph element
|
|
24
|
-
*/
|
|
25
|
-
export class Paragraph {
|
|
26
|
-
state: ParagraphState;
|
|
27
|
-
container: HTMLElement | null = null;
|
|
28
|
-
_id: string;
|
|
29
|
-
id: string;
|
|
30
|
-
|
|
31
|
-
// CRITICAL: Store bind/sync instructions for deferred wiring
|
|
32
|
-
private _bindings: Array<{ event: string, handler: Function }> = [];
|
|
33
|
-
private _syncBindings: Array<{
|
|
34
|
-
property: string,
|
|
35
|
-
stateObj: State<any>,
|
|
36
|
-
toState?: Function,
|
|
37
|
-
toComponent?: Function
|
|
38
|
-
}> = [];
|
|
39
|
-
|
|
19
|
+
export class Paragraph extends BaseComponent<ParagraphState> {
|
|
40
20
|
constructor(id: string, options: ParagraphOptions = {}) {
|
|
41
|
-
|
|
42
|
-
this.id = id;
|
|
43
|
-
|
|
44
|
-
this.state = {
|
|
21
|
+
super(id, {
|
|
45
22
|
text: options.text ?? '',
|
|
46
23
|
class: options.class ?? '',
|
|
47
24
|
style: options.style ?? ''
|
|
48
|
-
};
|
|
25
|
+
});
|
|
49
26
|
}
|
|
50
27
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
* ------------------------- */
|
|
54
|
-
|
|
55
|
-
text(value: string): this {
|
|
56
|
-
this.state.text = value;
|
|
57
|
-
return this;
|
|
28
|
+
protected getTriggerEvents(): readonly string[] {
|
|
29
|
+
return TRIGGER_EVENTS;
|
|
58
30
|
}
|
|
59
31
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
return this;
|
|
32
|
+
protected getCallbackEvents(): readonly string[] {
|
|
33
|
+
return CALLBACK_EVENTS;
|
|
63
34
|
}
|
|
64
35
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
36
|
+
/* ═════════════════════════════════════════════════════════════════
|
|
37
|
+
* FLUENT API
|
|
38
|
+
* ═════════════════════════════════════════════════════════════════ */
|
|
69
39
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
bind(event: string, handler: Function): this {
|
|
75
|
-
this._bindings.push({ event, handler });
|
|
76
|
-
return this;
|
|
77
|
-
}
|
|
40
|
+
// ✅ Inherited from BaseComponent:
|
|
41
|
+
// - style(), class()
|
|
42
|
+
// - bind(), sync(), renderTo()
|
|
43
|
+
// - All other base methods
|
|
78
44
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
*
|
|
82
|
-
* @param property - Component property to sync ('text', 'class', 'style')
|
|
83
|
-
* @param stateObj - State object to sync with
|
|
84
|
-
* @param transform - Optional transform function from state to component
|
|
85
|
-
*/
|
|
86
|
-
sync(property: string, stateObj: State<any>, toState?: Function, toComponent?: Function): this {
|
|
87
|
-
if (!stateObj || typeof stateObj.subscribe !== 'function') {
|
|
88
|
-
throw new Error(`Paragraph.sync: Expected a State object for property "${property}"`);
|
|
89
|
-
}
|
|
90
|
-
this._syncBindings.push({ property, stateObj, toState, toComponent });
|
|
45
|
+
text(value: string): this {
|
|
46
|
+
this.state.text = value;
|
|
91
47
|
return this;
|
|
92
48
|
}
|
|
93
49
|
|
|
94
|
-
/*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
50
|
+
/* ═════════════════════════════════════════════════════════════════
|
|
51
|
+
* RENDER
|
|
52
|
+
* ═════════════════════════════════════════════════════════════════ */
|
|
97
53
|
|
|
98
54
|
render(targetId?: string): this {
|
|
99
|
-
|
|
100
|
-
let container: HTMLElement;
|
|
101
|
-
if (targetId) {
|
|
102
|
-
const target = document.querySelector(targetId);
|
|
103
|
-
if (!target || !(target instanceof HTMLElement)) {
|
|
104
|
-
throw new Error(`Paragraph: Target "${targetId}" not found`);
|
|
105
|
-
}
|
|
106
|
-
container = target;
|
|
107
|
-
} else {
|
|
108
|
-
container = getOrCreateContainer(this._id);
|
|
109
|
-
}
|
|
110
|
-
this.container = container;
|
|
55
|
+
const container = this._setupContainer(targetId);
|
|
111
56
|
|
|
112
|
-
// === 2. PREPARE: Destructure state ===
|
|
113
57
|
const { text, style, class: className } = this.state;
|
|
114
58
|
|
|
115
|
-
// === 3. BUILD: Create DOM elements ===
|
|
116
59
|
const paragraph = document.createElement('p');
|
|
117
60
|
paragraph.className = 'jux-paragraph';
|
|
118
61
|
paragraph.id = this._id;
|
|
@@ -120,42 +63,35 @@ export class Paragraph {
|
|
|
120
63
|
if (className) paragraph.className += ` ${className}`;
|
|
121
64
|
if (style) paragraph.setAttribute('style', style);
|
|
122
65
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
// Wire custom bindings from .bind() calls
|
|
126
|
-
this._bindings.forEach(({ event, handler }) => {
|
|
127
|
-
paragraph.addEventListener(event, handler as EventListener);
|
|
128
|
-
});
|
|
66
|
+
this._wireStandardEvents(paragraph);
|
|
129
67
|
|
|
130
|
-
// Wire sync bindings
|
|
68
|
+
// Wire sync bindings
|
|
131
69
|
this._syncBindings.forEach(({ property, stateObj, toState, toComponent }) => {
|
|
132
70
|
if (property === 'text') {
|
|
133
|
-
const
|
|
71
|
+
const transform = toComponent || ((v: any) => String(v));
|
|
134
72
|
|
|
135
73
|
stateObj.subscribe((val: any) => {
|
|
136
|
-
const transformed =
|
|
74
|
+
const transformed = transform(val);
|
|
137
75
|
paragraph.textContent = transformed;
|
|
138
76
|
this.state.text = transformed;
|
|
139
77
|
});
|
|
140
78
|
}
|
|
79
|
+
else if (property === 'class') {
|
|
80
|
+
const transform = toComponent || ((v: any) => String(v));
|
|
81
|
+
|
|
82
|
+
stateObj.subscribe((val: any) => {
|
|
83
|
+
const transformed = transform(val);
|
|
84
|
+
paragraph.className = `jux-paragraph ${transformed}`;
|
|
85
|
+
this.state.class = transformed;
|
|
86
|
+
});
|
|
87
|
+
}
|
|
141
88
|
});
|
|
142
89
|
|
|
143
|
-
// === 5. RENDER: Append to DOM and finalize ===
|
|
144
90
|
container.appendChild(paragraph);
|
|
145
91
|
return this;
|
|
146
92
|
}
|
|
147
|
-
|
|
148
|
-
renderTo(juxComponent: any): this {
|
|
149
|
-
if (!juxComponent?._id) {
|
|
150
|
-
throw new Error('Paragraph.renderTo: Invalid component');
|
|
151
|
-
}
|
|
152
|
-
return this.render(`#${juxComponent._id}`);
|
|
153
|
-
}
|
|
154
93
|
}
|
|
155
94
|
|
|
156
|
-
/**
|
|
157
|
-
* Factory helper
|
|
158
|
-
*/
|
|
159
95
|
export function paragraph(id: string, options: ParagraphOptions = {}): Paragraph {
|
|
160
96
|
return new Paragraph(id, options);
|
|
161
97
|
}
|