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.
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 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../lib/components/list.ts"],"names":[],"mappings":"AAIA,UAAU,QAAQ;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACtB;AAED,UAAU,WAAW;IACjB,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,cAAM,IAAI;IACN,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,CAAC,QAAQ,CAAc;IAC9B,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,cAAc,CAAc;IACpC,OAAO,CAAC,SAAS,CAAiD;gBAEtD,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB;IAgCjD,OAAO,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI;IAY7B,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,IAAI;IAcjC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAUtC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI;IAUlE,UAAU,IAAI,IAAI;IASlB,QAAQ,IAAI,QAAQ,EAAE;IACtB,QAAQ,IAAI,MAAM;IAMlB,QAAQ,IAAI,MAAM,GAAG,IAAI;IAEzB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAQlC,UAAU,IAAI,MAAM;IAIpB,UAAU,IAAI,WAAW;IAEzB,QAAQ,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,GAAG,IAAI;IASlD,OAAO,CAAC,WAAW;IAqCnB,OAAO,CAAC,UAAU;IAQlB,OAAO,CAAC,kBAAkB;IAa1B,OAAO,CAAC,eAAe;CAI1B;AAED,wBAAgB,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,IAAI,CAIhE;AAED,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;AACvC,eAAe,IAAI,CAAC"}
@@ -0,0 +1,178 @@
1
+ import generateId from '../utils/idgen.js';
2
+ import niceName from '../utils/niceName.js';
3
+ import { pageState } from '../state/pageState.js';
4
+ class List {
5
+ constructor(id, options = {}) {
6
+ this._items = [];
7
+ this._value = null;
8
+ this._selectedIndex = -1;
9
+ this._onChange = null;
10
+ this.id = id || generateId();
11
+ this.opts = {
12
+ ordered: false,
13
+ selectable: false,
14
+ itemClass: 'jux-list-item',
15
+ activeClass: 'jux-list-item--active',
16
+ ...options
17
+ };
18
+ const tagName = this.opts.ordered ? 'ol' : 'ul';
19
+ this._element = document.createElement(tagName);
20
+ this._element.id = this.id;
21
+ this._element.setAttribute('role', 'list');
22
+ if (this.opts.class)
23
+ this._element.className = this.opts.class;
24
+ if (this.opts.style)
25
+ this._element.setAttribute('style', this.opts.style);
26
+ const resolvedTarget = this.opts.target;
27
+ const container = resolvedTarget
28
+ ? document.getElementById(resolvedTarget) || document.querySelector(resolvedTarget)
29
+ : document.getElementById('app');
30
+ container?.appendChild(this._element);
31
+ if (this.opts.items) {
32
+ this.addItems(this.opts.items);
33
+ }
34
+ }
35
+ // ═══════════════════════════════════════════════════════════
36
+ // STANDARD COLLECTION API
37
+ // ═══════════════════════════════════════════════════════════
38
+ addItem(item) {
39
+ const listItem = {
40
+ ...item,
41
+ id: item.id || `${this.id}-item-${this._items.length}`,
42
+ content: item.content || niceName(item.id || `item-${this._items.length}`)
43
+ };
44
+ this._items.push(listItem);
45
+ this._renderItem(listItem);
46
+ this._dispatchChange();
47
+ return this;
48
+ }
49
+ addItems(items) {
50
+ for (const item of items) {
51
+ const listItem = {
52
+ ...item,
53
+ id: item.id || `${this.id}-item-${this._items.length}`,
54
+ content: item.content || niceName(item.id || `item-${this._items.length}`)
55
+ };
56
+ this._items.push(listItem);
57
+ this._renderItem(listItem);
58
+ }
59
+ this._dispatchChange();
60
+ return this;
61
+ }
62
+ removeItem(key) {
63
+ const idx = typeof key === 'number' ? key : this._items.findIndex(i => i.id === key);
64
+ if (idx > -1) {
65
+ this._items.splice(idx, 1);
66
+ this._renderAll();
67
+ this._dispatchChange();
68
+ }
69
+ return this;
70
+ }
71
+ updateItem(key, updates) {
72
+ const idx = typeof key === 'number' ? key : this._items.findIndex(i => i.id === key);
73
+ if (idx > -1) {
74
+ this._items[idx] = { ...this._items[idx], ...updates };
75
+ this._renderAll();
76
+ this._dispatchChange();
77
+ }
78
+ return this;
79
+ }
80
+ clearItems() {
81
+ this._items = [];
82
+ this._value = null;
83
+ this._selectedIndex = -1;
84
+ this._element.innerHTML = '';
85
+ this._dispatchChange();
86
+ return this;
87
+ }
88
+ getItems() { return [...this._items]; }
89
+ getCount() { return this._items.length; }
90
+ // ═══════════════════════════════════════════════════════════
91
+ // PAGESTATE INTEGRATION
92
+ // ═══════════════════════════════════════════════════════════
93
+ getValue() { return this._value; }
94
+ setValue(val) {
95
+ this._value = val;
96
+ this._selectedIndex = this._items.findIndex(i => i.id === val);
97
+ this._updateActiveState();
98
+ this._dispatchChange();
99
+ return this;
100
+ }
101
+ getContent() {
102
+ return this._items.map(i => i.content).join(', ');
103
+ }
104
+ getElement() { return this._element; }
105
+ onChange(fn) {
106
+ this._onChange = fn;
107
+ return this;
108
+ }
109
+ // ═══════════════════════════════════════════════════════════
110
+ // INTERNAL
111
+ // ═══════════════════════════════════════════════════════════
112
+ _renderItem(item) {
113
+ const li = document.createElement('li');
114
+ li.id = item.id;
115
+ li.className = item.class || this.opts.itemClass || 'jux-list-item';
116
+ li.setAttribute('role', 'listitem');
117
+ if (item.icon) {
118
+ const iconSpan = document.createElement('span');
119
+ iconSpan.className = 'jux-list-item-icon';
120
+ iconSpan.textContent = item.icon;
121
+ li.appendChild(iconSpan);
122
+ const textSpan = document.createElement('span');
123
+ textSpan.className = 'jux-list-item-text';
124
+ textSpan.textContent = item.content;
125
+ li.appendChild(textSpan);
126
+ }
127
+ else {
128
+ li.textContent = item.content;
129
+ }
130
+ if (item.disabled)
131
+ li.setAttribute('data-disabled', 'true');
132
+ if (this.opts.selectable) {
133
+ li.style.cursor = 'pointer';
134
+ li.addEventListener('click', () => {
135
+ if (item.disabled)
136
+ return;
137
+ this._value = item.id;
138
+ this._selectedIndex = this._items.indexOf(item);
139
+ this._updateActiveState();
140
+ if (this._onChange)
141
+ this._onChange(this._value);
142
+ this._element.dispatchEvent(new Event('change', { bubbles: false }));
143
+ });
144
+ }
145
+ this._element.appendChild(li);
146
+ }
147
+ _renderAll() {
148
+ this._element.innerHTML = '';
149
+ for (const item of this._items) {
150
+ this._renderItem(item);
151
+ }
152
+ this._updateActiveState();
153
+ }
154
+ _updateActiveState() {
155
+ const children = this._element.querySelectorAll('[role="listitem"]');
156
+ children.forEach((el, idx) => {
157
+ if (idx === this._selectedIndex) {
158
+ el.classList.add(this.opts.activeClass);
159
+ el.setAttribute('data-active', 'true');
160
+ }
161
+ else {
162
+ el.classList.remove(this.opts.activeClass);
163
+ el.removeAttribute('data-active');
164
+ }
165
+ });
166
+ }
167
+ _dispatchChange() {
168
+ this._element.setAttribute('data-count', String(this._items.length));
169
+ this._element.dispatchEvent(new Event('change', { bubbles: false }));
170
+ }
171
+ }
172
+ export function list(id, options = {}) {
173
+ const l = new List(id, options);
174
+ pageState.__register(l);
175
+ return l;
176
+ }
177
+ export { List };
178
+ export default list;
@@ -0,0 +1,46 @@
1
+ interface NavItem {
2
+ id?: string;
3
+ label: string;
4
+ path?: string;
5
+ icon?: string;
6
+ disabled?: boolean;
7
+ [key: string]: any;
8
+ }
9
+ interface NavOptions {
10
+ label?: string;
11
+ items?: NavItem[];
12
+ orientation?: 'vertical' | 'horizontal';
13
+ class?: string;
14
+ style?: string;
15
+ target?: string;
16
+ activeClass?: string;
17
+ itemClass?: string;
18
+ }
19
+ declare class Nav {
20
+ id: string;
21
+ opts: NavOptions;
22
+ private _element;
23
+ private _items;
24
+ private _value;
25
+ private _onChange;
26
+ constructor(id: string, options?: NavOptions);
27
+ addItem(item: NavItem): this;
28
+ addItems(items: NavItem[]): this;
29
+ removeItem(key: string | number): this;
30
+ updateItem(key: string | number, updates: Partial<NavItem>): this;
31
+ clearItems(): this;
32
+ getItems(): NavItem[];
33
+ getCount(): number;
34
+ getValue(): string | null;
35
+ setValue(val: string | null): this;
36
+ getElement(): HTMLElement;
37
+ onChange(fn: (value: string | null) => void): this;
38
+ private _renderItem;
39
+ private _renderAll;
40
+ private _updateActiveState;
41
+ private _dispatchChange;
42
+ }
43
+ export declare function nav(id: string, options?: NavOptions): Nav;
44
+ export { Nav, NavItem, NavOptions };
45
+ export default nav;
46
+ //# sourceMappingURL=nav.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nav.d.ts","sourceRoot":"","sources":["../../../lib/components/nav.ts"],"names":[],"mappings":"AAIA,UAAU,OAAO;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACtB;AAED,UAAU,UAAU;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC;IAClB,WAAW,CAAC,EAAE,UAAU,GAAG,YAAY,CAAC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,cAAM,GAAG;IACL,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,CAAC,QAAQ,CAAc;IAC9B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,SAAS,CAAiD;gBAEtD,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,UAAe;IA+BhD,OAAO,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAY5B,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI;IAchC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAUtC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI;IAUjE,UAAU,IAAI,IAAI;IAQlB,QAAQ,IAAI,OAAO,EAAE;IACrB,QAAQ,IAAI,MAAM;IAMlB,QAAQ,IAAI,MAAM,GAAG,IAAI;IAEzB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAOlC,UAAU,IAAI,WAAW;IAEzB,QAAQ,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,GAAG,IAAI;IASlD,OAAO,CAAC,WAAW;IAqDnB,OAAO,CAAC,UAAU;IAQlB,OAAO,CAAC,kBAAkB;IAgB1B,OAAO,CAAC,eAAe;CAI1B;AAED,wBAAgB,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,UAAe,GAAG,GAAG,CAI7D;AAED,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;AACpC,eAAe,GAAG,CAAC"}
@@ -0,0 +1,189 @@
1
+ import generateId from '../utils/idgen.js';
2
+ import niceName from '../utils/niceName.js';
3
+ import { pageState } from '../state/pageState.js';
4
+ class Nav {
5
+ constructor(id, options = {}) {
6
+ this._items = [];
7
+ this._value = null;
8
+ this._onChange = null;
9
+ this.id = id || generateId();
10
+ this.opts = {
11
+ orientation: 'vertical',
12
+ activeClass: 'jux-nav-item--active',
13
+ itemClass: 'jux-nav-item',
14
+ ...options
15
+ };
16
+ this._element = document.createElement('nav');
17
+ this._element.id = this.id;
18
+ if (this.opts.class)
19
+ this._element.className = this.opts.class;
20
+ if (this.opts.style)
21
+ this._element.setAttribute('style', this.opts.style);
22
+ this._element.setAttribute('data-orientation', this.opts.orientation);
23
+ this._element.setAttribute('role', 'navigation');
24
+ const resolvedTarget = this.opts.target;
25
+ const container = resolvedTarget
26
+ ? document.getElementById(resolvedTarget) || document.querySelector(resolvedTarget)
27
+ : document.getElementById('app');
28
+ container?.appendChild(this._element);
29
+ if (this.opts.items) {
30
+ this.addItems(this.opts.items);
31
+ }
32
+ }
33
+ // ═══════════════════════════════════════════════════════════
34
+ // STANDARD COLLECTION API
35
+ // ═══════════════════════════════════════════════════════════
36
+ addItem(item) {
37
+ const navItem = {
38
+ ...item,
39
+ id: item.id || `${this.id}-item-${this._items.length}`,
40
+ label: item.label || niceName(item.id || `item-${this._items.length}`)
41
+ };
42
+ this._items.push(navItem);
43
+ this._renderItem(navItem);
44
+ this._dispatchChange();
45
+ return this;
46
+ }
47
+ addItems(items) {
48
+ for (const item of items) {
49
+ const navItem = {
50
+ ...item,
51
+ id: item.id || `${this.id}-item-${this._items.length}`,
52
+ label: item.label || niceName(item.id || `item-${this._items.length}`)
53
+ };
54
+ this._items.push(navItem);
55
+ this._renderItem(navItem);
56
+ }
57
+ this._dispatchChange();
58
+ return this;
59
+ }
60
+ removeItem(key) {
61
+ const idx = typeof key === 'number' ? key : this._items.findIndex(i => i.id === key);
62
+ if (idx > -1) {
63
+ this._items.splice(idx, 1);
64
+ this._renderAll();
65
+ this._dispatchChange();
66
+ }
67
+ return this;
68
+ }
69
+ updateItem(key, updates) {
70
+ const idx = typeof key === 'number' ? key : this._items.findIndex(i => i.id === key);
71
+ if (idx > -1) {
72
+ this._items[idx] = { ...this._items[idx], ...updates };
73
+ this._renderAll();
74
+ this._dispatchChange();
75
+ }
76
+ return this;
77
+ }
78
+ clearItems() {
79
+ this._items = [];
80
+ this._value = null;
81
+ this._element.innerHTML = '';
82
+ this._dispatchChange();
83
+ return this;
84
+ }
85
+ getItems() { return [...this._items]; }
86
+ getCount() { return this._items.length; }
87
+ // ═══════════════════════════════════════════════════════════
88
+ // PAGESTATE INTEGRATION
89
+ // ═══════════════════════════════════════════════════════════
90
+ getValue() { return this._value; }
91
+ setValue(val) {
92
+ this._value = val;
93
+ this._updateActiveState();
94
+ this._dispatchChange();
95
+ return this;
96
+ }
97
+ getElement() { return this._element; }
98
+ onChange(fn) {
99
+ this._onChange = fn;
100
+ return this;
101
+ }
102
+ // ═══════════════════════════════════════════════════════════
103
+ // INTERNAL
104
+ // ═══════════════════════════════════════════════════════════
105
+ _renderItem(item) {
106
+ const el = document.createElement('a');
107
+ el.id = item.id;
108
+ el.className = this.opts.itemClass || 'jux-nav-item';
109
+ el.setAttribute('role', 'link');
110
+ if (item.path) {
111
+ el.href = item.path;
112
+ }
113
+ if (item.disabled) {
114
+ el.setAttribute('data-disabled', 'true');
115
+ el.setAttribute('aria-disabled', 'true');
116
+ }
117
+ // Always render icon span for consistent alignment
118
+ const iconSpan = document.createElement('span');
119
+ iconSpan.className = 'jux-nav-item-icon';
120
+ if (item.icon) {
121
+ iconSpan.textContent = item.icon;
122
+ }
123
+ else {
124
+ // Bold first letter as fallback
125
+ iconSpan.className += ' jux-nav-item-no-icon';
126
+ iconSpan.textContent = (item.label || '').charAt(0).toUpperCase();
127
+ }
128
+ el.appendChild(iconSpan);
129
+ const textSpan = document.createElement('span');
130
+ textSpan.className = 'jux-nav-item-text';
131
+ textSpan.textContent = item.label;
132
+ el.appendChild(textSpan);
133
+ el.addEventListener('click', (e) => {
134
+ e.preventDefault();
135
+ if (item.disabled)
136
+ return;
137
+ this._value = item.path || item.id;
138
+ this._updateActiveState();
139
+ if (this._onChange)
140
+ this._onChange(this._value);
141
+ this._element.dispatchEvent(new Event('change', { bubbles: false }));
142
+ // SPA navigation
143
+ if (item.path) {
144
+ if (typeof window.navigateTo === 'function') {
145
+ window.navigateTo(item.path);
146
+ }
147
+ else {
148
+ window.history.pushState({}, '', item.path);
149
+ window.dispatchEvent(new PopStateEvent('popstate'));
150
+ }
151
+ }
152
+ });
153
+ this._element.appendChild(el);
154
+ }
155
+ _renderAll() {
156
+ this._element.innerHTML = '';
157
+ for (const item of this._items) {
158
+ this._renderItem(item);
159
+ }
160
+ this._updateActiveState();
161
+ }
162
+ _updateActiveState() {
163
+ const children = this._element.querySelectorAll('a[href]');
164
+ children.forEach(el => {
165
+ const href = el.getAttribute('href');
166
+ if (href === this._value) {
167
+ el.classList.add(this.opts.activeClass);
168
+ el.setAttribute('data-active', 'true');
169
+ el.setAttribute('aria-current', 'page');
170
+ }
171
+ else {
172
+ el.classList.remove(this.opts.activeClass);
173
+ el.removeAttribute('data-active');
174
+ el.removeAttribute('aria-current');
175
+ }
176
+ });
177
+ }
178
+ _dispatchChange() {
179
+ this._element.setAttribute('data-count', String(this._items.length));
180
+ this._element.dispatchEvent(new Event('change', { bubbles: false }));
181
+ }
182
+ }
183
+ export function nav(id, options = {}) {
184
+ const n = new Nav(id, options);
185
+ pageState.__register(n);
186
+ return n;
187
+ }
188
+ export { Nav };
189
+ export default nav;
@@ -0,0 +1,40 @@
1
+ interface RadioOption {
2
+ label: string;
3
+ value: string;
4
+ disabled?: boolean;
5
+ }
6
+ interface RadioGroupOptions {
7
+ label?: string;
8
+ name?: string;
9
+ options?: RadioOption[];
10
+ value?: string;
11
+ direction?: 'vertical' | 'horizontal';
12
+ required?: boolean;
13
+ disabled?: boolean;
14
+ class?: string;
15
+ style?: string;
16
+ }
17
+ declare class RadioGroup {
18
+ id: string;
19
+ opts: RadioGroupOptions;
20
+ private _wrapper;
21
+ private _inputs;
22
+ private _onChange;
23
+ constructor(id: string, options?: RadioGroupOptions);
24
+ label(value: string): this;
25
+ direction(value: 'vertical' | 'horizontal'): this;
26
+ required(value?: boolean): this;
27
+ disabled(value?: boolean): this;
28
+ style(value: string): this;
29
+ class(value: string): this;
30
+ options(opts: RadioOption[]): this;
31
+ value(val: string): this;
32
+ onChange(fn: (value: string, event: Event) => void): this;
33
+ getValue(): string;
34
+ private _rebuild;
35
+ private _buildOptions;
36
+ render(target?: string | HTMLElement): this;
37
+ }
38
+ export declare function radio(id: string, options?: RadioGroupOptions): RadioGroup;
39
+ export { RadioGroup, RadioOption, RadioGroupOptions };
40
+ //# sourceMappingURL=radio.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"radio.d.ts","sourceRoot":"","sources":["../../../lib/components/radio.ts"],"names":[],"mappings":"AAGA,UAAU,WAAW;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,UAAU,iBAAiB;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,UAAU,GAAG,YAAY,CAAC;IACtC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,cAAM,UAAU;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,iBAAiB,CAAC;IACxB,OAAO,CAAC,QAAQ,CAA4B;IAC5C,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,SAAS,CAAwD;gBAE7D,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB;IAWvD,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAC1B,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,YAAY,GAAG,IAAI;IACjD,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,OAAO,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,IAAI;IAMlC,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAMxB,QAAQ,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;IAKzD,QAAQ,IAAI,MAAM;IAKlB,OAAO,CAAC,QAAQ;IAShB,OAAO,CAAC,aAAa;IA6BrB,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;CA4B9C;AAED,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,GAAG,UAAU,CAK7E;AAED,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,iBAAiB,EAAE,CAAC"}
@@ -0,0 +1,112 @@
1
+ import generateId from '../utils/idgen.js';
2
+ import { pageState } from '../state/pageState.js';
3
+ class RadioGroup {
4
+ constructor(id, options = {}) {
5
+ this._wrapper = null;
6
+ this._inputs = [];
7
+ this._onChange = null;
8
+ this.id = id || generateId();
9
+ this.opts = {
10
+ options: [],
11
+ direction: 'vertical',
12
+ name: id,
13
+ ...options
14
+ };
15
+ }
16
+ // Fluent API
17
+ label(value) { this.opts.label = value; return this; }
18
+ direction(value) { this.opts.direction = value; return this; }
19
+ required(value = true) { this.opts.required = value; return this; }
20
+ disabled(value = true) { this.opts.disabled = value; return this; }
21
+ style(value) { this.opts.style = value; return this; }
22
+ class(value) { this.opts.class = value; return this; }
23
+ options(opts) {
24
+ this.opts.options = opts;
25
+ if (this._wrapper)
26
+ this._rebuild();
27
+ return this;
28
+ }
29
+ value(val) {
30
+ this.opts.value = val;
31
+ this._inputs.forEach(inp => { inp.checked = inp.value === val; });
32
+ return this;
33
+ }
34
+ onChange(fn) {
35
+ this._onChange = fn;
36
+ return this;
37
+ }
38
+ getValue() {
39
+ const checked = this._inputs.find(i => i.checked);
40
+ return checked?.value ?? this.opts.value ?? '';
41
+ }
42
+ _rebuild() {
43
+ if (!this._wrapper)
44
+ return;
45
+ const group = this._wrapper.querySelector('.jux-radio-options');
46
+ if (!group)
47
+ return;
48
+ group.innerHTML = '';
49
+ this._inputs = [];
50
+ this._buildOptions(group);
51
+ }
52
+ _buildOptions(container) {
53
+ for (const opt of this.opts.options || []) {
54
+ const item = document.createElement('label');
55
+ item.className = 'jux-radio-item';
56
+ const inp = document.createElement('input');
57
+ inp.type = 'radio';
58
+ inp.name = this.opts.name || this.id;
59
+ inp.value = opt.value;
60
+ inp.className = 'jux-radio-input';
61
+ if (opt.value === this.opts.value)
62
+ inp.checked = true;
63
+ if (opt.disabled || this.opts.disabled)
64
+ inp.disabled = true;
65
+ if (this.opts.required)
66
+ inp.required = true;
67
+ inp.addEventListener('change', (e) => {
68
+ if (this._onChange)
69
+ this._onChange(inp.value, e);
70
+ });
71
+ const text = document.createElement('span');
72
+ text.className = 'jux-radio-label';
73
+ text.textContent = opt.label;
74
+ item.appendChild(inp);
75
+ item.appendChild(text);
76
+ container.appendChild(item);
77
+ this._inputs.push(inp);
78
+ }
79
+ }
80
+ render(target) {
81
+ const wrapper = document.createElement('fieldset');
82
+ wrapper.className = 'jux-radio-group';
83
+ wrapper.id = this.id;
84
+ if (this.opts.class)
85
+ wrapper.className += ` ${this.opts.class}`;
86
+ if (this.opts.style)
87
+ wrapper.setAttribute('style', this.opts.style);
88
+ if (this.opts.label) {
89
+ const legend = document.createElement('legend');
90
+ legend.textContent = this.opts.label;
91
+ legend.className = 'jux-radio-group-label';
92
+ wrapper.appendChild(legend);
93
+ }
94
+ const optionsDiv = document.createElement('div');
95
+ optionsDiv.className = `jux-radio-options jux-radio-${this.opts.direction}`;
96
+ this._buildOptions(optionsDiv);
97
+ wrapper.appendChild(optionsDiv);
98
+ this._wrapper = wrapper;
99
+ const container = target
100
+ ? (typeof target === 'string' ? document.getElementById(target) || document.querySelector(target) : target)
101
+ : document.getElementById('app');
102
+ container?.appendChild(wrapper);
103
+ return this;
104
+ }
105
+ }
106
+ export function radio(id, options = {}) {
107
+ const r = new RadioGroup(id, options);
108
+ r.render();
109
+ pageState.__register(r);
110
+ return r;
111
+ }
112
+ export { RadioGroup };
@@ -0,0 +1,41 @@
1
+ interface SelectOption {
2
+ label: string;
3
+ value: string;
4
+ disabled?: boolean;
5
+ }
6
+ interface SelectOptions {
7
+ label?: string;
8
+ placeholder?: string;
9
+ options?: SelectOption[];
10
+ value?: string;
11
+ required?: boolean;
12
+ disabled?: boolean;
13
+ multiple?: boolean;
14
+ class?: string;
15
+ style?: string;
16
+ }
17
+ declare class Select {
18
+ id: string;
19
+ opts: SelectOptions;
20
+ private _element;
21
+ private _wrapper;
22
+ private _onChange;
23
+ constructor(id: string, options?: SelectOptions);
24
+ label(value: string): this;
25
+ placeholder(value: string): this;
26
+ required(value?: boolean): this;
27
+ disabled(value?: boolean): this;
28
+ multiple(value?: boolean): this;
29
+ style(value: string): this;
30
+ class(value: string): this;
31
+ options(opts: SelectOption[]): this;
32
+ value(val: string): this;
33
+ onChange(fn: (value: string, event: Event) => void): this;
34
+ getValue(): string;
35
+ getSelectedValues(): string[];
36
+ private _rebuildOptions;
37
+ render(target?: string | HTMLElement): this;
38
+ }
39
+ export declare function select(id: string, options?: SelectOptions): Select;
40
+ export { Select, SelectOption, SelectOptions };
41
+ //# sourceMappingURL=select.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../../lib/components/select.ts"],"names":[],"mappings":"AAGA,UAAU,YAAY;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,UAAU,aAAa;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,cAAM,MAAM;IACR,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,aAAa,CAAC;IACpB,OAAO,CAAC,QAAQ,CAAkC;IAClD,OAAO,CAAC,QAAQ,CAA4B;IAC5C,OAAO,CAAC,SAAS,CAAwD;gBAE7D,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB;IAMnD,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAC1B,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAChC,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,OAAO,CAAC,IAAI,EAAE,YAAY,EAAE,GAAG,IAAI;IAMnC,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAMxB,QAAQ,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;IAKzD,QAAQ,IAAI,MAAM;IAIlB,iBAAiB,IAAI,MAAM,EAAE;IAK7B,OAAO,CAAC,eAAe;IAuBvB,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;CAuC9C;AAED,wBAAgB,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,MAAM,CAKtE;AAED,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC"}