juxscript 1.1.301 → 1.1.303

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":"AAIA,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;IA4DnD,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,107 @@
1
+ import generateId from '../utils/idgen.js';
2
+ import niceName from '../utils/niceName.js';
3
+ import { pageState } from '../state/pageState.js';
4
+ class Button {
5
+ constructor(id, options = {}) {
6
+ this._onChange = null;
7
+ this.id = id || generateId();
8
+ this.opts = {
9
+ variant: 'default',
10
+ size: 'default',
11
+ type: 'button',
12
+ disabled: false,
13
+ ...options
14
+ };
15
+ // Auto-generate content from ID if not provided
16
+ if (!this.opts.content && this.id) {
17
+ this.opts.content = niceName(this.id);
18
+ }
19
+ this._element = document.createElement('button');
20
+ this._element.id = this.id;
21
+ this._element.type = this.opts.type;
22
+ if (this.opts.disabled)
23
+ this._element.disabled = true;
24
+ // Build class list
25
+ const classes = ['jux-button'];
26
+ if (this.opts.variant)
27
+ classes.push(`jux-button--${this.opts.variant}`);
28
+ if (this.opts.size && this.opts.size !== 'default')
29
+ classes.push(`jux-button--${this.opts.size}`);
30
+ if (this.opts.class)
31
+ classes.push(this.opts.class);
32
+ this._element.className = classes.join(' ');
33
+ if (this.opts.style)
34
+ this._element.setAttribute('style', this.opts.style);
35
+ // Content
36
+ if (this.opts.icon) {
37
+ const iconSpan = document.createElement('span');
38
+ iconSpan.className = 'jux-button-icon';
39
+ iconSpan.textContent = this.opts.icon;
40
+ this._element.appendChild(iconSpan);
41
+ }
42
+ if (this.opts.content) {
43
+ const textSpan = document.createElement('span');
44
+ textSpan.className = 'jux-button-text';
45
+ textSpan.textContent = this.opts.content;
46
+ this._element.appendChild(textSpan);
47
+ }
48
+ // Extra attributes
49
+ for (const [key, value] of Object.entries(this.opts)) {
50
+ if (['content', 'class', 'style', 'target', 'variant', 'size', 'type', 'disabled', 'icon'].includes(key))
51
+ continue;
52
+ this._element.setAttribute(`data-${key}`, String(value));
53
+ }
54
+ const resolvedTarget = this.opts.target;
55
+ const container = resolvedTarget
56
+ ? document.getElementById(resolvedTarget) || document.querySelector(resolvedTarget)
57
+ : document.getElementById('app');
58
+ container?.appendChild(this._element);
59
+ }
60
+ // ═══════════════════════════════════════════════════════════
61
+ // PAGESTATE INTEGRATION
62
+ // ═══════════════════════════════════════════════════════════
63
+ getValue() { return this.opts.content ?? ''; }
64
+ getContent() { return this.opts.content ?? ''; }
65
+ setValue(val) {
66
+ this.opts.content = val;
67
+ const textEl = this._element.querySelector('.jux-button-text');
68
+ if (textEl) {
69
+ textEl.textContent = val;
70
+ }
71
+ else {
72
+ this._element.textContent = val;
73
+ }
74
+ return this;
75
+ }
76
+ setContent(val) { return this.setValue(val); }
77
+ setDisabled(val) {
78
+ this.opts.disabled = val;
79
+ this._element.disabled = val;
80
+ return this;
81
+ }
82
+ setClass(val) {
83
+ this._element.className = val;
84
+ return this;
85
+ }
86
+ setStyle(val) {
87
+ this._element.setAttribute('style', val);
88
+ return this;
89
+ }
90
+ getElement() { return this._element; }
91
+ onChange(fn) {
92
+ this._onChange = fn;
93
+ return this;
94
+ }
95
+ }
96
+ export function button(id, options = {}) {
97
+ const b = new Button(id, options);
98
+ pageState.__register(b);
99
+ return b;
100
+ }
101
+ export function btn(id, options = {}) {
102
+ const b = new Button(id, options);
103
+ pageState.__register(b);
104
+ return b;
105
+ }
106
+ export { Button };
107
+ 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":"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
@@ -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;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"}