juxscript 1.0.19 → 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 +212 -165
- package/lib/components/badge.ts +93 -103
- package/lib/components/base/BaseComponent.ts +397 -0
- package/lib/components/base/FormInput.ts +322 -0
- package/lib/components/button.ts +63 -122
- package/lib/components/card.ts +109 -155
- 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/charts/lib/chart-types.ts +159 -0
- package/lib/components/charts/lib/chart-utils.ts +160 -0
- package/lib/components/charts/lib/chart.ts +707 -0
- package/lib/components/checkbox.ts +264 -127
- package/lib/components/code.ts +75 -108
- package/lib/components/container.ts +113 -130
- package/lib/components/data.ts +37 -5
- package/lib/components/datepicker.ts +195 -147
- package/lib/components/dialog.ts +187 -157
- package/lib/components/divider.ts +85 -191
- package/lib/components/docs-data.json +544 -2027
- package/lib/components/dropdown.ts +178 -136
- package/lib/components/element.ts +227 -171
- package/lib/components/fileupload.ts +285 -228
- package/lib/components/guard.ts +92 -0
- package/lib/components/heading.ts +46 -69
- package/lib/components/helpers.ts +13 -6
- package/lib/components/hero.ts +107 -95
- package/lib/components/icon.ts +160 -0
- package/lib/components/icons.ts +175 -0
- package/lib/components/include.ts +153 -5
- package/lib/components/input.ts +174 -374
- package/lib/components/kpicard.ts +16 -16
- package/lib/components/list.ts +378 -240
- package/lib/components/loading.ts +142 -211
- package/lib/components/menu.ts +103 -97
- package/lib/components/modal.ts +138 -144
- package/lib/components/nav.ts +169 -90
- package/lib/components/paragraph.ts +49 -150
- package/lib/components/progress.ts +118 -200
- package/lib/components/radio.ts +297 -149
- package/lib/components/script.ts +19 -87
- package/lib/components/select.ts +184 -186
- package/lib/components/sidebar.ts +152 -140
- package/lib/components/style.ts +19 -82
- package/lib/components/switch.ts +258 -188
- package/lib/components/table.ts +1117 -170
- package/lib/components/tabs.ts +162 -145
- package/lib/components/theme-toggle.ts +108 -169
- package/lib/components/tooltip.ts +86 -157
- package/lib/components/write.ts +108 -127
- package/lib/jux.ts +86 -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 -2
- 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 -1246
- package/lib/components/areachartsmooth.ts +0 -1380
- package/lib/components/barchart.ts +0 -1250
- package/lib/components/chart.ts +0 -127
- package/lib/components/doughnutchart.ts +0 -1191
- 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,72 +1,62 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BaseComponent } from './base/BaseComponent.js';
|
|
2
|
+
|
|
3
|
+
// Event definitions
|
|
4
|
+
const TRIGGER_EVENTS = [] as const;
|
|
5
|
+
const CALLBACK_EVENTS = ['toggle'] as const;
|
|
2
6
|
|
|
3
|
-
/**
|
|
4
|
-
* Sidebar component options
|
|
5
|
-
*/
|
|
6
7
|
export interface SidebarOptions {
|
|
7
|
-
title?: string;
|
|
8
|
-
width?: string;
|
|
9
8
|
position?: 'left' | 'right';
|
|
9
|
+
width?: string;
|
|
10
10
|
collapsible?: boolean;
|
|
11
11
|
collapsed?: boolean;
|
|
12
12
|
style?: string;
|
|
13
13
|
class?: string;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
/**
|
|
17
|
-
* Sidebar component state
|
|
18
|
-
*/
|
|
19
16
|
type SidebarState = {
|
|
20
|
-
|
|
21
|
-
width: string
|
|
22
|
-
position: string;
|
|
17
|
+
position: 'left' | 'right';
|
|
18
|
+
width: string;
|
|
23
19
|
collapsible: boolean;
|
|
24
20
|
collapsed: boolean;
|
|
25
21
|
style: string;
|
|
26
22
|
class: string;
|
|
27
23
|
};
|
|
28
24
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
*
|
|
32
|
-
* Usage:
|
|
33
|
-
* const sidebar = jux.sidebar('mySidebar', {
|
|
34
|
-
* title: 'Navigation',
|
|
35
|
-
* width: '250px',
|
|
36
|
-
* position: 'left'
|
|
37
|
-
* });
|
|
38
|
-
* sidebar.render('#appsidebar');
|
|
39
|
-
*/
|
|
40
|
-
export class Sidebar {
|
|
41
|
-
state: SidebarState;
|
|
42
|
-
container: HTMLElement | null = null;
|
|
43
|
-
_id: string;
|
|
44
|
-
id: string;
|
|
25
|
+
export class Sidebar extends BaseComponent<SidebarState> {
|
|
26
|
+
private _sidebar: HTMLElement | null = null;
|
|
45
27
|
|
|
46
28
|
constructor(id: string, options: SidebarOptions = {}) {
|
|
47
|
-
|
|
48
|
-
this.id = id;
|
|
49
|
-
|
|
50
|
-
this.state = {
|
|
51
|
-
title: options.title ?? '',
|
|
52
|
-
width: options.width ?? null, // No default width - let CSS handle it
|
|
29
|
+
super(id, {
|
|
53
30
|
position: options.position ?? 'left',
|
|
54
|
-
|
|
31
|
+
width: options.width ?? '',
|
|
32
|
+
collapsible: options.collapsible ?? true,
|
|
55
33
|
collapsed: options.collapsed ?? false,
|
|
56
34
|
style: options.style ?? '',
|
|
57
35
|
class: options.class ?? ''
|
|
58
|
-
};
|
|
36
|
+
});
|
|
59
37
|
}
|
|
60
38
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
39
|
+
protected getTriggerEvents(): readonly string[] {
|
|
40
|
+
return TRIGGER_EVENTS;
|
|
41
|
+
}
|
|
64
42
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
return this;
|
|
43
|
+
protected getCallbackEvents(): readonly string[] {
|
|
44
|
+
return CALLBACK_EVENTS;
|
|
68
45
|
}
|
|
69
46
|
|
|
47
|
+
/* ═════════════════════════════════════════════════════════════════
|
|
48
|
+
* FLUENT API
|
|
49
|
+
* ═════════════════════════════════════════════════════════════════ */
|
|
50
|
+
|
|
51
|
+
// ✅ Inherited from BaseComponent:
|
|
52
|
+
// - style(), class()
|
|
53
|
+
// - bind(), sync(), renderTo()
|
|
54
|
+
// - addClass(), removeClass(), toggleClass()
|
|
55
|
+
// - visible(), show(), hide()
|
|
56
|
+
// - attr(), attrs(), removeAttr()
|
|
57
|
+
// - disabled(), enable(), disable()
|
|
58
|
+
// - loading(), focus(), blur(), remove()
|
|
59
|
+
|
|
70
60
|
width(value: string): this {
|
|
71
61
|
this.state.width = value;
|
|
72
62
|
return this;
|
|
@@ -84,143 +74,165 @@ export class Sidebar {
|
|
|
84
74
|
|
|
85
75
|
collapsed(value: boolean): this {
|
|
86
76
|
this.state.collapsed = value;
|
|
77
|
+
this._updateCollapsedState();
|
|
87
78
|
return this;
|
|
88
79
|
}
|
|
89
80
|
|
|
90
|
-
|
|
91
|
-
this.state.style = value;
|
|
92
|
-
return this;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
class(value: string): this {
|
|
96
|
-
this.state.class = value;
|
|
97
|
-
return this;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
toggle(): this {
|
|
81
|
+
toggle(): void {
|
|
101
82
|
this.state.collapsed = !this.state.collapsed;
|
|
102
|
-
this.
|
|
103
|
-
|
|
83
|
+
this._updateCollapsedState();
|
|
84
|
+
// 🎯 Fire the toggle callback event
|
|
85
|
+
this._triggerCallback('toggle', this.state.collapsed);
|
|
104
86
|
}
|
|
105
87
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
private _updateDOM(): void {
|
|
111
|
-
if (!this.container) return;
|
|
112
|
-
|
|
113
|
-
const sidebar = this.container.querySelector(`#${this._id}`);
|
|
114
|
-
if (!sidebar || !(sidebar instanceof HTMLElement)) return;
|
|
115
|
-
|
|
116
|
-
const { width, collapsed } = this.state;
|
|
117
|
-
|
|
118
|
-
if (collapsed) {
|
|
119
|
-
sidebar.classList.add('jux-sidebar-collapsed');
|
|
120
|
-
if (width) {
|
|
121
|
-
sidebar.style.width = '0';
|
|
122
|
-
}
|
|
123
|
-
} else {
|
|
124
|
-
sidebar.classList.remove('jux-sidebar-collapsed');
|
|
125
|
-
if (width) {
|
|
126
|
-
sidebar.style.width = width;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
const toggleBtn = sidebar.querySelector('.jux-sidebar-toggle');
|
|
131
|
-
if (toggleBtn) {
|
|
132
|
-
toggleBtn.textContent = collapsed ? '>' : '<';
|
|
88
|
+
private _updateCollapsedState(): void {
|
|
89
|
+
if (this._sidebar) {
|
|
90
|
+
this._sidebar.classList.toggle('jux-sidebar-collapsed', this.state.collapsed);
|
|
133
91
|
}
|
|
134
92
|
}
|
|
135
93
|
|
|
136
|
-
/*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
94
|
+
/* ═════════════════════════════════════════════════════════════════
|
|
95
|
+
* RENDER
|
|
96
|
+
* ═════════════════════════════════════════════════════════════════ */
|
|
139
97
|
|
|
140
98
|
render(targetId?: string): this {
|
|
141
|
-
|
|
99
|
+
const container = this._setupContainer(targetId);
|
|
142
100
|
|
|
143
|
-
|
|
144
|
-
const target = document.querySelector(targetId);
|
|
145
|
-
if (!target || !(target instanceof HTMLElement)) {
|
|
146
|
-
throw new Error(`Sidebar: Target element "${targetId}" not found`);
|
|
147
|
-
}
|
|
148
|
-
container = target;
|
|
149
|
-
} else {
|
|
150
|
-
container = getOrCreateContainer(this._id);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
this.container = container;
|
|
154
|
-
const { title, width, position, collapsible, collapsed, style, class: className } = this.state;
|
|
101
|
+
const { position, width, collapsible, collapsed, style, class: className } = this.state;
|
|
155
102
|
|
|
103
|
+
// Build sidebar element
|
|
156
104
|
const sidebar = document.createElement('aside');
|
|
157
105
|
sidebar.className = `jux-sidebar jux-sidebar-${position}`;
|
|
158
106
|
sidebar.id = this._id;
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
if (width) {
|
|
162
|
-
sidebar.style.width = collapsed ? '0' : width;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
if (className) {
|
|
166
|
-
sidebar.className += ` ${className}`;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
if (style) {
|
|
170
|
-
sidebar.setAttribute('style', sidebar.getAttribute('style') + '; ' + style);
|
|
171
|
-
}
|
|
107
|
+
if (className) sidebar.className += ` ${className}`;
|
|
108
|
+
if (collapsed) sidebar.classList.add('jux-sidebar-collapsed');
|
|
172
109
|
|
|
173
|
-
|
|
174
|
-
|
|
110
|
+
const sidebarStyle = `${width ? `width: ${collapsed ? '60px' : width};` : ''} ${style}`;
|
|
111
|
+
if (sidebarStyle.trim()) {
|
|
112
|
+
sidebar.setAttribute('style', sidebarStyle);
|
|
175
113
|
}
|
|
176
114
|
|
|
177
|
-
if (title) {
|
|
178
|
-
const titleEl = document.createElement('div');
|
|
179
|
-
titleEl.className = 'jux-sidebar-title';
|
|
180
|
-
titleEl.textContent = title;
|
|
181
|
-
sidebar.appendChild(titleEl);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
const content = document.createElement('div');
|
|
185
|
-
content.className = 'jux-sidebar-content';
|
|
186
|
-
sidebar.appendChild(content);
|
|
187
|
-
|
|
188
|
-
// Event binding - toggle button
|
|
189
115
|
if (collapsible) {
|
|
190
116
|
const toggleBtn = document.createElement('button');
|
|
191
117
|
toggleBtn.className = 'jux-sidebar-toggle';
|
|
192
|
-
toggleBtn.
|
|
118
|
+
toggleBtn.innerHTML = collapsed
|
|
119
|
+
? (position === 'left' ? '▶' : '◀')
|
|
120
|
+
: (position === 'left' ? '◀' : '▶');
|
|
121
|
+
toggleBtn.setAttribute('aria-label', 'Toggle sidebar');
|
|
122
|
+
toggleBtn.setAttribute('title', collapsed ? 'Expand sidebar' : 'Collapse sidebar');
|
|
193
123
|
|
|
194
124
|
toggleBtn.addEventListener('click', () => {
|
|
195
125
|
this.toggle();
|
|
126
|
+
|
|
127
|
+
const isCollapsed = this.state.collapsed;
|
|
128
|
+
toggleBtn.innerHTML = isCollapsed
|
|
129
|
+
? (position === 'left' ? '▶' : '◀')
|
|
130
|
+
: (position === 'left' ? '◀' : '▶');
|
|
131
|
+
toggleBtn.setAttribute('title', isCollapsed ? 'Expand sidebar' : 'Collapse sidebar');
|
|
132
|
+
|
|
133
|
+
if (width) {
|
|
134
|
+
sidebar.style.width = isCollapsed ? '60px' : width;
|
|
135
|
+
}
|
|
196
136
|
});
|
|
197
137
|
|
|
198
138
|
sidebar.appendChild(toggleBtn);
|
|
199
139
|
}
|
|
200
140
|
|
|
141
|
+
// Wire events using inherited method
|
|
142
|
+
this._wireStandardEvents(sidebar);
|
|
143
|
+
|
|
144
|
+
// Wire sync bindings for 'collapsed' property
|
|
145
|
+
this._syncBindings.forEach(({ property, stateObj, toState, toComponent }) => {
|
|
146
|
+
if (property === 'collapsed') {
|
|
147
|
+
const transform = toComponent || ((v: any) => v);
|
|
148
|
+
|
|
149
|
+
stateObj.subscribe((val: any) => {
|
|
150
|
+
const transformed = transform(val);
|
|
151
|
+
const isCollapsed = Boolean(transformed);
|
|
152
|
+
this.state.collapsed = isCollapsed;
|
|
153
|
+
this._updateCollapsedState();
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
|
|
201
158
|
container.appendChild(sidebar);
|
|
159
|
+
this._sidebar = sidebar;
|
|
160
|
+
this._injectDefaultStyles();
|
|
161
|
+
|
|
202
162
|
return this;
|
|
203
163
|
}
|
|
204
164
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
165
|
+
private _injectDefaultStyles(): void {
|
|
166
|
+
const styleId = 'jux-sidebar-styles';
|
|
167
|
+
if (document.getElementById(styleId)) return;
|
|
168
|
+
|
|
169
|
+
const style = document.createElement('style');
|
|
170
|
+
style.id = styleId;
|
|
171
|
+
style.textContent = `
|
|
172
|
+
.jux-sidebar {
|
|
173
|
+
position: relative;
|
|
174
|
+
height: 100vh;
|
|
175
|
+
background: #f9fafb;
|
|
176
|
+
border-right: 1px solid #e5e7eb;
|
|
177
|
+
transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
178
|
+
overflow: hidden;
|
|
179
|
+
}
|
|
212
180
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
181
|
+
.jux-sidebar-right {
|
|
182
|
+
border-right: none;
|
|
183
|
+
border-left: 1px solid #e5e7eb;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.jux-sidebar-toggle {
|
|
187
|
+
position: absolute;
|
|
188
|
+
bottom: 20px;
|
|
189
|
+
right: 20px;
|
|
190
|
+
width: 32px;
|
|
191
|
+
height: 32px;
|
|
192
|
+
border: none;
|
|
193
|
+
background: #3b82f6;
|
|
194
|
+
color: white;
|
|
195
|
+
border-radius: 6px;
|
|
196
|
+
cursor: pointer;
|
|
197
|
+
font-size: 14px;
|
|
198
|
+
display: flex;
|
|
199
|
+
align-items: center;
|
|
200
|
+
justify-content: center;
|
|
201
|
+
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
|
202
|
+
z-index: 100;
|
|
203
|
+
box-shadow: 0 2px 8px rgba(59, 130, 246, 0.3);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.jux-sidebar-toggle:hover {
|
|
207
|
+
background: #2563eb;
|
|
208
|
+
transform: scale(1.05);
|
|
209
|
+
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.4);
|
|
210
|
+
}
|
|
216
211
|
|
|
217
|
-
|
|
212
|
+
.jux-sidebar-toggle:active {
|
|
213
|
+
transform: scale(0.95);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.jux-sidebar-collapsed {
|
|
217
|
+
width: 60px !important;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.jux-sidebar-collapsed > *:not(.jux-sidebar-toggle) {
|
|
221
|
+
opacity: 0;
|
|
222
|
+
pointer-events: none;
|
|
223
|
+
transition: opacity 0.2s ease-out;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.jux-sidebar > *:not(.jux-sidebar-toggle) {
|
|
227
|
+
opacity: 1;
|
|
228
|
+
pointer-events: auto;
|
|
229
|
+
transition: opacity 0.3s ease-in 0.1s;
|
|
230
|
+
}
|
|
231
|
+
`;
|
|
232
|
+
document.head.appendChild(style);
|
|
218
233
|
}
|
|
219
234
|
}
|
|
220
235
|
|
|
221
|
-
/**
|
|
222
|
-
* Factory helper
|
|
223
|
-
*/
|
|
224
236
|
export function sidebar(id: string, options: SidebarOptions = {}): Sidebar {
|
|
225
237
|
return new Sidebar(id, options);
|
|
226
238
|
}
|
package/lib/components/style.ts
CHANGED
|
@@ -6,101 +6,38 @@ import { ErrorHandler } from './error-handler.js';
|
|
|
6
6
|
* Auto-renders when created or modified
|
|
7
7
|
*/
|
|
8
8
|
export class Style {
|
|
9
|
-
private
|
|
10
|
-
private
|
|
9
|
+
private _id: string;
|
|
10
|
+
private css: string;
|
|
11
11
|
|
|
12
|
-
constructor(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
if (content) {
|
|
17
|
-
this.render();
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Set inline CSS content
|
|
23
|
-
*/
|
|
24
|
-
content(css: string): this {
|
|
25
|
-
this._content = css;
|
|
26
|
-
this.render();
|
|
27
|
-
return this;
|
|
12
|
+
constructor(css: string, id?: string) {
|
|
13
|
+
// ID only for deduplication, auto-generate if not provided
|
|
14
|
+
this._id = id || `jux-style-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
15
|
+
this.css = css;
|
|
28
16
|
}
|
|
29
17
|
|
|
30
|
-
/**
|
|
31
|
-
* Append CSS to existing content
|
|
32
|
-
*/
|
|
33
|
-
append(css: string): this {
|
|
34
|
-
this._content += '\n' + css;
|
|
35
|
-
this.render();
|
|
36
|
-
return this;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Prepend CSS to existing content
|
|
41
|
-
*/
|
|
42
|
-
prepend(css: string): this {
|
|
43
|
-
this._content = css + '\n' + this._content;
|
|
44
|
-
this.render();
|
|
45
|
-
return this;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Render the inline style element
|
|
50
|
-
*/
|
|
51
18
|
render(): this {
|
|
52
|
-
if
|
|
19
|
+
// Check if style with this ID already exists
|
|
20
|
+
if (document.getElementById(this._id)) {
|
|
53
21
|
return this;
|
|
54
22
|
}
|
|
55
23
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
// Create <style> element for inline CSS
|
|
61
|
-
const style = document.createElement('style');
|
|
62
|
-
style.textContent = this._content;
|
|
63
|
-
document.head.appendChild(style);
|
|
64
|
-
this._element = style;
|
|
65
|
-
|
|
66
|
-
console.log('✓ Inline styles rendered');
|
|
67
|
-
} catch (error: any) {
|
|
68
|
-
ErrorHandler.captureError({
|
|
69
|
-
component: 'Style',
|
|
70
|
-
method: 'render',
|
|
71
|
-
message: error.message,
|
|
72
|
-
stack: error.stack,
|
|
73
|
-
timestamp: new Date(),
|
|
74
|
-
context: {
|
|
75
|
-
type: 'inline',
|
|
76
|
-
error: 'runtime_exception'
|
|
77
|
-
}
|
|
78
|
-
});
|
|
79
|
-
}
|
|
24
|
+
const style = document.createElement('style');
|
|
25
|
+
style.id = this._id;
|
|
26
|
+
style.textContent = this.css;
|
|
27
|
+
document.head.appendChild(style);
|
|
80
28
|
|
|
81
29
|
return this;
|
|
82
30
|
}
|
|
83
31
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
if (this._element && this._element.parentNode) {
|
|
89
|
-
this._element.parentNode.removeChild(this._element);
|
|
90
|
-
this._element = null;
|
|
32
|
+
remove(): void {
|
|
33
|
+
const existing = document.getElementById(this._id);
|
|
34
|
+
if (existing) {
|
|
35
|
+
existing.remove();
|
|
91
36
|
}
|
|
92
|
-
return this;
|
|
93
37
|
}
|
|
94
38
|
}
|
|
95
39
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
* Usage:
|
|
100
|
-
* jux.style('body { margin: 0; }');
|
|
101
|
-
* jux.style().content('.highlight { color: red; }');
|
|
102
|
-
* jux.style('h1 { font-size: 2rem; }').append('h2 { font-size: 1.5rem; }');
|
|
103
|
-
*/
|
|
104
|
-
export function style(content: string = ''): Style {
|
|
105
|
-
return new Style(content);
|
|
40
|
+
// ✅ ID is optional
|
|
41
|
+
export function style(css: string, id?: string): Style {
|
|
42
|
+
return new Style(css, id);
|
|
106
43
|
}
|