@llui/components 0.0.1

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 (213) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +143 -0
  3. package/dist/components/accordion.d.ts +115 -0
  4. package/dist/components/accordion.d.ts.map +1 -0
  5. package/dist/components/accordion.js +138 -0
  6. package/dist/components/alert-dialog.d.ts +45 -0
  7. package/dist/components/alert-dialog.d.ts.map +1 -0
  8. package/dist/components/alert-dialog.js +12 -0
  9. package/dist/components/angle-slider.d.ts +121 -0
  10. package/dist/components/angle-slider.d.ts.map +1 -0
  11. package/dist/components/angle-slider.js +145 -0
  12. package/dist/components/async-list.d.ts +104 -0
  13. package/dist/components/async-list.d.ts.map +1 -0
  14. package/dist/components/async-list.js +117 -0
  15. package/dist/components/avatar.d.ts +58 -0
  16. package/dist/components/avatar.d.ts.map +1 -0
  17. package/dist/components/avatar.js +43 -0
  18. package/dist/components/carousel.d.ts +128 -0
  19. package/dist/components/carousel.d.ts.map +1 -0
  20. package/dist/components/carousel.js +131 -0
  21. package/dist/components/cascade-select.d.ts +95 -0
  22. package/dist/components/cascade-select.d.ts.map +1 -0
  23. package/dist/components/cascade-select.js +100 -0
  24. package/dist/components/checkbox.d.ts +74 -0
  25. package/dist/components/checkbox.d.ts.map +1 -0
  26. package/dist/components/checkbox.js +73 -0
  27. package/dist/components/clipboard.d.ts +72 -0
  28. package/dist/components/clipboard.d.ts.map +1 -0
  29. package/dist/components/clipboard.js +73 -0
  30. package/dist/components/collapsible.d.ts +64 -0
  31. package/dist/components/collapsible.d.ts.map +1 -0
  32. package/dist/components/collapsible.js +51 -0
  33. package/dist/components/color-picker.d.ts +125 -0
  34. package/dist/components/color-picker.d.ts.map +1 -0
  35. package/dist/components/color-picker.js +169 -0
  36. package/dist/components/combobox.d.ts +163 -0
  37. package/dist/components/combobox.d.ts.map +1 -0
  38. package/dist/components/combobox.js +345 -0
  39. package/dist/components/context-menu.d.ts +105 -0
  40. package/dist/components/context-menu.d.ts.map +1 -0
  41. package/dist/components/context-menu.js +177 -0
  42. package/dist/components/date-input.d.ts +117 -0
  43. package/dist/components/date-input.d.ts.map +1 -0
  44. package/dist/components/date-input.js +149 -0
  45. package/dist/components/date-picker.d.ts +142 -0
  46. package/dist/components/date-picker.d.ts.map +1 -0
  47. package/dist/components/date-picker.js +294 -0
  48. package/dist/components/dialog.d.ts +152 -0
  49. package/dist/components/dialog.d.ts.map +1 -0
  50. package/dist/components/dialog.js +140 -0
  51. package/dist/components/drawer.d.ts +106 -0
  52. package/dist/components/drawer.d.ts.map +1 -0
  53. package/dist/components/drawer.js +136 -0
  54. package/dist/components/editable.d.ts +92 -0
  55. package/dist/components/editable.d.ts.map +1 -0
  56. package/dist/components/editable.js +112 -0
  57. package/dist/components/file-upload.d.ts +251 -0
  58. package/dist/components/file-upload.d.ts.map +1 -0
  59. package/dist/components/file-upload.js +324 -0
  60. package/dist/components/floating-panel.d.ts +171 -0
  61. package/dist/components/floating-panel.d.ts.map +1 -0
  62. package/dist/components/floating-panel.js +198 -0
  63. package/dist/components/hover-card.d.ts +85 -0
  64. package/dist/components/hover-card.d.ts.map +1 -0
  65. package/dist/components/hover-card.js +128 -0
  66. package/dist/components/image-cropper.d.ts +129 -0
  67. package/dist/components/image-cropper.d.ts.map +1 -0
  68. package/dist/components/image-cropper.js +208 -0
  69. package/dist/components/index.d.ts +109 -0
  70. package/dist/components/index.d.ts.map +1 -0
  71. package/dist/components/index.js +54 -0
  72. package/dist/components/listbox.d.ts +98 -0
  73. package/dist/components/listbox.d.ts.map +1 -0
  74. package/dist/components/listbox.js +174 -0
  75. package/dist/components/marquee.d.ts +84 -0
  76. package/dist/components/marquee.d.ts.map +1 -0
  77. package/dist/components/marquee.js +73 -0
  78. package/dist/components/menu.d.ts +131 -0
  79. package/dist/components/menu.d.ts.map +1 -0
  80. package/dist/components/menu.js +262 -0
  81. package/dist/components/navigation-menu.d.ts +111 -0
  82. package/dist/components/navigation-menu.d.ts.map +1 -0
  83. package/dist/components/navigation-menu.js +102 -0
  84. package/dist/components/number-input.d.ts +106 -0
  85. package/dist/components/number-input.d.ts.map +1 -0
  86. package/dist/components/number-input.js +178 -0
  87. package/dist/components/pagination.d.ts +113 -0
  88. package/dist/components/pagination.d.ts.map +1 -0
  89. package/dist/components/pagination.js +135 -0
  90. package/dist/components/password-input.d.ts +64 -0
  91. package/dist/components/password-input.d.ts.map +1 -0
  92. package/dist/components/password-input.js +52 -0
  93. package/dist/components/pin-input.d.ts +89 -0
  94. package/dist/components/pin-input.d.ts.map +1 -0
  95. package/dist/components/pin-input.js +139 -0
  96. package/dist/components/popover.d.ts +116 -0
  97. package/dist/components/popover.d.ts.map +1 -0
  98. package/dist/components/popover.js +146 -0
  99. package/dist/components/presence.d.ts +71 -0
  100. package/dist/components/presence.d.ts.map +1 -0
  101. package/dist/components/presence.js +57 -0
  102. package/dist/components/progress.d.ts +74 -0
  103. package/dist/components/progress.d.ts.map +1 -0
  104. package/dist/components/progress.js +80 -0
  105. package/dist/components/qr-code.d.ts +114 -0
  106. package/dist/components/qr-code.d.ts.map +1 -0
  107. package/dist/components/qr-code.js +108 -0
  108. package/dist/components/radio-group.d.ts +89 -0
  109. package/dist/components/radio-group.d.ts.map +1 -0
  110. package/dist/components/radio-group.js +161 -0
  111. package/dist/components/rating-group.d.ts +88 -0
  112. package/dist/components/rating-group.d.ts.map +1 -0
  113. package/dist/components/rating-group.js +122 -0
  114. package/dist/components/scroll-area.d.ts +124 -0
  115. package/dist/components/scroll-area.d.ts.map +1 -0
  116. package/dist/components/scroll-area.js +152 -0
  117. package/dist/components/select.d.ts +161 -0
  118. package/dist/components/select.d.ts.map +1 -0
  119. package/dist/components/select.js +333 -0
  120. package/dist/components/signature-pad.d.ts +138 -0
  121. package/dist/components/signature-pad.d.ts.map +1 -0
  122. package/dist/components/signature-pad.js +142 -0
  123. package/dist/components/slider.d.ts +117 -0
  124. package/dist/components/slider.d.ts.map +1 -0
  125. package/dist/components/slider.js +210 -0
  126. package/dist/components/splitter.d.ts +87 -0
  127. package/dist/components/splitter.d.ts.map +1 -0
  128. package/dist/components/splitter.js +119 -0
  129. package/dist/components/steps.d.ts +104 -0
  130. package/dist/components/steps.d.ts.map +1 -0
  131. package/dist/components/steps.js +133 -0
  132. package/dist/components/switch.d.ts +66 -0
  133. package/dist/components/switch.d.ts.map +1 -0
  134. package/dist/components/switch.js +59 -0
  135. package/dist/components/tabs.d.ts +146 -0
  136. package/dist/components/tabs.d.ts.map +1 -0
  137. package/dist/components/tabs.js +244 -0
  138. package/dist/components/tags-input.d.ts +118 -0
  139. package/dist/components/tags-input.d.ts.map +1 -0
  140. package/dist/components/tags-input.js +168 -0
  141. package/dist/components/time-picker.d.ts +121 -0
  142. package/dist/components/time-picker.d.ts.map +1 -0
  143. package/dist/components/time-picker.js +147 -0
  144. package/dist/components/timer.d.ts +131 -0
  145. package/dist/components/timer.d.ts.map +1 -0
  146. package/dist/components/timer.js +117 -0
  147. package/dist/components/toast.d.ts +119 -0
  148. package/dist/components/toast.d.ts.map +1 -0
  149. package/dist/components/toast.js +102 -0
  150. package/dist/components/toc.d.ts +119 -0
  151. package/dist/components/toc.d.ts.map +1 -0
  152. package/dist/components/toc.js +107 -0
  153. package/dist/components/toggle-group.d.ts +80 -0
  154. package/dist/components/toggle-group.d.ts.map +1 -0
  155. package/dist/components/toggle-group.js +93 -0
  156. package/dist/components/toggle.d.ts +47 -0
  157. package/dist/components/toggle.d.ts.map +1 -0
  158. package/dist/components/toggle.js +41 -0
  159. package/dist/components/tooltip.d.ts +92 -0
  160. package/dist/components/tooltip.d.ts.map +1 -0
  161. package/dist/components/tooltip.js +147 -0
  162. package/dist/components/tour.d.ts +145 -0
  163. package/dist/components/tour.d.ts.map +1 -0
  164. package/dist/components/tour.js +133 -0
  165. package/dist/components/tree-view.d.ts +216 -0
  166. package/dist/components/tree-view.d.ts.map +1 -0
  167. package/dist/components/tree-view.js +293 -0
  168. package/dist/index.d.ts +3 -0
  169. package/dist/index.d.ts.map +1 -0
  170. package/dist/index.js +4 -0
  171. package/dist/patterns/confirm-dialog.d.ts +92 -0
  172. package/dist/patterns/confirm-dialog.d.ts.map +1 -0
  173. package/dist/patterns/confirm-dialog.js +92 -0
  174. package/dist/patterns/index.d.ts +3 -0
  175. package/dist/patterns/index.d.ts.map +1 -0
  176. package/dist/patterns/index.js +1 -0
  177. package/dist/utils/anatomy.d.ts +40 -0
  178. package/dist/utils/anatomy.d.ts.map +1 -0
  179. package/dist/utils/anatomy.js +41 -0
  180. package/dist/utils/aria-hidden.d.ts +12 -0
  181. package/dist/utils/aria-hidden.d.ts.map +1 -0
  182. package/dist/utils/aria-hidden.js +72 -0
  183. package/dist/utils/dismissable.d.ts +25 -0
  184. package/dist/utils/dismissable.d.ts.map +1 -0
  185. package/dist/utils/dismissable.js +65 -0
  186. package/dist/utils/dom.d.ts +8 -0
  187. package/dist/utils/dom.d.ts.map +1 -0
  188. package/dist/utils/dom.js +21 -0
  189. package/dist/utils/floating.d.ts +44 -0
  190. package/dist/utils/floating.d.ts.map +1 -0
  191. package/dist/utils/floating.js +44 -0
  192. package/dist/utils/focus-trap.d.ts +18 -0
  193. package/dist/utils/focus-trap.d.ts.map +1 -0
  194. package/dist/utils/focus-trap.js +85 -0
  195. package/dist/utils/focusables.d.ts +6 -0
  196. package/dist/utils/focusables.d.ts.map +1 -0
  197. package/dist/utils/focusables.js +65 -0
  198. package/dist/utils/index.d.ts +18 -0
  199. package/dist/utils/index.d.ts.map +1 -0
  200. package/dist/utils/index.js +10 -0
  201. package/dist/utils/interact-outside.d.ts +26 -0
  202. package/dist/utils/interact-outside.d.ts.map +1 -0
  203. package/dist/utils/interact-outside.js +46 -0
  204. package/dist/utils/remove-scroll.d.ts +8 -0
  205. package/dist/utils/remove-scroll.d.ts.map +1 -0
  206. package/dist/utils/remove-scroll.js +37 -0
  207. package/dist/utils/tree-collection.d.ts +61 -0
  208. package/dist/utils/tree-collection.d.ts.map +1 -0
  209. package/dist/utils/tree-collection.js +137 -0
  210. package/dist/utils/typeahead.d.ts +49 -0
  211. package/dist/utils/typeahead.d.ts.map +1 -0
  212. package/dist/utils/typeahead.js +81 -0
  213. package/package.json +282 -0
@@ -0,0 +1,139 @@
1
+ export function init(opts = {}) {
2
+ const length = opts.length ?? 4;
3
+ const values = opts.values ?? new Array(length).fill('');
4
+ return {
5
+ values,
6
+ length,
7
+ type: opts.type ?? 'numeric',
8
+ mask: opts.mask ?? false,
9
+ disabled: opts.disabled ?? false,
10
+ focusedIndex: 0,
11
+ };
12
+ }
13
+ function sanitize(char, type) {
14
+ if (char.length !== 1)
15
+ return '';
16
+ if (type === 'numeric' && !/\d/.test(char))
17
+ return '';
18
+ if (type === 'alphabetic' && !/[a-zA-Z]/.test(char))
19
+ return '';
20
+ if (type === 'alphanumeric' && !/[a-zA-Z0-9]/.test(char))
21
+ return '';
22
+ return char;
23
+ }
24
+ export function update(state, msg) {
25
+ if (state.disabled)
26
+ return [state, []];
27
+ switch (msg.type) {
28
+ case 'setValue': {
29
+ const char = sanitize(msg.value.slice(-1), state.type);
30
+ if (!char && msg.value !== '')
31
+ return [state, []];
32
+ const values = [...state.values];
33
+ values[msg.index] = char;
34
+ // Auto-advance
35
+ const nextIndex = char ? Math.min(msg.index + 1, state.length - 1) : msg.index;
36
+ return [{ ...state, values, focusedIndex: nextIndex }, []];
37
+ }
38
+ case 'setAll': {
39
+ const values = new Array(state.length).fill('');
40
+ for (let i = 0; i < Math.min(msg.values.length, state.length); i++) {
41
+ values[i] = sanitize(msg.values[i], state.type);
42
+ }
43
+ const lastFilled = values.findIndex((v) => v === '');
44
+ const focusedIndex = lastFilled === -1 ? state.length - 1 : lastFilled;
45
+ return [{ ...state, values, focusedIndex }, []];
46
+ }
47
+ case 'focus':
48
+ return [{ ...state, focusedIndex: Math.max(0, Math.min(msg.index, state.length - 1)) }, []];
49
+ case 'clear':
50
+ return [{ ...state, values: new Array(state.length).fill(''), focusedIndex: 0 }, []];
51
+ case 'backspace': {
52
+ const values = [...state.values];
53
+ if (values[msg.index]) {
54
+ values[msg.index] = '';
55
+ return [{ ...state, values }, []];
56
+ }
57
+ // Field is empty — move focus back and clear prior
58
+ const prev = Math.max(0, msg.index - 1);
59
+ values[prev] = '';
60
+ return [{ ...state, values, focusedIndex: prev }, []];
61
+ }
62
+ }
63
+ }
64
+ export function isComplete(state) {
65
+ return state.values.every((v) => v !== '');
66
+ }
67
+ export function getValue(state) {
68
+ return state.values.join('');
69
+ }
70
+ export function connect(get, send, opts) {
71
+ const labelId = `${opts.id}:label`;
72
+ const inputLabel = opts.inputLabel ?? ((i) => `Digit ${i + 1}`);
73
+ const validate = opts.validate;
74
+ return {
75
+ root: {
76
+ role: 'group',
77
+ 'aria-labelledby': labelId,
78
+ 'data-scope': 'pin-input',
79
+ 'data-part': 'root',
80
+ 'data-disabled': (s) => (get(s).disabled ? '' : undefined),
81
+ },
82
+ label: {
83
+ id: labelId,
84
+ 'data-scope': 'pin-input',
85
+ 'data-part': 'label',
86
+ },
87
+ input: (index) => ({
88
+ type: (s) => (get(s).mask ? 'password' : 'text'),
89
+ inputMode: (s) => (get(s).type === 'numeric' ? 'numeric' : 'text'),
90
+ pattern: (s) => {
91
+ switch (get(s).type) {
92
+ case 'numeric':
93
+ return '[0-9]*';
94
+ case 'alphabetic':
95
+ return '[a-zA-Z]*';
96
+ case 'alphanumeric':
97
+ return '[a-zA-Z0-9]*';
98
+ }
99
+ },
100
+ maxLength: 1,
101
+ autoComplete: 'off',
102
+ 'aria-label': inputLabel(index),
103
+ disabled: (s) => get(s).disabled,
104
+ value: (s) => get(s).values[index] ?? '',
105
+ 'data-scope': 'pin-input',
106
+ 'data-part': 'input',
107
+ 'data-index': String(index),
108
+ onInput: (e) => {
109
+ const value = e.target.value;
110
+ if (validate && value !== '') {
111
+ const errors = validate(value.slice(-1));
112
+ if (errors && errors.length > 0)
113
+ return;
114
+ }
115
+ send({ type: 'setValue', index, value });
116
+ },
117
+ onKeyDown: (e) => {
118
+ if (e.key === 'Backspace') {
119
+ send({ type: 'backspace', index });
120
+ }
121
+ else if (e.key === 'ArrowLeft') {
122
+ e.preventDefault();
123
+ send({ type: 'focus', index: index - 1 });
124
+ }
125
+ else if (e.key === 'ArrowRight') {
126
+ e.preventDefault();
127
+ send({ type: 'focus', index: index + 1 });
128
+ }
129
+ },
130
+ onFocus: () => send({ type: 'focus', index }),
131
+ onPaste: (e) => {
132
+ e.preventDefault();
133
+ const text = e.clipboardData?.getData('text') ?? '';
134
+ send({ type: 'setAll', values: text.split('') });
135
+ },
136
+ }),
137
+ };
138
+ }
139
+ export const pinInput = { init, update, connect, isComplete, getValue };
@@ -0,0 +1,116 @@
1
+ import type { Send, TransitionOptions } from '@llui/dom';
2
+ import { type Placement } from '../utils/floating';
3
+ /**
4
+ * Popover — click-triggered, non-modal floating overlay anchored to its
5
+ * trigger. Use for menus, date pickers, color pickers, filters, etc.
6
+ *
7
+ * Like dialog, has a pure state machine + a view helper (`overlay()`) that
8
+ * wires floating-ui positioning, dismissable, and optional focus trapping.
9
+ */
10
+ export interface PopoverState {
11
+ open: boolean;
12
+ }
13
+ export type PopoverMsg = {
14
+ type: 'open';
15
+ } | {
16
+ type: 'close';
17
+ } | {
18
+ type: 'toggle';
19
+ } | {
20
+ type: 'setOpen';
21
+ open: boolean;
22
+ };
23
+ export interface PopoverInit {
24
+ open?: boolean;
25
+ }
26
+ export declare function init(opts?: PopoverInit): PopoverState;
27
+ export declare function update(state: PopoverState, msg: PopoverMsg): [PopoverState, never[]];
28
+ export interface PopoverParts<S> {
29
+ trigger: {
30
+ type: 'button';
31
+ 'aria-haspopup': 'dialog';
32
+ 'aria-expanded': (s: S) => boolean;
33
+ 'aria-controls': string;
34
+ id: string;
35
+ 'data-state': (s: S) => 'open' | 'closed';
36
+ 'data-scope': 'popover';
37
+ 'data-part': 'trigger';
38
+ onClick: (e: MouseEvent) => void;
39
+ };
40
+ positioner: {
41
+ 'data-scope': 'popover';
42
+ 'data-part': 'positioner';
43
+ style: string;
44
+ };
45
+ content: {
46
+ role: 'dialog';
47
+ id: string;
48
+ 'aria-labelledby': string;
49
+ tabIndex: -1;
50
+ 'data-state': (s: S) => 'open' | 'closed';
51
+ 'data-scope': 'popover';
52
+ 'data-part': 'content';
53
+ };
54
+ title: {
55
+ id: string;
56
+ 'data-scope': 'popover';
57
+ 'data-part': 'title';
58
+ };
59
+ description: {
60
+ id: string;
61
+ 'data-scope': 'popover';
62
+ 'data-part': 'description';
63
+ };
64
+ arrow: {
65
+ 'data-scope': 'popover';
66
+ 'data-part': 'arrow';
67
+ };
68
+ closeTrigger: {
69
+ type: 'button';
70
+ 'aria-label': string;
71
+ 'data-scope': 'popover';
72
+ 'data-part': 'close-trigger';
73
+ onClick: (e: MouseEvent) => void;
74
+ };
75
+ }
76
+ export interface ConnectOptions {
77
+ id: string;
78
+ closeLabel?: string;
79
+ }
80
+ export declare function connect<S>(get: (s: S) => PopoverState, send: Send<PopoverMsg>, opts: ConnectOptions): PopoverParts<S>;
81
+ export interface OverlayOptions<S> {
82
+ get: (s: S) => PopoverState;
83
+ send: Send<PopoverMsg>;
84
+ parts: PopoverParts<S>;
85
+ content: () => Node[];
86
+ /** Placement preference — bottom | top | right | left with -start/-end variants. */
87
+ placement?: Placement;
88
+ /** Offset between trigger and content, px (default: 8). */
89
+ offset?: number;
90
+ /** Auto-flip to opposite side (default: true). */
91
+ flip?: boolean;
92
+ /** Shift to keep in viewport (default: true). */
93
+ shift?: boolean;
94
+ /** Optional transition. */
95
+ transition?: TransitionOptions;
96
+ /** Close on Escape (default: true). */
97
+ closeOnEscape?: boolean;
98
+ /** Close on outside click (default: true). */
99
+ closeOnOutsideClick?: boolean;
100
+ /** Trap focus inside popover while open (default: false — non-modal). */
101
+ trapFocus?: boolean;
102
+ /** Restore focus to trigger on close (default: true). */
103
+ restoreFocus?: boolean;
104
+ /** Portal target (default: 'body'). */
105
+ target?: string | HTMLElement;
106
+ /** Arrow element selector within content (optional). */
107
+ arrowSelector?: string;
108
+ }
109
+ export declare function overlay<S>(opts: OverlayOptions<S>): Node[];
110
+ export declare const popover: {
111
+ init: typeof init;
112
+ update: typeof update;
113
+ connect: typeof connect;
114
+ overlay: typeof overlay;
115
+ };
116
+ //# sourceMappingURL=popover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"popover.d.ts","sourceRoot":"","sources":["../../src/components/popover.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,146 @@
1
+ import { show, portal, onMount, div } from '@llui/dom';
2
+ import { pushDismissable } from '../utils/dismissable';
3
+ import { pushFocusTrap } from '../utils/focus-trap';
4
+ import { attachFloating } from '../utils/floating';
5
+ export function init(opts = {}) {
6
+ return { open: opts.open ?? false };
7
+ }
8
+ export function update(state, msg) {
9
+ switch (msg.type) {
10
+ case 'open':
11
+ return [{ ...state, open: true }, []];
12
+ case 'close':
13
+ return [{ ...state, open: false }, []];
14
+ case 'toggle':
15
+ return [{ ...state, open: !state.open }, []];
16
+ case 'setOpen':
17
+ return [{ ...state, open: msg.open }, []];
18
+ }
19
+ }
20
+ export function connect(get, send, opts) {
21
+ const base = opts.id;
22
+ const triggerId = `${base}:trigger`;
23
+ const contentId = `${base}:content`;
24
+ const titleId = `${base}:title`;
25
+ const descId = `${base}:description`;
26
+ const closeLabel = opts.closeLabel ?? 'Close';
27
+ return {
28
+ trigger: {
29
+ type: 'button',
30
+ 'aria-haspopup': 'dialog',
31
+ 'aria-expanded': (s) => get(s).open,
32
+ 'aria-controls': contentId,
33
+ id: triggerId,
34
+ 'data-state': (s) => (get(s).open ? 'open' : 'closed'),
35
+ 'data-scope': 'popover',
36
+ 'data-part': 'trigger',
37
+ onClick: () => send({ type: 'toggle' }),
38
+ },
39
+ positioner: {
40
+ 'data-scope': 'popover',
41
+ 'data-part': 'positioner',
42
+ style: 'position:absolute;top:0;left:0;',
43
+ },
44
+ content: {
45
+ role: 'dialog',
46
+ id: contentId,
47
+ 'aria-labelledby': titleId,
48
+ tabIndex: -1,
49
+ 'data-state': (s) => (get(s).open ? 'open' : 'closed'),
50
+ 'data-scope': 'popover',
51
+ 'data-part': 'content',
52
+ },
53
+ title: {
54
+ id: titleId,
55
+ 'data-scope': 'popover',
56
+ 'data-part': 'title',
57
+ },
58
+ description: {
59
+ id: descId,
60
+ 'data-scope': 'popover',
61
+ 'data-part': 'description',
62
+ },
63
+ arrow: {
64
+ 'data-scope': 'popover',
65
+ 'data-part': 'arrow',
66
+ },
67
+ closeTrigger: {
68
+ type: 'button',
69
+ 'aria-label': closeLabel,
70
+ 'data-scope': 'popover',
71
+ 'data-part': 'close-trigger',
72
+ onClick: () => send({ type: 'close' }),
73
+ },
74
+ };
75
+ }
76
+ export function overlay(opts) {
77
+ const target = opts.target ?? 'body';
78
+ const placement = opts.placement ?? 'bottom';
79
+ const offset = opts.offset ?? 8;
80
+ const flip = opts.flip !== false;
81
+ const shift = opts.shift !== false;
82
+ const closeOnEscape = opts.closeOnEscape !== false;
83
+ const closeOnOutsideClick = opts.closeOnOutsideClick !== false;
84
+ const trapFocus = opts.trapFocus === true;
85
+ const restoreFocus = opts.restoreFocus !== false;
86
+ const parts = opts.parts;
87
+ const contentId = parts.content.id;
88
+ const triggerId = parts.trigger.id;
89
+ return show({
90
+ when: (s) => opts.get(s).open,
91
+ render: () => portal({
92
+ target,
93
+ render: () => {
94
+ onMount(() => {
95
+ const contentEl = document.getElementById(contentId);
96
+ const triggerEl = document.getElementById(triggerId);
97
+ if (!contentEl || !triggerEl)
98
+ return;
99
+ const cleanups = [];
100
+ // Position content relative to trigger
101
+ const positioner = contentEl.closest('[data-part="positioner"]');
102
+ const floatingEl = positioner ?? contentEl;
103
+ const arrow = opts.arrowSelector
104
+ ? contentEl.querySelector(opts.arrowSelector)
105
+ : null;
106
+ cleanups.push(attachFloating({
107
+ anchor: triggerEl,
108
+ floating: floatingEl,
109
+ placement,
110
+ offset,
111
+ flip,
112
+ shift,
113
+ arrow: arrow ?? undefined,
114
+ }));
115
+ if (trapFocus) {
116
+ cleanups.push(pushFocusTrap({
117
+ container: contentEl,
118
+ restoreFocus,
119
+ }));
120
+ }
121
+ if (closeOnEscape || closeOnOutsideClick) {
122
+ cleanups.push(pushDismissable({
123
+ element: contentEl,
124
+ ignore: () => [triggerEl],
125
+ disableEscape: !closeOnEscape,
126
+ disableOutside: !closeOnOutsideClick,
127
+ onDismiss: () => {
128
+ opts.send({ type: 'close' });
129
+ if (restoreFocus)
130
+ triggerEl.focus();
131
+ },
132
+ }));
133
+ }
134
+ return () => {
135
+ for (let i = cleanups.length - 1; i >= 0; i--)
136
+ cleanups[i]();
137
+ };
138
+ });
139
+ return [div(parts.positioner, opts.content())];
140
+ },
141
+ }),
142
+ enter: opts.transition?.enter,
143
+ leave: opts.transition?.leave,
144
+ });
145
+ }
146
+ export const popover = { init, update, connect, overlay };
@@ -0,0 +1,71 @@
1
+ import type { Send } from '@llui/dom';
2
+ /**
3
+ * Presence — track mount/unmount lifecycle with exit-delay support.
4
+ *
5
+ * In many components (dialogs, tooltips, menus) the consumer wants to:
6
+ * 1. close the overlay (fire exit animation)
7
+ * 2. keep it mounted long enough for the animation to finish
8
+ * 3. unmount it
9
+ *
10
+ * LLui already provides `@llui/transitions` for most of this, but a
11
+ * presence machine is useful when you want to coordinate multiple
12
+ * elements or expose state outside the transition primitive.
13
+ *
14
+ * State flow:
15
+ * closed → (open) → opening → open
16
+ * open → (close) → closing → closed
17
+ *
18
+ * The consumer fires `animationEnd` to advance past opening/closing.
19
+ * If `unmountOnExit` is true, `closed` means "safe to remove from DOM";
20
+ * otherwise the element stays mounted even when closed (display:none).
21
+ */
22
+ export type PresenceStatus = 'closed' | 'opening' | 'open' | 'closing';
23
+ export interface PresenceState {
24
+ status: PresenceStatus;
25
+ unmountOnExit: boolean;
26
+ }
27
+ export type PresenceMsg = {
28
+ type: 'open';
29
+ } | {
30
+ type: 'close';
31
+ } | {
32
+ type: 'toggle';
33
+ } | {
34
+ type: 'animationEnd';
35
+ } | {
36
+ type: 'setPresent';
37
+ present: boolean;
38
+ };
39
+ export interface PresenceInit {
40
+ /** Initial presence — true starts in 'open', false starts in 'closed'. */
41
+ present?: boolean;
42
+ /** Whether 'closed' means "unmount" (true) or "hidden but mounted" (false). Default: true. */
43
+ unmountOnExit?: boolean;
44
+ }
45
+ export declare function init(opts?: PresenceInit): PresenceState;
46
+ export declare function update(state: PresenceState, msg: PresenceMsg): [PresenceState, never[]];
47
+ /** Whether the element should be in the DOM (mounted). */
48
+ export declare function isMounted(state: PresenceState): boolean;
49
+ /** Whether the element is visible (not running an exit animation). */
50
+ export declare function isVisible(state: PresenceState): boolean;
51
+ export declare function isAnimating(state: PresenceState): boolean;
52
+ export interface PresenceParts<S> {
53
+ root: {
54
+ 'data-scope': 'presence';
55
+ 'data-part': 'root';
56
+ 'data-state': (s: S) => PresenceStatus;
57
+ hidden: (s: S) => boolean;
58
+ onAnimationEnd: (e: AnimationEvent) => void;
59
+ onTransitionEnd: (e: TransitionEvent) => void;
60
+ };
61
+ }
62
+ export declare function connect<S>(get: (s: S) => PresenceState, send: Send<PresenceMsg>): PresenceParts<S>;
63
+ export declare const presence: {
64
+ init: typeof init;
65
+ update: typeof update;
66
+ connect: typeof connect;
67
+ isMounted: typeof isMounted;
68
+ isVisible: typeof isVisible;
69
+ isAnimating: typeof isAnimating;
70
+ };
71
+ //# sourceMappingURL=presence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presence.d.ts","sourceRoot":"","sources":["../../src/components/presence.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAErC;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAAA;AAEtE,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,cAAc,CAAA;IACtB,aAAa,EAAE,OAAO,CAAA;CACvB;AAED,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAClB;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,GACxB;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAA;AAE5C,MAAM,WAAW,YAAY;IAC3B,0EAA0E;IAC1E,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,8FAA8F;IAC9F,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB;AAED,wBAAgB,IAAI,CAAC,IAAI,GAAE,YAAiB,GAAG,aAAa,CAK3D;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,WAAW,GAAG,CAAC,aAAa,EAAE,KAAK,EAAE,CAAC,CAmBvF;AAED,0DAA0D;AAC1D,wBAAgB,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAGvD;AAED,sEAAsE;AACtE,wBAAgB,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAEvD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAEzD;AAED,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,IAAI,EAAE;QACJ,YAAY,EAAE,UAAU,CAAA;QACxB,WAAW,EAAE,MAAM,CAAA;QACnB,YAAY,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,cAAc,CAAA;QACtC,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,OAAO,CAAA;QACzB,cAAc,EAAE,CAAC,CAAC,EAAE,cAAc,KAAK,IAAI,CAAA;QAC3C,eAAe,EAAE,CAAC,CAAC,EAAE,eAAe,KAAK,IAAI,CAAA;KAC9C,CAAA;CACF;AAED,wBAAgB,OAAO,CAAC,CAAC,EACvB,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,aAAa,EAC5B,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,GACtB,aAAa,CAAC,CAAC,CAAC,CAYlB;AAED,eAAO,MAAM,QAAQ;;;;;;;CAA+D,CAAA"}
@@ -0,0 +1,57 @@
1
+ export function init(opts = {}) {
2
+ return {
3
+ status: opts.present ? 'open' : 'closed',
4
+ unmountOnExit: opts.unmountOnExit ?? true,
5
+ };
6
+ }
7
+ export function update(state, msg) {
8
+ switch (msg.type) {
9
+ case 'open':
10
+ if (state.status === 'open' || state.status === 'opening')
11
+ return [state, []];
12
+ return [{ ...state, status: 'opening' }, []];
13
+ case 'close':
14
+ if (state.status === 'closed' || state.status === 'closing')
15
+ return [state, []];
16
+ return [{ ...state, status: 'closing' }, []];
17
+ case 'toggle': {
18
+ const present = state.status === 'open' || state.status === 'opening';
19
+ return update(state, { type: present ? 'close' : 'open' });
20
+ }
21
+ case 'animationEnd':
22
+ if (state.status === 'opening')
23
+ return [{ ...state, status: 'open' }, []];
24
+ if (state.status === 'closing')
25
+ return [{ ...state, status: 'closed' }, []];
26
+ return [state, []];
27
+ case 'setPresent':
28
+ return [{ ...state, status: msg.present ? 'open' : 'closed' }, []];
29
+ }
30
+ }
31
+ /** Whether the element should be in the DOM (mounted). */
32
+ export function isMounted(state) {
33
+ if (!state.unmountOnExit)
34
+ return true;
35
+ return state.status !== 'closed';
36
+ }
37
+ /** Whether the element is visible (not running an exit animation). */
38
+ export function isVisible(state) {
39
+ return state.status === 'open' || state.status === 'opening';
40
+ }
41
+ export function isAnimating(state) {
42
+ return state.status === 'opening' || state.status === 'closing';
43
+ }
44
+ export function connect(get, send) {
45
+ const onEnd = () => send({ type: 'animationEnd' });
46
+ return {
47
+ root: {
48
+ 'data-scope': 'presence',
49
+ 'data-part': 'root',
50
+ 'data-state': (s) => get(s).status,
51
+ hidden: (s) => (get(s).status === 'closed' && !get(s).unmountOnExit ? true : false),
52
+ onAnimationEnd: onEnd,
53
+ onTransitionEnd: onEnd,
54
+ },
55
+ };
56
+ }
57
+ export const presence = { init, update, connect, isMounted, isVisible, isAnimating };
@@ -0,0 +1,74 @@
1
+ import type { Send } from '@llui/dom';
2
+ /**
3
+ * Progress — linear or circular progress indicator. Determinate (0..max) or
4
+ * indeterminate (`value: null`).
5
+ */
6
+ export type ProgressOrientation = 'horizontal' | 'vertical';
7
+ export interface ProgressState {
8
+ value: number | null;
9
+ min: number;
10
+ max: number;
11
+ orientation: ProgressOrientation;
12
+ }
13
+ export type ProgressMsg = {
14
+ type: 'setValue';
15
+ value: number | null;
16
+ } | {
17
+ type: 'setMax';
18
+ max: number;
19
+ };
20
+ export interface ProgressInit {
21
+ value?: number | null;
22
+ min?: number;
23
+ max?: number;
24
+ orientation?: ProgressOrientation;
25
+ }
26
+ export declare function init(opts?: ProgressInit): ProgressState;
27
+ export declare function update(state: ProgressState, msg: ProgressMsg): [ProgressState, never[]];
28
+ export declare function percent(state: ProgressState): number | null;
29
+ export declare function valueState(state: ProgressState): 'indeterminate' | 'complete' | 'loading';
30
+ export interface ProgressParts<S> {
31
+ root: {
32
+ role: 'progressbar';
33
+ 'aria-valuemin': (s: S) => number;
34
+ 'aria-valuemax': (s: S) => number;
35
+ 'aria-valuenow': (s: S) => number | undefined;
36
+ 'aria-label': string | undefined;
37
+ 'data-state': (s: S) => 'indeterminate' | 'complete' | 'loading';
38
+ 'data-orientation': (s: S) => ProgressOrientation;
39
+ 'data-scope': 'progress';
40
+ 'data-part': 'root';
41
+ };
42
+ track: {
43
+ 'data-state': (s: S) => 'indeterminate' | 'complete' | 'loading';
44
+ 'data-orientation': (s: S) => ProgressOrientation;
45
+ 'data-scope': 'progress';
46
+ 'data-part': 'track';
47
+ };
48
+ range: {
49
+ 'data-state': (s: S) => 'indeterminate' | 'complete' | 'loading';
50
+ 'data-orientation': (s: S) => ProgressOrientation;
51
+ 'data-scope': 'progress';
52
+ 'data-part': 'range';
53
+ style: (s: S) => string;
54
+ };
55
+ label: {
56
+ 'data-scope': 'progress';
57
+ 'data-part': 'label';
58
+ };
59
+ valueText: (s: S) => string;
60
+ }
61
+ export interface ConnectOptions {
62
+ label?: string;
63
+ /** Custom formatter for value text. */
64
+ format?: (value: number | null, max: number) => string;
65
+ }
66
+ export declare function connect<S>(get: (s: S) => ProgressState, _send: Send<ProgressMsg>, opts?: ConnectOptions): ProgressParts<S>;
67
+ export declare const progress: {
68
+ init: typeof init;
69
+ update: typeof update;
70
+ connect: typeof connect;
71
+ percent: typeof percent;
72
+ valueState: typeof valueState;
73
+ };
74
+ //# sourceMappingURL=progress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../src/components/progress.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAErC;;;GAGG;AAEH,MAAM,MAAM,mBAAmB,GAAG,YAAY,GAAG,UAAU,CAAA;AAE3D,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,WAAW,EAAE,mBAAmB,CAAA;CACjC;AAED,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAA;AAEnC,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,mBAAmB,CAAA;CAClC;AAED,wBAAgB,IAAI,CAAC,IAAI,GAAE,YAAiB,GAAG,aAAa,CAO3D;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,WAAW,GAAG,CAAC,aAAa,EAAE,KAAK,EAAE,CAAC,CAOvF;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAK3D;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,aAAa,GAAG,eAAe,GAAG,UAAU,GAAG,SAAS,CAIzF;AAED,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,IAAI,EAAE;QACJ,IAAI,EAAE,aAAa,CAAA;QACnB,eAAe,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;QACjC,eAAe,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;QACjC,eAAe,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,GAAG,SAAS,CAAA;QAC7C,YAAY,EAAE,MAAM,GAAG,SAAS,CAAA;QAChC,YAAY,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,eAAe,GAAG,UAAU,GAAG,SAAS,CAAA;QAChE,kBAAkB,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,mBAAmB,CAAA;QACjD,YAAY,EAAE,UAAU,CAAA;QACxB,WAAW,EAAE,MAAM,CAAA;KACpB,CAAA;IACD,KAAK,EAAE;QACL,YAAY,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,eAAe,GAAG,UAAU,GAAG,SAAS,CAAA;QAChE,kBAAkB,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,mBAAmB,CAAA;QACjD,YAAY,EAAE,UAAU,CAAA;QACxB,WAAW,EAAE,OAAO,CAAA;KACrB,CAAA;IACD,KAAK,EAAE;QACL,YAAY,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,eAAe,GAAG,UAAU,GAAG,SAAS,CAAA;QAChE,kBAAkB,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,mBAAmB,CAAA;QACjD,YAAY,EAAE,UAAU,CAAA;QACxB,WAAW,EAAE,OAAO,CAAA;QACpB,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;KACxB,CAAA;IACD,KAAK,EAAE;QACL,YAAY,EAAE,UAAU,CAAA;QACxB,WAAW,EAAE,OAAO,CAAA;KACrB,CAAA;IACD,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;CAC5B;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,uCAAuC;IACvC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;CACvD;AAED,wBAAgB,OAAO,CAAC,CAAC,EACvB,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,aAAa,EAC5B,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,EACxB,IAAI,GAAE,cAAmB,GACxB,aAAa,CAAC,CAAC,CAAC,CAmClB;AAeD,eAAO,MAAM,QAAQ;;;;;;CAAiD,CAAA"}