juxscript 1.1.350 → 1.1.353

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.
Files changed (85) hide show
  1. package/dist/lib/components/blocks/menu.d.ts +40 -0
  2. package/dist/lib/components/blocks/menu.d.ts.map +1 -0
  3. package/dist/lib/components/blocks/menu.js +136 -0
  4. package/dist/lib/components/button.d.ts +33 -0
  5. package/dist/lib/components/button.d.ts.map +1 -0
  6. package/dist/lib/components/button.js +107 -0
  7. package/dist/lib/components/checkbox.d.ts +62 -0
  8. package/dist/lib/components/checkbox.d.ts.map +1 -0
  9. package/dist/lib/components/checkbox.js +178 -0
  10. package/dist/lib/components/container.d.ts +58 -0
  11. package/dist/lib/components/container.d.ts.map +1 -0
  12. package/dist/lib/components/container.js +151 -0
  13. package/dist/lib/components/data.d.ts +58 -0
  14. package/dist/lib/components/data.d.ts.map +1 -0
  15. package/dist/lib/components/data.js +130 -0
  16. package/dist/lib/components/grid.d.ts +58 -0
  17. package/dist/lib/components/grid.d.ts.map +1 -0
  18. package/dist/lib/components/grid.js +127 -0
  19. package/dist/lib/components/include.d.ts +86 -0
  20. package/dist/lib/components/include.d.ts.map +1 -0
  21. package/dist/lib/components/include.js +238 -0
  22. package/dist/lib/components/input.d.ts +58 -0
  23. package/dist/lib/components/input.d.ts.map +1 -0
  24. package/dist/lib/components/input.js +161 -0
  25. package/dist/lib/components/link.d.ts +35 -0
  26. package/dist/lib/components/link.d.ts.map +1 -0
  27. package/dist/lib/components/link.js +135 -0
  28. package/dist/lib/components/list.d.ts +48 -0
  29. package/dist/lib/components/list.d.ts.map +1 -0
  30. package/dist/lib/components/list.js +178 -0
  31. package/dist/lib/components/nav.d.ts +46 -0
  32. package/dist/lib/components/nav.d.ts.map +1 -0
  33. package/dist/lib/components/nav.js +189 -0
  34. package/dist/lib/components/radio.d.ts +40 -0
  35. package/dist/lib/components/radio.d.ts.map +1 -0
  36. package/dist/lib/components/radio.js +112 -0
  37. package/dist/lib/components/select.d.ts +41 -0
  38. package/dist/lib/components/select.d.ts.map +1 -0
  39. package/dist/lib/components/select.js +111 -0
  40. package/dist/lib/components/sidebar.d.ts +40 -0
  41. package/dist/lib/components/sidebar.d.ts.map +1 -0
  42. package/dist/lib/components/sidebar.js +141 -0
  43. package/dist/lib/components/store.d.ts +78 -0
  44. package/dist/lib/components/store.d.ts.map +1 -0
  45. package/dist/lib/components/store.js +248 -0
  46. package/dist/lib/components/style.d.ts +27 -0
  47. package/dist/lib/components/style.d.ts.map +1 -0
  48. package/dist/lib/components/style.js +52 -0
  49. package/dist/lib/components/table.d.ts +56 -0
  50. package/dist/lib/components/table.d.ts.map +1 -0
  51. package/dist/lib/components/table.js +199 -0
  52. package/dist/lib/components/tabs.d.ts +52 -0
  53. package/dist/lib/components/tabs.d.ts.map +1 -0
  54. package/dist/lib/components/tabs.js +206 -0
  55. package/dist/lib/components/tag.d.ts +41 -0
  56. package/dist/lib/components/tag.d.ts.map +1 -0
  57. package/dist/lib/components/tag.js +103 -0
  58. package/dist/lib/devtools/devtools.d.ts +3 -0
  59. package/dist/lib/devtools/devtools.d.ts.map +1 -0
  60. package/dist/lib/devtools/devtools.js +181 -0
  61. package/dist/lib/index.d.ts +68 -0
  62. package/dist/lib/index.d.ts.map +1 -0
  63. package/dist/lib/index.js +63 -0
  64. package/dist/lib/state/pageState.d.ts +19 -0
  65. package/dist/lib/state/pageState.d.ts.map +1 -0
  66. package/dist/lib/state/pageState.js +360 -0
  67. package/dist/lib/utils/codeHighlight.d.ts +7 -0
  68. package/dist/lib/utils/codeHighlight.d.ts.map +1 -0
  69. package/dist/lib/utils/codeHighlight.js +105 -0
  70. package/dist/lib/utils/codeparser.d.ts +29 -0
  71. package/dist/lib/utils/codeparser.d.ts.map +1 -0
  72. package/dist/lib/utils/codeparser.js +384 -0
  73. package/dist/lib/utils/fetch.d.ts +176 -0
  74. package/dist/lib/utils/fetch.d.ts.map +1 -0
  75. package/dist/lib/utils/fetch.js +427 -0
  76. package/dist/lib/utils/formatId.d.ts +16 -0
  77. package/dist/lib/utils/formatId.d.ts.map +1 -0
  78. package/dist/lib/utils/formatId.js +27 -0
  79. package/dist/lib/utils/idgen.d.ts +2 -0
  80. package/dist/lib/utils/idgen.d.ts.map +1 -0
  81. package/dist/lib/utils/idgen.js +4 -0
  82. package/dist/lib/utils/niceName.d.ts +14 -0
  83. package/dist/lib/utils/niceName.d.ts.map +1 -0
  84. package/dist/lib/utils/niceName.js +22 -0
  85. package/package.json +1 -1
@@ -0,0 +1,151 @@
1
+ import generateId from '../utils/idgen.js';
2
+ import { pageState } from '../state/pageState.js';
3
+ const JUSTIFY_MAP = {
4
+ start: 'flex-start',
5
+ center: 'center',
6
+ end: 'flex-end',
7
+ between: 'space-between',
8
+ around: 'space-around',
9
+ evenly: 'space-evenly'
10
+ };
11
+ const ALIGN_MAP = {
12
+ start: 'flex-start',
13
+ center: 'center',
14
+ end: 'flex-end',
15
+ stretch: 'stretch',
16
+ baseline: 'baseline'
17
+ };
18
+ class Container {
19
+ constructor(id, options = {}) {
20
+ this.id = id || generateId();
21
+ this.opts = {
22
+ layout: 'flex',
23
+ direction: 'column',
24
+ tag: 'div',
25
+ ...options
26
+ };
27
+ this._element = document.createElement(this.opts.tag);
28
+ this._element.id = this.id;
29
+ // Classes
30
+ if (this.opts.class)
31
+ this._element.className = this.opts.class;
32
+ // Build computed style from layout options
33
+ const styles = this._buildStyles();
34
+ if (this.opts.style)
35
+ styles.push(this.opts.style);
36
+ if (styles.length)
37
+ this._element.setAttribute('style', styles.join(';'));
38
+ // Content (rare for containers, but supported)
39
+ if (this.opts.content)
40
+ this._element.textContent = this.opts.content;
41
+ // Extra attributes
42
+ for (const [key, value] of Object.entries(this.opts)) {
43
+ if ([
44
+ 'layout', 'direction', 'wrap', 'gap', 'padding', 'align', 'justify',
45
+ 'columns', 'width', 'height', 'maxWidth', 'minHeight',
46
+ 'class', 'style', 'target', 'tag', 'content'
47
+ ].includes(key))
48
+ continue;
49
+ this._element.setAttribute(`data-${key}`, String(value));
50
+ }
51
+ // Mount
52
+ const resolvedTarget = this.opts.target;
53
+ const parent = resolvedTarget
54
+ ? document.getElementById(resolvedTarget) || document.querySelector(resolvedTarget)
55
+ : document.getElementById('app');
56
+ parent?.appendChild(this._element);
57
+ }
58
+ // ═══════════════════════════════════════════════════════════
59
+ // LAYOUT HELPERS
60
+ // ═══════════════════════════════════════════════════════════
61
+ _buildStyles() {
62
+ const s = [];
63
+ const o = this.opts;
64
+ if (o.layout === 'grid') {
65
+ s.push('display:grid');
66
+ if (o.columns) {
67
+ const cols = typeof o.columns === 'number'
68
+ ? `repeat(${o.columns}, 1fr)`
69
+ : o.columns;
70
+ s.push(`grid-template-columns:${cols}`);
71
+ }
72
+ }
73
+ else if (o.layout === 'flex') {
74
+ s.push('display:flex');
75
+ if (o.direction)
76
+ s.push(`flex-direction:${o.direction}`);
77
+ if (o.wrap)
78
+ s.push('flex-wrap:wrap');
79
+ }
80
+ else {
81
+ s.push('display:block');
82
+ }
83
+ if (o.gap)
84
+ s.push(`gap:${o.gap}`);
85
+ if (o.padding)
86
+ s.push(`padding:${o.padding}`);
87
+ if (o.align)
88
+ s.push(`align-items:${ALIGN_MAP[o.align] || o.align}`);
89
+ if (o.justify)
90
+ s.push(`justify-content:${JUSTIFY_MAP[o.justify] || o.justify}`);
91
+ if (o.width)
92
+ s.push(`width:${o.width}`);
93
+ if (o.height)
94
+ s.push(`height:${o.height}`);
95
+ if (o.maxWidth)
96
+ s.push(`max-width:${o.maxWidth}`);
97
+ if (o.minHeight)
98
+ s.push(`min-height:${o.minHeight}`);
99
+ return s;
100
+ }
101
+ // ═══════════════════════════════════════════════════════════
102
+ // PAGESTATE INTEGRATION
103
+ // ═══════════════════════════════════════════════════════════
104
+ getValue() { return this._element.textContent ?? ''; }
105
+ getContent() { return this._element.textContent ?? this.opts.content ?? ''; }
106
+ setValue(val) {
107
+ this.opts.content = val;
108
+ this._element.textContent = val;
109
+ return this;
110
+ }
111
+ setContent(val) { return this.setValue(val); }
112
+ setClass(val) {
113
+ this._element.className = val;
114
+ return this;
115
+ }
116
+ setStyle(val) {
117
+ this._element.setAttribute('style', val);
118
+ return this;
119
+ }
120
+ setInnerHTML(val) {
121
+ this._element.innerHTML = val;
122
+ return this;
123
+ }
124
+ getElement() { return this._element; }
125
+ }
126
+ /**
127
+ * Create a layout container.
128
+ *
129
+ * @example
130
+ * // Flex column (default)
131
+ * jux.container('main', { gap: '16px', padding: '24px' });
132
+ *
133
+ * // Flex row
134
+ * jux.container('toolbar', { direction: 'row', gap: '8px', align: 'center' });
135
+ *
136
+ * // Grid
137
+ * jux.container('grid', { layout: 'grid', columns: 3, gap: '16px' });
138
+ *
139
+ * // Centered page wrapper
140
+ * jux.container('page', { maxWidth: '960px', padding: '24px 16px', align: 'center' });
141
+ *
142
+ * // Nested
143
+ * jux.container('card', { gap: '8px', padding: '16px', target: 'grid' });
144
+ */
145
+ export function container(id, options = {}) {
146
+ const c = new Container(id, options);
147
+ pageState.__register(c);
148
+ return c;
149
+ }
150
+ export { Container };
151
+ export default container;
@@ -0,0 +1,58 @@
1
+ interface DataOptions {
2
+ url?: string;
3
+ method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
4
+ headers?: Record<string, string>;
5
+ body?: any;
6
+ transform?: (raw: any) => any;
7
+ auto?: boolean;
8
+ }
9
+ declare class Data {
10
+ id: string;
11
+ options: DataOptions;
12
+ private _value;
13
+ private _loading;
14
+ private _error;
15
+ private _onChange;
16
+ constructor(id: string, options?: DataOptions);
17
+ url(value: string): this;
18
+ method(value: DataOptions['method']): this;
19
+ headers(value: Record<string, string>): this;
20
+ body(value: any): this;
21
+ transform(fn: (raw: any) => any): this;
22
+ onChange(fn: (value: any) => void): this;
23
+ getValue(): any;
24
+ getLoading(): boolean;
25
+ getError(): string | null;
26
+ setValue(val: any): this;
27
+ /**
28
+ * Re-fetch the data and notify pageState.
29
+ * Triggers all watchers that depend on this data's value.
30
+ */
31
+ refresh(): Promise<any>;
32
+ fetch(urlOverride?: string): Promise<any>;
33
+ }
34
+ /**
35
+ * Create a data source that integrates with pageState.
36
+ *
37
+ * @example
38
+ * // Auto-fetch on creation
39
+ * const api = await jux.data('api', { url: '/api/test' });
40
+ * // pageState['api'].value → { users: [...], posts: [...] }
41
+ *
42
+ * // With transform
43
+ * const users = await jux.data('users', {
44
+ * url: '/api/test',
45
+ * transform: raw => raw.users
46
+ * });
47
+ * // pageState['users'].value → [{ id: 1, name: 'Alice' }, ...]
48
+ *
49
+ * // Manual fetch
50
+ * const manual = jux.data('manual', { url: '/api/test', auto: false });
51
+ * await manual.fetch(); // fetch later
52
+ *
53
+ * // Re-fetch
54
+ * await pageState['api'].refresh();
55
+ */
56
+ export declare function data(id: string, options?: DataOptions): Promise<Data>;
57
+ export { Data, DataOptions };
58
+ //# sourceMappingURL=data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data.d.ts","sourceRoot":"","sources":["../../../lib/components/data.ts"],"names":[],"mappings":"AAGA,UAAU,WAAW;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,CAAC;IAC9B,IAAI,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,cAAM,IAAI;IACN,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,WAAW,CAAC;IACrB,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,SAAS,CAAuC;gBAE5C,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB;IAMjD,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IACxB,MAAM,CAAC,KAAK,EAAE,WAAW,CAAC,QAAQ,CAAC,GAAG,IAAI;IAC1C,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAC5C,IAAI,CAAC,KAAK,EAAE,GAAG,GAAG,IAAI;IACtB,SAAS,CAAC,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,GAAG,IAAI;IAEtC,QAAQ,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI;IAMxC,QAAQ,IAAI,GAAG;IACf,UAAU,IAAI,OAAO;IACrB,QAAQ,IAAI,MAAM,GAAG,IAAI;IAEzB,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI;IAMxB;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC;IAQvB,KAAK,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;CA+DlD;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAW/E;AAED,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC"}
@@ -0,0 +1,130 @@
1
+ import generateId from '../utils/idgen.js';
2
+ import { pageState } from '../state/pageState.js';
3
+ class Data {
4
+ constructor(id, options = {}) {
5
+ this._value = null;
6
+ this._loading = false;
7
+ this._error = null;
8
+ this._onChange = null;
9
+ this.id = id || generateId();
10
+ this.options = { method: 'GET', auto: true, ...options };
11
+ }
12
+ // Fluent API
13
+ url(value) { this.options.url = value; return this; }
14
+ method(value) { this.options.method = value; return this; }
15
+ headers(value) { this.options.headers = value; return this; }
16
+ body(value) { this.options.body = value; return this; }
17
+ transform(fn) { this.options.transform = fn; return this; }
18
+ onChange(fn) {
19
+ this._onChange = fn;
20
+ return this;
21
+ }
22
+ // Getters for pageState integration
23
+ getValue() { return this._value; }
24
+ getLoading() { return this._loading; }
25
+ getError() { return this._error; }
26
+ setValue(val) {
27
+ this._value = val;
28
+ if (this._onChange)
29
+ this._onChange(val);
30
+ return this;
31
+ }
32
+ /**
33
+ * Re-fetch the data and notify pageState.
34
+ * Triggers all watchers that depend on this data's value.
35
+ */
36
+ async refresh() {
37
+ const result = await this.fetch();
38
+ // Notify pageState so watchers re-run
39
+ pageState.__notify(`${this.id}.value`);
40
+ pageState.__notify(`${this.id}.loading`);
41
+ return result;
42
+ }
43
+ async fetch(urlOverride) {
44
+ const fetchUrl = urlOverride || this.options.url;
45
+ if (!fetchUrl) {
46
+ this._error = 'No URL provided';
47
+ return null;
48
+ }
49
+ this._loading = true;
50
+ this._error = null;
51
+ // Notify pageState of loading change
52
+ if (pageState.__notify) {
53
+ pageState.__notify(`${this.id}.loading`);
54
+ }
55
+ try {
56
+ const fetchOptions = {
57
+ method: this.options.method,
58
+ headers: this.options.headers,
59
+ };
60
+ if (this.options.body && this.options.method !== 'GET') {
61
+ fetchOptions.body = typeof this.options.body === 'string'
62
+ ? this.options.body
63
+ : JSON.stringify(this.options.body);
64
+ if (!this.options.headers?.['Content-Type']) {
65
+ fetchOptions.headers = {
66
+ 'Content-Type': 'application/json',
67
+ ...fetchOptions.headers
68
+ };
69
+ }
70
+ }
71
+ const res = await globalThis.fetch(fetchUrl, fetchOptions);
72
+ if (!res.ok) {
73
+ throw new Error(`HTTP ${res.status}: ${res.statusText}`);
74
+ }
75
+ const contentType = res.headers.get('content-type') || '';
76
+ let raw;
77
+ if (contentType.includes('application/json')) {
78
+ raw = await res.json();
79
+ }
80
+ else {
81
+ raw = await res.text();
82
+ }
83
+ this._value = this.options.transform ? this.options.transform(raw) : raw;
84
+ this._loading = false;
85
+ this._error = null;
86
+ if (this._onChange)
87
+ this._onChange(this._value);
88
+ return this._value;
89
+ }
90
+ catch (err) {
91
+ this._loading = false;
92
+ this._error = err.message || 'Fetch failed';
93
+ console.error(`❌ jux.data('${this.id}') fetch error:`, err.message);
94
+ return null;
95
+ }
96
+ }
97
+ }
98
+ /**
99
+ * Create a data source that integrates with pageState.
100
+ *
101
+ * @example
102
+ * // Auto-fetch on creation
103
+ * const api = await jux.data('api', { url: '/api/test' });
104
+ * // pageState['api'].value → { users: [...], posts: [...] }
105
+ *
106
+ * // With transform
107
+ * const users = await jux.data('users', {
108
+ * url: '/api/test',
109
+ * transform: raw => raw.users
110
+ * });
111
+ * // pageState['users'].value → [{ id: 1, name: 'Alice' }, ...]
112
+ *
113
+ * // Manual fetch
114
+ * const manual = jux.data('manual', { url: '/api/test', auto: false });
115
+ * await manual.fetch(); // fetch later
116
+ *
117
+ * // Re-fetch
118
+ * await pageState['api'].refresh();
119
+ */
120
+ export async function data(id, options = {}) {
121
+ const d = new Data(id, options);
122
+ pageState.__register(d);
123
+ if (options.auto !== false && options.url) {
124
+ await d.fetch();
125
+ // Re-register so pageState picks up the fetched value
126
+ pageState.__register(d);
127
+ }
128
+ return d;
129
+ }
130
+ export { Data };
@@ -0,0 +1,58 @@
1
+ type GridDensity = 'dense' | 'normal' | 'inflated';
2
+ interface GridColumn {
3
+ name: string;
4
+ width?: string;
5
+ }
6
+ interface GridOptions {
7
+ rows?: number;
8
+ cols?: number | GridColumn[];
9
+ density?: GridDensity;
10
+ class?: string;
11
+ style?: string;
12
+ target?: string;
13
+ [key: string]: any;
14
+ }
15
+ declare class Grid {
16
+ id: string;
17
+ opts: GridOptions;
18
+ private _element;
19
+ private _columns;
20
+ constructor(id: string, options?: GridOptions);
21
+ getValue(): string;
22
+ getContent(): string;
23
+ setContent(val: string): this;
24
+ setClass(val: string): this;
25
+ setStyle(val: string): this;
26
+ setInnerHTML(val: string): this;
27
+ getElement(): HTMLElement;
28
+ /** Get a named column cell element */
29
+ getColumn(name: string): HTMLElement | null;
30
+ getColumns(): GridColumn[];
31
+ }
32
+ /**
33
+ * Create a CSS grid layout container.
34
+ *
35
+ * @example
36
+ * // Simple: 3 equal columns
37
+ * jux.grid('cards', { cols: 3 });
38
+ *
39
+ * // Named columns with custom widths
40
+ * jux.grid('layout', {
41
+ * cols: [
42
+ * { name: 'sidebar', width: '260px' },
43
+ * { name: 'content', width: '3fr' },
44
+ * { name: 'aside', width: '1fr' },
45
+ * ]
46
+ * });
47
+ * // Then target into them:
48
+ * jux.nav('main-nav', { target: 'sidebar' });
49
+ * jux.h1('title', { content: 'Hello', target: 'content' });
50
+ *
51
+ * // Density options
52
+ * jux.grid('tight', { cols: 4, density: 'dense' });
53
+ * jux.grid('spacious', { cols: 2, density: 'inflated' });
54
+ */
55
+ export declare function grid(id: string, options?: GridOptions): Grid;
56
+ export { Grid, GridOptions, GridColumn, GridDensity };
57
+ export default grid;
58
+ //# sourceMappingURL=grid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grid.d.ts","sourceRoot":"","sources":["../../../lib/components/grid.ts"],"names":[],"mappings":"AAGA,KAAK,WAAW,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEnD,UAAU,UAAU;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,WAAW;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU,EAAE,CAAC;IAC7B,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACtB;AAQD,cAAM,IAAI;IACN,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,CAAC,QAAQ,CAAc;IAC9B,OAAO,CAAC,QAAQ,CAAoB;gBAExB,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB;IAoEjD,QAAQ,IAAI,MAAM;IAClB,UAAU,IAAI,MAAM;IAEpB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAK7B,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAK3B,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAK3B,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAK/B,UAAU,IAAI,WAAW;IAEzB,sCAAsC;IACtC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAI3C,UAAU,IAAI,UAAU,EAAE;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,IAAI,CAIhE;AAED,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC;AACtD,eAAe,IAAI,CAAC"}
@@ -0,0 +1,127 @@
1
+ import generateId from '../utils/idgen.js';
2
+ import { pageState } from '../state/pageState.js';
3
+ const DENSITY_MAP = {
4
+ dense: { gap: '4px', padding: '4px' },
5
+ normal: { gap: '12px', padding: '12px' },
6
+ inflated: { gap: '24px', padding: '24px' },
7
+ };
8
+ class Grid {
9
+ constructor(id, options = {}) {
10
+ this._columns = [];
11
+ this.id = id || generateId();
12
+ this.opts = {
13
+ cols: 2,
14
+ density: 'normal',
15
+ ...options
16
+ };
17
+ this._element = document.createElement('div');
18
+ this._element.id = this.id;
19
+ if (this.opts.class)
20
+ this._element.className = this.opts.class;
21
+ // Resolve columns
22
+ const cols = this.opts.cols;
23
+ let templateCols;
24
+ if (cols && typeof cols === 'object' && Array.isArray(cols)) {
25
+ this._columns = cols.map(c => ({
26
+ name: c.name,
27
+ width: c.width || '1fr'
28
+ }));
29
+ templateCols = this._columns.map(c => c.width).join(' ');
30
+ }
31
+ else {
32
+ const count = typeof cols === 'number' ? cols : 2;
33
+ templateCols = `repeat(${count}, 1fr)`;
34
+ }
35
+ const d = DENSITY_MAP[this.opts.density] || DENSITY_MAP.normal;
36
+ const parts = [
37
+ 'display:grid',
38
+ `grid-template-columns:${templateCols}`,
39
+ `gap:${d.gap}`,
40
+ `padding:${d.padding}`,
41
+ ];
42
+ if (this.opts.rows) {
43
+ parts.push(`grid-template-rows:repeat(${this.opts.rows}, auto)`);
44
+ }
45
+ if (this.opts.style)
46
+ parts.push(this.opts.style);
47
+ this._element.setAttribute('style', parts.join(';'));
48
+ // Extra attributes
49
+ for (const [key, value] of Object.entries(this.opts)) {
50
+ if (['rows', 'cols', 'density', 'class', 'style', 'target'].includes(key))
51
+ continue;
52
+ this._element.setAttribute(`data-${key}`, String(value));
53
+ }
54
+ // Mount
55
+ const resolvedTarget = this.opts.target;
56
+ const parent = resolvedTarget
57
+ ? document.getElementById(resolvedTarget) || document.querySelector(resolvedTarget)
58
+ : document.getElementById('app');
59
+ parent?.appendChild(this._element);
60
+ // Create named column cells if using array cols
61
+ if (this._columns.length > 0) {
62
+ for (const col of this._columns) {
63
+ const cell = document.createElement('div');
64
+ cell.id = col.name;
65
+ cell.setAttribute('data-grid-col', col.name);
66
+ this._element.appendChild(cell);
67
+ }
68
+ }
69
+ }
70
+ // ═══════════════════════════════════════════════════════════
71
+ // PAGESTATE INTEGRATION
72
+ // ═══════════════════════════════════════════════════════════
73
+ getValue() { return ''; }
74
+ getContent() { return this._element.textContent ?? ''; }
75
+ setContent(val) {
76
+ this._element.textContent = val;
77
+ return this;
78
+ }
79
+ setClass(val) {
80
+ this._element.className = val;
81
+ return this;
82
+ }
83
+ setStyle(val) {
84
+ this._element.setAttribute('style', val);
85
+ return this;
86
+ }
87
+ setInnerHTML(val) {
88
+ this._element.innerHTML = val;
89
+ return this;
90
+ }
91
+ getElement() { return this._element; }
92
+ /** Get a named column cell element */
93
+ getColumn(name) {
94
+ return this._element.querySelector(`[data-grid-col="${name}"]`);
95
+ }
96
+ getColumns() { return [...this._columns]; }
97
+ }
98
+ /**
99
+ * Create a CSS grid layout container.
100
+ *
101
+ * @example
102
+ * // Simple: 3 equal columns
103
+ * jux.grid('cards', { cols: 3 });
104
+ *
105
+ * // Named columns with custom widths
106
+ * jux.grid('layout', {
107
+ * cols: [
108
+ * { name: 'sidebar', width: '260px' },
109
+ * { name: 'content', width: '3fr' },
110
+ * { name: 'aside', width: '1fr' },
111
+ * ]
112
+ * });
113
+ * // Then target into them:
114
+ * jux.nav('main-nav', { target: 'sidebar' });
115
+ * jux.h1('title', { content: 'Hello', target: 'content' });
116
+ *
117
+ * // Density options
118
+ * jux.grid('tight', { cols: 4, density: 'dense' });
119
+ * jux.grid('spacious', { cols: 2, density: 'inflated' });
120
+ */
121
+ export function grid(id, options = {}) {
122
+ const g = new Grid(id, options);
123
+ pageState.__register(g);
124
+ return g;
125
+ }
126
+ export { Grid };
127
+ export default grid;
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Include - Simplified resource injection for bundled and external resources
3
+ * Supports page-specific scoping and cleanup
4
+ */
5
+ type ResourceType = 'css' | 'js' | 'module';
6
+ interface IncludeOptions {
7
+ type?: ResourceType;
8
+ target?: string;
9
+ async?: boolean;
10
+ defer?: boolean;
11
+ crossOrigin?: 'anonymous' | 'use-credentials';
12
+ integrity?: string;
13
+ pageScoped?: boolean;
14
+ }
15
+ export declare class Include {
16
+ private url;
17
+ private options;
18
+ private element;
19
+ private pageId;
20
+ constructor(url: string, options?: IncludeOptions);
21
+ css(): this;
22
+ js(): this;
23
+ module(): this;
24
+ async(): this;
25
+ defer(): this;
26
+ /**
27
+ * Inject into specific container instead of <head>
28
+ * Useful for page-specific styles
29
+ *
30
+ * @example
31
+ * jux.include('/css/page1.css').into('#page1-container');
32
+ */
33
+ into(selector: string): this;
34
+ /**
35
+ * Mark as page-scoped for automatic cleanup
36
+ *
37
+ * @example
38
+ * jux.include('/css/dashboard.css').forPage('dashboard');
39
+ * // Later: Include.cleanupPage('dashboard');
40
+ */
41
+ forPage(pageId: string): this;
42
+ render(): this;
43
+ private createStylesheet;
44
+ private createScript;
45
+ private getContainer;
46
+ private isAlreadyLoaded;
47
+ remove(): this;
48
+ /**
49
+ * Remove all resources for a specific page
50
+ *
51
+ * @example
52
+ * Include.cleanupPage('dashboard');
53
+ */
54
+ static cleanupPage(pageId: string): void;
55
+ /**
56
+ * Remove all page-scoped resources
57
+ */
58
+ static cleanupAll(): void;
59
+ }
60
+ /**
61
+ * Factory function - simplified usage
62
+ *
63
+ * Usage:
64
+ * // Basic (auto-detects from extension)
65
+ * jux.include('/css/styles.css');
66
+ * jux.include('/js/app.js');
67
+ *
68
+ * // Page-specific with cleanup
69
+ * jux.include('/css/dashboard.css').forPage('dashboard');
70
+ * jux.include('/js/dashboard.js').forPage('dashboard');
71
+ *
72
+ * // Later cleanup:
73
+ * Include.cleanupPage('dashboard');
74
+ *
75
+ * // Inject into specific container
76
+ * jux.include('/css/widget.css').into('#widget-container');
77
+ *
78
+ * // External CDN
79
+ * jux.include('https://cdn.tailwindcss.com').js();
80
+ *
81
+ * // Module
82
+ * jux.include('/js/app.mjs').module();
83
+ */
84
+ export declare function include(url: string, options?: IncludeOptions): Include;
85
+ export {};
86
+ //# sourceMappingURL=include.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"include.d.ts","sourceRoot":"","sources":["../../../lib/components/include.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,KAAK,YAAY,GAAG,KAAK,GAAG,IAAI,GAAG,QAAQ,CAAC;AAE5C,UAAU,cAAc;IACpB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,WAAW,GAAG,iBAAiB,CAAC;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;CACxB;AAKD,qBAAa,OAAO;IAChB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,MAAM,CAAuB;gBAEzB,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB;IAoBrD,GAAG,IAAI,IAAI;IAKX,EAAE,IAAI,IAAI;IAKV,MAAM,IAAI,IAAI;IAKd,KAAK,IAAI,IAAI;IAKb,KAAK,IAAI,IAAI;IAKb;;;;;;OAMG;IACH,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAK5B;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAU7B,MAAM,IAAI,IAAI;IAoDd,OAAO,CAAC,gBAAgB;IAiBxB,OAAO,CAAC,YAAY;IAuBpB,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,eAAe;IAKvB,MAAM,IAAI,IAAI;IAYd;;;;;OAKG;IACH,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAYxC;;OAEG;IACH,MAAM,CAAC,UAAU,IAAI,IAAI;CAS5B;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAItE"}