juxscript 1.0.3 → 1.0.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/README.md +37 -92
- package/bin/cli.js +57 -56
- package/lib/components/alert.ts +240 -0
- package/lib/components/app.ts +216 -82
- package/lib/components/badge.ts +164 -0
- package/lib/components/button.ts +188 -53
- package/lib/components/card.ts +75 -61
- package/lib/components/chart.ts +17 -15
- package/lib/components/checkbox.ts +228 -0
- package/lib/components/code.ts +66 -152
- package/lib/components/container.ts +104 -208
- package/lib/components/data.ts +1 -3
- package/lib/components/datepicker.ts +226 -0
- package/lib/components/dialog.ts +258 -0
- package/lib/components/docs-data.json +1697 -388
- package/lib/components/dropdown.ts +244 -0
- package/lib/components/element.ts +271 -0
- package/lib/components/fileupload.ts +319 -0
- package/lib/components/footer.ts +37 -18
- package/lib/components/header.ts +53 -33
- package/lib/components/heading.ts +119 -0
- package/lib/components/helpers.ts +34 -0
- package/lib/components/hero.ts +57 -31
- package/lib/components/include.ts +292 -0
- package/lib/components/input.ts +166 -78
- package/lib/components/layout.ts +144 -18
- package/lib/components/list.ts +83 -74
- package/lib/components/loading.ts +263 -0
- package/lib/components/main.ts +43 -17
- package/lib/components/menu.ts +108 -24
- package/lib/components/modal.ts +50 -21
- package/lib/components/nav.ts +60 -18
- package/lib/components/paragraph.ts +111 -0
- package/lib/components/progress.ts +276 -0
- package/lib/components/radio.ts +236 -0
- package/lib/components/req.ts +300 -0
- package/lib/components/script.ts +33 -74
- package/lib/components/select.ts +247 -0
- package/lib/components/sidebar.ts +86 -36
- package/lib/components/style.ts +47 -70
- package/lib/components/switch.ts +261 -0
- package/lib/components/table.ts +47 -24
- package/lib/components/tabs.ts +105 -63
- package/lib/components/theme-toggle.ts +361 -0
- package/lib/components/token-calculator.ts +380 -0
- package/lib/components/tooltip.ts +244 -0
- package/lib/components/view.ts +36 -20
- package/lib/components/write.ts +284 -0
- package/lib/globals.d.ts +21 -0
- package/lib/jux.ts +172 -68
- package/lib/presets/notion.css +521 -0
- package/lib/presets/notion.jux +27 -0
- package/lib/reactivity/state.ts +364 -0
- package/machinery/compiler.js +126 -38
- package/machinery/generators/html.js +2 -3
- package/machinery/server.js +2 -2
- package/package.json +29 -3
- package/lib/components/import.ts +0 -430
- package/lib/components/node.ts +0 -200
- package/lib/components/reactivity.js +0 -104
- package/lib/components/theme.ts +0 -97
- package/lib/layouts/notion.css +0 -258
- package/lib/styles/base-theme.css +0 -186
- package/lib/styles/dark-theme.css +0 -144
- package/lib/styles/light-theme.css +0 -144
- package/lib/styles/tokens/dark.css +0 -86
- package/lib/styles/tokens/light.css +0 -86
- package/lib/templates/index.juxt +0 -33
- package/lib/themes/dark.css +0 -86
- package/lib/themes/light.css +0 -86
- /package/lib/{styles → presets}/global.css +0 -0
package/lib/components/table.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getOrCreateContainer } from './helpers.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Table column configuration
|
|
@@ -20,7 +20,9 @@ export interface TableOptions {
|
|
|
20
20
|
striped?: boolean;
|
|
21
21
|
hoverable?: boolean;
|
|
22
22
|
bordered?: boolean;
|
|
23
|
-
allowHtml?: boolean;
|
|
23
|
+
allowHtml?: boolean;
|
|
24
|
+
style?: string;
|
|
25
|
+
class?: string;
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
/**
|
|
@@ -33,6 +35,8 @@ type TableState = {
|
|
|
33
35
|
hoverable: boolean;
|
|
34
36
|
bordered: boolean;
|
|
35
37
|
allowHtml: boolean;
|
|
38
|
+
style: string;
|
|
39
|
+
class: string;
|
|
36
40
|
};
|
|
37
41
|
|
|
38
42
|
/**
|
|
@@ -46,7 +50,7 @@ type TableState = {
|
|
|
46
50
|
* { name: 'Bob', age: 25 }
|
|
47
51
|
* ],
|
|
48
52
|
* striped: true,
|
|
49
|
-
* allowHtml: true
|
|
53
|
+
* allowHtml: true
|
|
50
54
|
* });
|
|
51
55
|
* table.render();
|
|
52
56
|
*
|
|
@@ -63,22 +67,26 @@ type TableState = {
|
|
|
63
67
|
* });
|
|
64
68
|
* table.render();
|
|
65
69
|
*/
|
|
66
|
-
export class Table
|
|
67
|
-
state
|
|
70
|
+
export class Table {
|
|
71
|
+
state: TableState;
|
|
68
72
|
container: HTMLElement | null = null;
|
|
73
|
+
_id: string;
|
|
74
|
+
id: string;
|
|
69
75
|
|
|
70
|
-
constructor(
|
|
71
|
-
|
|
72
|
-
this.
|
|
76
|
+
constructor(id: string, options: TableOptions = {}) {
|
|
77
|
+
this._id = id;
|
|
78
|
+
this.id = id;
|
|
73
79
|
|
|
74
|
-
this.state =
|
|
80
|
+
this.state = {
|
|
75
81
|
columns: options.columns ?? [],
|
|
76
82
|
data: options.data ?? [],
|
|
77
83
|
striped: options.striped ?? false,
|
|
78
84
|
hoverable: options.hoverable ?? true,
|
|
79
85
|
bordered: options.bordered ?? false,
|
|
80
|
-
allowHtml: options.allowHtml ?? true
|
|
81
|
-
|
|
86
|
+
allowHtml: options.allowHtml ?? true,
|
|
87
|
+
style: options.style ?? '',
|
|
88
|
+
class: options.class ?? ''
|
|
89
|
+
};
|
|
82
90
|
}
|
|
83
91
|
|
|
84
92
|
/* -------------------------
|
|
@@ -115,6 +123,16 @@ export class Table extends Reactive {
|
|
|
115
123
|
return this;
|
|
116
124
|
}
|
|
117
125
|
|
|
126
|
+
style(value: string): this {
|
|
127
|
+
this.state.style = value;
|
|
128
|
+
return this;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
class(value: string): this {
|
|
132
|
+
this.state.class = value;
|
|
133
|
+
return this;
|
|
134
|
+
}
|
|
135
|
+
|
|
118
136
|
/* -------------------------
|
|
119
137
|
* Helpers
|
|
120
138
|
* ------------------------- */
|
|
@@ -144,14 +162,12 @@ export class Table extends Reactive {
|
|
|
144
162
|
* 'user_id' -> 'User Id'
|
|
145
163
|
*/
|
|
146
164
|
private _formatLabel(key: string): string {
|
|
147
|
-
// Split on camelCase or snake_case
|
|
148
165
|
const words = key
|
|
149
|
-
.replace(/([A-Z])/g, ' $1')
|
|
150
|
-
.replace(/_/g, ' ')
|
|
166
|
+
.replace(/([A-Z])/g, ' $1')
|
|
167
|
+
.replace(/_/g, ' ')
|
|
151
168
|
.trim()
|
|
152
169
|
.split(/\s+/);
|
|
153
170
|
|
|
154
|
-
// Capitalize first letter of each word
|
|
155
171
|
return words
|
|
156
172
|
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
|
157
173
|
.join(' ');
|
|
@@ -171,11 +187,11 @@ export class Table extends Reactive {
|
|
|
171
187
|
}
|
|
172
188
|
container = target;
|
|
173
189
|
} else {
|
|
174
|
-
container = getOrCreateContainer(this.
|
|
190
|
+
container = getOrCreateContainer(this._id);
|
|
175
191
|
}
|
|
176
192
|
|
|
177
193
|
this.container = container;
|
|
178
|
-
let { columns, data, striped, hoverable, bordered, allowHtml } = this.state;
|
|
194
|
+
let { columns, data, striped, hoverable, bordered, allowHtml, style, class: className } = this.state;
|
|
179
195
|
|
|
180
196
|
// Auto-generate columns if not provided
|
|
181
197
|
if (columns.length === 0 && data.length > 0) {
|
|
@@ -184,7 +200,15 @@ export class Table extends Reactive {
|
|
|
184
200
|
|
|
185
201
|
const wrapper = document.createElement('div');
|
|
186
202
|
wrapper.className = 'jux-table-wrapper';
|
|
187
|
-
wrapper.id = this.
|
|
203
|
+
wrapper.id = this._id;
|
|
204
|
+
|
|
205
|
+
if (className) {
|
|
206
|
+
wrapper.className += ` ${className}`;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (style) {
|
|
210
|
+
wrapper.setAttribute('style', style);
|
|
211
|
+
}
|
|
188
212
|
|
|
189
213
|
const table = document.createElement('table');
|
|
190
214
|
table.className = 'jux-table';
|
|
@@ -218,7 +242,6 @@ export class Table extends Reactive {
|
|
|
218
242
|
const td = document.createElement('td');
|
|
219
243
|
if (col.align) td.style.textAlign = col.align;
|
|
220
244
|
|
|
221
|
-
// Get cell value
|
|
222
245
|
const cellValue = row[col.key] ?? '';
|
|
223
246
|
|
|
224
247
|
// Custom render function takes precedence
|
|
@@ -263,17 +286,17 @@ export class Table extends Reactive {
|
|
|
263
286
|
throw new Error('Table.renderTo: Invalid component - not an object');
|
|
264
287
|
}
|
|
265
288
|
|
|
266
|
-
if (!juxComponent.
|
|
267
|
-
throw new Error('Table.renderTo: Invalid component - missing
|
|
289
|
+
if (!juxComponent._id || typeof juxComponent._id !== 'string') {
|
|
290
|
+
throw new Error('Table.renderTo: Invalid component - missing _id (not a Jux component)');
|
|
268
291
|
}
|
|
269
292
|
|
|
270
|
-
return this.render(`#${juxComponent.
|
|
293
|
+
return this.render(`#${juxComponent._id}`);
|
|
271
294
|
}
|
|
272
295
|
}
|
|
273
296
|
|
|
274
297
|
/**
|
|
275
298
|
* Factory helper
|
|
276
299
|
*/
|
|
277
|
-
export function table(
|
|
278
|
-
return new Table(
|
|
300
|
+
export function table(id: string, options: TableOptions = {}): Table {
|
|
301
|
+
return new Table(id, options);
|
|
279
302
|
}
|
package/lib/components/tabs.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getOrCreateContainer } from './helpers.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Tab configuration
|
|
@@ -15,6 +15,8 @@ export interface Tab {
|
|
|
15
15
|
export interface TabsOptions {
|
|
16
16
|
tabs?: Tab[];
|
|
17
17
|
activeTab?: string;
|
|
18
|
+
style?: string;
|
|
19
|
+
class?: string;
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
/**
|
|
@@ -23,6 +25,8 @@ export interface TabsOptions {
|
|
|
23
25
|
type TabsState = {
|
|
24
26
|
tabs: Tab[];
|
|
25
27
|
activeTab: string;
|
|
28
|
+
style: string;
|
|
29
|
+
class: string;
|
|
26
30
|
};
|
|
27
31
|
|
|
28
32
|
/**
|
|
@@ -35,23 +39,27 @@ type TabsState = {
|
|
|
35
39
|
* { id: 'tab2', label: 'Tab 2', content: 'Content 2' }
|
|
36
40
|
* ]
|
|
37
41
|
* });
|
|
38
|
-
*
|
|
42
|
+
* tabs.render();
|
|
39
43
|
*/
|
|
40
|
-
export class Tabs
|
|
41
|
-
state
|
|
44
|
+
export class Tabs {
|
|
45
|
+
state: TabsState;
|
|
42
46
|
container: HTMLElement | null = null;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
_id: string;
|
|
48
|
+
id: string;
|
|
49
|
+
|
|
50
|
+
constructor(id: string, options: TabsOptions = {}) {
|
|
51
|
+
this._id = id;
|
|
52
|
+
this.id = id;
|
|
53
|
+
|
|
48
54
|
const tabs = options.tabs ?? [];
|
|
49
55
|
const activeTab = options.activeTab ?? (tabs.length > 0 ? tabs[0].id : '');
|
|
50
|
-
|
|
51
|
-
this.state =
|
|
56
|
+
|
|
57
|
+
this.state = {
|
|
52
58
|
tabs,
|
|
53
|
-
activeTab
|
|
54
|
-
|
|
59
|
+
activeTab,
|
|
60
|
+
style: options.style ?? '',
|
|
61
|
+
class: options.class ?? ''
|
|
62
|
+
};
|
|
55
63
|
}
|
|
56
64
|
|
|
57
65
|
/* -------------------------
|
|
@@ -64,7 +72,7 @@ export class Tabs extends Reactive {
|
|
|
64
72
|
}
|
|
65
73
|
|
|
66
74
|
addTab(tab: Tab): this {
|
|
67
|
-
this.state.tabs.
|
|
75
|
+
this.state.tabs = [...this.state.tabs, tab];
|
|
68
76
|
return this;
|
|
69
77
|
}
|
|
70
78
|
|
|
@@ -73,13 +81,57 @@ export class Tabs extends Reactive {
|
|
|
73
81
|
return this;
|
|
74
82
|
}
|
|
75
83
|
|
|
84
|
+
style(value: string): this {
|
|
85
|
+
this.state.style = value;
|
|
86
|
+
return this;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
class(value: string): this {
|
|
90
|
+
this.state.class = value;
|
|
91
|
+
return this;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* -------------------------
|
|
95
|
+
* Helpers
|
|
96
|
+
* ------------------------- */
|
|
97
|
+
|
|
98
|
+
private _updateActiveTab(tabId: string): void {
|
|
99
|
+
if (!this.container) return;
|
|
100
|
+
|
|
101
|
+
const wrapper = this.container.querySelector(`#${this._id}`);
|
|
102
|
+
if (!wrapper) return;
|
|
103
|
+
|
|
104
|
+
this.state.activeTab = tabId;
|
|
105
|
+
|
|
106
|
+
// Update tab buttons
|
|
107
|
+
const tabButtons = wrapper.querySelectorAll('.jux-tab-button');
|
|
108
|
+
tabButtons.forEach((btn, index) => {
|
|
109
|
+
if (this.state.tabs[index]?.id === tabId) {
|
|
110
|
+
btn.classList.add('jux-tab-button-active');
|
|
111
|
+
} else {
|
|
112
|
+
btn.classList.remove('jux-tab-button-active');
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// Update tab panels
|
|
117
|
+
const tabPanels = wrapper.querySelectorAll('.jux-tab-panel');
|
|
118
|
+
tabPanels.forEach(panel => {
|
|
119
|
+
const panelId = panel.getAttribute('data-tab-id');
|
|
120
|
+
if (panelId === tabId) {
|
|
121
|
+
panel.classList.add('jux-tab-panel-active');
|
|
122
|
+
} else {
|
|
123
|
+
panel.classList.remove('jux-tab-panel-active');
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
76
128
|
/* -------------------------
|
|
77
129
|
* Render
|
|
78
130
|
* ------------------------- */
|
|
79
131
|
|
|
80
|
-
|
|
132
|
+
render(targetId?: string): this {
|
|
81
133
|
let container: HTMLElement;
|
|
82
|
-
|
|
134
|
+
|
|
83
135
|
if (targetId) {
|
|
84
136
|
const target = document.querySelector(targetId);
|
|
85
137
|
if (!target || !(target instanceof HTMLElement)) {
|
|
@@ -87,105 +139,95 @@ export class Tabs extends Reactive {
|
|
|
87
139
|
}
|
|
88
140
|
container = target;
|
|
89
141
|
} else {
|
|
90
|
-
container = getOrCreateContainer(this.
|
|
142
|
+
container = getOrCreateContainer(this._id);
|
|
91
143
|
}
|
|
92
|
-
|
|
144
|
+
|
|
93
145
|
this.container = container;
|
|
94
|
-
const { tabs, activeTab } = this.state;
|
|
95
|
-
|
|
146
|
+
const { tabs, activeTab, style, class: className } = this.state;
|
|
147
|
+
|
|
96
148
|
const wrapper = document.createElement('div');
|
|
97
149
|
wrapper.className = 'jux-tabs';
|
|
98
|
-
wrapper.id = this.
|
|
99
|
-
|
|
150
|
+
wrapper.id = this._id;
|
|
151
|
+
|
|
152
|
+
if (className) {
|
|
153
|
+
wrapper.className += ` ${className}`;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (style) {
|
|
157
|
+
wrapper.setAttribute('style', style);
|
|
158
|
+
}
|
|
159
|
+
|
|
100
160
|
// Tab headers
|
|
101
161
|
const tabHeaders = document.createElement('div');
|
|
102
162
|
tabHeaders.className = 'jux-tabs-header';
|
|
103
|
-
|
|
163
|
+
|
|
104
164
|
tabs.forEach(tab => {
|
|
105
165
|
const tabBtn = document.createElement('button');
|
|
106
166
|
tabBtn.className = 'jux-tab-button';
|
|
107
167
|
tabBtn.textContent = tab.label;
|
|
108
|
-
|
|
168
|
+
|
|
109
169
|
if (tab.id === activeTab) {
|
|
110
170
|
tabBtn.classList.add('jux-tab-button-active');
|
|
111
171
|
}
|
|
112
|
-
|
|
172
|
+
|
|
113
173
|
tabHeaders.appendChild(tabBtn);
|
|
114
|
-
|
|
174
|
+
|
|
115
175
|
// Event binding - tab click
|
|
116
176
|
tabBtn.addEventListener('click', () => {
|
|
117
|
-
this.
|
|
118
|
-
|
|
119
|
-
// Update active states
|
|
120
|
-
tabHeaders.querySelectorAll('.jux-tab-button').forEach(btn => {
|
|
121
|
-
btn.classList.remove('jux-tab-button-active');
|
|
122
|
-
});
|
|
123
|
-
tabBtn.classList.add('jux-tab-button-active');
|
|
124
|
-
|
|
125
|
-
// Update content
|
|
126
|
-
tabPanels.querySelectorAll('.jux-tab-panel').forEach(panel => {
|
|
127
|
-
panel.classList.remove('jux-tab-panel-active');
|
|
128
|
-
});
|
|
129
|
-
const activePanel = tabPanels.querySelector(`[data-tab-id="${tab.id}"]`);
|
|
130
|
-
if (activePanel) {
|
|
131
|
-
activePanel.classList.add('jux-tab-panel-active');
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
this.emit('tabChange', { tabId: tab.id });
|
|
177
|
+
this._updateActiveTab(tab.id);
|
|
135
178
|
});
|
|
136
179
|
});
|
|
137
|
-
|
|
180
|
+
|
|
138
181
|
wrapper.appendChild(tabHeaders);
|
|
139
|
-
|
|
182
|
+
|
|
140
183
|
// Tab panels
|
|
141
184
|
const tabPanels = document.createElement('div');
|
|
142
185
|
tabPanels.className = 'jux-tabs-panels';
|
|
143
|
-
|
|
144
|
-
|
|
186
|
+
|
|
187
|
+
tabs.forEach(tab => {
|
|
145
188
|
const panel = document.createElement('div');
|
|
146
189
|
panel.className = 'jux-tab-panel';
|
|
147
190
|
panel.setAttribute('data-tab-id', tab.id);
|
|
148
|
-
|
|
191
|
+
|
|
149
192
|
if (tab.id === activeTab) {
|
|
150
193
|
panel.classList.add('jux-tab-panel-active');
|
|
151
194
|
}
|
|
152
|
-
|
|
195
|
+
|
|
153
196
|
// Render content
|
|
154
197
|
if (typeof tab.content === 'function') {
|
|
155
198
|
panel.innerHTML = tab.content();
|
|
156
199
|
} else {
|
|
157
200
|
panel.innerHTML = tab.content;
|
|
158
201
|
}
|
|
159
|
-
|
|
202
|
+
|
|
160
203
|
tabPanels.appendChild(panel);
|
|
161
|
-
}
|
|
162
|
-
|
|
204
|
+
});
|
|
205
|
+
|
|
163
206
|
wrapper.appendChild(tabPanels);
|
|
164
207
|
container.appendChild(wrapper);
|
|
165
|
-
|
|
166
|
-
this.emit('rendered');
|
|
208
|
+
|
|
167
209
|
return this;
|
|
168
210
|
}
|
|
169
211
|
|
|
170
212
|
/**
|
|
171
213
|
* Render to another Jux component's container
|
|
172
214
|
*/
|
|
173
|
-
|
|
215
|
+
renderTo(juxComponent: any): this {
|
|
174
216
|
if (!juxComponent || typeof juxComponent !== 'object') {
|
|
175
217
|
throw new Error('Tabs.renderTo: Invalid component - not an object');
|
|
176
218
|
}
|
|
177
|
-
|
|
178
|
-
if (!juxComponent.
|
|
179
|
-
throw new Error('Tabs.renderTo: Invalid component - missing
|
|
219
|
+
|
|
220
|
+
if (!juxComponent._id || typeof juxComponent._id !== 'string') {
|
|
221
|
+
throw new Error('Tabs.renderTo: Invalid component - missing _id (not a Jux component)');
|
|
180
222
|
}
|
|
181
|
-
|
|
182
|
-
return this.render(`#${juxComponent.
|
|
223
|
+
|
|
224
|
+
return this.render(`#${juxComponent._id}`);
|
|
183
225
|
}
|
|
184
226
|
}
|
|
185
227
|
|
|
186
228
|
/**
|
|
187
229
|
* Factory helper
|
|
188
230
|
*/
|
|
189
|
-
export function tabs(
|
|
190
|
-
return new Tabs(
|
|
231
|
+
export function tabs(id: string, options: TabsOptions = {}): Tabs {
|
|
232
|
+
return new Tabs(id, options);
|
|
191
233
|
}
|