@llui/components 0.4.10 → 0.5.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 (243) hide show
  1. package/dist/components/accordion.d.ts +13 -13
  2. package/dist/components/accordion.d.ts.map +1 -1
  3. package/dist/components/accordion.js +9 -9
  4. package/dist/components/accordion.js.map +1 -1
  5. package/dist/components/alert-dialog.d.ts +8 -8
  6. package/dist/components/alert-dialog.d.ts.map +1 -1
  7. package/dist/components/alert-dialog.js +2 -2
  8. package/dist/components/alert-dialog.js.map +1 -1
  9. package/dist/components/angle-slider.d.ts +13 -13
  10. package/dist/components/angle-slider.d.ts.map +1 -1
  11. package/dist/components/angle-slider.js +11 -11
  12. package/dist/components/angle-slider.js.map +1 -1
  13. package/dist/components/async-list.d.ts +7 -7
  14. package/dist/components/async-list.d.ts.map +1 -1
  15. package/dist/components/async-list.js +5 -8
  16. package/dist/components/async-list.js.map +1 -1
  17. package/dist/components/avatar.d.ts +9 -9
  18. package/dist/components/avatar.d.ts.map +1 -1
  19. package/dist/components/avatar.js +7 -7
  20. package/dist/components/avatar.js.map +1 -1
  21. package/dist/components/carousel.d.ts +18 -18
  22. package/dist/components/carousel.d.ts.map +1 -1
  23. package/dist/components/carousel.js +12 -12
  24. package/dist/components/carousel.js.map +1 -1
  25. package/dist/components/cascade-select.d.ts +12 -12
  26. package/dist/components/cascade-select.d.ts.map +1 -1
  27. package/dist/components/cascade-select.js +8 -8
  28. package/dist/components/cascade-select.js.map +1 -1
  29. package/dist/components/checkbox.d.ts +14 -14
  30. package/dist/components/checkbox.d.ts.map +1 -1
  31. package/dist/components/checkbox.js +12 -12
  32. package/dist/components/checkbox.js.map +1 -1
  33. package/dist/components/clipboard.d.ts +8 -8
  34. package/dist/components/clipboard.d.ts.map +1 -1
  35. package/dist/components/clipboard.js +6 -6
  36. package/dist/components/clipboard.js.map +1 -1
  37. package/dist/components/collapsible.d.ts +11 -11
  38. package/dist/components/collapsible.d.ts.map +1 -1
  39. package/dist/components/collapsible.js +9 -9
  40. package/dist/components/collapsible.js.map +1 -1
  41. package/dist/components/color-picker.d.ts +19 -19
  42. package/dist/components/color-picker.d.ts.map +1 -1
  43. package/dist/components/color-picker.js +21 -21
  44. package/dist/components/color-picker.js.map +1 -1
  45. package/dist/components/combobox.d.ts +25 -25
  46. package/dist/components/combobox.d.ts.map +1 -1
  47. package/dist/components/combobox.js +54 -59
  48. package/dist/components/combobox.js.map +1 -1
  49. package/dist/components/context-menu.d.ts +14 -14
  50. package/dist/components/context-menu.d.ts.map +1 -1
  51. package/dist/components/context-menu.js +15 -19
  52. package/dist/components/context-menu.js.map +1 -1
  53. package/dist/components/date-input.d.ts +13 -13
  54. package/dist/components/date-input.d.ts.map +1 -1
  55. package/dist/components/date-input.js +11 -11
  56. package/dist/components/date-input.js.map +1 -1
  57. package/dist/components/date-picker.d.ts +11 -11
  58. package/dist/components/date-picker.d.ts.map +1 -1
  59. package/dist/components/date-picker.js +7 -7
  60. package/dist/components/date-picker.js.map +1 -1
  61. package/dist/components/dialog.d.ts +15 -15
  62. package/dist/components/dialog.d.ts.map +1 -1
  63. package/dist/components/dialog.js +45 -50
  64. package/dist/components/dialog.js.map +1 -1
  65. package/dist/components/drawer.d.ts +13 -13
  66. package/dist/components/drawer.d.ts.map +1 -1
  67. package/dist/components/drawer.js +44 -49
  68. package/dist/components/drawer.js.map +1 -1
  69. package/dist/components/editable.d.ts +11 -11
  70. package/dist/components/editable.d.ts.map +1 -1
  71. package/dist/components/editable.js +9 -9
  72. package/dist/components/editable.js.map +1 -1
  73. package/dist/components/file-upload.d.ts +19 -19
  74. package/dist/components/file-upload.d.ts.map +1 -1
  75. package/dist/components/file-upload.js +14 -14
  76. package/dist/components/file-upload.js.map +1 -1
  77. package/dist/components/floating-panel.d.ts +14 -14
  78. package/dist/components/floating-panel.d.ts.map +1 -1
  79. package/dist/components/floating-panel.js +13 -14
  80. package/dist/components/floating-panel.js.map +1 -1
  81. package/dist/components/form.d.ts +9 -9
  82. package/dist/components/form.d.ts.map +1 -1
  83. package/dist/components/form.js +7 -7
  84. package/dist/components/form.js.map +1 -1
  85. package/dist/components/hover-card.d.ts +9 -9
  86. package/dist/components/hover-card.d.ts.map +1 -1
  87. package/dist/components/hover-card.js +12 -13
  88. package/dist/components/hover-card.js.map +1 -1
  89. package/dist/components/image-cropper.d.ts +8 -8
  90. package/dist/components/image-cropper.d.ts.map +1 -1
  91. package/dist/components/image-cropper.js +7 -8
  92. package/dist/components/image-cropper.js.map +1 -1
  93. package/dist/components/in-view.d.ts +6 -6
  94. package/dist/components/in-view.d.ts.map +1 -1
  95. package/dist/components/in-view.js +2 -2
  96. package/dist/components/in-view.js.map +1 -1
  97. package/dist/components/listbox.d.ts +16 -16
  98. package/dist/components/listbox.d.ts.map +1 -1
  99. package/dist/components/listbox.js +16 -16
  100. package/dist/components/listbox.js.map +1 -1
  101. package/dist/components/marquee.d.ts +8 -8
  102. package/dist/components/marquee.d.ts.map +1 -1
  103. package/dist/components/marquee.js +8 -11
  104. package/dist/components/marquee.js.map +1 -1
  105. package/dist/components/menu.d.ts +15 -15
  106. package/dist/components/menu.d.ts.map +1 -1
  107. package/dist/components/menu.js +16 -17
  108. package/dist/components/menu.js.map +1 -1
  109. package/dist/components/navigation-menu.d.ts +12 -12
  110. package/dist/components/navigation-menu.d.ts.map +1 -1
  111. package/dist/components/navigation-menu.js +8 -8
  112. package/dist/components/navigation-menu.js.map +1 -1
  113. package/dist/components/number-input.d.ts +18 -18
  114. package/dist/components/number-input.d.ts.map +1 -1
  115. package/dist/components/number-input.js +16 -20
  116. package/dist/components/number-input.js.map +1 -1
  117. package/dist/components/pagination.d.ts +13 -13
  118. package/dist/components/pagination.d.ts.map +1 -1
  119. package/dist/components/pagination.js +11 -17
  120. package/dist/components/pagination.js.map +1 -1
  121. package/dist/components/password-input.d.ts +11 -11
  122. package/dist/components/password-input.d.ts.map +1 -1
  123. package/dist/components/password-input.js +11 -11
  124. package/dist/components/password-input.js.map +1 -1
  125. package/dist/components/pin-input.d.ts +9 -9
  126. package/dist/components/pin-input.d.ts.map +1 -1
  127. package/dist/components/pin-input.js +9 -9
  128. package/dist/components/pin-input.js.map +1 -1
  129. package/dist/components/popover.d.ts +11 -11
  130. package/dist/components/popover.d.ts.map +1 -1
  131. package/dist/components/popover.js +61 -60
  132. package/dist/components/popover.js.map +1 -1
  133. package/dist/components/presence.d.ts +7 -5
  134. package/dist/components/presence.d.ts.map +1 -1
  135. package/dist/components/presence.js +5 -3
  136. package/dist/components/presence.js.map +1 -1
  137. package/dist/components/progress.d.ts +14 -14
  138. package/dist/components/progress.d.ts.map +1 -1
  139. package/dist/components/progress.js +12 -12
  140. package/dist/components/progress.js.map +1 -1
  141. package/dist/components/qr-code.d.ts +7 -7
  142. package/dist/components/qr-code.d.ts.map +1 -1
  143. package/dist/components/qr-code.js +7 -7
  144. package/dist/components/qr-code.js.map +1 -1
  145. package/dist/components/radio-group.d.ts +15 -15
  146. package/dist/components/radio-group.d.ts.map +1 -1
  147. package/dist/components/radio-group.js +12 -13
  148. package/dist/components/radio-group.js.map +1 -1
  149. package/dist/components/rating-group.d.ts +13 -13
  150. package/dist/components/rating-group.d.ts.map +1 -1
  151. package/dist/components/rating-group.js +10 -11
  152. package/dist/components/rating-group.js.map +1 -1
  153. package/dist/components/scroll-area.d.ts +10 -10
  154. package/dist/components/scroll-area.d.ts.map +1 -1
  155. package/dist/components/scroll-area.js +10 -15
  156. package/dist/components/scroll-area.js.map +1 -1
  157. package/dist/components/select.d.ts +26 -26
  158. package/dist/components/select.d.ts.map +1 -1
  159. package/dist/components/select.js +29 -33
  160. package/dist/components/select.js.map +1 -1
  161. package/dist/components/signature-pad.d.ts +12 -12
  162. package/dist/components/signature-pad.d.ts.map +1 -1
  163. package/dist/components/signature-pad.js +10 -10
  164. package/dist/components/signature-pad.js.map +1 -1
  165. package/dist/components/slider.d.ts +22 -22
  166. package/dist/components/slider.d.ts.map +1 -1
  167. package/dist/components/slider.js +17 -17
  168. package/dist/components/slider.js.map +1 -1
  169. package/dist/components/sortable.d.ts +11 -11
  170. package/dist/components/sortable.d.ts.map +1 -1
  171. package/dist/components/sortable.js +20 -20
  172. package/dist/components/sortable.js.map +1 -1
  173. package/dist/components/splitter.d.ts +15 -15
  174. package/dist/components/splitter.d.ts.map +1 -1
  175. package/dist/components/splitter.js +15 -15
  176. package/dist/components/splitter.js.map +1 -1
  177. package/dist/components/steps.d.ts +14 -14
  178. package/dist/components/steps.d.ts.map +1 -1
  179. package/dist/components/steps.js +10 -16
  180. package/dist/components/steps.js.map +1 -1
  181. package/dist/components/switch.d.ts +12 -12
  182. package/dist/components/switch.d.ts.map +1 -1
  183. package/dist/components/switch.js +10 -10
  184. package/dist/components/switch.js.map +1 -1
  185. package/dist/components/tabs.d.ts +15 -15
  186. package/dist/components/tabs.d.ts.map +1 -1
  187. package/dist/components/tabs.js +11 -11
  188. package/dist/components/tabs.js.map +1 -1
  189. package/dist/components/tags-input.d.ts +14 -14
  190. package/dist/components/tags-input.d.ts.map +1 -1
  191. package/dist/components/tags-input.js +10 -10
  192. package/dist/components/tags-input.js.map +1 -1
  193. package/dist/components/theme-switch.d.ts +5 -5
  194. package/dist/components/theme-switch.d.ts.map +1 -1
  195. package/dist/components/theme-switch.js +3 -3
  196. package/dist/components/theme-switch.js.map +1 -1
  197. package/dist/components/time-picker.d.ts +19 -19
  198. package/dist/components/time-picker.d.ts.map +1 -1
  199. package/dist/components/time-picker.js +17 -17
  200. package/dist/components/time-picker.js.map +1 -1
  201. package/dist/components/timer.d.ts +10 -10
  202. package/dist/components/timer.d.ts.map +1 -1
  203. package/dist/components/timer.js +8 -8
  204. package/dist/components/timer.js.map +1 -1
  205. package/dist/components/toast.d.ts +8 -8
  206. package/dist/components/toast.d.ts.map +1 -1
  207. package/dist/components/toast.js +4 -4
  208. package/dist/components/toast.js.map +1 -1
  209. package/dist/components/toc.d.ts +12 -12
  210. package/dist/components/toc.d.ts.map +1 -1
  211. package/dist/components/toc.js +8 -8
  212. package/dist/components/toc.js.map +1 -1
  213. package/dist/components/toggle-group.d.ts +13 -13
  214. package/dist/components/toggle-group.d.ts.map +1 -1
  215. package/dist/components/toggle-group.js +9 -9
  216. package/dist/components/toggle-group.js.map +1 -1
  217. package/dist/components/toggle.d.ts +8 -8
  218. package/dist/components/toggle.d.ts.map +1 -1
  219. package/dist/components/toggle.js +6 -6
  220. package/dist/components/toggle.js.map +1 -1
  221. package/dist/components/tooltip.d.ts +10 -10
  222. package/dist/components/tooltip.d.ts.map +1 -1
  223. package/dist/components/tooltip.js +13 -14
  224. package/dist/components/tooltip.js.map +1 -1
  225. package/dist/components/tour.d.ts +7 -7
  226. package/dist/components/tour.d.ts.map +1 -1
  227. package/dist/components/tour.js +5 -5
  228. package/dist/components/tour.js.map +1 -1
  229. package/dist/components/tree-view.d.ts +19 -19
  230. package/dist/components/tree-view.d.ts.map +1 -1
  231. package/dist/components/tree-view.js +23 -23
  232. package/dist/components/tree-view.js.map +1 -1
  233. package/dist/patterns/confirm-dialog.d.ts +4 -4
  234. package/dist/patterns/confirm-dialog.d.ts.map +1 -1
  235. package/dist/patterns/confirm-dialog.js +7 -9
  236. package/dist/patterns/confirm-dialog.js.map +1 -1
  237. package/package.json +3 -3
  238. package/dist/components/enter-view.d.ts +0 -73
  239. package/dist/components/enter-view.d.ts.map +0 -1
  240. package/dist/components/enter-view.js +0 -51
  241. package/dist/utils/validators.d.ts +0 -34
  242. package/dist/utils/validators.d.ts.map +0 -1
  243. package/dist/utils/validators.js +0 -83
@@ -78,10 +78,10 @@ export function update(state, msg) {
78
78
  return [{ ...state, disabled: msg.disabled }, []];
79
79
  }
80
80
  }
81
- export function connect(get, send, opts = {}) {
81
+ export function connect(state, send, opts = {}) {
82
82
  const locale = useContext(LocaleContext);
83
- const incrementLabel = opts.incrementLabel ?? ((s) => locale(s).numberInput.increment);
84
- const decrementLabel = opts.decrementLabel ?? ((s) => locale(s).numberInput.decrement);
83
+ const incrementLabel = opts.incrementLabel ?? locale.numberInput.increment;
84
+ const decrementLabel = opts.decrementLabel ?? locale.numberInput.decrement;
85
85
  const validate = opts.validate;
86
86
  const trySetValue = (value) => {
87
87
  if (validate) {
@@ -95,20 +95,20 @@ export function connect(get, send, opts = {}) {
95
95
  root: {
96
96
  'data-scope': 'number-input',
97
97
  'data-part': 'root',
98
- 'data-disabled': (s) => (get(s).disabled ? '' : undefined),
98
+ 'data-disabled': state.map((st) => (st.disabled ? '' : undefined)),
99
99
  },
100
100
  input: {
101
101
  type: 'text',
102
102
  role: 'spinbutton',
103
103
  inputMode: 'decimal',
104
- 'aria-valuemin': (s) => (isFinite(get(s).min) ? get(s).min : undefined),
105
- 'aria-valuemax': (s) => (isFinite(get(s).max) ? get(s).max : undefined),
106
- 'aria-valuenow': (s) => get(s).value ?? undefined,
107
- 'aria-disabled': (s) => (get(s).disabled ? 'true' : undefined),
108
- 'aria-readonly': (s) => (get(s).readOnly ? 'true' : undefined),
109
- disabled: (s) => get(s).disabled,
110
- readOnly: (s) => get(s).readOnly,
111
- value: (s) => get(s).rawText,
104
+ 'aria-valuemin': state.map((st) => (isFinite(st.min) ? st.min : undefined)),
105
+ 'aria-valuemax': state.map((st) => (isFinite(st.max) ? st.max : undefined)),
106
+ 'aria-valuenow': state.map((st) => st.value ?? undefined),
107
+ 'aria-disabled': state.map((st) => (st.disabled ? 'true' : undefined)),
108
+ 'aria-readonly': state.map((st) => (st.readOnly ? 'true' : undefined)),
109
+ disabled: state.map((st) => st.disabled),
110
+ readOnly: state.map((st) => st.readOnly),
111
+ value: state.map((st) => st.rawText),
112
112
  'data-scope': 'number-input',
113
113
  'data-part': 'input',
114
114
  onInput: tagSend(send, ['setRawText'], (e) => {
@@ -155,10 +155,8 @@ export function connect(get, send, opts = {}) {
155
155
  increment: {
156
156
  type: 'button',
157
157
  'aria-label': incrementLabel,
158
- 'aria-disabled': (s) => get(s).disabled || get(s).readOnly || (get(s).value ?? 0) >= get(s).max
159
- ? 'true'
160
- : undefined,
161
- disabled: (s) => get(s).disabled || get(s).readOnly || (get(s).value ?? 0) >= get(s).max,
158
+ 'aria-disabled': state.map((st) => st.disabled || st.readOnly || (st.value ?? 0) >= st.max ? 'true' : undefined),
159
+ disabled: state.map((st) => st.disabled || st.readOnly || (st.value ?? 0) >= st.max),
162
160
  'data-scope': 'number-input',
163
161
  'data-part': 'increment',
164
162
  tabIndex: -1,
@@ -167,10 +165,8 @@ export function connect(get, send, opts = {}) {
167
165
  decrement: {
168
166
  type: 'button',
169
167
  'aria-label': decrementLabel,
170
- 'aria-disabled': (s) => get(s).disabled || get(s).readOnly || (get(s).value ?? 0) <= get(s).min
171
- ? 'true'
172
- : undefined,
173
- disabled: (s) => get(s).disabled || get(s).readOnly || (get(s).value ?? 0) <= get(s).min,
168
+ 'aria-disabled': state.map((st) => st.disabled || st.readOnly || (st.value ?? 0) <= st.min ? 'true' : undefined),
169
+ disabled: state.map((st) => st.disabled || st.readOnly || (st.value ?? 0) <= st.min),
174
170
  'data-scope': 'number-input',
175
171
  'data-part': 'decrement',
176
172
  tabIndex: -1,
@@ -1 +1 @@
1
- {"version":3,"file":"number-input.js","sourceRoot":"","sources":["../../src/components/number-input.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Send } from '@llui/dom'\nimport { useContext, tagSend } from '@llui/dom'\nimport { LocaleContext } from '../locale.js'\nimport type { Locale } from '../locale.js'\n\n/**\n * Number input — numeric field with increment/decrement buttons. Clamps\n * to min/max and snaps to step. Keyboard: Arrow Up/Down, PageUp/PageDown,\n * Home/End.\n */\n\nexport interface NumberInputState {\n value: number | null\n min: number\n max: number\n step: number\n disabled: boolean\n readOnly: boolean\n /** Allow a free-text input value while the user is typing. */\n rawText: string\n}\n\nexport type NumberInputMsg =\n /** @intent(\"Set the numeric value (clamped to min/max, snapped to step)\") */\n | { type: 'setValue'; value: number | null }\n /** @humanOnly */\n | { type: 'setRawText'; text: string }\n /** @intent(\"Commit the in-progress text input — parse, clamp, snap, and update value\") */\n | { type: 'commit' }\n /** @intent(\"Increase value by step (or step × multiplier)\") */\n | { type: 'increment'; multiplier?: number }\n /** @intent(\"Decrease value by step (or step × multiplier)\") */\n | { type: 'decrement'; multiplier?: number }\n /** @intent(\"Snap value to the configured minimum\") */\n | { type: 'toMin' }\n /** @intent(\"Snap value to the configured maximum\") */\n | { type: 'toMax' }\n /** @humanOnly */\n | { type: 'setDisabled'; disabled: boolean }\n\nexport interface NumberInputInit {\n value?: number | null\n min?: number\n max?: number\n step?: number\n disabled?: boolean\n readOnly?: boolean\n}\n\nexport function init(opts: NumberInputInit = {}): NumberInputState {\n const value = opts.value ?? null\n return {\n value,\n min: opts.min ?? -Infinity,\n max: opts.max ?? Infinity,\n step: opts.step ?? 1,\n disabled: opts.disabled ?? false,\n readOnly: opts.readOnly ?? false,\n rawText: value === null ? '' : String(value),\n }\n}\n\nfunction clamp(n: number, min: number, max: number): number {\n if (n < min) return min\n if (n > max) return max\n return n\n}\n\nfunction snap(n: number, step: number, anchor = 0): number {\n if (step <= 0) return n\n const origin = isFinite(anchor) ? anchor : 0\n const decimals = decimalPlaces(step)\n const steps = Math.round((n - origin) / step)\n const snapped = origin + steps * step\n return Number(snapped.toFixed(decimals))\n}\n\nfunction decimalPlaces(n: number): number {\n if (Math.floor(n) === n) return 0\n const str = n.toString()\n const dot = str.indexOf('.')\n return dot === -1 ? 0 : str.length - dot - 1\n}\n\nexport function update(state: NumberInputState, msg: NumberInputMsg): [NumberInputState, never[]] {\n if (msg.type !== 'setDisabled' && (state.disabled || state.readOnly)) {\n // Allow setRawText for controlled typing? No — disabled means no interaction.\n return [state, []]\n }\n switch (msg.type) {\n case 'setValue': {\n const v =\n msg.value === null\n ? null\n : clamp(snap(msg.value, state.step, state.min), state.min, state.max)\n return [{ ...state, value: v, rawText: v === null ? '' : String(v) }, []]\n }\n case 'setRawText':\n return [{ ...state, rawText: msg.text }, []]\n case 'commit': {\n const parsed = parseFloat(state.rawText)\n if (isNaN(parsed))\n return [{ ...state, rawText: state.value === null ? '' : String(state.value) }, []]\n const v = clamp(snap(parsed, state.step, state.min), state.min, state.max)\n return [{ ...state, value: v, rawText: String(v) }, []]\n }\n case 'increment': {\n const base = state.value ?? 0\n const raw = base + state.step * (msg.multiplier ?? 1)\n const decimals = decimalPlaces(state.step)\n const v = clamp(Number(raw.toFixed(decimals)), state.min, state.max)\n return [{ ...state, value: v, rawText: String(v) }, []]\n }\n case 'decrement': {\n const base = state.value ?? 0\n const raw = base - state.step * (msg.multiplier ?? 1)\n const decimals = decimalPlaces(state.step)\n const v = clamp(Number(raw.toFixed(decimals)), state.min, state.max)\n return [{ ...state, value: v, rawText: String(v) }, []]\n }\n case 'toMin':\n return [{ ...state, value: state.min, rawText: String(state.min) }, []]\n case 'toMax':\n return [{ ...state, value: state.max, rawText: String(state.max) }, []]\n case 'setDisabled':\n return [{ ...state, disabled: msg.disabled }, []]\n }\n}\n\nexport interface NumberInputParts<S> {\n root: {\n 'data-scope': 'number-input'\n 'data-part': 'root'\n 'data-disabled': (s: S) => '' | undefined\n }\n input: {\n type: 'text'\n role: 'spinbutton'\n inputMode: 'decimal'\n 'aria-valuemin': (s: S) => number | undefined\n 'aria-valuemax': (s: S) => number | undefined\n 'aria-valuenow': (s: S) => number | undefined\n 'aria-disabled': (s: S) => 'true' | undefined\n 'aria-readonly': (s: S) => 'true' | undefined\n disabled: (s: S) => boolean\n readOnly: (s: S) => boolean\n value: (s: S) => string\n 'data-scope': 'number-input'\n 'data-part': 'input'\n onInput: (e: Event) => void\n onBlur: (e: FocusEvent) => void\n onKeyDown: (e: KeyboardEvent) => void\n }\n increment: {\n type: 'button'\n 'aria-label': string | ((s: S) => string)\n 'aria-disabled': (s: S) => 'true' | undefined\n disabled: (s: S) => boolean\n 'data-scope': 'number-input'\n 'data-part': 'increment'\n tabIndex: -1\n onClick: (e: MouseEvent) => void\n }\n decrement: {\n type: 'button'\n 'aria-label': string | ((s: S) => string)\n 'aria-disabled': (s: S) => 'true' | undefined\n disabled: (s: S) => boolean\n 'data-scope': 'number-input'\n 'data-part': 'decrement'\n tabIndex: -1\n onClick: (e: MouseEvent) => void\n }\n}\n\nexport interface ConnectOptions {\n incrementLabel?: string\n decrementLabel?: string\n /** Validate the numeric value before committing. Non-empty array blocks setValue. */\n validate?: (value: number) => string[] | null\n}\n\nexport function connect<S>(\n get: (s: S) => NumberInputState,\n send: Send<NumberInputMsg>,\n opts: ConnectOptions = {},\n): NumberInputParts<S> {\n const locale = useContext<S, Locale>(LocaleContext)\n const incrementLabel: string | ((s: S) => string) =\n opts.incrementLabel ?? ((s: S) => locale(s).numberInput.increment)\n const decrementLabel: string | ((s: S) => string) =\n opts.decrementLabel ?? ((s: S) => locale(s).numberInput.decrement)\n const validate = opts.validate\n\n const trySetValue = (value: number) => {\n if (validate) {\n const errors = validate(value)\n if (errors && errors.length > 0) return\n }\n send({ type: 'setValue', value })\n }\n\n return {\n root: {\n 'data-scope': 'number-input',\n 'data-part': 'root',\n 'data-disabled': (s) => (get(s).disabled ? '' : undefined),\n },\n input: {\n type: 'text',\n role: 'spinbutton',\n inputMode: 'decimal',\n 'aria-valuemin': (s) => (isFinite(get(s).min) ? get(s).min : undefined),\n 'aria-valuemax': (s) => (isFinite(get(s).max) ? get(s).max : undefined),\n 'aria-valuenow': (s) => get(s).value ?? undefined,\n 'aria-disabled': (s) => (get(s).disabled ? 'true' : undefined),\n 'aria-readonly': (s) => (get(s).readOnly ? 'true' : undefined),\n disabled: (s) => get(s).disabled,\n readOnly: (s) => get(s).readOnly,\n value: (s) => get(s).rawText,\n 'data-scope': 'number-input',\n 'data-part': 'input',\n onInput: tagSend(send, ['setRawText'], (e) => {\n const text = (e.target as HTMLInputElement).value\n send({ type: 'setRawText', text })\n const parsed = parseFloat(text)\n if (!isNaN(parsed)) trySetValue(parsed)\n }),\n onBlur: tagSend(send, ['commit'], () => send({ type: 'commit' })),\n onKeyDown: tagSend(send, ['increment', 'decrement', 'toMin', 'toMax', 'commit'], (e) => {\n switch (e.key) {\n case 'ArrowUp':\n e.preventDefault()\n send({ type: 'increment' })\n return\n case 'ArrowDown':\n e.preventDefault()\n send({ type: 'decrement' })\n return\n case 'PageUp':\n e.preventDefault()\n send({ type: 'increment', multiplier: 10 })\n return\n case 'PageDown':\n e.preventDefault()\n send({ type: 'decrement', multiplier: 10 })\n return\n case 'Home':\n e.preventDefault()\n send({ type: 'toMin' })\n return\n case 'End':\n e.preventDefault()\n send({ type: 'toMax' })\n return\n case 'Enter':\n e.preventDefault()\n send({ type: 'commit' })\n return\n }\n }),\n },\n increment: {\n type: 'button',\n 'aria-label': incrementLabel,\n 'aria-disabled': (s) =>\n get(s).disabled || get(s).readOnly || (get(s).value ?? 0) >= get(s).max\n ? 'true'\n : undefined,\n disabled: (s) => get(s).disabled || get(s).readOnly || (get(s).value ?? 0) >= get(s).max,\n 'data-scope': 'number-input',\n 'data-part': 'increment',\n tabIndex: -1,\n onClick: tagSend(send, ['increment'], () => send({ type: 'increment' })),\n },\n decrement: {\n type: 'button',\n 'aria-label': decrementLabel,\n 'aria-disabled': (s) =>\n get(s).disabled || get(s).readOnly || (get(s).value ?? 0) <= get(s).min\n ? 'true'\n : undefined,\n disabled: (s) => get(s).disabled || get(s).readOnly || (get(s).value ?? 0) <= get(s).min,\n 'data-scope': 'number-input',\n 'data-part': 'decrement',\n tabIndex: -1,\n onClick: tagSend(send, ['decrement'], () => send({ type: 'decrement' })),\n },\n }\n}\n\nexport const numberInput = { init, update, connect }\n"]}
1
+ {"version":3,"file":"number-input.js","sourceRoot":"","sources":["../../src/components/number-input.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Send, Signal } from '@llui/dom'\nimport { useContext, tagSend } from '@llui/dom'\nimport { LocaleContext } from '../locale.js'\n\n/**\n * Number input — numeric field with increment/decrement buttons. Clamps\n * to min/max and snaps to step. Keyboard: Arrow Up/Down, PageUp/PageDown,\n * Home/End.\n */\n\nexport interface NumberInputState {\n value: number | null\n min: number\n max: number\n step: number\n disabled: boolean\n readOnly: boolean\n /** Allow a free-text input value while the user is typing. */\n rawText: string\n}\n\nexport type NumberInputMsg =\n /** @intent(\"Set the numeric value (clamped to min/max, snapped to step)\") */\n | { type: 'setValue'; value: number | null }\n /** @humanOnly */\n | { type: 'setRawText'; text: string }\n /** @intent(\"Commit the in-progress text input — parse, clamp, snap, and update value\") */\n | { type: 'commit' }\n /** @intent(\"Increase value by step (or step × multiplier)\") */\n | { type: 'increment'; multiplier?: number }\n /** @intent(\"Decrease value by step (or step × multiplier)\") */\n | { type: 'decrement'; multiplier?: number }\n /** @intent(\"Snap value to the configured minimum\") */\n | { type: 'toMin' }\n /** @intent(\"Snap value to the configured maximum\") */\n | { type: 'toMax' }\n /** @humanOnly */\n | { type: 'setDisabled'; disabled: boolean }\n\nexport interface NumberInputInit {\n value?: number | null\n min?: number\n max?: number\n step?: number\n disabled?: boolean\n readOnly?: boolean\n}\n\nexport function init(opts: NumberInputInit = {}): NumberInputState {\n const value = opts.value ?? null\n return {\n value,\n min: opts.min ?? -Infinity,\n max: opts.max ?? Infinity,\n step: opts.step ?? 1,\n disabled: opts.disabled ?? false,\n readOnly: opts.readOnly ?? false,\n rawText: value === null ? '' : String(value),\n }\n}\n\nfunction clamp(n: number, min: number, max: number): number {\n if (n < min) return min\n if (n > max) return max\n return n\n}\n\nfunction snap(n: number, step: number, anchor = 0): number {\n if (step <= 0) return n\n const origin = isFinite(anchor) ? anchor : 0\n const decimals = decimalPlaces(step)\n const steps = Math.round((n - origin) / step)\n const snapped = origin + steps * step\n return Number(snapped.toFixed(decimals))\n}\n\nfunction decimalPlaces(n: number): number {\n if (Math.floor(n) === n) return 0\n const str = n.toString()\n const dot = str.indexOf('.')\n return dot === -1 ? 0 : str.length - dot - 1\n}\n\nexport function update(state: NumberInputState, msg: NumberInputMsg): [NumberInputState, never[]] {\n if (msg.type !== 'setDisabled' && (state.disabled || state.readOnly)) {\n // Allow setRawText for controlled typing? No — disabled means no interaction.\n return [state, []]\n }\n switch (msg.type) {\n case 'setValue': {\n const v =\n msg.value === null\n ? null\n : clamp(snap(msg.value, state.step, state.min), state.min, state.max)\n return [{ ...state, value: v, rawText: v === null ? '' : String(v) }, []]\n }\n case 'setRawText':\n return [{ ...state, rawText: msg.text }, []]\n case 'commit': {\n const parsed = parseFloat(state.rawText)\n if (isNaN(parsed))\n return [{ ...state, rawText: state.value === null ? '' : String(state.value) }, []]\n const v = clamp(snap(parsed, state.step, state.min), state.min, state.max)\n return [{ ...state, value: v, rawText: String(v) }, []]\n }\n case 'increment': {\n const base = state.value ?? 0\n const raw = base + state.step * (msg.multiplier ?? 1)\n const decimals = decimalPlaces(state.step)\n const v = clamp(Number(raw.toFixed(decimals)), state.min, state.max)\n return [{ ...state, value: v, rawText: String(v) }, []]\n }\n case 'decrement': {\n const base = state.value ?? 0\n const raw = base - state.step * (msg.multiplier ?? 1)\n const decimals = decimalPlaces(state.step)\n const v = clamp(Number(raw.toFixed(decimals)), state.min, state.max)\n return [{ ...state, value: v, rawText: String(v) }, []]\n }\n case 'toMin':\n return [{ ...state, value: state.min, rawText: String(state.min) }, []]\n case 'toMax':\n return [{ ...state, value: state.max, rawText: String(state.max) }, []]\n case 'setDisabled':\n return [{ ...state, disabled: msg.disabled }, []]\n }\n}\n\nexport interface NumberInputParts {\n root: {\n 'data-scope': 'number-input'\n 'data-part': 'root'\n 'data-disabled': Signal<'' | undefined>\n }\n input: {\n type: 'text'\n role: 'spinbutton'\n inputMode: 'decimal'\n 'aria-valuemin': Signal<number | undefined>\n 'aria-valuemax': Signal<number | undefined>\n 'aria-valuenow': Signal<number | undefined>\n 'aria-disabled': Signal<'true' | undefined>\n 'aria-readonly': Signal<'true' | undefined>\n disabled: Signal<boolean>\n readOnly: Signal<boolean>\n value: Signal<string>\n 'data-scope': 'number-input'\n 'data-part': 'input'\n onInput: (e: Event) => void\n onBlur: (e: FocusEvent) => void\n onKeyDown: (e: KeyboardEvent) => void\n }\n increment: {\n type: 'button'\n 'aria-label': string\n 'aria-disabled': Signal<'true' | undefined>\n disabled: Signal<boolean>\n 'data-scope': 'number-input'\n 'data-part': 'increment'\n tabIndex: -1\n onClick: (e: MouseEvent) => void\n }\n decrement: {\n type: 'button'\n 'aria-label': string\n 'aria-disabled': Signal<'true' | undefined>\n disabled: Signal<boolean>\n 'data-scope': 'number-input'\n 'data-part': 'decrement'\n tabIndex: -1\n onClick: (e: MouseEvent) => void\n }\n}\n\nexport interface ConnectOptions {\n incrementLabel?: string\n decrementLabel?: string\n /** Validate the numeric value before committing. Non-empty array blocks setValue. */\n validate?: (value: number) => string[] | null\n}\n\nexport function connect(\n state: Signal<NumberInputState>,\n send: Send<NumberInputMsg>,\n opts: ConnectOptions = {},\n): NumberInputParts {\n const locale = useContext(LocaleContext)\n const incrementLabel = opts.incrementLabel ?? locale.numberInput.increment\n const decrementLabel = opts.decrementLabel ?? locale.numberInput.decrement\n const validate = opts.validate\n\n const trySetValue = (value: number) => {\n if (validate) {\n const errors = validate(value)\n if (errors && errors.length > 0) return\n }\n send({ type: 'setValue', value })\n }\n\n return {\n root: {\n 'data-scope': 'number-input',\n 'data-part': 'root',\n 'data-disabled': state.map((st) => (st.disabled ? '' : undefined)),\n },\n input: {\n type: 'text',\n role: 'spinbutton',\n inputMode: 'decimal',\n 'aria-valuemin': state.map((st) => (isFinite(st.min) ? st.min : undefined)),\n 'aria-valuemax': state.map((st) => (isFinite(st.max) ? st.max : undefined)),\n 'aria-valuenow': state.map((st) => st.value ?? undefined),\n 'aria-disabled': state.map((st) => (st.disabled ? 'true' : undefined)),\n 'aria-readonly': state.map((st) => (st.readOnly ? 'true' : undefined)),\n disabled: state.map((st) => st.disabled),\n readOnly: state.map((st) => st.readOnly),\n value: state.map((st) => st.rawText),\n 'data-scope': 'number-input',\n 'data-part': 'input',\n onInput: tagSend(send, ['setRawText'], (e) => {\n const text = (e.target as HTMLInputElement).value\n send({ type: 'setRawText', text })\n const parsed = parseFloat(text)\n if (!isNaN(parsed)) trySetValue(parsed)\n }),\n onBlur: tagSend(send, ['commit'], () => send({ type: 'commit' })),\n onKeyDown: tagSend(send, ['increment', 'decrement', 'toMin', 'toMax', 'commit'], (e) => {\n switch (e.key) {\n case 'ArrowUp':\n e.preventDefault()\n send({ type: 'increment' })\n return\n case 'ArrowDown':\n e.preventDefault()\n send({ type: 'decrement' })\n return\n case 'PageUp':\n e.preventDefault()\n send({ type: 'increment', multiplier: 10 })\n return\n case 'PageDown':\n e.preventDefault()\n send({ type: 'decrement', multiplier: 10 })\n return\n case 'Home':\n e.preventDefault()\n send({ type: 'toMin' })\n return\n case 'End':\n e.preventDefault()\n send({ type: 'toMax' })\n return\n case 'Enter':\n e.preventDefault()\n send({ type: 'commit' })\n return\n }\n }),\n },\n increment: {\n type: 'button',\n 'aria-label': incrementLabel,\n 'aria-disabled': state.map((st) =>\n st.disabled || st.readOnly || (st.value ?? 0) >= st.max ? 'true' : undefined,\n ),\n disabled: state.map((st) => st.disabled || st.readOnly || (st.value ?? 0) >= st.max),\n 'data-scope': 'number-input',\n 'data-part': 'increment',\n tabIndex: -1,\n onClick: tagSend(send, ['increment'], () => send({ type: 'increment' })),\n },\n decrement: {\n type: 'button',\n 'aria-label': decrementLabel,\n 'aria-disabled': state.map((st) =>\n st.disabled || st.readOnly || (st.value ?? 0) <= st.min ? 'true' : undefined,\n ),\n disabled: state.map((st) => st.disabled || st.readOnly || (st.value ?? 0) <= st.min),\n 'data-scope': 'number-input',\n 'data-part': 'decrement',\n tabIndex: -1,\n onClick: tagSend(send, ['decrement'], () => send({ type: 'decrement' })),\n },\n }\n}\n\nexport const numberInput = { init, update, connect }\n"]}
@@ -1,4 +1,4 @@
1
- import type { Send } from '@llui/dom';
1
+ import type { Send, Signal } from '@llui/dom';
2
2
  /**
3
3
  * Pagination — page navigation with ellipses for large ranges.
4
4
  * `page` is 1-based. Siblings are the count of pages shown on each side
@@ -67,28 +67,28 @@ export type PageItem = {
67
67
  * `[first ..boundaries] … [siblings around current] … [boundaries ..last]`.
68
68
  */
69
69
  export declare function pageItems(state: PaginationState): PageItem[];
70
- export interface PaginationParts<S> {
70
+ export interface PaginationParts {
71
71
  root: {
72
72
  role: 'navigation';
73
- 'aria-label': string | ((s: S) => string);
73
+ 'aria-label': string;
74
74
  'data-scope': 'pagination';
75
75
  'data-part': 'root';
76
- 'data-disabled': (s: S) => '' | undefined;
76
+ 'data-disabled': Signal<'' | undefined>;
77
77
  };
78
78
  prevTrigger: {
79
79
  type: 'button';
80
- 'aria-label': string | ((s: S) => string);
81
- 'aria-disabled': (s: S) => 'true' | undefined;
82
- disabled: (s: S) => boolean;
80
+ 'aria-label': string;
81
+ 'aria-disabled': Signal<'true' | undefined>;
82
+ disabled: Signal<boolean>;
83
83
  'data-scope': 'pagination';
84
84
  'data-part': 'prev-trigger';
85
85
  onClick: (e: MouseEvent) => void;
86
86
  };
87
87
  nextTrigger: {
88
88
  type: 'button';
89
- 'aria-label': string | ((s: S) => string);
90
- 'aria-disabled': (s: S) => 'true' | undefined;
91
- disabled: (s: S) => boolean;
89
+ 'aria-label': string;
90
+ 'aria-disabled': Signal<'true' | undefined>;
91
+ disabled: Signal<boolean>;
92
92
  'data-scope': 'pagination';
93
93
  'data-part': 'next-trigger';
94
94
  onClick: (e: MouseEvent) => void;
@@ -96,8 +96,8 @@ export interface PaginationParts<S> {
96
96
  item: (page: number) => {
97
97
  type: 'button';
98
98
  'aria-label': string;
99
- 'aria-current': (s: S) => 'page' | undefined;
100
- 'data-selected': (s: S) => '' | undefined;
99
+ 'aria-current': Signal<'page' | undefined>;
100
+ 'data-selected': Signal<'' | undefined>;
101
101
  'data-scope': 'pagination';
102
102
  'data-part': 'item';
103
103
  'data-value': string;
@@ -116,7 +116,7 @@ export interface ConnectOptions {
116
116
  nextLabel?: string;
117
117
  pageLabel?: (page: number) => string;
118
118
  }
119
- export declare function connect<S>(get: (s: S) => PaginationState, send: Send<PaginationMsg>, opts?: ConnectOptions): PaginationParts<S>;
119
+ export declare function connect(state: Signal<PaginationState>, send: Send<PaginationMsg>, opts?: ConnectOptions): PaginationParts;
120
120
  export declare const pagination: {
121
121
  init: typeof init;
122
122
  update: typeof update;
@@ -1 +1 @@
1
- {"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../../src/components/pagination.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../../src/components/pagination.ts"],"names":[],"mappings":"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"}
@@ -79,11 +79,11 @@ export function pageItems(state) {
79
79
  }
80
80
  return items;
81
81
  }
82
- export function connect(get, send, opts = {}) {
82
+ export function connect(state, send, opts = {}) {
83
83
  const locale = useContext(LocaleContext);
84
- const label = opts.label ?? ((s) => locale(s).pagination.label);
85
- const prevLabel = opts.prevLabel ?? ((s) => locale(s).pagination.prev);
86
- const nextLabel = opts.nextLabel ?? ((s) => locale(s).pagination.next);
84
+ const label = opts.label ?? locale.pagination.label;
85
+ const prevLabel = opts.prevLabel ?? locale.pagination.prev;
86
+ const nextLabel = opts.nextLabel ?? locale.pagination.next;
87
87
  const pageLabel = opts.pageLabel ?? en.pagination.page;
88
88
  return {
89
89
  root: {
@@ -91,13 +91,13 @@ export function connect(get, send, opts = {}) {
91
91
  'aria-label': label,
92
92
  'data-scope': 'pagination',
93
93
  'data-part': 'root',
94
- 'data-disabled': (s) => (get(s).disabled ? '' : undefined),
94
+ 'data-disabled': state.map((st) => (st.disabled ? '' : undefined)),
95
95
  },
96
96
  prevTrigger: {
97
97
  type: 'button',
98
98
  'aria-label': prevLabel,
99
- 'aria-disabled': (s) => (get(s).page <= 1 || get(s).disabled ? 'true' : undefined),
100
- disabled: (s) => get(s).page <= 1 || get(s).disabled,
99
+ 'aria-disabled': state.map((st) => (st.page <= 1 || st.disabled ? 'true' : undefined)),
100
+ disabled: state.map((st) => st.page <= 1 || st.disabled),
101
101
  'data-scope': 'pagination',
102
102
  'data-part': 'prev-trigger',
103
103
  onClick: tagSend(send, ['prev'], () => send({ type: 'prev' })),
@@ -105,14 +105,8 @@ export function connect(get, send, opts = {}) {
105
105
  nextTrigger: {
106
106
  type: 'button',
107
107
  'aria-label': nextLabel,
108
- 'aria-disabled': (s) => {
109
- const st = get(s);
110
- return st.page >= totalPages(st) || st.disabled ? 'true' : undefined;
111
- },
112
- disabled: (s) => {
113
- const st = get(s);
114
- return st.page >= totalPages(st) || st.disabled;
115
- },
108
+ 'aria-disabled': state.map((st) => st.page >= totalPages(st) || st.disabled ? 'true' : undefined),
109
+ disabled: state.map((st) => st.page >= totalPages(st) || st.disabled),
116
110
  'data-scope': 'pagination',
117
111
  'data-part': 'next-trigger',
118
112
  onClick: tagSend(send, ['next'], () => send({ type: 'next' })),
@@ -120,8 +114,8 @@ export function connect(get, send, opts = {}) {
120
114
  item: (page) => ({
121
115
  type: 'button',
122
116
  'aria-label': pageLabel(page),
123
- 'aria-current': (s) => (get(s).page === page ? 'page' : undefined),
124
- 'data-selected': (s) => (get(s).page === page ? '' : undefined),
117
+ 'aria-current': state.map((st) => (st.page === page ? 'page' : undefined)),
118
+ 'data-selected': state.map((st) => (st.page === page ? '' : undefined)),
125
119
  'data-scope': 'pagination',
126
120
  'data-part': 'item',
127
121
  'data-value': String(page),
@@ -1 +1 @@
1
- {"version":3,"file":"pagination.js","sourceRoot":"","sources":["../../src/components/pagination.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Send } from '@llui/dom'\nimport { useContext, tagSend } from '@llui/dom'\nimport { LocaleContext, en } from '../locale.js'\nimport type { Locale } from '../locale.js'\n\n/**\n * Pagination — page navigation with ellipses for large ranges.\n * `page` is 1-based. Siblings are the count of pages shown on each side\n * of the current page. Boundaries are shown at the start/end.\n */\n\nexport interface PaginationState {\n page: number\n pageSize: number\n total: number\n siblings: number\n boundaries: number\n disabled: boolean\n}\n\nexport type PaginationMsg =\n /** @intent(\"Jump to a specific 1-based page number\") */\n | { type: 'goTo'; page: number }\n /** @intent(\"Advance to the next page\") */\n | { type: 'next' }\n /** @intent(\"Go back to the previous page\") */\n | { type: 'prev' }\n /** @intent(\"Jump to the first page\") */\n | { type: 'first' }\n /** @intent(\"Jump to the last page\") */\n | { type: 'last' }\n /** @intent(\"Change how many items each page contains\") */\n | { type: 'setPageSize'; pageSize: number }\n /** @humanOnly */\n | { type: 'setTotal'; total: number }\n\nexport interface PaginationInit {\n page?: number\n pageSize?: number\n total?: number\n siblings?: number\n boundaries?: number\n disabled?: boolean\n}\n\nexport function init(opts: PaginationInit = {}): PaginationState {\n return {\n page: opts.page ?? 1,\n pageSize: opts.pageSize ?? 10,\n total: opts.total ?? 0,\n siblings: opts.siblings ?? 1,\n boundaries: opts.boundaries ?? 1,\n disabled: opts.disabled ?? false,\n }\n}\n\nexport function totalPages(state: PaginationState): number {\n if (state.pageSize <= 0 || state.total <= 0) return 0\n return Math.max(1, Math.ceil(state.total / state.pageSize))\n}\n\nfunction clampPage(page: number, total: number): number {\n if (total === 0) return 1\n return Math.max(1, Math.min(page, total))\n}\n\nexport function update(state: PaginationState, msg: PaginationMsg): [PaginationState, never[]] {\n if (state.disabled) return [state, []]\n const pages = totalPages(state)\n switch (msg.type) {\n case 'goTo':\n return [{ ...state, page: clampPage(msg.page, pages) }, []]\n case 'next':\n return [{ ...state, page: clampPage(state.page + 1, pages) }, []]\n case 'prev':\n return [{ ...state, page: clampPage(state.page - 1, pages) }, []]\n case 'first':\n return [{ ...state, page: 1 }, []]\n case 'last':\n return [{ ...state, page: pages }, []]\n case 'setPageSize': {\n // Preserve first visible item when pageSize changes\n const firstItem = (state.page - 1) * state.pageSize\n const nextPage = Math.floor(firstItem / msg.pageSize) + 1\n const nextPages = Math.max(1, Math.ceil(state.total / msg.pageSize))\n return [{ ...state, pageSize: msg.pageSize, page: Math.min(nextPage, nextPages) }, []]\n }\n case 'setTotal': {\n const nextPages = Math.max(1, Math.ceil(msg.total / state.pageSize))\n return [{ ...state, total: msg.total, page: Math.min(state.page, nextPages) }, []]\n }\n }\n}\n\nexport type PageItem =\n | { type: 'page'; page: number }\n | { type: 'ellipsis'; position: 'start' | 'end' }\n\n/**\n * Compute the visible page buttons with ellipses:\n * `[first ..boundaries] … [siblings around current] … [boundaries ..last]`.\n */\nexport function pageItems(state: PaginationState): PageItem[] {\n const pages = totalPages(state)\n if (pages === 0) return []\n\n // Build the set of pages we want to show: first boundary, last boundary,\n // and current ± siblings.\n const pageSet = new Set<number>()\n for (let i = 1; i <= Math.min(state.boundaries, pages); i++) pageSet.add(i)\n for (let i = Math.max(pages - state.boundaries + 1, 1); i <= pages; i++) pageSet.add(i)\n const start = Math.max(1, state.page - state.siblings)\n const end = Math.min(pages, state.page + state.siblings)\n for (let i = start; i <= end; i++) pageSet.add(i)\n\n // Emit items in order, inserting ellipses for gaps > 1.\n const sorted = [...pageSet].sort((a, b) => a - b)\n const items: PageItem[] = []\n for (let i = 0; i < sorted.length; i++) {\n const page = sorted[i]!\n items.push({ type: 'page', page })\n if (i < sorted.length - 1 && sorted[i + 1]! - page > 1) {\n items.push({ type: 'ellipsis', position: page < state.page ? 'start' : 'end' })\n }\n }\n return items\n}\n\nexport interface PaginationParts<S> {\n root: {\n role: 'navigation'\n 'aria-label': string | ((s: S) => string)\n 'data-scope': 'pagination'\n 'data-part': 'root'\n 'data-disabled': (s: S) => '' | undefined\n }\n prevTrigger: {\n type: 'button'\n 'aria-label': string | ((s: S) => string)\n 'aria-disabled': (s: S) => 'true' | undefined\n disabled: (s: S) => boolean\n 'data-scope': 'pagination'\n 'data-part': 'prev-trigger'\n onClick: (e: MouseEvent) => void\n }\n nextTrigger: {\n type: 'button'\n 'aria-label': string | ((s: S) => string)\n 'aria-disabled': (s: S) => 'true' | undefined\n disabled: (s: S) => boolean\n 'data-scope': 'pagination'\n 'data-part': 'next-trigger'\n onClick: (e: MouseEvent) => void\n }\n item: (page: number) => {\n type: 'button'\n 'aria-label': string\n 'aria-current': (s: S) => 'page' | undefined\n 'data-selected': (s: S) => '' | undefined\n 'data-scope': 'pagination'\n 'data-part': 'item'\n 'data-value': string\n onClick: (e: MouseEvent) => void\n }\n ellipsis: (position: 'start' | 'end') => {\n 'aria-hidden': 'true'\n 'data-scope': 'pagination'\n 'data-part': 'ellipsis'\n 'data-position': 'start' | 'end'\n }\n}\n\nexport interface ConnectOptions {\n label?: string\n prevLabel?: string\n nextLabel?: string\n pageLabel?: (page: number) => string\n}\n\nexport function connect<S>(\n get: (s: S) => PaginationState,\n send: Send<PaginationMsg>,\n opts: ConnectOptions = {},\n): PaginationParts<S> {\n const locale = useContext<S, Locale>(LocaleContext)\n const label: string | ((s: S) => string) = opts.label ?? ((s: S) => locale(s).pagination.label)\n const prevLabel: string | ((s: S) => string) =\n opts.prevLabel ?? ((s: S) => locale(s).pagination.prev)\n const nextLabel: string | ((s: S) => string) =\n opts.nextLabel ?? ((s: S) => locale(s).pagination.next)\n const pageLabel = opts.pageLabel ?? en.pagination.page\n\n return {\n root: {\n role: 'navigation',\n 'aria-label': label,\n 'data-scope': 'pagination',\n 'data-part': 'root',\n 'data-disabled': (s) => (get(s).disabled ? '' : undefined),\n },\n prevTrigger: {\n type: 'button',\n 'aria-label': prevLabel,\n 'aria-disabled': (s) => (get(s).page <= 1 || get(s).disabled ? 'true' : undefined),\n disabled: (s) => get(s).page <= 1 || get(s).disabled,\n 'data-scope': 'pagination',\n 'data-part': 'prev-trigger',\n onClick: tagSend(send, ['prev'], () => send({ type: 'prev' })),\n },\n nextTrigger: {\n type: 'button',\n 'aria-label': nextLabel,\n 'aria-disabled': (s) => {\n const st = get(s)\n return st.page >= totalPages(st) || st.disabled ? 'true' : undefined\n },\n disabled: (s) => {\n const st = get(s)\n return st.page >= totalPages(st) || st.disabled\n },\n 'data-scope': 'pagination',\n 'data-part': 'next-trigger',\n onClick: tagSend(send, ['next'], () => send({ type: 'next' })),\n },\n item: (page: number) => ({\n type: 'button',\n 'aria-label': pageLabel(page),\n 'aria-current': (s) => (get(s).page === page ? 'page' : undefined),\n 'data-selected': (s) => (get(s).page === page ? '' : undefined),\n 'data-scope': 'pagination',\n 'data-part': 'item',\n 'data-value': String(page),\n onClick: tagSend(send, ['goTo'], () => send({ type: 'goTo', page })),\n }),\n ellipsis: (position: 'start' | 'end') => ({\n 'aria-hidden': 'true',\n 'data-scope': 'pagination',\n 'data-part': 'ellipsis',\n 'data-position': position,\n }),\n }\n}\n\nexport const pagination = { init, update, connect, totalPages, pageItems }\n"]}
1
+ {"version":3,"file":"pagination.js","sourceRoot":"","sources":["../../src/components/pagination.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAC/C,OAAO,EAAE,aAAa,EAAE,EAAE,EAAE,MAAM,cAAc,CAAA;AA0ChD,MAAM,UAAU,IAAI,CAAC,OAAuB,EAAE;IAC5C,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC;QACpB,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,EAAE;QAC7B,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,CAAC;QACtB,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,CAAC;QAC5B,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,CAAC;QAChC,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,KAAK;KACjC,CAAA;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAsB;IAC/C,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,IAAI,KAAK,CAAC,KAAK,IAAI,CAAC;QAAE,OAAO,CAAC,CAAA;IACrD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAA;AAC7D,CAAC;AAED,SAAS,SAAS,CAAC,IAAY,EAAE,KAAa;IAC5C,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,CAAC,CAAA;IACzB,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAA;AAC3C,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,KAAsB,EAAE,GAAkB;IAC/D,IAAI,KAAK,CAAC,QAAQ;QAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IACtC,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAA;IAC/B,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;QACjB,KAAK,MAAM;YACT,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;QAC7D,KAAK,MAAM;YACT,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,SAAS,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;QACnE,KAAK,MAAM;YACT,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,SAAS,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;QACnE,KAAK,OAAO;YACV,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;QACpC,KAAK,MAAM;YACT,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAA;QACxC,KAAK,aAAa,CAAC,CAAC,CAAC;YACnB,oDAAoD;YACpD,MAAM,SAAS,GAAG,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAA;YACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAA;YACzD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAA;YACpE,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;QACxF,CAAC;QACD,KAAK,UAAU,CAAC,CAAC,CAAC;YAChB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAA;YACpE,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;QACpF,CAAC;IACH,CAAC;AACH,CAAC;AAMD;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,KAAsB;IAC9C,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAA;IAC/B,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IAE1B,yEAAyE;IACzE,0BAA0B;IAC1B,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAA;IACjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,EAAE;QAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;IAC3E,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC,EAAE;QAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;IACvF,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAA;IACtD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAA;IACxD,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,EAAE;QAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;IAEjD,wDAAwD;IACxD,MAAM,MAAM,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IACjD,MAAM,KAAK,GAAe,EAAE,CAAA;IAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAE,CAAA;QACvB,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAA;QAClC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,CAAC,GAAG,CAAC,CAAE,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC;YACvD,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAA;QACjF,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAqDD,MAAM,UAAU,OAAO,CACrB,KAA8B,EAC9B,IAAyB,EACzB,OAAuB,EAAE;IAEzB,MAAM,MAAM,GAAG,UAAU,CAAC,aAAa,CAAC,CAAA;IACxC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,MAAM,CAAC,UAAU,CAAC,KAAK,CAAA;IACnD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,CAAA;IAC1D,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,CAAA;IAC1D,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAA;IAEtD,OAAO;QACL,IAAI,EAAE;YACJ,IAAI,EAAE,YAAY;YAClB,YAAY,EAAE,KAAK;YACnB,YAAY,EAAE,YAAY;YAC1B,WAAW,EAAE,MAAM;YACnB,eAAe,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;SACnE;QACD,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,YAAY,EAAE,SAAS;YACvB,eAAe,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YACtF,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC;YACxD,YAAY,EAAE,YAAY;YAC1B,WAAW,EAAE,cAAc;YAC3B,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;SAC/D;QACD,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,YAAY,EAAE,SAAS;YACvB,eAAe,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAChC,EAAE,CAAC,IAAI,IAAI,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAC9D;YACD,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,IAAI,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC;YACrE,YAAY,EAAE,YAAY;YAC1B,WAAW,EAAE,cAAc;YAC3B,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;SAC/D;QACD,IAAI,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC;YACvB,IAAI,EAAE,QAAQ;YACd,YAAY,EAAE,SAAS,CAAC,IAAI,CAAC;YAC7B,cAAc,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YAC1E,eAAe,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YACvE,YAAY,EAAE,YAAY;YAC1B,WAAW,EAAE,MAAM;YACnB,YAAY,EAAE,MAAM,CAAC,IAAI,CAAC;YAC1B,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;SACrE,CAAC;QACF,QAAQ,EAAE,CAAC,QAAyB,EAAE,EAAE,CAAC,CAAC;YACxC,aAAa,EAAE,MAAM;YACrB,YAAY,EAAE,YAAY;YAC1B,WAAW,EAAE,UAAU;YACvB,eAAe,EAAE,QAAQ;SAC1B,CAAC;KACH,CAAA;AACH,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,CAAA","sourcesContent":["import type { Send, Signal } from '@llui/dom'\nimport { useContext, tagSend } from '@llui/dom'\nimport { LocaleContext, en } from '../locale.js'\n\n/**\n * Pagination — page navigation with ellipses for large ranges.\n * `page` is 1-based. Siblings are the count of pages shown on each side\n * of the current page. Boundaries are shown at the start/end.\n */\n\nexport interface PaginationState {\n page: number\n pageSize: number\n total: number\n siblings: number\n boundaries: number\n disabled: boolean\n}\n\nexport type PaginationMsg =\n /** @intent(\"Jump to a specific 1-based page number\") */\n | { type: 'goTo'; page: number }\n /** @intent(\"Advance to the next page\") */\n | { type: 'next' }\n /** @intent(\"Go back to the previous page\") */\n | { type: 'prev' }\n /** @intent(\"Jump to the first page\") */\n | { type: 'first' }\n /** @intent(\"Jump to the last page\") */\n | { type: 'last' }\n /** @intent(\"Change how many items each page contains\") */\n | { type: 'setPageSize'; pageSize: number }\n /** @humanOnly */\n | { type: 'setTotal'; total: number }\n\nexport interface PaginationInit {\n page?: number\n pageSize?: number\n total?: number\n siblings?: number\n boundaries?: number\n disabled?: boolean\n}\n\nexport function init(opts: PaginationInit = {}): PaginationState {\n return {\n page: opts.page ?? 1,\n pageSize: opts.pageSize ?? 10,\n total: opts.total ?? 0,\n siblings: opts.siblings ?? 1,\n boundaries: opts.boundaries ?? 1,\n disabled: opts.disabled ?? false,\n }\n}\n\nexport function totalPages(state: PaginationState): number {\n if (state.pageSize <= 0 || state.total <= 0) return 0\n return Math.max(1, Math.ceil(state.total / state.pageSize))\n}\n\nfunction clampPage(page: number, total: number): number {\n if (total === 0) return 1\n return Math.max(1, Math.min(page, total))\n}\n\nexport function update(state: PaginationState, msg: PaginationMsg): [PaginationState, never[]] {\n if (state.disabled) return [state, []]\n const pages = totalPages(state)\n switch (msg.type) {\n case 'goTo':\n return [{ ...state, page: clampPage(msg.page, pages) }, []]\n case 'next':\n return [{ ...state, page: clampPage(state.page + 1, pages) }, []]\n case 'prev':\n return [{ ...state, page: clampPage(state.page - 1, pages) }, []]\n case 'first':\n return [{ ...state, page: 1 }, []]\n case 'last':\n return [{ ...state, page: pages }, []]\n case 'setPageSize': {\n // Preserve first visible item when pageSize changes\n const firstItem = (state.page - 1) * state.pageSize\n const nextPage = Math.floor(firstItem / msg.pageSize) + 1\n const nextPages = Math.max(1, Math.ceil(state.total / msg.pageSize))\n return [{ ...state, pageSize: msg.pageSize, page: Math.min(nextPage, nextPages) }, []]\n }\n case 'setTotal': {\n const nextPages = Math.max(1, Math.ceil(msg.total / state.pageSize))\n return [{ ...state, total: msg.total, page: Math.min(state.page, nextPages) }, []]\n }\n }\n}\n\nexport type PageItem =\n | { type: 'page'; page: number }\n | { type: 'ellipsis'; position: 'start' | 'end' }\n\n/**\n * Compute the visible page buttons with ellipses:\n * `[first ..boundaries] … [siblings around current] … [boundaries ..last]`.\n */\nexport function pageItems(state: PaginationState): PageItem[] {\n const pages = totalPages(state)\n if (pages === 0) return []\n\n // Build the set of pages we want to show: first boundary, last boundary,\n // and current ± siblings.\n const pageSet = new Set<number>()\n for (let i = 1; i <= Math.min(state.boundaries, pages); i++) pageSet.add(i)\n for (let i = Math.max(pages - state.boundaries + 1, 1); i <= pages; i++) pageSet.add(i)\n const start = Math.max(1, state.page - state.siblings)\n const end = Math.min(pages, state.page + state.siblings)\n for (let i = start; i <= end; i++) pageSet.add(i)\n\n // Emit items in order, inserting ellipses for gaps > 1.\n const sorted = [...pageSet].sort((a, b) => a - b)\n const items: PageItem[] = []\n for (let i = 0; i < sorted.length; i++) {\n const page = sorted[i]!\n items.push({ type: 'page', page })\n if (i < sorted.length - 1 && sorted[i + 1]! - page > 1) {\n items.push({ type: 'ellipsis', position: page < state.page ? 'start' : 'end' })\n }\n }\n return items\n}\n\nexport interface PaginationParts {\n root: {\n role: 'navigation'\n 'aria-label': string\n 'data-scope': 'pagination'\n 'data-part': 'root'\n 'data-disabled': Signal<'' | undefined>\n }\n prevTrigger: {\n type: 'button'\n 'aria-label': string\n 'aria-disabled': Signal<'true' | undefined>\n disabled: Signal<boolean>\n 'data-scope': 'pagination'\n 'data-part': 'prev-trigger'\n onClick: (e: MouseEvent) => void\n }\n nextTrigger: {\n type: 'button'\n 'aria-label': string\n 'aria-disabled': Signal<'true' | undefined>\n disabled: Signal<boolean>\n 'data-scope': 'pagination'\n 'data-part': 'next-trigger'\n onClick: (e: MouseEvent) => void\n }\n item: (page: number) => {\n type: 'button'\n 'aria-label': string\n 'aria-current': Signal<'page' | undefined>\n 'data-selected': Signal<'' | undefined>\n 'data-scope': 'pagination'\n 'data-part': 'item'\n 'data-value': string\n onClick: (e: MouseEvent) => void\n }\n ellipsis: (position: 'start' | 'end') => {\n 'aria-hidden': 'true'\n 'data-scope': 'pagination'\n 'data-part': 'ellipsis'\n 'data-position': 'start' | 'end'\n }\n}\n\nexport interface ConnectOptions {\n label?: string\n prevLabel?: string\n nextLabel?: string\n pageLabel?: (page: number) => string\n}\n\nexport function connect(\n state: Signal<PaginationState>,\n send: Send<PaginationMsg>,\n opts: ConnectOptions = {},\n): PaginationParts {\n const locale = useContext(LocaleContext)\n const label = opts.label ?? locale.pagination.label\n const prevLabel = opts.prevLabel ?? locale.pagination.prev\n const nextLabel = opts.nextLabel ?? locale.pagination.next\n const pageLabel = opts.pageLabel ?? en.pagination.page\n\n return {\n root: {\n role: 'navigation',\n 'aria-label': label,\n 'data-scope': 'pagination',\n 'data-part': 'root',\n 'data-disabled': state.map((st) => (st.disabled ? '' : undefined)),\n },\n prevTrigger: {\n type: 'button',\n 'aria-label': prevLabel,\n 'aria-disabled': state.map((st) => (st.page <= 1 || st.disabled ? 'true' : undefined)),\n disabled: state.map((st) => st.page <= 1 || st.disabled),\n 'data-scope': 'pagination',\n 'data-part': 'prev-trigger',\n onClick: tagSend(send, ['prev'], () => send({ type: 'prev' })),\n },\n nextTrigger: {\n type: 'button',\n 'aria-label': nextLabel,\n 'aria-disabled': state.map((st) =>\n st.page >= totalPages(st) || st.disabled ? 'true' : undefined,\n ),\n disabled: state.map((st) => st.page >= totalPages(st) || st.disabled),\n 'data-scope': 'pagination',\n 'data-part': 'next-trigger',\n onClick: tagSend(send, ['next'], () => send({ type: 'next' })),\n },\n item: (page: number) => ({\n type: 'button',\n 'aria-label': pageLabel(page),\n 'aria-current': state.map((st) => (st.page === page ? 'page' : undefined)),\n 'data-selected': state.map((st) => (st.page === page ? '' : undefined)),\n 'data-scope': 'pagination',\n 'data-part': 'item',\n 'data-value': String(page),\n onClick: tagSend(send, ['goTo'], () => send({ type: 'goTo', page })),\n }),\n ellipsis: (position: 'start' | 'end') => ({\n 'aria-hidden': 'true',\n 'data-scope': 'pagination',\n 'data-part': 'ellipsis',\n 'data-position': position,\n }),\n }\n}\n\nexport const pagination = { init, update, connect, totalPages, pageItems }\n"]}
@@ -1,4 +1,4 @@
1
- import type { Send } from '@llui/dom';
1
+ import type { Send, Signal } from '@llui/dom';
2
2
  /**
3
3
  * Password input — text input with show/hide visibility toggle.
4
4
  */
@@ -29,27 +29,27 @@ export interface PasswordInputInit {
29
29
  }
30
30
  export declare function init(opts?: PasswordInputInit): PasswordInputState;
31
31
  export declare function update(state: PasswordInputState, msg: PasswordInputMsg): [PasswordInputState, never[]];
32
- export interface PasswordInputParts<S> {
32
+ export interface PasswordInputParts {
33
33
  root: {
34
34
  'data-scope': 'password-input';
35
35
  'data-part': 'root';
36
- 'data-visible': (s: S) => '' | undefined;
37
- 'data-disabled': (s: S) => '' | undefined;
36
+ 'data-visible': Signal<'' | undefined>;
37
+ 'data-disabled': Signal<'' | undefined>;
38
38
  };
39
39
  input: {
40
- type: (s: S) => 'text' | 'password';
40
+ type: Signal<'text' | 'password'>;
41
41
  autoComplete: string;
42
- disabled: (s: S) => boolean;
43
- value: (s: S) => string;
42
+ disabled: Signal<boolean>;
43
+ value: Signal<string>;
44
44
  'data-scope': 'password-input';
45
45
  'data-part': 'input';
46
46
  onInput: (e: Event) => void;
47
47
  };
48
48
  visibilityTrigger: {
49
49
  type: 'button';
50
- 'aria-label': (s: S) => string;
51
- 'aria-pressed': (s: S) => boolean;
52
- disabled: (s: S) => boolean;
50
+ 'aria-label': Signal<string>;
51
+ 'aria-pressed': Signal<boolean>;
52
+ disabled: Signal<boolean>;
53
53
  tabIndex: -1;
54
54
  'data-scope': 'password-input';
55
55
  'data-part': 'visibility-trigger';
@@ -61,7 +61,7 @@ export interface ConnectOptions {
61
61
  showLabel?: string;
62
62
  hideLabel?: string;
63
63
  }
64
- export declare function connect<S>(get: (s: S) => PasswordInputState, send: Send<PasswordInputMsg>, opts?: ConnectOptions): PasswordInputParts<S>;
64
+ export declare function connect(state: Signal<PasswordInputState>, send: Send<PasswordInputMsg>, opts?: ConnectOptions): PasswordInputParts;
65
65
  export declare const passwordInput: {
66
66
  init: typeof init;
67
67
  update: typeof update;
@@ -1 +1 @@
1
- {"version":3,"file":"password-input.d.ts","sourceRoot":"","sources":["../../src/components/password-input.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAKrC;;GAEG;AAEH,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,MAAM,gBAAgB;AAC1B,6DAA6D;AAC3D;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE;AACrC,qDAAqD;GACnD;IAAE,IAAI,EAAE,kBAAkB,CAAA;CAAE;AAC9B,sEAAsE;GACpE;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAA;AAE5C,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,wBAAgB,IAAI,CAAC,IAAI,GAAE,iBAAsB,GAAG,kBAAkB,CAMrE;AAED,wBAAgB,MAAM,CACpB,KAAK,EAAE,kBAAkB,EACzB,GAAG,EAAE,gBAAgB,GACpB,CAAC,kBAAkB,EAAE,KAAK,EAAE,CAAC,CAU/B;AAED,MAAM,WAAW,kBAAkB,CAAC,CAAC;IACnC,IAAI,EAAE;QACJ,YAAY,EAAE,gBAAgB,CAAA;QAC9B,WAAW,EAAE,MAAM,CAAA;QACnB,cAAc,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,SAAS,CAAA;QACxC,eAAe,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,SAAS,CAAA;KAC1C,CAAA;IACD,KAAK,EAAE;QACL,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,GAAG,UAAU,CAAA;QACnC,YAAY,EAAE,MAAM,CAAA;QACpB,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,OAAO,CAAA;QAC3B,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;QACvB,YAAY,EAAE,gBAAgB,CAAA;QAC9B,WAAW,EAAE,OAAO,CAAA;QACpB,OAAO,EAAE,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,CAAA;KAC5B,CAAA;IACD,iBAAiB,EAAE;QACjB,IAAI,EAAE,QAAQ,CAAA;QACd,YAAY,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;QAC9B,cAAc,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,OAAO,CAAA;QACjC,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,OAAO,CAAA;QAC3B,QAAQ,EAAE,CAAC,CAAC,CAAA;QACZ,YAAY,EAAE,gBAAgB,CAAA;QAC9B,WAAW,EAAE,oBAAoB,CAAA;QACjC,OAAO,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAA;KACjC,CAAA;CACF;AAED,MAAM,WAAW,cAAc;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,OAAO,CAAC,CAAC,EACvB,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,kBAAkB,EACjC,IAAI,EAAE,IAAI,CAAC,gBAAgB,CAAC,EAC5B,IAAI,GAAE,cAAmB,GACxB,kBAAkB,CAAC,CAAC,CAAC,CAsCvB;AAED,eAAO,MAAM,aAAa;;;;CAA4B,CAAA"}
1
+ {"version":3,"file":"password-input.d.ts","sourceRoot":"","sources":["../../src/components/password-input.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAI7C;;GAEG;AAEH,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,MAAM,gBAAgB;AAC1B,6DAA6D;AAC3D;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE;AACrC,qDAAqD;GACnD;IAAE,IAAI,EAAE,kBAAkB,CAAA;CAAE;AAC9B,sEAAsE;GACpE;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAA;AAE5C,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,wBAAgB,IAAI,CAAC,IAAI,GAAE,iBAAsB,GAAG,kBAAkB,CAMrE;AAED,wBAAgB,MAAM,CACpB,KAAK,EAAE,kBAAkB,EACzB,GAAG,EAAE,gBAAgB,GACpB,CAAC,kBAAkB,EAAE,KAAK,EAAE,CAAC,CAU/B;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE;QACJ,YAAY,EAAE,gBAAgB,CAAA;QAC9B,WAAW,EAAE,MAAM,CAAA;QACnB,cAAc,EAAE,MAAM,CAAC,EAAE,GAAG,SAAS,CAAC,CAAA;QACtC,eAAe,EAAE,MAAM,CAAC,EAAE,GAAG,SAAS,CAAC,CAAA;KACxC,CAAA;IACD,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAC,MAAM,GAAG,UAAU,CAAC,CAAA;QACjC,YAAY,EAAE,MAAM,CAAA;QACpB,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,CAAA;QACzB,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAA;QACrB,YAAY,EAAE,gBAAgB,CAAA;QAC9B,WAAW,EAAE,OAAO,CAAA;QACpB,OAAO,EAAE,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,CAAA;KAC5B,CAAA;IACD,iBAAiB,EAAE;QACjB,IAAI,EAAE,QAAQ,CAAA;QACd,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,CAAA;QAC5B,cAAc,EAAE,MAAM,CAAC,OAAO,CAAC,CAAA;QAC/B,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,CAAA;QACzB,QAAQ,EAAE,CAAC,CAAC,CAAA;QACZ,YAAY,EAAE,gBAAgB,CAAA;QAC9B,WAAW,EAAE,oBAAoB,CAAA;QACjC,OAAO,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAA;KACjC,CAAA;CACF;AAED,MAAM,WAAW,cAAc;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,OAAO,CACrB,KAAK,EAAE,MAAM,CAAC,kBAAkB,CAAC,EACjC,IAAI,EAAE,IAAI,CAAC,gBAAgB,CAAC,EAC5B,IAAI,GAAE,cAAmB,GACxB,kBAAkB,CAuCpB;AAED,eAAO,MAAM,aAAa;;;;CAA4B,CAAA"}
@@ -19,7 +19,7 @@ export function update(state, msg) {
19
19
  return [{ ...state, visible: msg.visible }, []];
20
20
  }
21
21
  }
22
- export function connect(get, send, opts = {}) {
22
+ export function connect(state, send, opts = {}) {
23
23
  const locale = useContext(LocaleContext);
24
24
  const autoComplete = opts.autoComplete ?? 'current-password';
25
25
  const showLabel = opts.showLabel;
@@ -28,25 +28,25 @@ export function connect(get, send, opts = {}) {
28
28
  root: {
29
29
  'data-scope': 'password-input',
30
30
  'data-part': 'root',
31
- 'data-visible': (s) => (get(s).visible ? '' : undefined),
32
- 'data-disabled': (s) => (get(s).disabled ? '' : undefined),
31
+ 'data-visible': state.map((st) => (st.visible ? '' : undefined)),
32
+ 'data-disabled': state.map((st) => (st.disabled ? '' : undefined)),
33
33
  },
34
34
  input: {
35
- type: (s) => (get(s).visible ? 'text' : 'password'),
35
+ type: state.map((st) => (st.visible ? 'text' : 'password')),
36
36
  autoComplete,
37
- disabled: (s) => get(s).disabled,
38
- value: (s) => get(s).value,
37
+ disabled: state.map((st) => st.disabled),
38
+ value: state.map((st) => st.value),
39
39
  'data-scope': 'password-input',
40
40
  'data-part': 'input',
41
41
  onInput: tagSend(send, ['setValue'], (e) => send({ type: 'setValue', value: e.target.value })),
42
42
  },
43
43
  visibilityTrigger: {
44
44
  type: 'button',
45
- 'aria-label': (s) => get(s).visible
46
- ? (hideLabel ?? locale(s).passwordInput.hide)
47
- : (showLabel ?? locale(s).passwordInput.show),
48
- 'aria-pressed': (s) => get(s).visible,
49
- disabled: (s) => get(s).disabled,
45
+ 'aria-label': state.map((st) => st.visible
46
+ ? (hideLabel ?? locale.passwordInput.hide)
47
+ : (showLabel ?? locale.passwordInput.show)),
48
+ 'aria-pressed': state.map((st) => st.visible),
49
+ disabled: state.map((st) => st.disabled),
50
50
  tabIndex: -1,
51
51
  'data-scope': 'password-input',
52
52
  'data-part': 'visibility-trigger',
@@ -1 +1 @@
1
- {"version":3,"file":"password-input.js","sourceRoot":"","sources":["../../src/components/password-input.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Send } from '@llui/dom'\nimport { useContext, tagSend } from '@llui/dom'\nimport { LocaleContext } from '../locale.js'\nimport type { Locale } from '../locale.js'\n\n/**\n * Password input — text input with show/hide visibility toggle.\n */\n\nexport interface PasswordInputState {\n value: string\n visible: boolean\n disabled: boolean\n}\n\nexport type PasswordInputMsg =\n /** @intent(\"Update the password value as the user types\") */\n | { type: 'setValue'; value: string }\n /** @intent(\"Toggle the show/hide-password state\") */\n | { type: 'toggleVisibility' }\n /** @intent(\"Set the show/hide-password state to a specific value\") */\n | { type: 'setVisible'; visible: boolean }\n\nexport interface PasswordInputInit {\n value?: string\n visible?: boolean\n disabled?: boolean\n}\n\nexport function init(opts: PasswordInputInit = {}): PasswordInputState {\n return {\n value: opts.value ?? '',\n visible: opts.visible ?? false,\n disabled: opts.disabled ?? false,\n }\n}\n\nexport function update(\n state: PasswordInputState,\n msg: PasswordInputMsg,\n): [PasswordInputState, never[]] {\n if (state.disabled && msg.type !== 'setValue') return [state, []]\n switch (msg.type) {\n case 'setValue':\n return [{ ...state, value: msg.value }, []]\n case 'toggleVisibility':\n return [{ ...state, visible: !state.visible }, []]\n case 'setVisible':\n return [{ ...state, visible: msg.visible }, []]\n }\n}\n\nexport interface PasswordInputParts<S> {\n root: {\n 'data-scope': 'password-input'\n 'data-part': 'root'\n 'data-visible': (s: S) => '' | undefined\n 'data-disabled': (s: S) => '' | undefined\n }\n input: {\n type: (s: S) => 'text' | 'password'\n autoComplete: string\n disabled: (s: S) => boolean\n value: (s: S) => string\n 'data-scope': 'password-input'\n 'data-part': 'input'\n onInput: (e: Event) => void\n }\n visibilityTrigger: {\n type: 'button'\n 'aria-label': (s: S) => string\n 'aria-pressed': (s: S) => boolean\n disabled: (s: S) => boolean\n tabIndex: -1\n 'data-scope': 'password-input'\n 'data-part': 'visibility-trigger'\n onClick: (e: MouseEvent) => void\n }\n}\n\nexport interface ConnectOptions {\n autoComplete?: string\n showLabel?: string\n hideLabel?: string\n}\n\nexport function connect<S>(\n get: (s: S) => PasswordInputState,\n send: Send<PasswordInputMsg>,\n opts: ConnectOptions = {},\n): PasswordInputParts<S> {\n const locale = useContext<S, Locale>(LocaleContext)\n const autoComplete = opts.autoComplete ?? 'current-password'\n const showLabel = opts.showLabel\n const hideLabel = opts.hideLabel\n\n return {\n root: {\n 'data-scope': 'password-input',\n 'data-part': 'root',\n 'data-visible': (s) => (get(s).visible ? '' : undefined),\n 'data-disabled': (s) => (get(s).disabled ? '' : undefined),\n },\n input: {\n type: (s) => (get(s).visible ? 'text' : 'password'),\n autoComplete,\n disabled: (s) => get(s).disabled,\n value: (s) => get(s).value,\n 'data-scope': 'password-input',\n 'data-part': 'input',\n onInput: tagSend(send, ['setValue'], (e) =>\n send({ type: 'setValue', value: (e.target as HTMLInputElement).value }),\n ),\n },\n visibilityTrigger: {\n type: 'button',\n 'aria-label': (s) =>\n get(s).visible\n ? (hideLabel ?? locale(s).passwordInput.hide)\n : (showLabel ?? locale(s).passwordInput.show),\n 'aria-pressed': (s) => get(s).visible,\n disabled: (s) => get(s).disabled,\n tabIndex: -1,\n 'data-scope': 'password-input',\n 'data-part': 'visibility-trigger',\n onClick: tagSend(send, ['toggleVisibility'], () => send({ type: 'toggleVisibility' })),\n },\n }\n}\n\nexport const passwordInput = { init, update, connect }\n"]}
1
+ {"version":3,"file":"password-input.js","sourceRoot":"","sources":["../../src/components/password-input.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Send, Signal } from '@llui/dom'\nimport { useContext, tagSend } from '@llui/dom'\nimport { LocaleContext } from '../locale.js'\n\n/**\n * Password input — text input with show/hide visibility toggle.\n */\n\nexport interface PasswordInputState {\n value: string\n visible: boolean\n disabled: boolean\n}\n\nexport type PasswordInputMsg =\n /** @intent(\"Update the password value as the user types\") */\n | { type: 'setValue'; value: string }\n /** @intent(\"Toggle the show/hide-password state\") */\n | { type: 'toggleVisibility' }\n /** @intent(\"Set the show/hide-password state to a specific value\") */\n | { type: 'setVisible'; visible: boolean }\n\nexport interface PasswordInputInit {\n value?: string\n visible?: boolean\n disabled?: boolean\n}\n\nexport function init(opts: PasswordInputInit = {}): PasswordInputState {\n return {\n value: opts.value ?? '',\n visible: opts.visible ?? false,\n disabled: opts.disabled ?? false,\n }\n}\n\nexport function update(\n state: PasswordInputState,\n msg: PasswordInputMsg,\n): [PasswordInputState, never[]] {\n if (state.disabled && msg.type !== 'setValue') return [state, []]\n switch (msg.type) {\n case 'setValue':\n return [{ ...state, value: msg.value }, []]\n case 'toggleVisibility':\n return [{ ...state, visible: !state.visible }, []]\n case 'setVisible':\n return [{ ...state, visible: msg.visible }, []]\n }\n}\n\nexport interface PasswordInputParts {\n root: {\n 'data-scope': 'password-input'\n 'data-part': 'root'\n 'data-visible': Signal<'' | undefined>\n 'data-disabled': Signal<'' | undefined>\n }\n input: {\n type: Signal<'text' | 'password'>\n autoComplete: string\n disabled: Signal<boolean>\n value: Signal<string>\n 'data-scope': 'password-input'\n 'data-part': 'input'\n onInput: (e: Event) => void\n }\n visibilityTrigger: {\n type: 'button'\n 'aria-label': Signal<string>\n 'aria-pressed': Signal<boolean>\n disabled: Signal<boolean>\n tabIndex: -1\n 'data-scope': 'password-input'\n 'data-part': 'visibility-trigger'\n onClick: (e: MouseEvent) => void\n }\n}\n\nexport interface ConnectOptions {\n autoComplete?: string\n showLabel?: string\n hideLabel?: string\n}\n\nexport function connect(\n state: Signal<PasswordInputState>,\n send: Send<PasswordInputMsg>,\n opts: ConnectOptions = {},\n): PasswordInputParts {\n const locale = useContext(LocaleContext)\n const autoComplete = opts.autoComplete ?? 'current-password'\n const showLabel = opts.showLabel\n const hideLabel = opts.hideLabel\n\n return {\n root: {\n 'data-scope': 'password-input',\n 'data-part': 'root',\n 'data-visible': state.map((st) => (st.visible ? '' : undefined)),\n 'data-disabled': state.map((st) => (st.disabled ? '' : undefined)),\n },\n input: {\n type: state.map((st) => (st.visible ? 'text' : 'password')),\n autoComplete,\n disabled: state.map((st) => st.disabled),\n value: state.map((st) => st.value),\n 'data-scope': 'password-input',\n 'data-part': 'input',\n onInput: tagSend(send, ['setValue'], (e) =>\n send({ type: 'setValue', value: (e.target as HTMLInputElement).value }),\n ),\n },\n visibilityTrigger: {\n type: 'button',\n 'aria-label': state.map((st) =>\n st.visible\n ? (hideLabel ?? locale.passwordInput.hide)\n : (showLabel ?? locale.passwordInput.show),\n ),\n 'aria-pressed': state.map((st) => st.visible),\n disabled: state.map((st) => st.disabled),\n tabIndex: -1,\n 'data-scope': 'password-input',\n 'data-part': 'visibility-trigger',\n onClick: tagSend(send, ['toggleVisibility'], () => send({ type: 'toggleVisibility' })),\n },\n }\n}\n\nexport const passwordInput = { init, update, connect }\n"]}
@@ -1,4 +1,4 @@
1
- import type { Send } from '@llui/dom';
1
+ import type { Send, Signal } from '@llui/dom';
2
2
  /**
3
3
  * Pin input — a sequence of single-character fields for OTP codes, etc.
4
4
  * Auto-advances on input, handles backspace to previous field, supports
@@ -50,13 +50,13 @@ export declare function init(opts?: PinInputInit): PinInputState;
50
50
  export declare function update(state: PinInputState, msg: PinInputMsg): [PinInputState, never[]];
51
51
  export declare function isComplete(state: PinInputState): boolean;
52
52
  export declare function getValue(state: PinInputState): string;
53
- export interface PinInputParts<S> {
53
+ export interface PinInputParts {
54
54
  root: {
55
55
  role: 'group';
56
56
  'aria-labelledby': string;
57
57
  'data-scope': 'pin-input';
58
58
  'data-part': 'root';
59
- 'data-disabled': (s: S) => '' | undefined;
59
+ 'data-disabled': Signal<'' | undefined>;
60
60
  };
61
61
  label: {
62
62
  id: string;
@@ -65,14 +65,14 @@ export interface PinInputParts<S> {
65
65
  };
66
66
  /** Props for the input at a given index. */
67
67
  input: (index: number) => {
68
- type: (s: S) => 'text' | 'password';
69
- inputMode: (s: S) => 'numeric' | 'text';
70
- pattern: (s: S) => string;
68
+ type: Signal<'text' | 'password'>;
69
+ inputMode: Signal<'numeric' | 'text'>;
70
+ pattern: Signal<string>;
71
71
  maxLength: 1;
72
72
  autoComplete: 'off';
73
73
  'aria-label': string;
74
- disabled: (s: S) => boolean;
75
- value: (s: S) => string;
74
+ disabled: Signal<boolean>;
75
+ value: Signal<string>;
76
76
  'data-scope': 'pin-input';
77
77
  'data-part': 'input';
78
78
  'data-index': string;
@@ -88,7 +88,7 @@ export interface ConnectOptions {
88
88
  /** Validate each character before setting. Non-empty array blocks setDigit. */
89
89
  validate?: (value: string) => string[] | null;
90
90
  }
91
- export declare function connect<S>(get: (s: S) => PinInputState, send: Send<PinInputMsg>, opts: ConnectOptions): PinInputParts<S>;
91
+ export declare function connect(state: Signal<PinInputState>, send: Send<PinInputMsg>, opts: ConnectOptions): PinInputParts;
92
92
  export declare const pinInput: {
93
93
  init: typeof init;
94
94
  update: typeof update;