juxscript 1.1.300 → 1.1.302

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.
@@ -0,0 +1,33 @@
1
+ interface ButtonOptions {
2
+ content?: string;
3
+ variant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link';
4
+ size?: 'default' | 'sm' | 'lg' | 'icon';
5
+ disabled?: boolean;
6
+ type?: 'button' | 'submit' | 'reset';
7
+ class?: string;
8
+ style?: string;
9
+ target?: string;
10
+ icon?: string;
11
+ [key: string]: any;
12
+ }
13
+ declare class Button {
14
+ id: string;
15
+ opts: ButtonOptions;
16
+ private _element;
17
+ private _onChange;
18
+ constructor(id: string, options?: ButtonOptions);
19
+ getValue(): string;
20
+ getContent(): string;
21
+ setValue(val: string): this;
22
+ setContent(val: string): this;
23
+ setDisabled(val: boolean): this;
24
+ setClass(val: string): this;
25
+ setStyle(val: string): this;
26
+ getElement(): HTMLButtonElement;
27
+ onChange(fn: (value: string) => void): this;
28
+ }
29
+ export declare function button(id: string, options?: ButtonOptions): Button;
30
+ export declare function btn(id: string, options?: ButtonOptions): Button;
31
+ export { Button, ButtonOptions };
32
+ export default button;
33
+ //# sourceMappingURL=button.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../lib/components/button.ts"],"names":[],"mappings":"AAGA,UAAU,aAAa;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,SAAS,GAAG,aAAa,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,GAAG,MAAM,CAAC;IACjF,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACtB;AAED,cAAM,MAAM;IACR,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,aAAa,CAAC;IACpB,OAAO,CAAC,QAAQ,CAAoB;IACpC,OAAO,CAAC,SAAS,CAA0C;gBAE/C,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB;IAuDnD,QAAQ,IAAI,MAAM;IAClB,UAAU,IAAI,MAAM;IAEpB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAW3B,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAE7B,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI;IAM/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,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,MAAM,CAItE;AAED,wBAAgB,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,MAAM,CAInE;AAED,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;AACjC,eAAe,MAAM,CAAC"}
@@ -0,0 +1,102 @@
1
+ import generateId from '../utils/idgen.js';
2
+ import { pageState } from '../state/pageState.js';
3
+ class Button {
4
+ constructor(id, options = {}) {
5
+ this._onChange = null;
6
+ this.id = id || generateId();
7
+ this.opts = {
8
+ variant: 'default',
9
+ size: 'default',
10
+ type: 'button',
11
+ disabled: false,
12
+ ...options
13
+ };
14
+ this._element = document.createElement('button');
15
+ this._element.id = this.id;
16
+ this._element.type = this.opts.type;
17
+ if (this.opts.disabled)
18
+ this._element.disabled = true;
19
+ // Build class list
20
+ const classes = ['jux-button'];
21
+ if (this.opts.variant)
22
+ classes.push(`jux-button--${this.opts.variant}`);
23
+ if (this.opts.size && this.opts.size !== 'default')
24
+ classes.push(`jux-button--${this.opts.size}`);
25
+ if (this.opts.class)
26
+ classes.push(this.opts.class);
27
+ this._element.className = classes.join(' ');
28
+ if (this.opts.style)
29
+ this._element.setAttribute('style', this.opts.style);
30
+ // Content
31
+ if (this.opts.icon) {
32
+ const iconSpan = document.createElement('span');
33
+ iconSpan.className = 'jux-button-icon';
34
+ iconSpan.textContent = this.opts.icon;
35
+ this._element.appendChild(iconSpan);
36
+ }
37
+ if (this.opts.content) {
38
+ const textSpan = document.createElement('span');
39
+ textSpan.className = 'jux-button-text';
40
+ textSpan.textContent = this.opts.content;
41
+ this._element.appendChild(textSpan);
42
+ }
43
+ // Extra attributes
44
+ for (const [key, value] of Object.entries(this.opts)) {
45
+ if (['content', 'class', 'style', 'target', 'variant', 'size', 'type', 'disabled', 'icon'].includes(key))
46
+ continue;
47
+ this._element.setAttribute(`data-${key}`, String(value));
48
+ }
49
+ const resolvedTarget = this.opts.target;
50
+ const container = resolvedTarget
51
+ ? document.getElementById(resolvedTarget) || document.querySelector(resolvedTarget)
52
+ : document.getElementById('app');
53
+ container?.appendChild(this._element);
54
+ }
55
+ // ═══════════════════════════════════════════════════════════
56
+ // PAGESTATE INTEGRATION
57
+ // ═══════════════════════════════════════════════════════════
58
+ getValue() { return this.opts.content ?? ''; }
59
+ getContent() { return this.opts.content ?? ''; }
60
+ setValue(val) {
61
+ this.opts.content = val;
62
+ const textEl = this._element.querySelector('.jux-button-text');
63
+ if (textEl) {
64
+ textEl.textContent = val;
65
+ }
66
+ else {
67
+ this._element.textContent = val;
68
+ }
69
+ return this;
70
+ }
71
+ setContent(val) { return this.setValue(val); }
72
+ setDisabled(val) {
73
+ this.opts.disabled = val;
74
+ this._element.disabled = val;
75
+ return this;
76
+ }
77
+ setClass(val) {
78
+ this._element.className = val;
79
+ return this;
80
+ }
81
+ setStyle(val) {
82
+ this._element.setAttribute('style', val);
83
+ return this;
84
+ }
85
+ getElement() { return this._element; }
86
+ onChange(fn) {
87
+ this._onChange = fn;
88
+ return this;
89
+ }
90
+ }
91
+ export function button(id, options = {}) {
92
+ const b = new Button(id, options);
93
+ pageState.__register(b);
94
+ return b;
95
+ }
96
+ export function btn(id, options = {}) {
97
+ const b = new Button(id, options);
98
+ pageState.__register(b);
99
+ return b;
100
+ }
101
+ export { Button };
102
+ export default button;
@@ -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":"AAGA,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;IAuEjD,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,130 @@
1
+ import generateId from '../utils/idgen.js';
2
+ import { pageState } from '../state/pageState.js';
3
+ class Link {
4
+ constructor(id, options = {}) {
5
+ this._onChange = null;
6
+ this.id = id || generateId();
7
+ this.opts = {
8
+ spa: true,
9
+ external: false,
10
+ disabled: false,
11
+ ...options
12
+ };
13
+ this._element = document.createElement('a');
14
+ this._element.id = this.id;
15
+ this._element.className = this.opts.class || 'jux-link';
16
+ if (this.opts.style)
17
+ this._element.setAttribute('style', this.opts.style);
18
+ if (this.opts.href)
19
+ this._element.href = this.opts.href;
20
+ if (this.opts.disabled)
21
+ this._element.setAttribute('data-disabled', 'true');
22
+ // External link handling
23
+ if (this.opts.external || this.opts.linkTarget === '_blank') {
24
+ this._element.target = this.opts.linkTarget || '_blank';
25
+ this._element.rel = 'noopener noreferrer';
26
+ }
27
+ // Content
28
+ if (this.opts.icon) {
29
+ const iconSpan = document.createElement('span');
30
+ iconSpan.className = 'jux-link-icon';
31
+ iconSpan.textContent = this.opts.icon;
32
+ this._element.appendChild(iconSpan);
33
+ }
34
+ if (this.opts.content) {
35
+ const textSpan = document.createElement('span');
36
+ textSpan.className = 'jux-link-text';
37
+ textSpan.textContent = this.opts.content;
38
+ this._element.appendChild(textSpan);
39
+ }
40
+ // Extra attributes
41
+ for (const [key, value] of Object.entries(this.opts)) {
42
+ if (['content', 'class', 'style', 'target', 'href', 'spa', 'external', 'disabled', 'icon', 'linkTarget'].includes(key))
43
+ continue;
44
+ this._element.setAttribute(`data-${key}`, String(value));
45
+ }
46
+ // SPA navigation
47
+ if (this.opts.spa && !this.opts.external) {
48
+ this._element.addEventListener('click', (e) => {
49
+ if (this.opts.disabled) {
50
+ e.preventDefault();
51
+ return;
52
+ }
53
+ const href = this._element.href;
54
+ if (href && !href.startsWith('http') && !href.startsWith('//')) {
55
+ e.preventDefault();
56
+ const path = new URL(href, window.location.origin).pathname;
57
+ if (typeof window.navigateTo === 'function') {
58
+ window.navigateTo(path);
59
+ }
60
+ else {
61
+ window.history.pushState({}, '', path);
62
+ window.dispatchEvent(new PopStateEvent('popstate'));
63
+ }
64
+ }
65
+ });
66
+ }
67
+ const resolvedTarget = this.opts.target;
68
+ const container = resolvedTarget
69
+ ? document.getElementById(resolvedTarget) || document.querySelector(resolvedTarget)
70
+ : document.getElementById('app');
71
+ container?.appendChild(this._element);
72
+ }
73
+ // ═══════════════════════════════════════════════════════════
74
+ // PAGESTATE INTEGRATION
75
+ // ═══════════════════════════════════════════════════════════
76
+ getValue() { return this.opts.href ?? ''; }
77
+ getContent() { return this.opts.content ?? ''; }
78
+ setValue(val) {
79
+ this.opts.href = val;
80
+ this._element.href = val;
81
+ return this;
82
+ }
83
+ setContent(val) {
84
+ this.opts.content = val;
85
+ const textEl = this._element.querySelector('.jux-link-text');
86
+ if (textEl) {
87
+ textEl.textContent = val;
88
+ }
89
+ else {
90
+ this._element.textContent = val;
91
+ }
92
+ return this;
93
+ }
94
+ setHref(val) { return this.setValue(val); }
95
+ setDisabled(val) {
96
+ this.opts.disabled = val;
97
+ if (val) {
98
+ this._element.setAttribute('data-disabled', 'true');
99
+ }
100
+ else {
101
+ this._element.removeAttribute('data-disabled');
102
+ }
103
+ return this;
104
+ }
105
+ setClass(val) {
106
+ this._element.className = val;
107
+ return this;
108
+ }
109
+ setStyle(val) {
110
+ this._element.setAttribute('style', val);
111
+ return this;
112
+ }
113
+ getElement() { return this._element; }
114
+ onChange(fn) {
115
+ this._onChange = fn;
116
+ return this;
117
+ }
118
+ }
119
+ export function link(id, options = {}) {
120
+ const l = new Link(id, options);
121
+ pageState.__register(l);
122
+ return l;
123
+ }
124
+ export function a(id, options = {}) {
125
+ const l = new Link(id, options);
126
+ pageState.__register(l);
127
+ return l;
128
+ }
129
+ export { Link };
130
+ 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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../lib/components/list.ts"],"names":[],"mappings":"AAGA,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;IAQ7B,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,IAAI;IAUjC,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,169 @@
1
+ import generateId from '../utils/idgen.js';
2
+ import { pageState } from '../state/pageState.js';
3
+ class List {
4
+ constructor(id, options = {}) {
5
+ this._items = [];
6
+ this._value = null;
7
+ this._selectedIndex = -1;
8
+ this._onChange = null;
9
+ this.id = id || generateId();
10
+ this.opts = {
11
+ ordered: false,
12
+ selectable: false,
13
+ itemClass: 'jux-list-item',
14
+ activeClass: 'jux-list-item--active',
15
+ ...options
16
+ };
17
+ const tagName = this.opts.ordered ? 'ol' : 'ul';
18
+ this._element = document.createElement(tagName);
19
+ this._element.id = this.id;
20
+ this._element.setAttribute('role', 'list');
21
+ if (this.opts.class)
22
+ this._element.className = this.opts.class;
23
+ if (this.opts.style)
24
+ this._element.setAttribute('style', this.opts.style);
25
+ const resolvedTarget = this.opts.target;
26
+ const container = resolvedTarget
27
+ ? document.getElementById(resolvedTarget) || document.querySelector(resolvedTarget)
28
+ : document.getElementById('app');
29
+ container?.appendChild(this._element);
30
+ if (this.opts.items) {
31
+ this.addItems(this.opts.items);
32
+ }
33
+ }
34
+ // ═══════════════════════════════════════════════════════════
35
+ // STANDARD COLLECTION API
36
+ // ═══════════════════════════════════════════════════════════
37
+ addItem(item) {
38
+ const listItem = { ...item, id: item.id || `${this.id}-item-${this._items.length}` };
39
+ this._items.push(listItem);
40
+ this._renderItem(listItem);
41
+ this._dispatchChange();
42
+ return this;
43
+ }
44
+ addItems(items) {
45
+ for (const item of items) {
46
+ const listItem = { ...item, id: item.id || `${this.id}-item-${this._items.length}` };
47
+ this._items.push(listItem);
48
+ this._renderItem(listItem);
49
+ }
50
+ this._dispatchChange();
51
+ return this;
52
+ }
53
+ removeItem(key) {
54
+ const idx = typeof key === 'number' ? key : this._items.findIndex(i => i.id === key);
55
+ if (idx > -1) {
56
+ this._items.splice(idx, 1);
57
+ this._renderAll();
58
+ this._dispatchChange();
59
+ }
60
+ return this;
61
+ }
62
+ updateItem(key, updates) {
63
+ const idx = typeof key === 'number' ? key : this._items.findIndex(i => i.id === key);
64
+ if (idx > -1) {
65
+ this._items[idx] = { ...this._items[idx], ...updates };
66
+ this._renderAll();
67
+ this._dispatchChange();
68
+ }
69
+ return this;
70
+ }
71
+ clearItems() {
72
+ this._items = [];
73
+ this._value = null;
74
+ this._selectedIndex = -1;
75
+ this._element.innerHTML = '';
76
+ this._dispatchChange();
77
+ return this;
78
+ }
79
+ getItems() { return [...this._items]; }
80
+ getCount() { return this._items.length; }
81
+ // ═══════════════════════════════════════════════════════════
82
+ // PAGESTATE INTEGRATION
83
+ // ═══════════════════════════════════════════════════════════
84
+ getValue() { return this._value; }
85
+ setValue(val) {
86
+ this._value = val;
87
+ this._selectedIndex = this._items.findIndex(i => i.id === val);
88
+ this._updateActiveState();
89
+ this._dispatchChange();
90
+ return this;
91
+ }
92
+ getContent() {
93
+ return this._items.map(i => i.content).join(', ');
94
+ }
95
+ getElement() { return this._element; }
96
+ onChange(fn) {
97
+ this._onChange = fn;
98
+ return this;
99
+ }
100
+ // ═══════════════════════════════════════════════════════════
101
+ // INTERNAL
102
+ // ═══════════════════════════════════════════════════════════
103
+ _renderItem(item) {
104
+ const li = document.createElement('li');
105
+ li.id = item.id;
106
+ li.className = item.class || this.opts.itemClass || 'jux-list-item';
107
+ li.setAttribute('role', 'listitem');
108
+ if (item.icon) {
109
+ const iconSpan = document.createElement('span');
110
+ iconSpan.className = 'jux-list-item-icon';
111
+ iconSpan.textContent = item.icon;
112
+ li.appendChild(iconSpan);
113
+ const textSpan = document.createElement('span');
114
+ textSpan.className = 'jux-list-item-text';
115
+ textSpan.textContent = item.content;
116
+ li.appendChild(textSpan);
117
+ }
118
+ else {
119
+ li.textContent = item.content;
120
+ }
121
+ if (item.disabled)
122
+ li.setAttribute('data-disabled', 'true');
123
+ if (this.opts.selectable) {
124
+ li.style.cursor = 'pointer';
125
+ li.addEventListener('click', () => {
126
+ if (item.disabled)
127
+ return;
128
+ this._value = item.id;
129
+ this._selectedIndex = this._items.indexOf(item);
130
+ this._updateActiveState();
131
+ if (this._onChange)
132
+ this._onChange(this._value);
133
+ this._element.dispatchEvent(new Event('change', { bubbles: false }));
134
+ });
135
+ }
136
+ this._element.appendChild(li);
137
+ }
138
+ _renderAll() {
139
+ this._element.innerHTML = '';
140
+ for (const item of this._items) {
141
+ this._renderItem(item);
142
+ }
143
+ this._updateActiveState();
144
+ }
145
+ _updateActiveState() {
146
+ const children = this._element.querySelectorAll('[role="listitem"]');
147
+ children.forEach((el, idx) => {
148
+ if (idx === this._selectedIndex) {
149
+ el.classList.add(this.opts.activeClass);
150
+ el.setAttribute('data-active', 'true');
151
+ }
152
+ else {
153
+ el.classList.remove(this.opts.activeClass);
154
+ el.removeAttribute('data-active');
155
+ }
156
+ });
157
+ }
158
+ _dispatchChange() {
159
+ this._element.setAttribute('data-count', String(this._items.length));
160
+ this._element.dispatchEvent(new Event('change', { bubbles: false }));
161
+ }
162
+ }
163
+ export function list(id, options = {}) {
164
+ const l = new List(id, options);
165
+ pageState.__register(l);
166
+ return l;
167
+ }
168
+ export { List };
169
+ 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":"AAGA,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;IAQ5B,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI;IAUhC,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;IAsBnB,OAAO,CAAC,UAAU;IAQlB,OAAO,CAAC,kBAAkB;IAc1B,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"}