juxscript 1.1.350 → 1.1.352
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/dist/lib/components/blocks/menu.d.ts +40 -0
- package/dist/lib/components/blocks/menu.d.ts.map +1 -0
- package/dist/lib/components/blocks/menu.js +136 -0
- package/dist/lib/components/button.d.ts +33 -0
- package/dist/lib/components/button.d.ts.map +1 -0
- package/dist/lib/components/button.js +107 -0
- package/dist/lib/components/checkbox.d.ts +62 -0
- package/dist/lib/components/checkbox.d.ts.map +1 -0
- package/dist/lib/components/checkbox.js +178 -0
- package/dist/lib/components/container.d.ts +58 -0
- package/dist/lib/components/container.d.ts.map +1 -0
- package/dist/lib/components/container.js +151 -0
- package/dist/lib/components/data.d.ts +58 -0
- package/dist/lib/components/data.d.ts.map +1 -0
- package/dist/lib/components/data.js +130 -0
- package/dist/lib/components/grid.d.ts +58 -0
- package/dist/lib/components/grid.d.ts.map +1 -0
- package/dist/lib/components/grid.js +127 -0
- package/dist/lib/components/include.d.ts +86 -0
- package/dist/lib/components/include.d.ts.map +1 -0
- package/dist/lib/components/include.js +238 -0
- package/dist/lib/components/input.d.ts +58 -0
- package/dist/lib/components/input.d.ts.map +1 -0
- package/dist/lib/components/input.js +161 -0
- package/dist/lib/components/link.d.ts +35 -0
- package/dist/lib/components/link.d.ts.map +1 -0
- package/dist/lib/components/link.js +135 -0
- package/dist/lib/components/list.d.ts +48 -0
- package/dist/lib/components/list.d.ts.map +1 -0
- package/dist/lib/components/list.js +178 -0
- package/dist/lib/components/nav.d.ts +46 -0
- package/dist/lib/components/nav.d.ts.map +1 -0
- package/dist/lib/components/nav.js +189 -0
- package/dist/lib/components/radio.d.ts +40 -0
- package/dist/lib/components/radio.d.ts.map +1 -0
- package/dist/lib/components/radio.js +112 -0
- package/dist/lib/components/select.d.ts +41 -0
- package/dist/lib/components/select.d.ts.map +1 -0
- package/dist/lib/components/select.js +111 -0
- package/dist/lib/components/sidebar.d.ts +40 -0
- package/dist/lib/components/sidebar.d.ts.map +1 -0
- package/dist/lib/components/sidebar.js +141 -0
- package/dist/lib/components/store.d.ts +78 -0
- package/dist/lib/components/store.d.ts.map +1 -0
- package/dist/lib/components/store.js +248 -0
- package/dist/lib/components/style.d.ts +27 -0
- package/dist/lib/components/style.d.ts.map +1 -0
- package/dist/lib/components/style.js +52 -0
- package/dist/lib/components/table.d.ts +56 -0
- package/dist/lib/components/table.d.ts.map +1 -0
- package/dist/lib/components/table.js +199 -0
- package/dist/lib/components/tabs.d.ts +52 -0
- package/dist/lib/components/tabs.d.ts.map +1 -0
- package/dist/lib/components/tabs.js +206 -0
- package/dist/lib/components/tag.d.ts +41 -0
- package/dist/lib/components/tag.d.ts.map +1 -0
- package/dist/lib/components/tag.js +103 -0
- package/dist/lib/devtools/devtools.d.ts +3 -0
- package/dist/lib/devtools/devtools.d.ts.map +1 -0
- package/dist/lib/devtools/devtools.js +181 -0
- package/dist/lib/index.d.ts +68 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +63 -0
- package/dist/lib/state/pageState.d.ts +19 -0
- package/dist/lib/state/pageState.d.ts.map +1 -0
- package/dist/lib/state/pageState.js +360 -0
- package/dist/lib/utils/codeHighlight.d.ts +7 -0
- package/dist/lib/utils/codeHighlight.d.ts.map +1 -0
- package/dist/lib/utils/codeHighlight.js +105 -0
- package/dist/lib/utils/codeparser.d.ts +29 -0
- package/dist/lib/utils/codeparser.d.ts.map +1 -0
- package/dist/lib/utils/codeparser.js +384 -0
- package/dist/lib/utils/fetch.d.ts +176 -0
- package/dist/lib/utils/fetch.d.ts.map +1 -0
- package/dist/lib/utils/fetch.js +427 -0
- package/dist/lib/utils/formatId.d.ts +16 -0
- package/dist/lib/utils/formatId.d.ts.map +1 -0
- package/dist/lib/utils/formatId.js +27 -0
- package/dist/lib/utils/idgen.d.ts +2 -0
- package/dist/lib/utils/idgen.d.ts.map +1 -0
- package/dist/lib/utils/idgen.js +4 -0
- package/dist/lib/utils/niceName.d.ts +14 -0
- package/dist/lib/utils/niceName.d.ts.map +1 -0
- package/dist/lib/utils/niceName.js +22 -0
- package/package.json +1 -1
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Include - Simplified resource injection for bundled and external resources
|
|
3
|
+
* Supports page-specific scoping and cleanup
|
|
4
|
+
*/
|
|
5
|
+
// Global registry for page-scoped resources
|
|
6
|
+
const scopedResources = new Map();
|
|
7
|
+
export class Include {
|
|
8
|
+
constructor(url, options = {}) {
|
|
9
|
+
this.element = null;
|
|
10
|
+
this.pageId = null;
|
|
11
|
+
this.url = url;
|
|
12
|
+
this.options = options;
|
|
13
|
+
// Auto-detect type from extension if not provided
|
|
14
|
+
if (!options.type) {
|
|
15
|
+
if (url.endsWith('.css')) {
|
|
16
|
+
this.options.type = 'css';
|
|
17
|
+
}
|
|
18
|
+
else if (url.endsWith('.mjs') || url.endsWith('.module.js')) {
|
|
19
|
+
this.options.type = 'module';
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
this.options.type = 'js';
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/* -------------------------
|
|
27
|
+
* Fluent API
|
|
28
|
+
* ------------------------- */
|
|
29
|
+
css() {
|
|
30
|
+
this.options.type = 'css';
|
|
31
|
+
return this;
|
|
32
|
+
}
|
|
33
|
+
js() {
|
|
34
|
+
this.options.type = 'js';
|
|
35
|
+
return this;
|
|
36
|
+
}
|
|
37
|
+
module() {
|
|
38
|
+
this.options.type = 'module';
|
|
39
|
+
return this;
|
|
40
|
+
}
|
|
41
|
+
async() {
|
|
42
|
+
this.options.async = true;
|
|
43
|
+
return this;
|
|
44
|
+
}
|
|
45
|
+
defer() {
|
|
46
|
+
this.options.defer = true;
|
|
47
|
+
return this;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Inject into specific container instead of <head>
|
|
51
|
+
* Useful for page-specific styles
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* jux.include('/css/page1.css').into('#page1-container');
|
|
55
|
+
*/
|
|
56
|
+
into(selector) {
|
|
57
|
+
this.options.target = selector;
|
|
58
|
+
return this;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Mark as page-scoped for automatic cleanup
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* jux.include('/css/dashboard.css').forPage('dashboard');
|
|
65
|
+
* // Later: Include.cleanupPage('dashboard');
|
|
66
|
+
*/
|
|
67
|
+
forPage(pageId) {
|
|
68
|
+
this.pageId = pageId;
|
|
69
|
+
this.options.pageScoped = true;
|
|
70
|
+
return this;
|
|
71
|
+
}
|
|
72
|
+
/* -------------------------
|
|
73
|
+
* Render
|
|
74
|
+
* ------------------------- */
|
|
75
|
+
render() {
|
|
76
|
+
if (typeof document === 'undefined')
|
|
77
|
+
return this;
|
|
78
|
+
try {
|
|
79
|
+
// Check if already loaded
|
|
80
|
+
if (this.isAlreadyLoaded()) {
|
|
81
|
+
console.log(`⚠️ Resource already loaded: ${this.url}`);
|
|
82
|
+
return this;
|
|
83
|
+
}
|
|
84
|
+
// Create element based on type
|
|
85
|
+
let element;
|
|
86
|
+
switch (this.options.type) {
|
|
87
|
+
case 'css':
|
|
88
|
+
element = this.createStylesheet();
|
|
89
|
+
break;
|
|
90
|
+
case 'js':
|
|
91
|
+
case 'module':
|
|
92
|
+
element = this.createScript();
|
|
93
|
+
break;
|
|
94
|
+
default:
|
|
95
|
+
throw new Error(`Unknown resource type: ${this.options.type}`);
|
|
96
|
+
}
|
|
97
|
+
// Get target container
|
|
98
|
+
const container = this.getContainer();
|
|
99
|
+
container.appendChild(element);
|
|
100
|
+
this.element = element;
|
|
101
|
+
// Register for page cleanup if needed
|
|
102
|
+
if (this.options.pageScoped && this.pageId) {
|
|
103
|
+
if (!scopedResources.has(this.pageId)) {
|
|
104
|
+
scopedResources.set(this.pageId, new Set());
|
|
105
|
+
}
|
|
106
|
+
scopedResources.get(this.pageId).add(element);
|
|
107
|
+
}
|
|
108
|
+
console.log(`✓ Loaded ${this.options.type}: ${this.url}`);
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
console.error(`✗ Failed to load ${this.options.type}: ${this.url}`, error);
|
|
112
|
+
throw error;
|
|
113
|
+
}
|
|
114
|
+
return this;
|
|
115
|
+
}
|
|
116
|
+
/* -------------------------
|
|
117
|
+
* Element Creation
|
|
118
|
+
* ------------------------- */
|
|
119
|
+
createStylesheet() {
|
|
120
|
+
const link = document.createElement('link');
|
|
121
|
+
link.rel = 'stylesheet';
|
|
122
|
+
link.href = this.url;
|
|
123
|
+
link.dataset.juxInclude = this.url;
|
|
124
|
+
if (this.options.crossOrigin)
|
|
125
|
+
link.crossOrigin = this.options.crossOrigin;
|
|
126
|
+
if (this.options.integrity)
|
|
127
|
+
link.integrity = this.options.integrity;
|
|
128
|
+
link.onload = () => console.log(`✓ Stylesheet loaded: ${this.url}`);
|
|
129
|
+
link.onerror = () => {
|
|
130
|
+
throw new Error(`Failed to load stylesheet: ${this.url}`);
|
|
131
|
+
};
|
|
132
|
+
return link;
|
|
133
|
+
}
|
|
134
|
+
createScript() {
|
|
135
|
+
const script = document.createElement('script');
|
|
136
|
+
script.src = this.url;
|
|
137
|
+
script.dataset.juxInclude = this.url;
|
|
138
|
+
if (this.options.type === 'module')
|
|
139
|
+
script.type = 'module';
|
|
140
|
+
if (this.options.async)
|
|
141
|
+
script.async = true;
|
|
142
|
+
if (this.options.defer)
|
|
143
|
+
script.defer = true;
|
|
144
|
+
if (this.options.crossOrigin)
|
|
145
|
+
script.crossOrigin = this.options.crossOrigin;
|
|
146
|
+
if (this.options.integrity)
|
|
147
|
+
script.integrity = this.options.integrity;
|
|
148
|
+
script.onload = () => console.log(`✓ Script loaded: ${this.url}`);
|
|
149
|
+
script.onerror = () => {
|
|
150
|
+
throw new Error(`Failed to load script: ${this.url}`);
|
|
151
|
+
};
|
|
152
|
+
return script;
|
|
153
|
+
}
|
|
154
|
+
/* -------------------------
|
|
155
|
+
* Helpers
|
|
156
|
+
* ------------------------- */
|
|
157
|
+
getContainer() {
|
|
158
|
+
if (this.options.target) {
|
|
159
|
+
const container = document.querySelector(this.options.target);
|
|
160
|
+
if (!container) {
|
|
161
|
+
throw new Error(`Target container not found: ${this.options.target}`);
|
|
162
|
+
}
|
|
163
|
+
return container;
|
|
164
|
+
}
|
|
165
|
+
return document.head;
|
|
166
|
+
}
|
|
167
|
+
isAlreadyLoaded() {
|
|
168
|
+
const selector = `[data-jux-include="${this.url}"]`;
|
|
169
|
+
return document.querySelector(selector) !== null;
|
|
170
|
+
}
|
|
171
|
+
remove() {
|
|
172
|
+
if (this.element?.parentNode) {
|
|
173
|
+
this.element.parentNode.removeChild(this.element);
|
|
174
|
+
this.element = null;
|
|
175
|
+
}
|
|
176
|
+
return this;
|
|
177
|
+
}
|
|
178
|
+
/* -------------------------
|
|
179
|
+
* Static Page Cleanup
|
|
180
|
+
* ------------------------- */
|
|
181
|
+
/**
|
|
182
|
+
* Remove all resources for a specific page
|
|
183
|
+
*
|
|
184
|
+
* @example
|
|
185
|
+
* Include.cleanupPage('dashboard');
|
|
186
|
+
*/
|
|
187
|
+
static cleanupPage(pageId) {
|
|
188
|
+
const resources = scopedResources.get(pageId);
|
|
189
|
+
if (!resources)
|
|
190
|
+
return;
|
|
191
|
+
resources.forEach(element => {
|
|
192
|
+
element.parentNode?.removeChild(element);
|
|
193
|
+
});
|
|
194
|
+
scopedResources.delete(pageId);
|
|
195
|
+
console.log(`✓ Cleaned up page resources: ${pageId}`);
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Remove all page-scoped resources
|
|
199
|
+
*/
|
|
200
|
+
static cleanupAll() {
|
|
201
|
+
scopedResources.forEach((resources, pageId) => {
|
|
202
|
+
resources.forEach(element => {
|
|
203
|
+
element.parentNode?.removeChild(element);
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
scopedResources.clear();
|
|
207
|
+
console.log('✓ Cleaned up all page-scoped resources');
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Factory function - simplified usage
|
|
212
|
+
*
|
|
213
|
+
* Usage:
|
|
214
|
+
* // Basic (auto-detects from extension)
|
|
215
|
+
* jux.include('/css/styles.css');
|
|
216
|
+
* jux.include('/js/app.js');
|
|
217
|
+
*
|
|
218
|
+
* // Page-specific with cleanup
|
|
219
|
+
* jux.include('/css/dashboard.css').forPage('dashboard');
|
|
220
|
+
* jux.include('/js/dashboard.js').forPage('dashboard');
|
|
221
|
+
*
|
|
222
|
+
* // Later cleanup:
|
|
223
|
+
* Include.cleanupPage('dashboard');
|
|
224
|
+
*
|
|
225
|
+
* // Inject into specific container
|
|
226
|
+
* jux.include('/css/widget.css').into('#widget-container');
|
|
227
|
+
*
|
|
228
|
+
* // External CDN
|
|
229
|
+
* jux.include('https://cdn.tailwindcss.com').js();
|
|
230
|
+
*
|
|
231
|
+
* // Module
|
|
232
|
+
* jux.include('/js/app.mjs').module();
|
|
233
|
+
*/
|
|
234
|
+
export function include(url, options) {
|
|
235
|
+
const inc = new Include(url, options);
|
|
236
|
+
inc.render();
|
|
237
|
+
return inc;
|
|
238
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
type InputType = 'text' | 'email' | 'password' | 'number' | 'tel' | 'url' | 'search' | 'date' | 'time' | 'datetime-local' | 'color' | 'range' | 'file' | 'hidden';
|
|
2
|
+
interface InputOptions {
|
|
3
|
+
type?: InputType;
|
|
4
|
+
label?: string;
|
|
5
|
+
placeholder?: string;
|
|
6
|
+
value?: string;
|
|
7
|
+
name?: string;
|
|
8
|
+
required?: boolean;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
readonly?: boolean;
|
|
11
|
+
min?: string | number;
|
|
12
|
+
max?: string | number;
|
|
13
|
+
step?: string | number;
|
|
14
|
+
pattern?: string;
|
|
15
|
+
autocomplete?: string;
|
|
16
|
+
class?: string;
|
|
17
|
+
style?: string;
|
|
18
|
+
}
|
|
19
|
+
declare class Input {
|
|
20
|
+
id: string;
|
|
21
|
+
options: InputOptions;
|
|
22
|
+
private _element;
|
|
23
|
+
private _wrapper;
|
|
24
|
+
private _onChange;
|
|
25
|
+
constructor(id: string, options?: InputOptions);
|
|
26
|
+
type(value: InputType): this;
|
|
27
|
+
label(value: string): this;
|
|
28
|
+
placeholder(value: string): this;
|
|
29
|
+
value(value: string): this;
|
|
30
|
+
name(value: string): this;
|
|
31
|
+
required(value?: boolean): this;
|
|
32
|
+
disabled(value?: boolean): this;
|
|
33
|
+
readonly(value?: boolean): this;
|
|
34
|
+
style(value: string): this;
|
|
35
|
+
class(value: string): this;
|
|
36
|
+
onChange(fn: (value: string, event: Event) => void): this;
|
|
37
|
+
getValue(): string;
|
|
38
|
+
getFiles(): FileList | null;
|
|
39
|
+
setValue(val: string): this;
|
|
40
|
+
setContent(val: string): this;
|
|
41
|
+
render(target?: string | HTMLElement): this;
|
|
42
|
+
}
|
|
43
|
+
export declare function input(id: string, options?: InputOptions): Input;
|
|
44
|
+
export declare function email(id: string, options?: InputOptions): Input;
|
|
45
|
+
export declare function password(id: string, options?: InputOptions): Input;
|
|
46
|
+
export declare function number(id: string, options?: InputOptions): Input;
|
|
47
|
+
export declare function tel(id: string, options?: InputOptions): Input;
|
|
48
|
+
export declare function url(id: string, options?: InputOptions): Input;
|
|
49
|
+
export declare function search(id: string, options?: InputOptions): Input;
|
|
50
|
+
export declare function date(id: string, options?: InputOptions): Input;
|
|
51
|
+
export declare function time(id: string, options?: InputOptions): Input;
|
|
52
|
+
export declare function datetime(id: string, options?: InputOptions): Input;
|
|
53
|
+
export declare function color(id: string, options?: InputOptions): Input;
|
|
54
|
+
export declare function range(id: string, options?: InputOptions): Input;
|
|
55
|
+
export declare function file(id: string, options?: InputOptions): Input;
|
|
56
|
+
export declare function hidden(id: string, options?: InputOptions): Input;
|
|
57
|
+
export { Input, InputOptions };
|
|
58
|
+
//# sourceMappingURL=input.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../../lib/components/input.ts"],"names":[],"mappings":"AAIA,KAAK,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,GAAG,KAAK,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,gBAAgB,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;AAElK,UAAU,YAAY;IAClB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,cAAM,KAAK;IACP,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,CAAC,QAAQ,CAAiC;IACjD,OAAO,CAAC,QAAQ,CAA4B;IAC5C,OAAO,CAAC,SAAS,CAAwD;gBAE7D,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB;IAclD,IAAI,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAC5B,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAC1B,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAChC,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAC1B,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IACzB,QAAQ,CAAC,KAAK,GAAE,OAAc,GAAG,IAAI;IACrC,QAAQ,CAAC,KAAK,GAAE,OAAc,GAAG,IAAI;IACrC,QAAQ,CAAC,KAAK,GAAE,OAAc,GAAG,IAAI;IACrC,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAC1B,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAE1B,QAAQ,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;IAKzD,QAAQ,IAAI,MAAM;IAIlB,QAAQ,IAAI,QAAQ,GAAG,IAAI;IAI3B,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAM3B,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAI7B,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,WAAW;CAqDvC;AAED,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,KAAK,CAKnE;AAMD,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,KAAK,CAEnE;AAED,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,KAAK,CAEtE;AAED,wBAAgB,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,KAAK,CAEpE;AAED,wBAAgB,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,KAAK,CAEjE;AAED,wBAAgB,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,KAAK,CAEjE;AAED,wBAAgB,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,KAAK,CAEpE;AAED,wBAAgB,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,KAAK,CAElE;AAED,wBAAgB,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,KAAK,CAElE;AAED,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,KAAK,CAEtE;AAED,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,KAAK,CAEnE;AAED,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,KAAK,CAEnE;AAED,wBAAgB,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,KAAK,CAElE;AAED,wBAAgB,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,KAAK,CAEpE;AAED,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import generateId from '../utils/idgen.js';
|
|
2
|
+
import niceName from '../utils/niceName.js';
|
|
3
|
+
import { pageState } from '../state/pageState.js';
|
|
4
|
+
class Input {
|
|
5
|
+
constructor(id, options = {}) {
|
|
6
|
+
this._element = null;
|
|
7
|
+
this._wrapper = null;
|
|
8
|
+
this._onChange = null;
|
|
9
|
+
this.id = id || generateId();
|
|
10
|
+
this.options = {
|
|
11
|
+
type: 'text',
|
|
12
|
+
...options
|
|
13
|
+
};
|
|
14
|
+
// Auto-generate label from ID if not provided
|
|
15
|
+
if (!this.options.label && this.id) {
|
|
16
|
+
this.options.label = niceName(this.id);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
// Fluent API
|
|
20
|
+
type(value) { this.options.type = value; return this; }
|
|
21
|
+
label(value) { this.options.label = value; return this; }
|
|
22
|
+
placeholder(value) { this.options.placeholder = value; return this; }
|
|
23
|
+
value(value) { this.options.value = value; if (this._element)
|
|
24
|
+
this._element.value = value; return this; }
|
|
25
|
+
name(value) { this.options.name = value; return this; }
|
|
26
|
+
required(value = true) { this.options.required = value; return this; }
|
|
27
|
+
disabled(value = true) { this.options.disabled = value; if (this._element)
|
|
28
|
+
this._element.disabled = value; return this; }
|
|
29
|
+
readonly(value = true) { this.options.readonly = value; return this; }
|
|
30
|
+
style(value) { this.options.style = value; return this; }
|
|
31
|
+
class(value) { this.options.class = value; return this; }
|
|
32
|
+
onChange(fn) {
|
|
33
|
+
this._onChange = fn;
|
|
34
|
+
return this;
|
|
35
|
+
}
|
|
36
|
+
getValue() {
|
|
37
|
+
return this._element?.value ?? this.options.value ?? '';
|
|
38
|
+
}
|
|
39
|
+
getFiles() {
|
|
40
|
+
return this._element?.files ?? null;
|
|
41
|
+
}
|
|
42
|
+
setValue(val) {
|
|
43
|
+
if (this._element)
|
|
44
|
+
this._element.value = val;
|
|
45
|
+
this.options.value = val;
|
|
46
|
+
return this;
|
|
47
|
+
}
|
|
48
|
+
setContent(val) {
|
|
49
|
+
return this.setValue(val);
|
|
50
|
+
}
|
|
51
|
+
render(target) {
|
|
52
|
+
const wrapper = document.createElement('div');
|
|
53
|
+
wrapper.className = 'jux-input';
|
|
54
|
+
wrapper.id = `${this.id}-wrapper`;
|
|
55
|
+
if (this.options.class)
|
|
56
|
+
wrapper.className += ` ${this.options.class}`;
|
|
57
|
+
if (this.options.style)
|
|
58
|
+
wrapper.setAttribute('style', this.options.style);
|
|
59
|
+
if (this.options.label) {
|
|
60
|
+
const labelEl = document.createElement('label');
|
|
61
|
+
labelEl.htmlFor = this.id;
|
|
62
|
+
labelEl.textContent = this.options.label;
|
|
63
|
+
labelEl.className = 'jux-input-label';
|
|
64
|
+
wrapper.appendChild(labelEl);
|
|
65
|
+
}
|
|
66
|
+
const input = document.createElement('input');
|
|
67
|
+
input.id = this.id;
|
|
68
|
+
input.type = this.options.type || 'text';
|
|
69
|
+
input.className = 'jux-input-element';
|
|
70
|
+
if (this.options.placeholder)
|
|
71
|
+
input.placeholder = this.options.placeholder;
|
|
72
|
+
if (this.options.value)
|
|
73
|
+
input.value = this.options.value;
|
|
74
|
+
if (this.options.name)
|
|
75
|
+
input.name = this.options.name;
|
|
76
|
+
if (this.options.required)
|
|
77
|
+
input.required = true;
|
|
78
|
+
if (this.options.disabled)
|
|
79
|
+
input.disabled = true;
|
|
80
|
+
if (this.options.readonly)
|
|
81
|
+
input.readOnly = true;
|
|
82
|
+
if (this.options.min != null)
|
|
83
|
+
input.min = String(this.options.min);
|
|
84
|
+
if (this.options.max != null)
|
|
85
|
+
input.max = String(this.options.max);
|
|
86
|
+
if (this.options.step != null)
|
|
87
|
+
input.step = String(this.options.step);
|
|
88
|
+
if (this.options.pattern)
|
|
89
|
+
input.pattern = this.options.pattern;
|
|
90
|
+
if (this.options.autocomplete)
|
|
91
|
+
input.autocomplete = this.options.autocomplete;
|
|
92
|
+
input.addEventListener('input', (e) => {
|
|
93
|
+
if (this._onChange)
|
|
94
|
+
this._onChange(input.value, e);
|
|
95
|
+
});
|
|
96
|
+
// For file inputs, also listen to 'change'
|
|
97
|
+
if (this.options.type === 'file') {
|
|
98
|
+
input.addEventListener('change', (e) => {
|
|
99
|
+
if (this._onChange)
|
|
100
|
+
this._onChange(input.value, e);
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
wrapper.appendChild(input);
|
|
104
|
+
this._element = input;
|
|
105
|
+
this._wrapper = wrapper;
|
|
106
|
+
const container = target
|
|
107
|
+
? (typeof target === 'string' ? document.getElementById(target) || document.querySelector(target) : target)
|
|
108
|
+
: document.getElementById('app');
|
|
109
|
+
container?.appendChild(wrapper);
|
|
110
|
+
return this;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
export function input(id, options = {}) {
|
|
114
|
+
const inp = new Input(id, options);
|
|
115
|
+
inp.render();
|
|
116
|
+
pageState.__register(inp);
|
|
117
|
+
return inp;
|
|
118
|
+
}
|
|
119
|
+
// ═══════════════════════════════════════════════════════════════
|
|
120
|
+
// TYPE-SPECIFIC FACTORY METHODS
|
|
121
|
+
// ═══════════════════════════════════════════════════════════════
|
|
122
|
+
export function email(id, options = {}) {
|
|
123
|
+
return input(id, { placeholder: 'name@example.com', autocomplete: 'email', ...options, type: 'email' });
|
|
124
|
+
}
|
|
125
|
+
export function password(id, options = {}) {
|
|
126
|
+
return input(id, { placeholder: '••••••••', autocomplete: 'current-password', ...options, type: 'password' });
|
|
127
|
+
}
|
|
128
|
+
export function number(id, options = {}) {
|
|
129
|
+
return input(id, { placeholder: '0', ...options, type: 'number' });
|
|
130
|
+
}
|
|
131
|
+
export function tel(id, options = {}) {
|
|
132
|
+
return input(id, { placeholder: '+1 (555) 000-0000', autocomplete: 'tel', ...options, type: 'tel' });
|
|
133
|
+
}
|
|
134
|
+
export function url(id, options = {}) {
|
|
135
|
+
return input(id, { placeholder: 'https://', autocomplete: 'url', ...options, type: 'url' });
|
|
136
|
+
}
|
|
137
|
+
export function search(id, options = {}) {
|
|
138
|
+
return input(id, { placeholder: 'Search...', ...options, type: 'search' });
|
|
139
|
+
}
|
|
140
|
+
export function date(id, options = {}) {
|
|
141
|
+
return input(id, { ...options, type: 'date' });
|
|
142
|
+
}
|
|
143
|
+
export function time(id, options = {}) {
|
|
144
|
+
return input(id, { ...options, type: 'time' });
|
|
145
|
+
}
|
|
146
|
+
export function datetime(id, options = {}) {
|
|
147
|
+
return input(id, { ...options, type: 'datetime-local' });
|
|
148
|
+
}
|
|
149
|
+
export function color(id, options = {}) {
|
|
150
|
+
return input(id, { ...options, type: 'color' });
|
|
151
|
+
}
|
|
152
|
+
export function range(id, options = {}) {
|
|
153
|
+
return input(id, { min: '0', max: '100', ...options, type: 'range' });
|
|
154
|
+
}
|
|
155
|
+
export function file(id, options = {}) {
|
|
156
|
+
return input(id, { ...options, type: 'file' });
|
|
157
|
+
}
|
|
158
|
+
export function hidden(id, options = {}) {
|
|
159
|
+
return input(id, { ...options, type: 'hidden' });
|
|
160
|
+
}
|
|
161
|
+
export { Input };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
interface LinkOptions {
|
|
2
|
+
content?: string;
|
|
3
|
+
href?: string;
|
|
4
|
+
spa?: boolean;
|
|
5
|
+
external?: boolean;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
class?: string;
|
|
8
|
+
style?: string;
|
|
9
|
+
target?: string;
|
|
10
|
+
linkTarget?: '_blank' | '_self' | '_parent' | '_top';
|
|
11
|
+
icon?: string;
|
|
12
|
+
[key: string]: any;
|
|
13
|
+
}
|
|
14
|
+
declare class Link {
|
|
15
|
+
id: string;
|
|
16
|
+
opts: LinkOptions;
|
|
17
|
+
private _element;
|
|
18
|
+
private _onChange;
|
|
19
|
+
constructor(id: string, options?: LinkOptions);
|
|
20
|
+
getValue(): string;
|
|
21
|
+
getContent(): string;
|
|
22
|
+
setValue(val: string): this;
|
|
23
|
+
setContent(val: string): this;
|
|
24
|
+
setHref(val: string): this;
|
|
25
|
+
setDisabled(val: boolean): this;
|
|
26
|
+
setClass(val: string): this;
|
|
27
|
+
setStyle(val: string): this;
|
|
28
|
+
getElement(): HTMLAnchorElement;
|
|
29
|
+
onChange(fn: (value: string) => void): this;
|
|
30
|
+
}
|
|
31
|
+
export declare function link(id: string, options?: LinkOptions): Link;
|
|
32
|
+
export declare function a(id: string, options?: LinkOptions): Link;
|
|
33
|
+
export { Link, LinkOptions };
|
|
34
|
+
export default link;
|
|
35
|
+
//# sourceMappingURL=link.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../../lib/components/link.ts"],"names":[],"mappings":"AAIA,UAAU,WAAW;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IACrD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACtB;AAED,cAAM,IAAI;IACN,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,CAAC,QAAQ,CAAoB;IACpC,OAAO,CAAC,SAAS,CAA0C;gBAE/C,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB;IA4EjD,QAAQ,IAAI,MAAM;IAClB,UAAU,IAAI,MAAM;IAEpB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAM3B,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAW7B,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAE1B,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI;IAU/B,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAK3B,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAK3B,UAAU,IAAI,iBAAiB;IAE/B,QAAQ,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;CAI9C;AAED,wBAAgB,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,IAAI,CAIhE;AAED,wBAAgB,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,IAAI,CAI7D;AAED,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;AAC7B,eAAe,IAAI,CAAC"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import generateId from '../utils/idgen.js';
|
|
2
|
+
import niceName from '../utils/niceName.js';
|
|
3
|
+
import { pageState } from '../state/pageState.js';
|
|
4
|
+
class Link {
|
|
5
|
+
constructor(id, options = {}) {
|
|
6
|
+
this._onChange = null;
|
|
7
|
+
this.id = id || generateId();
|
|
8
|
+
this.opts = {
|
|
9
|
+
spa: true,
|
|
10
|
+
external: false,
|
|
11
|
+
disabled: false,
|
|
12
|
+
...options
|
|
13
|
+
};
|
|
14
|
+
// Auto-generate content from ID if not provided
|
|
15
|
+
if (!this.opts.content && this.id) {
|
|
16
|
+
this.opts.content = niceName(this.id);
|
|
17
|
+
}
|
|
18
|
+
this._element = document.createElement('a');
|
|
19
|
+
this._element.id = this.id;
|
|
20
|
+
this._element.className = this.opts.class || 'jux-link';
|
|
21
|
+
if (this.opts.style)
|
|
22
|
+
this._element.setAttribute('style', this.opts.style);
|
|
23
|
+
if (this.opts.href)
|
|
24
|
+
this._element.href = this.opts.href;
|
|
25
|
+
if (this.opts.disabled)
|
|
26
|
+
this._element.setAttribute('data-disabled', 'true');
|
|
27
|
+
// External link handling
|
|
28
|
+
if (this.opts.external || this.opts.linkTarget === '_blank') {
|
|
29
|
+
this._element.target = this.opts.linkTarget || '_blank';
|
|
30
|
+
this._element.rel = 'noopener noreferrer';
|
|
31
|
+
}
|
|
32
|
+
// Content
|
|
33
|
+
if (this.opts.icon) {
|
|
34
|
+
const iconSpan = document.createElement('span');
|
|
35
|
+
iconSpan.className = 'jux-link-icon';
|
|
36
|
+
iconSpan.textContent = this.opts.icon;
|
|
37
|
+
this._element.appendChild(iconSpan);
|
|
38
|
+
}
|
|
39
|
+
if (this.opts.content) {
|
|
40
|
+
const textSpan = document.createElement('span');
|
|
41
|
+
textSpan.className = 'jux-link-text';
|
|
42
|
+
textSpan.textContent = this.opts.content;
|
|
43
|
+
this._element.appendChild(textSpan);
|
|
44
|
+
}
|
|
45
|
+
// Extra attributes
|
|
46
|
+
for (const [key, value] of Object.entries(this.opts)) {
|
|
47
|
+
if (['content', 'class', 'style', 'target', 'href', 'spa', 'external', 'disabled', 'icon', 'linkTarget'].includes(key))
|
|
48
|
+
continue;
|
|
49
|
+
this._element.setAttribute(`data-${key}`, String(value));
|
|
50
|
+
}
|
|
51
|
+
// SPA navigation
|
|
52
|
+
if (this.opts.spa && !this.opts.external) {
|
|
53
|
+
this._element.addEventListener('click', (e) => {
|
|
54
|
+
if (this.opts.disabled) {
|
|
55
|
+
e.preventDefault();
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const href = this._element.href;
|
|
59
|
+
if (href && !href.startsWith('http') && !href.startsWith('//')) {
|
|
60
|
+
e.preventDefault();
|
|
61
|
+
const path = new URL(href, window.location.origin).pathname;
|
|
62
|
+
if (typeof window.navigateTo === 'function') {
|
|
63
|
+
window.navigateTo(path);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
window.history.pushState({}, '', path);
|
|
67
|
+
window.dispatchEvent(new PopStateEvent('popstate'));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
const resolvedTarget = this.opts.target;
|
|
73
|
+
const container = resolvedTarget
|
|
74
|
+
? document.getElementById(resolvedTarget) || document.querySelector(resolvedTarget)
|
|
75
|
+
: document.getElementById('app');
|
|
76
|
+
container?.appendChild(this._element);
|
|
77
|
+
}
|
|
78
|
+
// ═══════════════════════════════════════════════════════════
|
|
79
|
+
// PAGESTATE INTEGRATION
|
|
80
|
+
// ═══════════════════════════════════════════════════════════
|
|
81
|
+
getValue() { return this.opts.href ?? ''; }
|
|
82
|
+
getContent() { return this.opts.content ?? ''; }
|
|
83
|
+
setValue(val) {
|
|
84
|
+
this.opts.href = val;
|
|
85
|
+
this._element.href = val;
|
|
86
|
+
return this;
|
|
87
|
+
}
|
|
88
|
+
setContent(val) {
|
|
89
|
+
this.opts.content = val;
|
|
90
|
+
const textEl = this._element.querySelector('.jux-link-text');
|
|
91
|
+
if (textEl) {
|
|
92
|
+
textEl.textContent = val;
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
this._element.textContent = val;
|
|
96
|
+
}
|
|
97
|
+
return this;
|
|
98
|
+
}
|
|
99
|
+
setHref(val) { return this.setValue(val); }
|
|
100
|
+
setDisabled(val) {
|
|
101
|
+
this.opts.disabled = val;
|
|
102
|
+
if (val) {
|
|
103
|
+
this._element.setAttribute('data-disabled', 'true');
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
this._element.removeAttribute('data-disabled');
|
|
107
|
+
}
|
|
108
|
+
return this;
|
|
109
|
+
}
|
|
110
|
+
setClass(val) {
|
|
111
|
+
this._element.className = val;
|
|
112
|
+
return this;
|
|
113
|
+
}
|
|
114
|
+
setStyle(val) {
|
|
115
|
+
this._element.setAttribute('style', val);
|
|
116
|
+
return this;
|
|
117
|
+
}
|
|
118
|
+
getElement() { return this._element; }
|
|
119
|
+
onChange(fn) {
|
|
120
|
+
this._onChange = fn;
|
|
121
|
+
return this;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
export function link(id, options = {}) {
|
|
125
|
+
const l = new Link(id, options);
|
|
126
|
+
pageState.__register(l);
|
|
127
|
+
return l;
|
|
128
|
+
}
|
|
129
|
+
export function a(id, options = {}) {
|
|
130
|
+
const l = new Link(id, options);
|
|
131
|
+
pageState.__register(l);
|
|
132
|
+
return l;
|
|
133
|
+
}
|
|
134
|
+
export { Link };
|
|
135
|
+
export default link;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
interface ListItem {
|
|
2
|
+
id?: string;
|
|
3
|
+
content: string;
|
|
4
|
+
icon?: string;
|
|
5
|
+
class?: string;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
[key: string]: any;
|
|
8
|
+
}
|
|
9
|
+
interface ListOptions {
|
|
10
|
+
items?: ListItem[];
|
|
11
|
+
ordered?: boolean;
|
|
12
|
+
selectable?: boolean;
|
|
13
|
+
class?: string;
|
|
14
|
+
style?: string;
|
|
15
|
+
target?: string;
|
|
16
|
+
itemClass?: string;
|
|
17
|
+
activeClass?: string;
|
|
18
|
+
}
|
|
19
|
+
declare class List {
|
|
20
|
+
id: string;
|
|
21
|
+
opts: ListOptions;
|
|
22
|
+
private _element;
|
|
23
|
+
private _items;
|
|
24
|
+
private _value;
|
|
25
|
+
private _selectedIndex;
|
|
26
|
+
private _onChange;
|
|
27
|
+
constructor(id: string, options?: ListOptions);
|
|
28
|
+
addItem(item: ListItem): this;
|
|
29
|
+
addItems(items: ListItem[]): this;
|
|
30
|
+
removeItem(key: string | number): this;
|
|
31
|
+
updateItem(key: string | number, updates: Partial<ListItem>): this;
|
|
32
|
+
clearItems(): this;
|
|
33
|
+
getItems(): ListItem[];
|
|
34
|
+
getCount(): number;
|
|
35
|
+
getValue(): string | null;
|
|
36
|
+
setValue(val: string | null): this;
|
|
37
|
+
getContent(): string;
|
|
38
|
+
getElement(): HTMLElement;
|
|
39
|
+
onChange(fn: (value: string | null) => void): this;
|
|
40
|
+
private _renderItem;
|
|
41
|
+
private _renderAll;
|
|
42
|
+
private _updateActiveState;
|
|
43
|
+
private _dispatchChange;
|
|
44
|
+
}
|
|
45
|
+
export declare function list(id: string, options?: ListOptions): List;
|
|
46
|
+
export { List, ListItem, ListOptions };
|
|
47
|
+
export default list;
|
|
48
|
+
//# sourceMappingURL=list.d.ts.map
|