juxscript 1.1.2 → 1.1.4
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/machinery/build3.js +7 -91
- package/machinery/compiler3.js +3 -209
- package/machinery/config.js +93 -6
- package/machinery/serve.js +255 -0
- package/machinery/watcher.js +49 -161
- package/package.json +19 -5
- package/lib/components/alert.ts +0 -200
- package/lib/components/app.ts +0 -247
- package/lib/components/badge.ts +0 -101
- package/lib/components/base/BaseComponent.ts +0 -421
- package/lib/components/base/FormInput.ts +0 -227
- package/lib/components/button.ts +0 -178
- package/lib/components/card.ts +0 -173
- package/lib/components/chart.ts +0 -231
- package/lib/components/checkbox.ts +0 -242
- package/lib/components/code.ts +0 -123
- package/lib/components/container.ts +0 -140
- package/lib/components/data.ts +0 -135
- package/lib/components/datepicker.ts +0 -234
- package/lib/components/dialog.ts +0 -172
- package/lib/components/divider.ts +0 -100
- package/lib/components/dropdown.ts +0 -186
- package/lib/components/element.ts +0 -267
- package/lib/components/fileupload.ts +0 -309
- package/lib/components/grid.ts +0 -291
- package/lib/components/guard.ts +0 -92
- package/lib/components/heading.ts +0 -96
- package/lib/components/helpers.ts +0 -41
- package/lib/components/hero.ts +0 -224
- package/lib/components/icon.ts +0 -178
- package/lib/components/icons.ts +0 -464
- package/lib/components/include.ts +0 -410
- package/lib/components/input.ts +0 -457
- package/lib/components/list.ts +0 -419
- package/lib/components/loading.ts +0 -100
- package/lib/components/menu.ts +0 -275
- package/lib/components/modal.ts +0 -284
- package/lib/components/nav.ts +0 -257
- package/lib/components/paragraph.ts +0 -97
- package/lib/components/progress.ts +0 -159
- package/lib/components/radio.ts +0 -278
- package/lib/components/req.ts +0 -303
- package/lib/components/script.ts +0 -41
- package/lib/components/select.ts +0 -252
- package/lib/components/sidebar.ts +0 -275
- package/lib/components/style.ts +0 -41
- package/lib/components/switch.ts +0 -246
- package/lib/components/table.ts +0 -1249
- package/lib/components/tabs.ts +0 -250
- package/lib/components/theme-toggle.ts +0 -293
- package/lib/components/tooltip.ts +0 -144
- package/lib/components/view.ts +0 -190
- package/lib/components/write.ts +0 -272
- package/lib/layouts/default.css +0 -260
- package/lib/layouts/figma.css +0 -334
- package/lib/reactivity/state.ts +0 -78
- package/lib/utils/fetch.ts +0 -553
- package/machinery/ast.js +0 -347
- package/machinery/build.js +0 -466
- package/machinery/bundleAssets.js +0 -0
- package/machinery/bundleJux.js +0 -0
- package/machinery/bundleVendors.js +0 -0
- package/machinery/doc-generator.js +0 -136
- package/machinery/imports.js +0 -155
- package/machinery/server.js +0 -166
- package/machinery/ts-shim.js +0 -46
- package/machinery/validators/file-validator.js +0 -123
package/lib/components/alert.ts
DELETED
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
import { BaseComponent } from './base/BaseComponent.js';
|
|
2
|
-
import { renderIcon } from './icons.js';
|
|
3
|
-
|
|
4
|
-
// Event definitions
|
|
5
|
-
const TRIGGER_EVENTS = [] as const;
|
|
6
|
-
const CALLBACK_EVENTS = ['dismiss'] as const;
|
|
7
|
-
|
|
8
|
-
export interface AlertOptions {
|
|
9
|
-
content?: string;
|
|
10
|
-
type?: 'info' | 'success' | 'warning' | 'error';
|
|
11
|
-
dismissible?: boolean;
|
|
12
|
-
icon?: string;
|
|
13
|
-
style?: string;
|
|
14
|
-
class?: string;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
type AlertState = {
|
|
18
|
-
content: string;
|
|
19
|
-
type: string;
|
|
20
|
-
dismissible: boolean;
|
|
21
|
-
icon: string;
|
|
22
|
-
visible: boolean;
|
|
23
|
-
style: string;
|
|
24
|
-
class: string;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
export class Alert extends BaseComponent<AlertState> {
|
|
28
|
-
private _alert: HTMLElement | null = null;
|
|
29
|
-
|
|
30
|
-
constructor(id: string, options: AlertOptions = {}) {
|
|
31
|
-
super(id, {
|
|
32
|
-
content: options.content ?? '',
|
|
33
|
-
type: options.type ?? 'info',
|
|
34
|
-
dismissible: options.dismissible ?? true,
|
|
35
|
-
icon: options.icon ?? '',
|
|
36
|
-
visible: true,
|
|
37
|
-
style: options.style ?? '',
|
|
38
|
-
class: options.class ?? ''
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
protected getTriggerEvents(): readonly string[] {
|
|
43
|
-
return TRIGGER_EVENTS;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
protected getCallbackEvents(): readonly string[] {
|
|
47
|
-
return CALLBACK_EVENTS;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/* ═════════════════════════════════════════════════════════════════
|
|
51
|
-
* FLUENT API
|
|
52
|
-
* ═════════════════════════════════════════════════════════════════ */
|
|
53
|
-
|
|
54
|
-
// ✅ Inherited from BaseComponent:
|
|
55
|
-
// - style(), class()
|
|
56
|
-
// - bind(), sync(), renderTo()
|
|
57
|
-
// - addClass(), removeClass(), toggleClass()
|
|
58
|
-
// - visible(), show(), hide(), toggleVisibility()
|
|
59
|
-
// - attr(), attrs(), removeAttr()
|
|
60
|
-
// - disabled(), enable(), disable()
|
|
61
|
-
// - loading(), focus(), blur(), remove()
|
|
62
|
-
|
|
63
|
-
content(value: string): this {
|
|
64
|
-
this.state.content = value;
|
|
65
|
-
return this;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
type(value: 'info' | 'success' | 'warning' | 'error'): this {
|
|
69
|
-
this.state.type = value;
|
|
70
|
-
return this;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
dismissible(value: boolean): this {
|
|
74
|
-
this.state.dismissible = value;
|
|
75
|
-
return this;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
icon(value: string): this {
|
|
79
|
-
this.state.icon = value;
|
|
80
|
-
return this;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/* ═════════════════════════════════════════════════════════════════
|
|
84
|
-
* RENDER
|
|
85
|
-
* ═════════════════════════════════════════════════════════════════ */
|
|
86
|
-
|
|
87
|
-
render(targetId?: string): this {
|
|
88
|
-
const container = this._setupContainer(targetId);
|
|
89
|
-
|
|
90
|
-
const { content, type, dismissible, icon, style, class: className } = this.state;
|
|
91
|
-
const hasVisibleSync = this._syncBindings.some(b => b.property === 'visible');
|
|
92
|
-
|
|
93
|
-
// Build alert element
|
|
94
|
-
const alert = document.createElement('div');
|
|
95
|
-
alert.className = `jux-alert jux-alert-${type}`;
|
|
96
|
-
alert.id = this._id;
|
|
97
|
-
if (className) alert.className += ` ${className}`;
|
|
98
|
-
if (style) alert.setAttribute('style', style);
|
|
99
|
-
|
|
100
|
-
if (icon) {
|
|
101
|
-
const iconEl = document.createElement('span');
|
|
102
|
-
iconEl.className = 'jux-alert-icon';
|
|
103
|
-
iconEl.appendChild(renderIcon(icon));
|
|
104
|
-
alert.appendChild(iconEl);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const contentEl = document.createElement('div');
|
|
108
|
-
contentEl.className = 'jux-alert-content';
|
|
109
|
-
contentEl.textContent = content;
|
|
110
|
-
alert.appendChild(contentEl);
|
|
111
|
-
|
|
112
|
-
if (dismissible) {
|
|
113
|
-
const closeBtn = document.createElement('button');
|
|
114
|
-
closeBtn.className = 'jux-alert-close';
|
|
115
|
-
closeBtn.innerHTML = '×';
|
|
116
|
-
alert.appendChild(closeBtn);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// Default dismiss behavior (only if NOT using sync)
|
|
120
|
-
if (!hasVisibleSync && dismissible) {
|
|
121
|
-
const closeBtn = alert.querySelector('.jux-alert-close');
|
|
122
|
-
closeBtn?.addEventListener('click', () => {
|
|
123
|
-
// 🎯 Fire the dismiss callback event
|
|
124
|
-
this._triggerCallback('dismiss');
|
|
125
|
-
alert.remove();
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// Wire events using inherited method
|
|
130
|
-
this._wireStandardEvents(alert);
|
|
131
|
-
|
|
132
|
-
// Wire sync bindings
|
|
133
|
-
this._syncBindings.forEach(({ property, stateObj, toState, toComponent }) => {
|
|
134
|
-
if (property === 'content') {
|
|
135
|
-
const transform = toComponent || ((v: any) => String(v));
|
|
136
|
-
|
|
137
|
-
stateObj.subscribe((val: any) => {
|
|
138
|
-
const transformed = transform(val);
|
|
139
|
-
contentEl.textContent = transformed;
|
|
140
|
-
this.state.content = transformed;
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
else if (property === 'type') {
|
|
144
|
-
const transform = toComponent || ((v: any) => String(v));
|
|
145
|
-
|
|
146
|
-
stateObj.subscribe((val: any) => {
|
|
147
|
-
const transformed = transform(val);
|
|
148
|
-
alert.className = `jux-alert jux-alert-${transformed}`;
|
|
149
|
-
if (className) alert.className += ` ${className}`;
|
|
150
|
-
this.state.type = transformed;
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
else if (property === 'visible') {
|
|
154
|
-
const transformToState = toState || ((v: any) => Boolean(v));
|
|
155
|
-
const transform = toComponent || ((v: any) => Boolean(v));
|
|
156
|
-
|
|
157
|
-
let isUpdating = false;
|
|
158
|
-
|
|
159
|
-
// State → Component
|
|
160
|
-
stateObj.subscribe((val: any) => {
|
|
161
|
-
if (isUpdating) return;
|
|
162
|
-
const transformed = transform(val);
|
|
163
|
-
alert.style.display = transformed ? 'flex' : 'none';
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
// Component → State (close button)
|
|
167
|
-
if (dismissible) {
|
|
168
|
-
const closeBtn = alert.querySelector('.jux-alert-close');
|
|
169
|
-
closeBtn?.addEventListener('click', () => {
|
|
170
|
-
if (isUpdating) return;
|
|
171
|
-
isUpdating = true;
|
|
172
|
-
|
|
173
|
-
alert.style.display = 'none';
|
|
174
|
-
stateObj.set(transformToState(false));
|
|
175
|
-
|
|
176
|
-
// 🎯 Fire the dismiss callback event
|
|
177
|
-
this._triggerCallback('dismiss');
|
|
178
|
-
|
|
179
|
-
setTimeout(() => { isUpdating = false; }, 0);
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
container.appendChild(alert);
|
|
186
|
-
this._alert = alert;
|
|
187
|
-
|
|
188
|
-
requestAnimationFrame(() => {
|
|
189
|
-
if ((window as any).lucide) {
|
|
190
|
-
(window as any).lucide.createIcons();
|
|
191
|
-
}
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
return this;
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
export function alert(id: string, options: AlertOptions = {}): Alert {
|
|
199
|
-
return new Alert(id, options);
|
|
200
|
-
}
|
package/lib/components/app.ts
DELETED
|
@@ -1,247 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* App component options
|
|
5
|
-
*/
|
|
6
|
-
export interface AppOptions {
|
|
7
|
-
title?: string;
|
|
8
|
-
theme?: 'light' | 'dark' | 'auto';
|
|
9
|
-
favicon?: string;
|
|
10
|
-
meta?: Record<string, string>;
|
|
11
|
-
stylesheets?: string[];
|
|
12
|
-
scripts?: string[];
|
|
13
|
-
layout?: {
|
|
14
|
-
header?: boolean | string;
|
|
15
|
-
subheader?: boolean | string;
|
|
16
|
-
sidebar?: boolean | string;
|
|
17
|
-
main?: boolean | string;
|
|
18
|
-
aside?: boolean | string;
|
|
19
|
-
footer?: boolean | string;
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* App component state
|
|
25
|
-
*/
|
|
26
|
-
type AppState = {
|
|
27
|
-
title: string;
|
|
28
|
-
theme: string;
|
|
29
|
-
favicon: string;
|
|
30
|
-
meta: Map<string, string>;
|
|
31
|
-
stylesheets: string[];
|
|
32
|
-
scripts: string[];
|
|
33
|
-
layout: {
|
|
34
|
-
header: boolean | string;
|
|
35
|
-
subheader: boolean | string;
|
|
36
|
-
sidebar: boolean | string;
|
|
37
|
-
main: boolean | string;
|
|
38
|
-
aside: boolean | string;
|
|
39
|
-
footer: boolean | string;
|
|
40
|
-
};
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* App - Configure application-level settings
|
|
45
|
-
* Manages document metadata, theme, and global configuration
|
|
46
|
-
*
|
|
47
|
-
* Usage:
|
|
48
|
-
* jux.app('myApp').setup({
|
|
49
|
-
* title: 'My App',
|
|
50
|
-
* theme: 'dark',
|
|
51
|
-
* favicon: '/favicon.ico',
|
|
52
|
-
* stylesheets: [
|
|
53
|
-
* '/lib/layouts/notion.css',
|
|
54
|
-
* '/lib/presets/light.css'
|
|
55
|
-
* ],
|
|
56
|
-
* layout: {
|
|
57
|
-
* header: true,
|
|
58
|
-
* sidebar: true,
|
|
59
|
-
* main: true,
|
|
60
|
-
* footer: true
|
|
61
|
-
* }
|
|
62
|
-
* });
|
|
63
|
-
*
|
|
64
|
-
* // Or fluent
|
|
65
|
-
* jux.app('myApp')
|
|
66
|
-
* .title('My App')
|
|
67
|
-
* .theme('dark')
|
|
68
|
-
* .addStylesheet('/presets/main.css')
|
|
69
|
-
* .render();
|
|
70
|
-
*/
|
|
71
|
-
export class App {
|
|
72
|
-
state: AppState;
|
|
73
|
-
_componentId: string;
|
|
74
|
-
id: string;
|
|
75
|
-
|
|
76
|
-
constructor(id: string, options?: AppOptions) {
|
|
77
|
-
this._componentId = id;
|
|
78
|
-
this.id = id;
|
|
79
|
-
|
|
80
|
-
const opts = options || {};
|
|
81
|
-
|
|
82
|
-
this.state = {
|
|
83
|
-
title: opts.title ?? '',
|
|
84
|
-
theme: opts.theme ?? 'auto',
|
|
85
|
-
favicon: opts.favicon ?? '',
|
|
86
|
-
meta: new Map(Object.entries(opts.meta || {})),
|
|
87
|
-
stylesheets: opts.stylesheets || [],
|
|
88
|
-
scripts: opts.scripts || [],
|
|
89
|
-
layout: {
|
|
90
|
-
header: opts.layout?.header ?? false,
|
|
91
|
-
subheader: opts.layout?.subheader ?? false,
|
|
92
|
-
sidebar: opts.layout?.sidebar ?? false,
|
|
93
|
-
main: opts.layout?.main ?? true,
|
|
94
|
-
aside: opts.layout?.aside ?? false,
|
|
95
|
-
footer: opts.layout?.footer ?? false
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/* -------------------------
|
|
101
|
-
* Fluent API
|
|
102
|
-
* ------------------------- */
|
|
103
|
-
|
|
104
|
-
title(value: string): this {
|
|
105
|
-
this.state.title = value;
|
|
106
|
-
return this;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
theme(value: 'light' | 'dark' | 'auto'): this {
|
|
110
|
-
this.state.theme = value;
|
|
111
|
-
return this;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
favicon(value: string): this {
|
|
115
|
-
this.state.favicon = value;
|
|
116
|
-
return this;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
meta(name: string, content: string): this {
|
|
120
|
-
this.state.meta.set(name, content);
|
|
121
|
-
return this;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
addStylesheet(url: string): this {
|
|
125
|
-
if (!this.state.stylesheets.includes(url)) {
|
|
126
|
-
this.state.stylesheets.push(url);
|
|
127
|
-
}
|
|
128
|
-
return this;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
addScript(url: string): this {
|
|
132
|
-
if (!this.state.scripts.includes(url)) {
|
|
133
|
-
this.state.scripts.push(url);
|
|
134
|
-
}
|
|
135
|
-
return this;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Setup app with comprehensive configuration
|
|
140
|
-
*/
|
|
141
|
-
setup(options: AppOptions): this {
|
|
142
|
-
if (options.title) this.state.title = options.title;
|
|
143
|
-
if (options.theme) this.state.theme = options.theme;
|
|
144
|
-
if (options.favicon) this.state.favicon = options.favicon;
|
|
145
|
-
|
|
146
|
-
if (options.meta) {
|
|
147
|
-
Object.entries(options.meta).forEach(([name, content]) => {
|
|
148
|
-
this.state.meta.set(name, content);
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
if (options.stylesheets) {
|
|
153
|
-
options.stylesheets.forEach(url => this.addStylesheet(url));
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
if (options.scripts) {
|
|
157
|
-
options.scripts.forEach(url => this.addScript(url));
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
if (options.layout) {
|
|
161
|
-
this.state.layout = { ...this.state.layout, ...options.layout };
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
return this;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/* -------------------------
|
|
168
|
-
* Render
|
|
169
|
-
* ------------------------- */
|
|
170
|
-
|
|
171
|
-
render(): this {
|
|
172
|
-
if (typeof document === 'undefined') return this;
|
|
173
|
-
|
|
174
|
-
try {
|
|
175
|
-
const { title, theme, favicon, meta, stylesheets, scripts } = this.state;
|
|
176
|
-
|
|
177
|
-
// Apply title
|
|
178
|
-
if (title) {
|
|
179
|
-
document.title = title;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// Apply theme
|
|
183
|
-
if (theme) {
|
|
184
|
-
document.body.setAttribute('data-theme', theme);
|
|
185
|
-
document.body.classList.remove('theme-light', 'theme-dark', 'theme-auto');
|
|
186
|
-
document.body.classList.add(`theme-${theme}`);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// Apply favicon
|
|
190
|
-
if (favicon) {
|
|
191
|
-
let link = document.querySelector<HTMLLinkElement>('link[rel="icon"]');
|
|
192
|
-
|
|
193
|
-
if (!link) {
|
|
194
|
-
link = document.createElement('link');
|
|
195
|
-
link.rel = 'icon';
|
|
196
|
-
document.head.appendChild(link);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
link.href = favicon;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// Apply meta tags
|
|
203
|
-
meta.forEach((content, name) => {
|
|
204
|
-
let metaEl = document.querySelector<HTMLMetaElement>(`meta[name="${name}"]`);
|
|
205
|
-
|
|
206
|
-
if (!metaEl) {
|
|
207
|
-
metaEl = document.createElement('meta');
|
|
208
|
-
metaEl.name = name;
|
|
209
|
-
document.head.appendChild(metaEl);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
metaEl.content = content;
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
// Load stylesheets
|
|
216
|
-
stylesheets.forEach(url => {
|
|
217
|
-
if (!document.querySelector(`link[href="${url}"]`)) {
|
|
218
|
-
const link = document.createElement('link');
|
|
219
|
-
link.rel = 'stylesheet';
|
|
220
|
-
link.href = url;
|
|
221
|
-
document.head.appendChild(link);
|
|
222
|
-
}
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
// Load scripts
|
|
226
|
-
scripts.forEach(url => {
|
|
227
|
-
if (!document.querySelector(`script[src="${url}"]`)) {
|
|
228
|
-
const script = document.createElement('script');
|
|
229
|
-
script.src = url;
|
|
230
|
-
document.head.appendChild(script);
|
|
231
|
-
}
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
} catch (error: any) {
|
|
235
|
-
throw new Error(`App render failed: ${error.message}`);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
return this;
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* Factory helper
|
|
244
|
-
*/
|
|
245
|
-
export function app(id: string, options?: AppOptions): App {
|
|
246
|
-
return new App(id, options);
|
|
247
|
-
}
|
package/lib/components/badge.ts
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { BaseComponent } from './base/BaseComponent.js';
|
|
2
|
-
|
|
3
|
-
// Event definitions
|
|
4
|
-
const TRIGGER_EVENTS = [] as const;
|
|
5
|
-
const CALLBACK_EVENTS = [] as const;
|
|
6
|
-
|
|
7
|
-
export interface BadgeOptions {
|
|
8
|
-
label?: string;
|
|
9
|
-
variant?: 'default' | 'success' | 'warning' | 'error' | 'info';
|
|
10
|
-
pill?: boolean;
|
|
11
|
-
style?: string;
|
|
12
|
-
class?: string;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
type BadgeState = {
|
|
16
|
-
label: string;
|
|
17
|
-
variant: string;
|
|
18
|
-
pill: boolean;
|
|
19
|
-
style: string;
|
|
20
|
-
class: string;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export class Badge extends BaseComponent<BadgeState> {
|
|
24
|
-
constructor(id: string, options: BadgeOptions = {}) {
|
|
25
|
-
super(id, {
|
|
26
|
-
label: options.label ?? '',
|
|
27
|
-
variant: options.variant ?? 'default',
|
|
28
|
-
pill: options.pill ?? false,
|
|
29
|
-
style: options.style ?? '',
|
|
30
|
-
class: options.class ?? ''
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
protected getTriggerEvents(): readonly string[] {
|
|
35
|
-
return TRIGGER_EVENTS;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
protected getCallbackEvents(): readonly string[] {
|
|
39
|
-
return CALLBACK_EVENTS;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/* ═════════════════════════════════════════════════════════════════
|
|
43
|
-
* FLUENT API
|
|
44
|
-
* ═════════════════════════════════════════════════════════════════ */
|
|
45
|
-
|
|
46
|
-
// ✅ Inherited from BaseComponent
|
|
47
|
-
|
|
48
|
-
label(value: string): this {
|
|
49
|
-
this.state.label = value;
|
|
50
|
-
return this;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
variant(value: 'default' | 'success' | 'warning' | 'error' | 'info'): this {
|
|
54
|
-
this.state.variant = value;
|
|
55
|
-
return this;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
pill(value: boolean): this {
|
|
59
|
-
this.state.pill = value;
|
|
60
|
-
return this;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/* ═════════════════════════════════════════════════════════════════
|
|
64
|
-
* RENDER
|
|
65
|
-
* ═════════════════════════════════════════════════════════════════ */
|
|
66
|
-
|
|
67
|
-
render(targetId?: string): this {
|
|
68
|
-
const container = this._setupContainer(targetId);
|
|
69
|
-
|
|
70
|
-
const { label, variant, pill, style, class: className } = this.state;
|
|
71
|
-
|
|
72
|
-
const badge = document.createElement('span');
|
|
73
|
-
badge.className = `jux-badge jux-badge-${variant}`;
|
|
74
|
-
if (pill) badge.classList.add('jux-badge-pill');
|
|
75
|
-
badge.id = this._id;
|
|
76
|
-
if (className) badge.className += ` ${className}`;
|
|
77
|
-
if (style) badge.setAttribute('style', style);
|
|
78
|
-
badge.textContent = label;
|
|
79
|
-
|
|
80
|
-
this._wireStandardEvents(badge);
|
|
81
|
-
|
|
82
|
-
// Wire sync for label
|
|
83
|
-
this._syncBindings.forEach(({ property, stateObj, toState, toComponent }) => {
|
|
84
|
-
if (property === 'label') {
|
|
85
|
-
const transform = toComponent || ((v: any) => String(v));
|
|
86
|
-
stateObj.subscribe((val: any) => {
|
|
87
|
-
badge.textContent = transform(val);
|
|
88
|
-
this.state.label = transform(val);
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
container.appendChild(badge);
|
|
94
|
-
|
|
95
|
-
return this;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
export function badge(id: string, options: BadgeOptions = {}): Badge {
|
|
100
|
-
return new Badge(id, options);
|
|
101
|
-
}
|