@llui/components 0.4.10 → 0.5.0

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
@@ -1 +1 @@
1
- {"version":3,"file":"cascade-select.js","sourceRoot":"","sources":["../../src/components/cascade-select.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 * Cascade select — a series of dependent selects where each level's\n * choice filters the options of the next. Classic example: country\n * → state → city. The machine stores a flat list of selections\n * (one per level, or null) and the options at each level; filtering\n * logic is left to the view/consumer.\n *\n * Level shape: the consumer passes an array of Level descriptors on\n * setLevels, each with its own options. Selecting at level N clears\n * selections at levels > N.\n */\n\nexport interface CascadeLevel {\n id: string\n label: string\n options: Array<{ value: string; label: string; disabled?: boolean }>\n}\n\nexport interface CascadeSelectState {\n levels: CascadeLevel[]\n /** Parallel to levels: one value per level, or null. */\n values: (string | null)[]\n disabled: boolean\n}\n\nexport type CascadeSelectMsg =\n /** @humanOnly */\n | { type: 'setLevels'; levels: CascadeLevel[] }\n /** @intent(\"Pick a value at the given level (clears selections at deeper levels)\") */\n | { type: 'setValue'; levelIndex: number; value: string | null }\n /** @intent(\"Clear every level's selection\") */\n | { type: 'clear' }\n\nexport interface CascadeSelectInit {\n levels?: CascadeLevel[]\n values?: (string | null)[]\n disabled?: boolean\n}\n\nexport function init(opts: CascadeSelectInit = {}): CascadeSelectState {\n const levels = opts.levels ?? []\n const values = opts.values ?? new Array<string | null>(levels.length).fill(null)\n // Normalize: pad or trim values array to match levels length\n const normalized: (string | null)[] = []\n for (let i = 0; i < levels.length; i++) {\n normalized.push(values[i] ?? null)\n }\n return {\n levels,\n values: normalized,\n disabled: opts.disabled ?? false,\n }\n}\n\nexport function update(\n state: CascadeSelectState,\n msg: CascadeSelectMsg,\n): [CascadeSelectState, never[]] {\n if (state.disabled && msg.type !== 'clear') return [state, []]\n switch (msg.type) {\n case 'setLevels': {\n const values = new Array<string | null>(msg.levels.length).fill(null)\n return [{ ...state, levels: msg.levels, values }, []]\n }\n case 'setValue': {\n if (msg.levelIndex < 0 || msg.levelIndex >= state.levels.length) return [state, []]\n // Setting a level clears all levels below it.\n const next = state.values.slice()\n next[msg.levelIndex] = msg.value\n for (let i = msg.levelIndex + 1; i < next.length; i++) {\n next[i] = null\n }\n return [{ ...state, values: next }, []]\n }\n case 'clear':\n return [{ ...state, values: new Array<string | null>(state.levels.length).fill(null) }, []]\n }\n}\n\nexport function isLevelReady(state: CascadeSelectState, levelIndex: number): boolean {\n // A level is ready to accept input if all prior levels have values.\n for (let i = 0; i < levelIndex; i++) {\n if (state.values[i] === null) return false\n }\n return true\n}\n\nexport function isComplete(state: CascadeSelectState): boolean {\n return state.values.every((v) => v !== null)\n}\n\nexport function completeValues(state: CascadeSelectState): string[] | null {\n if (!isComplete(state)) return null\n return state.values as string[]\n}\n\nexport interface CascadeLevelParts<S> {\n label: {\n for: string\n 'data-scope': 'cascade-select'\n 'data-part': 'level-label'\n }\n select: {\n id: string\n disabled: (s: S) => boolean\n value: (s: S) => string\n 'data-scope': 'cascade-select'\n 'data-part': 'level-select'\n 'data-level': string\n 'data-ready': (s: S) => '' | undefined\n onChange: (e: Event) => void\n }\n}\n\nexport interface CascadeSelectParts<S> {\n root: {\n 'data-scope': 'cascade-select'\n 'data-part': 'root'\n 'data-disabled': (s: S) => '' | undefined\n 'data-complete': (s: S) => '' | undefined\n }\n clearTrigger: {\n type: 'button'\n 'aria-label': string | ((s: S) => string)\n disabled: (s: S) => boolean\n 'data-scope': 'cascade-select'\n 'data-part': 'clear-trigger'\n onClick: (e: MouseEvent) => void\n }\n level: (index: number) => CascadeLevelParts<S>\n}\n\nexport interface ConnectOptions {\n id: string\n clearLabel?: string\n}\n\nexport function connect<S>(\n get: (s: S) => CascadeSelectState,\n send: Send<CascadeSelectMsg>,\n opts: ConnectOptions,\n): CascadeSelectParts<S> {\n const locale = useContext<S, Locale>(LocaleContext)\n const levelId = (i: number): string => `${opts.id}:level:${i}`\n\n return {\n root: {\n 'data-scope': 'cascade-select',\n 'data-part': 'root',\n 'data-disabled': (s) => (get(s).disabled ? '' : undefined),\n 'data-complete': (s) => (isComplete(get(s)) ? '' : undefined),\n },\n clearTrigger: {\n type: 'button',\n 'aria-label': opts.clearLabel ?? ((s: S) => locale(s).cascadeSelect.clear),\n disabled: (s) => get(s).values.every((v) => v === null),\n 'data-scope': 'cascade-select',\n 'data-part': 'clear-trigger',\n onClick: tagSend(send, ['clear'], () => send({ type: 'clear' })),\n },\n level: (index: number): CascadeLevelParts<S> => ({\n label: {\n for: levelId(index),\n 'data-scope': 'cascade-select',\n 'data-part': 'level-label',\n },\n select: {\n id: levelId(index),\n disabled: (s) => get(s).disabled || !isLevelReady(get(s), index),\n value: (s) => get(s).values[index] ?? '',\n 'data-scope': 'cascade-select',\n 'data-part': 'level-select',\n 'data-level': String(index),\n 'data-ready': (s) => (isLevelReady(get(s), index) ? '' : undefined),\n onChange: tagSend(send, ['setValue'], (e) => {\n const el = e.target as HTMLSelectElement\n send({ type: 'setValue', levelIndex: index, value: el.value || null })\n }),\n },\n }),\n }\n}\n\nexport const cascadeSelect = {\n init,\n update,\n connect,\n isLevelReady,\n isComplete,\n completeValues,\n}\n"]}
1
+ {"version":3,"file":"cascade-select.js","sourceRoot":"","sources":["../../src/components/cascade-select.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAyC5C,MAAM,UAAU,IAAI,CAAC,OAA0B,EAAE;IAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,EAAE,CAAA;IAChC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,KAAK,CAAgB,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAChF,6DAA6D;IAC7D,MAAM,UAAU,GAAsB,EAAE,CAAA;IACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAA;IACpC,CAAC;IACD,OAAO;QACL,MAAM;QACN,MAAM,EAAE,UAAU;QAClB,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,KAAK;KACjC,CAAA;AACH,CAAC;AAED,MAAM,UAAU,MAAM,CACpB,KAAyB,EACzB,GAAqB;IAErB,IAAI,KAAK,CAAC,QAAQ,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO;QAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IAC9D,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;QACjB,KAAK,WAAW,CAAC,CAAC,CAAC;YACjB,MAAM,MAAM,GAAG,IAAI,KAAK,CAAgB,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACrE,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAA;QACvD,CAAC;QACD,KAAK,UAAU,CAAC,CAAC,CAAC;YAChB,IAAI,GAAG,CAAC,UAAU,GAAG,CAAC,IAAI,GAAG,CAAC,UAAU,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM;gBAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;YACnF,8CAA8C;YAC9C,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;YACjC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC,KAAK,CAAA;YAChC,KAAK,IAAI,CAAC,GAAG,GAAG,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACtD,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;YAChB,CAAC;YACD,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAA;QACzC,CAAC;QACD,KAAK,OAAO;YACV,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,IAAI,KAAK,CAAgB,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;IAC/F,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAyB,EAAE,UAAkB;IACxE,oEAAoE;IACpE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI;YAAE,OAAO,KAAK,CAAA;IAC5C,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAyB;IAClD,OAAO,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAA;AAC9C,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAyB;IACtD,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IACnC,OAAO,KAAK,CAAC,MAAkB,CAAA;AACjC,CAAC;AA2CD,MAAM,UAAU,OAAO,CACrB,KAAiC,EACjC,IAA4B,EAC5B,IAAoB;IAEpB,MAAM,MAAM,GAAG,UAAU,CAAC,aAAa,CAAC,CAAA;IACxC,MAAM,OAAO,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,UAAU,CAAC,EAAE,CAAA;IAE9D,OAAO;QACL,IAAI,EAAE;YACJ,YAAY,EAAE,gBAAgB;YAC9B,WAAW,EAAE,MAAM;YACnB,eAAe,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YAChE,eAAe,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;SACpE;QACD,YAAY,EAAE;YACZ,IAAI,EAAE,QAAQ;YACd,YAAY,EAAE,IAAI,CAAC,UAAU,IAAI,MAAM,CAAC,aAAa,CAAC,KAAK;YAC3D,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;YAC7D,YAAY,EAAE,gBAAgB;YAC9B,WAAW,EAAE,eAAe;YAC5B,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;SACjE;QACD,KAAK,EAAE,CAAC,KAAa,EAAqB,EAAE,CAAC,CAAC;YAC5C,KAAK,EAAE;gBACL,GAAG,EAAE,OAAO,CAAC,KAAK,CAAC;gBACnB,YAAY,EAAE,gBAAgB;gBAC9B,WAAW,EAAE,aAAa;aAC3B;YACD,MAAM,EAAE;gBACN,EAAE,EAAE,OAAO,CAAC,KAAK,CAAC;gBAClB,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,YAAY,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;gBACjE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;gBAC9C,YAAY,EAAE,gBAAgB;gBAC9B,WAAW,EAAE,cAAc;gBAC3B,YAAY,EAAE,MAAM,CAAC,KAAK,CAAC;gBAC3B,YAAY,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;gBACzE,QAAQ,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE;oBAC1C,MAAM,EAAE,GAAG,CAAC,CAAC,MAA2B,CAAA;oBACxC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC,CAAA;gBACxE,CAAC,CAAC;aACH;SACF,CAAC;KACH,CAAA;AACH,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,IAAI;IACJ,MAAM;IACN,OAAO;IACP,YAAY;IACZ,UAAU;IACV,cAAc;CACf,CAAA","sourcesContent":["import type { Send, Signal } from '@llui/dom'\nimport { useContext, tagSend } from '@llui/dom'\nimport { LocaleContext } from '../locale.js'\n\n/**\n * Cascade select — a series of dependent selects where each level's\n * choice filters the options of the next. Classic example: country\n * → state → city. The machine stores a flat list of selections\n * (one per level, or null) and the options at each level; filtering\n * logic is left to the view/consumer.\n *\n * Level shape: the consumer passes an array of Level descriptors on\n * setLevels, each with its own options. Selecting at level N clears\n * selections at levels > N.\n */\n\nexport interface CascadeLevel {\n id: string\n label: string\n options: Array<{ value: string; label: string; disabled?: boolean }>\n}\n\nexport interface CascadeSelectState {\n levels: CascadeLevel[]\n /** Parallel to levels: one value per level, or null. */\n values: (string | null)[]\n disabled: boolean\n}\n\nexport type CascadeSelectMsg =\n /** @humanOnly */\n | { type: 'setLevels'; levels: CascadeLevel[] }\n /** @intent(\"Pick a value at the given level (clears selections at deeper levels)\") */\n | { type: 'setValue'; levelIndex: number; value: string | null }\n /** @intent(\"Clear every level's selection\") */\n | { type: 'clear' }\n\nexport interface CascadeSelectInit {\n levels?: CascadeLevel[]\n values?: (string | null)[]\n disabled?: boolean\n}\n\nexport function init(opts: CascadeSelectInit = {}): CascadeSelectState {\n const levels = opts.levels ?? []\n const values = opts.values ?? new Array<string | null>(levels.length).fill(null)\n // Normalize: pad or trim values array to match levels length\n const normalized: (string | null)[] = []\n for (let i = 0; i < levels.length; i++) {\n normalized.push(values[i] ?? null)\n }\n return {\n levels,\n values: normalized,\n disabled: opts.disabled ?? false,\n }\n}\n\nexport function update(\n state: CascadeSelectState,\n msg: CascadeSelectMsg,\n): [CascadeSelectState, never[]] {\n if (state.disabled && msg.type !== 'clear') return [state, []]\n switch (msg.type) {\n case 'setLevels': {\n const values = new Array<string | null>(msg.levels.length).fill(null)\n return [{ ...state, levels: msg.levels, values }, []]\n }\n case 'setValue': {\n if (msg.levelIndex < 0 || msg.levelIndex >= state.levels.length) return [state, []]\n // Setting a level clears all levels below it.\n const next = state.values.slice()\n next[msg.levelIndex] = msg.value\n for (let i = msg.levelIndex + 1; i < next.length; i++) {\n next[i] = null\n }\n return [{ ...state, values: next }, []]\n }\n case 'clear':\n return [{ ...state, values: new Array<string | null>(state.levels.length).fill(null) }, []]\n }\n}\n\nexport function isLevelReady(state: CascadeSelectState, levelIndex: number): boolean {\n // A level is ready to accept input if all prior levels have values.\n for (let i = 0; i < levelIndex; i++) {\n if (state.values[i] === null) return false\n }\n return true\n}\n\nexport function isComplete(state: CascadeSelectState): boolean {\n return state.values.every((v) => v !== null)\n}\n\nexport function completeValues(state: CascadeSelectState): string[] | null {\n if (!isComplete(state)) return null\n return state.values as string[]\n}\n\nexport interface CascadeLevelParts {\n label: {\n for: string\n 'data-scope': 'cascade-select'\n 'data-part': 'level-label'\n }\n select: {\n id: string\n disabled: Signal<boolean>\n value: Signal<string>\n 'data-scope': 'cascade-select'\n 'data-part': 'level-select'\n 'data-level': string\n 'data-ready': Signal<'' | undefined>\n onChange: (e: Event) => void\n }\n}\n\nexport interface CascadeSelectParts {\n root: {\n 'data-scope': 'cascade-select'\n 'data-part': 'root'\n 'data-disabled': Signal<'' | undefined>\n 'data-complete': Signal<'' | undefined>\n }\n clearTrigger: {\n type: 'button'\n 'aria-label': string\n disabled: Signal<boolean>\n 'data-scope': 'cascade-select'\n 'data-part': 'clear-trigger'\n onClick: (e: MouseEvent) => void\n }\n level: (index: number) => CascadeLevelParts\n}\n\nexport interface ConnectOptions {\n id: string\n clearLabel?: string\n}\n\nexport function connect(\n state: Signal<CascadeSelectState>,\n send: Send<CascadeSelectMsg>,\n opts: ConnectOptions,\n): CascadeSelectParts {\n const locale = useContext(LocaleContext)\n const levelId = (i: number): string => `${opts.id}:level:${i}`\n\n return {\n root: {\n 'data-scope': 'cascade-select',\n 'data-part': 'root',\n 'data-disabled': state.map((s) => (s.disabled ? '' : undefined)),\n 'data-complete': state.map((s) => (isComplete(s) ? '' : undefined)),\n },\n clearTrigger: {\n type: 'button',\n 'aria-label': opts.clearLabel ?? locale.cascadeSelect.clear,\n disabled: state.map((s) => s.values.every((v) => v === null)),\n 'data-scope': 'cascade-select',\n 'data-part': 'clear-trigger',\n onClick: tagSend(send, ['clear'], () => send({ type: 'clear' })),\n },\n level: (index: number): CascadeLevelParts => ({\n label: {\n for: levelId(index),\n 'data-scope': 'cascade-select',\n 'data-part': 'level-label',\n },\n select: {\n id: levelId(index),\n disabled: state.map((s) => s.disabled || !isLevelReady(s, index)),\n value: state.map((s) => s.values[index] ?? ''),\n 'data-scope': 'cascade-select',\n 'data-part': 'level-select',\n 'data-level': String(index),\n 'data-ready': state.map((s) => (isLevelReady(s, index) ? '' : undefined)),\n onChange: tagSend(send, ['setValue'], (e) => {\n const el = e.target as HTMLSelectElement\n send({ type: 'setValue', levelIndex: index, value: el.value || null })\n }),\n },\n }),\n }\n}\n\nexport const cascadeSelect = {\n init,\n update,\n connect,\n isLevelReady,\n isComplete,\n completeValues,\n}\n"]}
@@ -1,4 +1,4 @@
1
- import type { Send } from '@llui/dom';
1
+ import type { Send, Signal } from '@llui/dom';
2
2
  /**
3
3
  * Checkbox — a tri-state form control (checked / unchecked / indeterminate).
4
4
  * The `indeterminate` state is a visual-only state used to represent "partial"
@@ -36,18 +36,18 @@ export interface CheckboxInit {
36
36
  }
37
37
  export declare function init(opts?: CheckboxInit): CheckboxState;
38
38
  export declare function update(state: CheckboxState, msg: CheckboxMsg): [CheckboxState, never[]];
39
- export interface CheckboxParts<S> {
39
+ export interface CheckboxParts {
40
40
  /** The visual box/container — `role="checkbox"` for accessibility. */
41
41
  root: {
42
42
  role: 'checkbox';
43
- 'aria-checked': (s: S) => 'true' | 'false' | 'mixed';
44
- 'aria-disabled': (s: S) => 'true' | undefined;
45
- 'aria-required': (s: S) => 'true' | undefined;
46
- 'data-state': (s: S) => 'checked' | 'unchecked' | 'indeterminate';
47
- 'data-disabled': (s: S) => '' | undefined;
43
+ 'aria-checked': Signal<'true' | 'false' | 'mixed'>;
44
+ 'aria-disabled': Signal<'true' | undefined>;
45
+ 'aria-required': Signal<'true' | undefined>;
46
+ 'data-state': Signal<'checked' | 'unchecked' | 'indeterminate'>;
47
+ 'data-disabled': Signal<'' | undefined>;
48
48
  'data-scope': 'checkbox';
49
49
  'data-part': 'root';
50
- tabIndex: (s: S) => number;
50
+ tabIndex: Signal<number>;
51
51
  onClick: (e: MouseEvent) => void;
52
52
  onKeyDown: (e: KeyboardEvent) => void;
53
53
  };
@@ -57,21 +57,21 @@ export interface CheckboxParts<S> {
57
57
  'aria-hidden': 'true';
58
58
  tabIndex: -1;
59
59
  style: string;
60
- checked: (s: S) => boolean;
61
- indeterminate: (s: S) => boolean;
62
- disabled: (s: S) => boolean;
63
- required: (s: S) => boolean;
60
+ checked: Signal<boolean>;
61
+ indeterminate: Signal<boolean>;
62
+ disabled: Signal<boolean>;
63
+ required: Signal<boolean>;
64
64
  'data-scope': 'checkbox';
65
65
  'data-part': 'hidden-input';
66
66
  };
67
67
  /** Optional indicator child (the checkmark). */
68
68
  indicator: {
69
- 'data-state': (s: S) => 'checked' | 'unchecked' | 'indeterminate';
69
+ 'data-state': Signal<'checked' | 'unchecked' | 'indeterminate'>;
70
70
  'data-scope': 'checkbox';
71
71
  'data-part': 'indicator';
72
72
  };
73
73
  }
74
- export declare function connect<S>(get: (s: S) => CheckboxState, send: Send<CheckboxMsg>): CheckboxParts<S>;
74
+ export declare function connect(state: Signal<CheckboxState>, send: Send<CheckboxMsg>): CheckboxParts;
75
75
  export declare const checkbox: {
76
76
  init: typeof init;
77
77
  update: typeof update;
@@ -1 +1 @@
1
- {"version":3,"file":"checkbox.d.ts","sourceRoot":"","sources":["../../src/components/checkbox.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAErC;;;;;;;;GAQG;AAEH,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,eAAe,CAAA;AAEpD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,YAAY,CAAA;IACrB,QAAQ,EAAE,OAAO,CAAA;IACjB,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,MAAM,WAAW;AACrB,mEAAmE;AACjE;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE;AACpB,gFAAgF;GAC9E;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,YAAY,CAAA;CAAE;AAC/C,iBAAiB;GACf;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAA;AAE9C,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,YAAY,CAAA;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,wBAAgB,IAAI,CAAC,IAAI,GAAE,YAAiB,GAAG,aAAa,CAM3D;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,WAAW,GAAG,CAAC,aAAa,EAAE,KAAK,EAAE,CAAC,CAYvF;AAYD,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,sEAAsE;IACtE,IAAI,EAAE;QACJ,IAAI,EAAE,UAAU,CAAA;QAChB,cAAc,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,GAAG,OAAO,GAAG,OAAO,CAAA;QACpD,eAAe,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,GAAG,SAAS,CAAA;QAC7C,eAAe,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,GAAG,SAAS,CAAA;QAC7C,YAAY,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,SAAS,GAAG,WAAW,GAAG,eAAe,CAAA;QACjE,eAAe,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,SAAS,CAAA;QACzC,YAAY,EAAE,UAAU,CAAA;QACxB,WAAW,EAAE,MAAM,CAAA;QACnB,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;QAC1B,OAAO,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAA;QAChC,SAAS,EAAE,CAAC,CAAC,EAAE,aAAa,KAAK,IAAI,CAAA;KACtC,CAAA;IACD,oDAAoD;IACpD,WAAW,EAAE;QACX,IAAI,EAAE,UAAU,CAAA;QAChB,aAAa,EAAE,MAAM,CAAA;QACrB,QAAQ,EAAE,CAAC,CAAC,CAAA;QACZ,KAAK,EAAE,MAAM,CAAA;QACb,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,OAAO,CAAA;QAC1B,aAAa,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,OAAO,CAAA;QAChC,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,OAAO,CAAA;QAC3B,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,OAAO,CAAA;QAC3B,YAAY,EAAE,UAAU,CAAA;QACxB,WAAW,EAAE,cAAc,CAAA;KAC5B,CAAA;IACD,gDAAgD;IAChD,SAAS,EAAE;QACT,YAAY,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,SAAS,GAAG,WAAW,GAAG,eAAe,CAAA;QACjE,YAAY,EAAE,UAAU,CAAA;QACxB,WAAW,EAAE,WAAW,CAAA;KACzB,CAAA;CACF;AAKD,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,CAsClB;AAED,eAAO,MAAM,QAAQ;;;;CAA4B,CAAA"}
1
+ {"version":3,"file":"checkbox.d.ts","sourceRoot":"","sources":["../../src/components/checkbox.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAE7C;;;;;;;;GAQG;AAEH,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,eAAe,CAAA;AAEpD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,YAAY,CAAA;IACrB,QAAQ,EAAE,OAAO,CAAA;IACjB,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,MAAM,WAAW;AACrB,mEAAmE;AACjE;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE;AACpB,gFAAgF;GAC9E;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,YAAY,CAAA;CAAE;AAC/C,iBAAiB;GACf;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAA;AAE9C,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,YAAY,CAAA;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,wBAAgB,IAAI,CAAC,IAAI,GAAE,YAAiB,GAAG,aAAa,CAM3D;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,WAAW,GAAG,CAAC,aAAa,EAAE,KAAK,EAAE,CAAC,CAYvF;AAYD,MAAM,WAAW,aAAa;IAC5B,sEAAsE;IACtE,IAAI,EAAE;QACJ,IAAI,EAAE,UAAU,CAAA;QAChB,cAAc,EAAE,MAAM,CAAC,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC,CAAA;QAClD,eAAe,EAAE,MAAM,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;QAC3C,eAAe,EAAE,MAAM,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;QAC3C,YAAY,EAAE,MAAM,CAAC,SAAS,GAAG,WAAW,GAAG,eAAe,CAAC,CAAA;QAC/D,eAAe,EAAE,MAAM,CAAC,EAAE,GAAG,SAAS,CAAC,CAAA;QACvC,YAAY,EAAE,UAAU,CAAA;QACxB,WAAW,EAAE,MAAM,CAAA;QACnB,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAA;QACxB,OAAO,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAA;QAChC,SAAS,EAAE,CAAC,CAAC,EAAE,aAAa,KAAK,IAAI,CAAA;KACtC,CAAA;IACD,oDAAoD;IACpD,WAAW,EAAE;QACX,IAAI,EAAE,UAAU,CAAA;QAChB,aAAa,EAAE,MAAM,CAAA;QACrB,QAAQ,EAAE,CAAC,CAAC,CAAA;QACZ,KAAK,EAAE,MAAM,CAAA;QACb,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAA;QACxB,aAAa,EAAE,MAAM,CAAC,OAAO,CAAC,CAAA;QAC9B,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,CAAA;QACzB,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,CAAA;QACzB,YAAY,EAAE,UAAU,CAAA;QACxB,WAAW,EAAE,cAAc,CAAA;KAC5B,CAAA;IACD,gDAAgD;IAChD,SAAS,EAAE;QACT,YAAY,EAAE,MAAM,CAAC,SAAS,GAAG,WAAW,GAAG,eAAe,CAAC,CAAA;QAC/D,YAAY,EAAE,UAAU,CAAA;QACxB,WAAW,EAAE,WAAW,CAAA;KACzB,CAAA;CACF;AAKD,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,GAAG,aAAa,CAsC5F;AAED,eAAO,MAAM,QAAQ;;;;CAA4B,CAAA"}
@@ -32,18 +32,18 @@ function dataState(c) {
32
32
  return c ? 'checked' : 'unchecked';
33
33
  }
34
34
  const HIDDEN_STYLE = 'position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;';
35
- export function connect(get, send) {
35
+ export function connect(state, send) {
36
36
  return {
37
37
  root: {
38
38
  role: 'checkbox',
39
- 'aria-checked': (s) => ariaChecked(get(s).checked),
40
- 'aria-disabled': (s) => (get(s).disabled ? 'true' : undefined),
41
- 'aria-required': (s) => (get(s).required ? 'true' : undefined),
42
- 'data-state': (s) => dataState(get(s).checked),
43
- 'data-disabled': (s) => (get(s).disabled ? '' : undefined),
39
+ 'aria-checked': state.map((s) => ariaChecked(s.checked)),
40
+ 'aria-disabled': state.map((s) => (s.disabled ? 'true' : undefined)),
41
+ 'aria-required': state.map((s) => (s.required ? 'true' : undefined)),
42
+ 'data-state': state.map((s) => dataState(s.checked)),
43
+ 'data-disabled': state.map((s) => (s.disabled ? '' : undefined)),
44
44
  'data-scope': 'checkbox',
45
45
  'data-part': 'root',
46
- tabIndex: (s) => (get(s).disabled ? -1 : 0),
46
+ tabIndex: state.map((s) => (s.disabled ? -1 : 0)),
47
47
  onClick: tagSend(send, ['toggle'], () => send({ type: 'toggle' })),
48
48
  onKeyDown: tagSend(send, ['toggle'], (e) => {
49
49
  if (e.key === ' ') {
@@ -57,15 +57,15 @@ export function connect(get, send) {
57
57
  'aria-hidden': 'true',
58
58
  tabIndex: -1,
59
59
  style: HIDDEN_STYLE,
60
- checked: (s) => get(s).checked === true,
61
- indeterminate: (s) => get(s).checked === 'indeterminate',
62
- disabled: (s) => get(s).disabled,
63
- required: (s) => get(s).required,
60
+ checked: state.map((s) => s.checked === true),
61
+ indeterminate: state.map((s) => s.checked === 'indeterminate'),
62
+ disabled: state.map((s) => s.disabled),
63
+ required: state.map((s) => s.required),
64
64
  'data-scope': 'checkbox',
65
65
  'data-part': 'hidden-input',
66
66
  },
67
67
  indicator: {
68
- 'data-state': (s) => dataState(get(s).checked),
68
+ 'data-state': state.map((s) => dataState(s.checked)),
69
69
  'data-scope': 'checkbox',
70
70
  'data-part': 'indicator',
71
71
  },
@@ -1 +1 @@
1
- {"version":3,"file":"checkbox.js","sourceRoot":"","sources":["../../src/components/checkbox.ts"],"names":[],"mappings":"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","sourcesContent":["import { tagSend } from '@llui/dom'\nimport type { Send } from '@llui/dom'\n\n/**\n * Checkbox — a tri-state form control (checked / unchecked / indeterminate).\n * The `indeterminate` state is a visual-only state used to represent \"partial\"\n * selection (e.g. a parent whose children are mixed checked).\n *\n * Rendering typically uses two elements: a visual indicator (the styled box)\n * and a hidden native `<input type=\"checkbox\">` for form participation +\n * accessibility. `connect()` returns props for both.\n */\n\nexport type CheckedState = boolean | 'indeterminate'\n\nexport interface CheckboxState {\n checked: CheckedState\n disabled: boolean\n required: boolean\n}\n\nexport type CheckboxMsg =\n /** @intent(\"Toggle the checkbox between checked and unchecked\") */\n | { type: 'toggle' }\n /** @intent(\"Set the checkbox state to checked, unchecked, or indeterminate\") */\n | { type: 'setChecked'; checked: CheckedState }\n /** @humanOnly */\n | { type: 'setDisabled'; disabled: boolean }\n\nexport interface CheckboxInit {\n checked?: CheckedState\n disabled?: boolean\n required?: boolean\n}\n\nexport function init(opts: CheckboxInit = {}): CheckboxState {\n return {\n checked: opts.checked ?? false,\n disabled: opts.disabled ?? false,\n required: opts.required ?? false,\n }\n}\n\nexport function update(state: CheckboxState, msg: CheckboxMsg): [CheckboxState, never[]] {\n switch (msg.type) {\n case 'toggle':\n if (state.disabled) return [state, []]\n // Tri-state toggle: indeterminate → checked, otherwise flip boolean\n if (state.checked === 'indeterminate') return [{ ...state, checked: true }, []]\n return [{ ...state, checked: !state.checked }, []]\n case 'setChecked':\n return [{ ...state, checked: msg.checked }, []]\n case 'setDisabled':\n return [{ ...state, disabled: msg.disabled }, []]\n }\n}\n\nfunction ariaChecked(c: CheckedState): 'true' | 'false' | 'mixed' {\n if (c === 'indeterminate') return 'mixed'\n return c ? 'true' : 'false'\n}\n\nfunction dataState(c: CheckedState): 'checked' | 'unchecked' | 'indeterminate' {\n if (c === 'indeterminate') return 'indeterminate'\n return c ? 'checked' : 'unchecked'\n}\n\nexport interface CheckboxParts<S> {\n /** The visual box/container — `role=\"checkbox\"` for accessibility. */\n root: {\n role: 'checkbox'\n 'aria-checked': (s: S) => 'true' | 'false' | 'mixed'\n 'aria-disabled': (s: S) => 'true' | undefined\n 'aria-required': (s: S) => 'true' | undefined\n 'data-state': (s: S) => 'checked' | 'unchecked' | 'indeterminate'\n 'data-disabled': (s: S) => '' | undefined\n 'data-scope': 'checkbox'\n 'data-part': 'root'\n tabIndex: (s: S) => number\n onClick: (e: MouseEvent) => void\n onKeyDown: (e: KeyboardEvent) => void\n }\n /** A native hidden input for form participation. */\n hiddenInput: {\n type: 'checkbox'\n 'aria-hidden': 'true'\n tabIndex: -1\n style: string\n checked: (s: S) => boolean\n indeterminate: (s: S) => boolean\n disabled: (s: S) => boolean\n required: (s: S) => boolean\n 'data-scope': 'checkbox'\n 'data-part': 'hidden-input'\n }\n /** Optional indicator child (the checkmark). */\n indicator: {\n 'data-state': (s: S) => 'checked' | 'unchecked' | 'indeterminate'\n 'data-scope': 'checkbox'\n 'data-part': 'indicator'\n }\n}\n\nconst HIDDEN_STYLE =\n 'position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;'\n\nexport function connect<S>(\n get: (s: S) => CheckboxState,\n send: Send<CheckboxMsg>,\n): CheckboxParts<S> {\n return {\n root: {\n role: 'checkbox',\n 'aria-checked': (s) => ariaChecked(get(s).checked),\n 'aria-disabled': (s) => (get(s).disabled ? 'true' : undefined),\n 'aria-required': (s) => (get(s).required ? 'true' : undefined),\n 'data-state': (s) => dataState(get(s).checked),\n 'data-disabled': (s) => (get(s).disabled ? '' : undefined),\n 'data-scope': 'checkbox',\n 'data-part': 'root',\n tabIndex: (s) => (get(s).disabled ? -1 : 0),\n onClick: tagSend(send, ['toggle'], () => send({ type: 'toggle' })),\n onKeyDown: tagSend(send, ['toggle'], (e: KeyboardEvent) => {\n if (e.key === ' ') {\n e.preventDefault()\n send({ type: 'toggle' })\n }\n }),\n },\n hiddenInput: {\n type: 'checkbox',\n 'aria-hidden': 'true',\n tabIndex: -1,\n style: HIDDEN_STYLE,\n checked: (s) => get(s).checked === true,\n indeterminate: (s) => get(s).checked === 'indeterminate',\n disabled: (s) => get(s).disabled,\n required: (s) => get(s).required,\n 'data-scope': 'checkbox',\n 'data-part': 'hidden-input',\n },\n indicator: {\n 'data-state': (s) => dataState(get(s).checked),\n 'data-scope': 'checkbox',\n 'data-part': 'indicator',\n },\n }\n}\n\nexport const checkbox = { init, update, connect }\n"]}
1
+ {"version":3,"file":"checkbox.js","sourceRoot":"","sources":["../../src/components/checkbox.ts"],"names":[],"mappings":"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","sourcesContent":["import { tagSend } from '@llui/dom'\nimport type { Send, Signal } from '@llui/dom'\n\n/**\n * Checkbox — a tri-state form control (checked / unchecked / indeterminate).\n * The `indeterminate` state is a visual-only state used to represent \"partial\"\n * selection (e.g. a parent whose children are mixed checked).\n *\n * Rendering typically uses two elements: a visual indicator (the styled box)\n * and a hidden native `<input type=\"checkbox\">` for form participation +\n * accessibility. `connect()` returns props for both.\n */\n\nexport type CheckedState = boolean | 'indeterminate'\n\nexport interface CheckboxState {\n checked: CheckedState\n disabled: boolean\n required: boolean\n}\n\nexport type CheckboxMsg =\n /** @intent(\"Toggle the checkbox between checked and unchecked\") */\n | { type: 'toggle' }\n /** @intent(\"Set the checkbox state to checked, unchecked, or indeterminate\") */\n | { type: 'setChecked'; checked: CheckedState }\n /** @humanOnly */\n | { type: 'setDisabled'; disabled: boolean }\n\nexport interface CheckboxInit {\n checked?: CheckedState\n disabled?: boolean\n required?: boolean\n}\n\nexport function init(opts: CheckboxInit = {}): CheckboxState {\n return {\n checked: opts.checked ?? false,\n disabled: opts.disabled ?? false,\n required: opts.required ?? false,\n }\n}\n\nexport function update(state: CheckboxState, msg: CheckboxMsg): [CheckboxState, never[]] {\n switch (msg.type) {\n case 'toggle':\n if (state.disabled) return [state, []]\n // Tri-state toggle: indeterminate → checked, otherwise flip boolean\n if (state.checked === 'indeterminate') return [{ ...state, checked: true }, []]\n return [{ ...state, checked: !state.checked }, []]\n case 'setChecked':\n return [{ ...state, checked: msg.checked }, []]\n case 'setDisabled':\n return [{ ...state, disabled: msg.disabled }, []]\n }\n}\n\nfunction ariaChecked(c: CheckedState): 'true' | 'false' | 'mixed' {\n if (c === 'indeterminate') return 'mixed'\n return c ? 'true' : 'false'\n}\n\nfunction dataState(c: CheckedState): 'checked' | 'unchecked' | 'indeterminate' {\n if (c === 'indeterminate') return 'indeterminate'\n return c ? 'checked' : 'unchecked'\n}\n\nexport interface CheckboxParts {\n /** The visual box/container — `role=\"checkbox\"` for accessibility. */\n root: {\n role: 'checkbox'\n 'aria-checked': Signal<'true' | 'false' | 'mixed'>\n 'aria-disabled': Signal<'true' | undefined>\n 'aria-required': Signal<'true' | undefined>\n 'data-state': Signal<'checked' | 'unchecked' | 'indeterminate'>\n 'data-disabled': Signal<'' | undefined>\n 'data-scope': 'checkbox'\n 'data-part': 'root'\n tabIndex: Signal<number>\n onClick: (e: MouseEvent) => void\n onKeyDown: (e: KeyboardEvent) => void\n }\n /** A native hidden input for form participation. */\n hiddenInput: {\n type: 'checkbox'\n 'aria-hidden': 'true'\n tabIndex: -1\n style: string\n checked: Signal<boolean>\n indeterminate: Signal<boolean>\n disabled: Signal<boolean>\n required: Signal<boolean>\n 'data-scope': 'checkbox'\n 'data-part': 'hidden-input'\n }\n /** Optional indicator child (the checkmark). */\n indicator: {\n 'data-state': Signal<'checked' | 'unchecked' | 'indeterminate'>\n 'data-scope': 'checkbox'\n 'data-part': 'indicator'\n }\n}\n\nconst HIDDEN_STYLE =\n 'position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;'\n\nexport function connect(state: Signal<CheckboxState>, send: Send<CheckboxMsg>): CheckboxParts {\n return {\n root: {\n role: 'checkbox',\n 'aria-checked': state.map((s) => ariaChecked(s.checked)),\n 'aria-disabled': state.map((s) => (s.disabled ? 'true' : undefined)),\n 'aria-required': state.map((s) => (s.required ? 'true' : undefined)),\n 'data-state': state.map((s) => dataState(s.checked)),\n 'data-disabled': state.map((s) => (s.disabled ? '' : undefined)),\n 'data-scope': 'checkbox',\n 'data-part': 'root',\n tabIndex: state.map((s) => (s.disabled ? -1 : 0)),\n onClick: tagSend(send, ['toggle'], () => send({ type: 'toggle' })),\n onKeyDown: tagSend(send, ['toggle'], (e: KeyboardEvent) => {\n if (e.key === ' ') {\n e.preventDefault()\n send({ type: 'toggle' })\n }\n }),\n },\n hiddenInput: {\n type: 'checkbox',\n 'aria-hidden': 'true',\n tabIndex: -1,\n style: HIDDEN_STYLE,\n checked: state.map((s) => s.checked === true),\n indeterminate: state.map((s) => s.checked === 'indeterminate'),\n disabled: state.map((s) => s.disabled),\n required: state.map((s) => s.required),\n 'data-scope': 'checkbox',\n 'data-part': 'hidden-input',\n },\n indicator: {\n 'data-state': state.map((s) => dataState(s.checked)),\n 'data-scope': 'checkbox',\n 'data-part': 'indicator',\n },\n }\n}\n\nexport const checkbox = { 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
  * Clipboard — copy-to-clipboard with transient "copied" feedback. The
4
4
  * actual clipboard write is performed by the consumer via an effect (or
@@ -37,24 +37,24 @@ export declare function update(state: ClipboardState, msg: ClipboardMsg): [Clipb
37
37
  * on success. Consumer dispatches `copied` or `reset` based on the result.
38
38
  */
39
39
  export declare function copyToClipboard(value: string): Promise<void>;
40
- export interface ClipboardParts<S> {
40
+ export interface ClipboardParts {
41
41
  root: {
42
42
  'data-scope': 'clipboard';
43
43
  'data-part': 'root';
44
- 'data-copied': (s: S) => '' | undefined;
44
+ 'data-copied': Signal<'' | undefined>;
45
45
  };
46
46
  trigger: {
47
47
  type: 'button';
48
- 'aria-label': string | ((s: S) => string);
48
+ 'aria-label': string;
49
49
  'data-scope': 'clipboard';
50
50
  'data-part': 'trigger';
51
- 'data-copied': (s: S) => '' | undefined;
51
+ 'data-copied': Signal<'' | undefined>;
52
52
  onClick: (e: MouseEvent) => void;
53
53
  };
54
54
  input: {
55
55
  type: 'text';
56
56
  readOnly: true;
57
- value: (s: S) => string;
57
+ value: Signal<string>;
58
58
  'data-scope': 'clipboard';
59
59
  'data-part': 'input';
60
60
  onFocus: (e: FocusEvent) => void;
@@ -62,7 +62,7 @@ export interface ClipboardParts<S> {
62
62
  indicator: {
63
63
  'data-scope': 'clipboard';
64
64
  'data-part': 'indicator';
65
- 'data-copied': (s: S) => '' | undefined;
65
+ 'data-copied': Signal<'' | undefined>;
66
66
  'aria-live': 'polite';
67
67
  };
68
68
  }
@@ -70,7 +70,7 @@ export interface ConnectOptions {
70
70
  copyLabel?: string;
71
71
  onCopy?: (value: string) => void;
72
72
  }
73
- export declare function connect<S>(get: (s: S) => ClipboardState, send: Send<ClipboardMsg>, opts?: ConnectOptions): ClipboardParts<S>;
73
+ export declare function connect(state: Signal<ClipboardState>, send: Send<ClipboardMsg>, opts?: ConnectOptions): ClipboardParts;
74
74
  export declare const clipboard: {
75
75
  init: typeof init;
76
76
  update: typeof update;
@@ -1 +1 @@
1
- {"version":3,"file":"clipboard.d.ts","sourceRoot":"","sources":["../../src/components/clipboard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAKrC;;;;;GAKG;AAEH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,OAAO,CAAA;CAChB;AAED,MAAM,MAAM,YAAY;AACtB,+CAA+C;AAC7C;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE;AACrC,gEAAgE;GAC9D;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE;AAClB,iBAAiB;GACf;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE;AACpB,+DAA+D;GAC7D;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAA;AAErB,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,wBAAgB,IAAI,CAAC,IAAI,GAAE,aAAkB,GAAG,cAAc,CAE7D;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,YAAY,GAAG,CAAC,cAAc,EAAE,KAAK,EAAE,CAAC,CAU1F;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBlE;AAED,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,IAAI,EAAE;QACJ,YAAY,EAAE,WAAW,CAAA;QACzB,WAAW,EAAE,MAAM,CAAA;QACnB,aAAa,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,SAAS,CAAA;KACxC,CAAA;IACD,OAAO,EAAE;QACP,IAAI,EAAE,QAAQ,CAAA;QACd,YAAY,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAC,CAAA;QACzC,YAAY,EAAE,WAAW,CAAA;QACzB,WAAW,EAAE,SAAS,CAAA;QACtB,aAAa,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,SAAS,CAAA;QACvC,OAAO,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAA;KACjC,CAAA;IACD,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAA;QACZ,QAAQ,EAAE,IAAI,CAAA;QACd,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;QACvB,YAAY,EAAE,WAAW,CAAA;QACzB,WAAW,EAAE,OAAO,CAAA;QACpB,OAAO,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAA;KACjC,CAAA;IACD,SAAS,EAAE;QACT,YAAY,EAAE,WAAW,CAAA;QACzB,WAAW,EAAE,WAAW,CAAA;QACxB,aAAa,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,SAAS,CAAA;QACvC,WAAW,EAAE,QAAQ,CAAA;KACtB,CAAA;CACF;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CACjC;AAED,wBAAgB,OAAO,CAAC,CAAC,EACvB,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,cAAc,EAC7B,IAAI,EAAE,IAAI,CAAC,YAAY,CAAC,EACxB,IAAI,GAAE,cAAmB,GACxB,cAAc,CAAC,CAAC,CAAC,CAoCnB;AAED,eAAO,MAAM,SAAS;;;;;CAA6C,CAAA"}
1
+ {"version":3,"file":"clipboard.d.ts","sourceRoot":"","sources":["../../src/components/clipboard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAI7C;;;;;GAKG;AAEH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,OAAO,CAAA;CAChB;AAED,MAAM,MAAM,YAAY;AACtB,+CAA+C;AAC7C;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE;AACrC,gEAAgE;GAC9D;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE;AAClB,iBAAiB;GACf;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE;AACpB,+DAA+D;GAC7D;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAA;AAErB,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,wBAAgB,IAAI,CAAC,IAAI,GAAE,aAAkB,GAAG,cAAc,CAE7D;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,YAAY,GAAG,CAAC,cAAc,EAAE,KAAK,EAAE,CAAC,CAU1F;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBlE;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE;QACJ,YAAY,EAAE,WAAW,CAAA;QACzB,WAAW,EAAE,MAAM,CAAA;QACnB,aAAa,EAAE,MAAM,CAAC,EAAE,GAAG,SAAS,CAAC,CAAA;KACtC,CAAA;IACD,OAAO,EAAE;QACP,IAAI,EAAE,QAAQ,CAAA;QACd,YAAY,EAAE,MAAM,CAAA;QACpB,YAAY,EAAE,WAAW,CAAA;QACzB,WAAW,EAAE,SAAS,CAAA;QACtB,aAAa,EAAE,MAAM,CAAC,EAAE,GAAG,SAAS,CAAC,CAAA;QACrC,OAAO,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAA;KACjC,CAAA;IACD,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAA;QACZ,QAAQ,EAAE,IAAI,CAAA;QACd,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAA;QACrB,YAAY,EAAE,WAAW,CAAA;QACzB,WAAW,EAAE,OAAO,CAAA;QACpB,OAAO,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAA;KACjC,CAAA;IACD,SAAS,EAAE;QACT,YAAY,EAAE,WAAW,CAAA;QACzB,WAAW,EAAE,WAAW,CAAA;QACxB,aAAa,EAAE,MAAM,CAAC,EAAE,GAAG,SAAS,CAAC,CAAA;QACrC,WAAW,EAAE,QAAQ,CAAA;KACtB,CAAA;CACF;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CACjC;AAED,wBAAgB,OAAO,CACrB,KAAK,EAAE,MAAM,CAAC,cAAc,CAAC,EAC7B,IAAI,EAAE,IAAI,CAAC,YAAY,CAAC,EACxB,IAAI,GAAE,cAAmB,GACxB,cAAc,CAmChB;AAED,eAAO,MAAM,SAAS;;;;;CAA6C,CAAA"}
@@ -37,21 +37,21 @@ export async function copyToClipboard(value) {
37
37
  document.body.removeChild(textarea);
38
38
  }
39
39
  }
40
- export function connect(get, send, opts = {}) {
40
+ export function connect(state, send, opts = {}) {
41
41
  const locale = useContext(LocaleContext);
42
- const copyLabel = opts.copyLabel ?? ((s) => locale(s).clipboard.copy);
42
+ const copyLabel = opts.copyLabel ?? locale.clipboard.copy;
43
43
  return {
44
44
  root: {
45
45
  'data-scope': 'clipboard',
46
46
  'data-part': 'root',
47
- 'data-copied': (s) => (get(s).copied ? '' : undefined),
47
+ 'data-copied': state.map((s) => (s.copied ? '' : undefined)),
48
48
  },
49
49
  trigger: {
50
50
  type: 'button',
51
51
  'aria-label': copyLabel,
52
52
  'data-scope': 'clipboard',
53
53
  'data-part': 'trigger',
54
- 'data-copied': (s) => (get(s).copied ? '' : undefined),
54
+ 'data-copied': state.map((s) => (s.copied ? '' : undefined)),
55
55
  onClick: tagSend(send, ['copy'], () => {
56
56
  send({ type: 'copy' });
57
57
  opts.onCopy?.('');
@@ -60,7 +60,7 @@ export function connect(get, send, opts = {}) {
60
60
  input: {
61
61
  type: 'text',
62
62
  readOnly: true,
63
- value: (s) => get(s).value,
63
+ value: state.map((s) => s.value),
64
64
  'data-scope': 'clipboard',
65
65
  'data-part': 'input',
66
66
  onFocus: (e) => e.currentTarget.select(),
@@ -68,7 +68,7 @@ export function connect(get, send, opts = {}) {
68
68
  indicator: {
69
69
  'data-scope': 'clipboard',
70
70
  'data-part': 'indicator',
71
- 'data-copied': (s) => (get(s).copied ? '' : undefined),
71
+ 'data-copied': state.map((s) => (s.copied ? '' : undefined)),
72
72
  'aria-live': 'polite',
73
73
  },
74
74
  };
@@ -1 +1 @@
1
- {"version":3,"file":"clipboard.js","sourceRoot":"","sources":["../../src/components/clipboard.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 * Clipboard — copy-to-clipboard with transient \"copied\" feedback. The\n * actual clipboard write is performed by the consumer via an effect (or\n * inline in the trigger's onClick handler). Reducer tracks the success\n * state flag and an auto-reset timestamp.\n */\n\nexport interface ClipboardState {\n value: string\n copied: boolean\n}\n\nexport type ClipboardMsg =\n /** @intent(\"Update the value to be copied\") */\n | { type: 'setValue'; value: string }\n /** @intent(\"Initiate a clipboard copy of the current value\") */\n | { type: 'copy' }\n /** @humanOnly */\n | { type: 'copied' }\n /** @intent(\"Clear the transient \\\"copied\\\" feedback state\") */\n | { type: 'reset' }\n\nexport interface ClipboardInit {\n value?: string\n}\n\nexport function init(opts: ClipboardInit = {}): ClipboardState {\n return { value: opts.value ?? '', copied: false }\n}\n\nexport function update(state: ClipboardState, msg: ClipboardMsg): [ClipboardState, never[]] {\n switch (msg.type) {\n case 'setValue':\n return [{ ...state, value: msg.value, copied: false }, []]\n case 'copy':\n case 'copied':\n return [{ ...state, copied: true }, []]\n case 'reset':\n return [{ ...state, copied: false }, []]\n }\n}\n\n/**\n * Attempt to copy the value to the clipboard. Returns a Promise that resolves\n * on success. Consumer dispatches `copied` or `reset` based on the result.\n */\nexport async function copyToClipboard(value: string): Promise<void> {\n if (typeof navigator !== 'undefined' && navigator.clipboard?.writeText) {\n await navigator.clipboard.writeText(value)\n return\n }\n // Fallback: ephemeral textarea\n const textarea = document.createElement('textarea')\n textarea.value = value\n textarea.style.position = 'fixed'\n textarea.style.opacity = '0'\n document.body.appendChild(textarea)\n textarea.select()\n try {\n document.execCommand('copy')\n } finally {\n document.body.removeChild(textarea)\n }\n}\n\nexport interface ClipboardParts<S> {\n root: {\n 'data-scope': 'clipboard'\n 'data-part': 'root'\n 'data-copied': (s: S) => '' | undefined\n }\n trigger: {\n type: 'button'\n 'aria-label': string | ((s: S) => string)\n 'data-scope': 'clipboard'\n 'data-part': 'trigger'\n 'data-copied': (s: S) => '' | undefined\n onClick: (e: MouseEvent) => void\n }\n input: {\n type: 'text'\n readOnly: true\n value: (s: S) => string\n 'data-scope': 'clipboard'\n 'data-part': 'input'\n onFocus: (e: FocusEvent) => void\n }\n indicator: {\n 'data-scope': 'clipboard'\n 'data-part': 'indicator'\n 'data-copied': (s: S) => '' | undefined\n 'aria-live': 'polite'\n }\n}\n\nexport interface ConnectOptions {\n copyLabel?: string\n onCopy?: (value: string) => void\n}\n\nexport function connect<S>(\n get: (s: S) => ClipboardState,\n send: Send<ClipboardMsg>,\n opts: ConnectOptions = {},\n): ClipboardParts<S> {\n const locale = useContext<S, Locale>(LocaleContext)\n const copyLabel: string | ((s: S) => string) =\n opts.copyLabel ?? ((s: S) => locale(s).clipboard.copy)\n return {\n root: {\n 'data-scope': 'clipboard',\n 'data-part': 'root',\n 'data-copied': (s) => (get(s).copied ? '' : undefined),\n },\n trigger: {\n type: 'button',\n 'aria-label': copyLabel,\n 'data-scope': 'clipboard',\n 'data-part': 'trigger',\n 'data-copied': (s) => (get(s).copied ? '' : undefined),\n onClick: tagSend(send, ['copy'], () => {\n send({ type: 'copy' })\n opts.onCopy?.('')\n }),\n },\n input: {\n type: 'text',\n readOnly: true,\n value: (s) => get(s).value,\n 'data-scope': 'clipboard',\n 'data-part': 'input',\n onFocus: (e) => (e.currentTarget as HTMLInputElement).select(),\n },\n indicator: {\n 'data-scope': 'clipboard',\n 'data-part': 'indicator',\n 'data-copied': (s) => (get(s).copied ? '' : undefined),\n 'aria-live': 'polite',\n },\n }\n}\n\nexport const clipboard = { init, update, connect, copyToClipboard }\n"]}
1
+ {"version":3,"file":"clipboard.js","sourceRoot":"","sources":["../../src/components/clipboard.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 * Clipboard — copy-to-clipboard with transient \"copied\" feedback. The\n * actual clipboard write is performed by the consumer via an effect (or\n * inline in the trigger's onClick handler). Reducer tracks the success\n * state flag and an auto-reset timestamp.\n */\n\nexport interface ClipboardState {\n value: string\n copied: boolean\n}\n\nexport type ClipboardMsg =\n /** @intent(\"Update the value to be copied\") */\n | { type: 'setValue'; value: string }\n /** @intent(\"Initiate a clipboard copy of the current value\") */\n | { type: 'copy' }\n /** @humanOnly */\n | { type: 'copied' }\n /** @intent(\"Clear the transient \\\"copied\\\" feedback state\") */\n | { type: 'reset' }\n\nexport interface ClipboardInit {\n value?: string\n}\n\nexport function init(opts: ClipboardInit = {}): ClipboardState {\n return { value: opts.value ?? '', copied: false }\n}\n\nexport function update(state: ClipboardState, msg: ClipboardMsg): [ClipboardState, never[]] {\n switch (msg.type) {\n case 'setValue':\n return [{ ...state, value: msg.value, copied: false }, []]\n case 'copy':\n case 'copied':\n return [{ ...state, copied: true }, []]\n case 'reset':\n return [{ ...state, copied: false }, []]\n }\n}\n\n/**\n * Attempt to copy the value to the clipboard. Returns a Promise that resolves\n * on success. Consumer dispatches `copied` or `reset` based on the result.\n */\nexport async function copyToClipboard(value: string): Promise<void> {\n if (typeof navigator !== 'undefined' && navigator.clipboard?.writeText) {\n await navigator.clipboard.writeText(value)\n return\n }\n // Fallback: ephemeral textarea\n const textarea = document.createElement('textarea')\n textarea.value = value\n textarea.style.position = 'fixed'\n textarea.style.opacity = '0'\n document.body.appendChild(textarea)\n textarea.select()\n try {\n document.execCommand('copy')\n } finally {\n document.body.removeChild(textarea)\n }\n}\n\nexport interface ClipboardParts {\n root: {\n 'data-scope': 'clipboard'\n 'data-part': 'root'\n 'data-copied': Signal<'' | undefined>\n }\n trigger: {\n type: 'button'\n 'aria-label': string\n 'data-scope': 'clipboard'\n 'data-part': 'trigger'\n 'data-copied': Signal<'' | undefined>\n onClick: (e: MouseEvent) => void\n }\n input: {\n type: 'text'\n readOnly: true\n value: Signal<string>\n 'data-scope': 'clipboard'\n 'data-part': 'input'\n onFocus: (e: FocusEvent) => void\n }\n indicator: {\n 'data-scope': 'clipboard'\n 'data-part': 'indicator'\n 'data-copied': Signal<'' | undefined>\n 'aria-live': 'polite'\n }\n}\n\nexport interface ConnectOptions {\n copyLabel?: string\n onCopy?: (value: string) => void\n}\n\nexport function connect(\n state: Signal<ClipboardState>,\n send: Send<ClipboardMsg>,\n opts: ConnectOptions = {},\n): ClipboardParts {\n const locale = useContext(LocaleContext)\n const copyLabel = opts.copyLabel ?? locale.clipboard.copy\n return {\n root: {\n 'data-scope': 'clipboard',\n 'data-part': 'root',\n 'data-copied': state.map((s) => (s.copied ? '' : undefined)),\n },\n trigger: {\n type: 'button',\n 'aria-label': copyLabel,\n 'data-scope': 'clipboard',\n 'data-part': 'trigger',\n 'data-copied': state.map((s) => (s.copied ? '' : undefined)),\n onClick: tagSend(send, ['copy'], () => {\n send({ type: 'copy' })\n opts.onCopy?.('')\n }),\n },\n input: {\n type: 'text',\n readOnly: true,\n value: state.map((s) => s.value),\n 'data-scope': 'clipboard',\n 'data-part': 'input',\n onFocus: (e) => (e.currentTarget as HTMLInputElement).select(),\n },\n indicator: {\n 'data-scope': 'clipboard',\n 'data-part': 'indicator',\n 'data-copied': state.map((s) => (s.copied ? '' : undefined)),\n 'aria-live': 'polite',\n },\n }\n}\n\nexport const clipboard = { init, update, connect, copyToClipboard }\n"]}
@@ -1,4 +1,4 @@
1
- import type { Send } from '@llui/dom';
1
+ import type { Send, Signal } from '@llui/dom';
2
2
  /**
3
3
  * Collapsible — a single expandable/collapsible section. Simpler than
4
4
  * accordion (no grouping, no keyboard navigation between siblings).
@@ -31,21 +31,21 @@ export interface CollapsibleInit {
31
31
  }
32
32
  export declare function init(opts?: CollapsibleInit): CollapsibleState;
33
33
  export declare function update(state: CollapsibleState, msg: CollapsibleMsg): [CollapsibleState, never[]];
34
- export interface CollapsibleParts<S> {
34
+ export interface CollapsibleParts {
35
35
  root: {
36
- 'data-state': (s: S) => 'open' | 'closed';
37
- 'data-disabled': (s: S) => '' | undefined;
36
+ 'data-state': Signal<'open' | 'closed'>;
37
+ 'data-disabled': Signal<'' | undefined>;
38
38
  'data-scope': 'collapsible';
39
39
  'data-part': 'root';
40
40
  };
41
41
  trigger: {
42
42
  type: 'button';
43
- 'aria-expanded': (s: S) => boolean;
43
+ 'aria-expanded': Signal<boolean>;
44
44
  'aria-controls': string;
45
45
  id: string;
46
- disabled: (s: S) => boolean;
47
- 'data-state': (s: S) => 'open' | 'closed';
48
- 'data-disabled': (s: S) => '' | undefined;
46
+ disabled: Signal<boolean>;
47
+ 'data-state': Signal<'open' | 'closed'>;
48
+ 'data-disabled': Signal<'' | undefined>;
49
49
  'data-scope': 'collapsible';
50
50
  'data-part': 'trigger';
51
51
  onClick: (e: MouseEvent) => void;
@@ -54,8 +54,8 @@ export interface CollapsibleParts<S> {
54
54
  role: 'region';
55
55
  id: string;
56
56
  'aria-labelledby': string;
57
- hidden: (s: S) => boolean;
58
- 'data-state': (s: S) => 'open' | 'closed';
57
+ hidden: Signal<boolean>;
58
+ 'data-state': Signal<'open' | 'closed'>;
59
59
  'data-scope': 'collapsible';
60
60
  'data-part': 'content';
61
61
  };
@@ -63,7 +63,7 @@ export interface CollapsibleParts<S> {
63
63
  export interface ConnectOptions {
64
64
  id: string;
65
65
  }
66
- export declare function connect<S>(get: (s: S) => CollapsibleState, send: Send<CollapsibleMsg>, opts: ConnectOptions): CollapsibleParts<S>;
66
+ export declare function connect(state: Signal<CollapsibleState>, send: Send<CollapsibleMsg>, opts: ConnectOptions): CollapsibleParts;
67
67
  export declare const collapsible: {
68
68
  init: typeof init;
69
69
  update: typeof update;
@@ -1 +1 @@
1
- {"version":3,"file":"collapsible.d.ts","sourceRoot":"","sources":["../../src/components/collapsible.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAErC;;;GAGG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,OAAO,CAAA;IACb,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,MAAM,cAAc;AACxB,0DAA0D;AACxD;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE;AACpB,8CAA8C;GAC5C;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE;AAClB,oCAAoC;GAClC;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE;AACnB,gEAAgE;GAC9D;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAA;AAEtC,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,wBAAgB,IAAI,CAAC,IAAI,GAAE,eAAoB,GAAG,gBAAgB,CAEjE;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,gBAAgB,EAAE,GAAG,EAAE,cAAc,GAAG,CAAC,gBAAgB,EAAE,KAAK,EAAE,CAAC,CAYhG;AAED,MAAM,WAAW,gBAAgB,CAAC,CAAC;IACjC,IAAI,EAAE;QACJ,YAAY,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,GAAG,QAAQ,CAAA;QACzC,eAAe,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,SAAS,CAAA;QACzC,YAAY,EAAE,aAAa,CAAA;QAC3B,WAAW,EAAE,MAAM,CAAA;KACpB,CAAA;IACD,OAAO,EAAE;QACP,IAAI,EAAE,QAAQ,CAAA;QACd,eAAe,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,OAAO,CAAA;QAClC,eAAe,EAAE,MAAM,CAAA;QACvB,EAAE,EAAE,MAAM,CAAA;QACV,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,OAAO,CAAA;QAC3B,YAAY,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,GAAG,QAAQ,CAAA;QACzC,eAAe,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,SAAS,CAAA;QACzC,YAAY,EAAE,aAAa,CAAA;QAC3B,WAAW,EAAE,SAAS,CAAA;QACtB,OAAO,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAA;KACjC,CAAA;IACD,OAAO,EAAE;QACP,IAAI,EAAE,QAAQ,CAAA;QACd,EAAE,EAAE,MAAM,CAAA;QACV,iBAAiB,EAAE,MAAM,CAAA;QACzB,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,OAAO,CAAA;QACzB,YAAY,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,GAAG,QAAQ,CAAA;QACzC,YAAY,EAAE,aAAa,CAAA;QAC3B,WAAW,EAAE,SAAS,CAAA;KACvB,CAAA;CACF;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAA;CACX;AAED,wBAAgB,OAAO,CAAC,CAAC,EACvB,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,gBAAgB,EAC/B,IAAI,EAAE,IAAI,CAAC,cAAc,CAAC,EAC1B,IAAI,EAAE,cAAc,GACnB,gBAAgB,CAAC,CAAC,CAAC,CAiCrB;AAED,eAAO,MAAM,WAAW;;;;CAA4B,CAAA"}
1
+ {"version":3,"file":"collapsible.d.ts","sourceRoot":"","sources":["../../src/components/collapsible.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAE7C;;;GAGG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,OAAO,CAAA;IACb,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,MAAM,cAAc;AACxB,0DAA0D;AACxD;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE;AACpB,8CAA8C;GAC5C;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE;AAClB,oCAAoC;GAClC;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE;AACnB,gEAAgE;GAC9D;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAA;AAEtC,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,wBAAgB,IAAI,CAAC,IAAI,GAAE,eAAoB,GAAG,gBAAgB,CAEjE;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,gBAAgB,EAAE,GAAG,EAAE,cAAc,GAAG,CAAC,gBAAgB,EAAE,KAAK,EAAE,CAAC,CAYhG;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE;QACJ,YAAY,EAAE,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC,CAAA;QACvC,eAAe,EAAE,MAAM,CAAC,EAAE,GAAG,SAAS,CAAC,CAAA;QACvC,YAAY,EAAE,aAAa,CAAA;QAC3B,WAAW,EAAE,MAAM,CAAA;KACpB,CAAA;IACD,OAAO,EAAE;QACP,IAAI,EAAE,QAAQ,CAAA;QACd,eAAe,EAAE,MAAM,CAAC,OAAO,CAAC,CAAA;QAChC,eAAe,EAAE,MAAM,CAAA;QACvB,EAAE,EAAE,MAAM,CAAA;QACV,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,CAAA;QACzB,YAAY,EAAE,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC,CAAA;QACvC,eAAe,EAAE,MAAM,CAAC,EAAE,GAAG,SAAS,CAAC,CAAA;QACvC,YAAY,EAAE,aAAa,CAAA;QAC3B,WAAW,EAAE,SAAS,CAAA;QACtB,OAAO,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAA;KACjC,CAAA;IACD,OAAO,EAAE;QACP,IAAI,EAAE,QAAQ,CAAA;QACd,EAAE,EAAE,MAAM,CAAA;QACV,iBAAiB,EAAE,MAAM,CAAA;QACzB,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAA;QACvB,YAAY,EAAE,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC,CAAA;QACvC,YAAY,EAAE,aAAa,CAAA;QAC3B,WAAW,EAAE,SAAS,CAAA;KACvB,CAAA;CACF;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAA;CACX;AAED,wBAAgB,OAAO,CACrB,KAAK,EAAE,MAAM,CAAC,gBAAgB,CAAC,EAC/B,IAAI,EAAE,IAAI,CAAC,cAAc,CAAC,EAC1B,IAAI,EAAE,cAAc,GACnB,gBAAgB,CAiClB;AAED,eAAO,MAAM,WAAW;;;;CAA4B,CAAA"}
@@ -16,24 +16,24 @@ export function update(state, msg) {
16
16
  return [{ ...state, open: msg.open }, []];
17
17
  }
18
18
  }
19
- export function connect(get, send, opts) {
19
+ export function connect(state, send, opts) {
20
20
  const triggerId = `${opts.id}:trigger`;
21
21
  const contentId = `${opts.id}:content`;
22
22
  return {
23
23
  root: {
24
- 'data-state': (s) => (get(s).open ? 'open' : 'closed'),
25
- 'data-disabled': (s) => (get(s).disabled ? '' : undefined),
24
+ 'data-state': state.map((s) => (s.open ? 'open' : 'closed')),
25
+ 'data-disabled': state.map((s) => (s.disabled ? '' : undefined)),
26
26
  'data-scope': 'collapsible',
27
27
  'data-part': 'root',
28
28
  },
29
29
  trigger: {
30
30
  type: 'button',
31
- 'aria-expanded': (s) => get(s).open,
31
+ 'aria-expanded': state.map((s) => s.open),
32
32
  'aria-controls': contentId,
33
33
  id: triggerId,
34
- disabled: (s) => get(s).disabled,
35
- 'data-state': (s) => (get(s).open ? 'open' : 'closed'),
36
- 'data-disabled': (s) => (get(s).disabled ? '' : undefined),
34
+ disabled: state.map((s) => s.disabled),
35
+ 'data-state': state.map((s) => (s.open ? 'open' : 'closed')),
36
+ 'data-disabled': state.map((s) => (s.disabled ? '' : undefined)),
37
37
  'data-scope': 'collapsible',
38
38
  'data-part': 'trigger',
39
39
  onClick: tagSend(send, ['toggle'], () => send({ type: 'toggle' })),
@@ -42,8 +42,8 @@ export function connect(get, send, opts) {
42
42
  role: 'region',
43
43
  id: contentId,
44
44
  'aria-labelledby': triggerId,
45
- hidden: (s) => !get(s).open,
46
- 'data-state': (s) => (get(s).open ? 'open' : 'closed'),
45
+ hidden: state.map((s) => !s.open),
46
+ 'data-state': state.map((s) => (s.open ? 'open' : 'closed')),
47
47
  'data-scope': 'collapsible',
48
48
  'data-part': 'content',
49
49
  },
@@ -1 +1 @@
1
- {"version":3,"file":"collapsible.js","sourceRoot":"","sources":["../../src/components/collapsible.ts"],"names":[],"mappings":"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","sourcesContent":["import { tagSend } from '@llui/dom'\nimport type { Send } from '@llui/dom'\n\n/**\n * Collapsible — a single expandable/collapsible section. Simpler than\n * accordion (no grouping, no keyboard navigation between siblings).\n */\n\nexport interface CollapsibleState {\n open: boolean\n disabled: boolean\n}\n\nexport type CollapsibleMsg =\n /** @intent(\"Toggle the collapsible panel open/closed\") */\n | { type: 'toggle' }\n /** @intent(\"Expand the collapsible panel\") */\n | { type: 'open' }\n /** @intent(\"Collapse the panel\") */\n | { type: 'close' }\n /** @intent(\"Set the panel's open state to a specific value\") */\n | { type: 'setOpen'; open: boolean }\n\nexport interface CollapsibleInit {\n open?: boolean\n disabled?: boolean\n}\n\nexport function init(opts: CollapsibleInit = {}): CollapsibleState {\n return { open: opts.open ?? false, disabled: opts.disabled ?? false }\n}\n\nexport function update(state: CollapsibleState, msg: CollapsibleMsg): [CollapsibleState, never[]] {\n if (state.disabled) return [state, []]\n switch (msg.type) {\n case 'toggle':\n return [{ ...state, open: !state.open }, []]\n case 'open':\n return [{ ...state, open: true }, []]\n case 'close':\n return [{ ...state, open: false }, []]\n case 'setOpen':\n return [{ ...state, open: msg.open }, []]\n }\n}\n\nexport interface CollapsibleParts<S> {\n root: {\n 'data-state': (s: S) => 'open' | 'closed'\n 'data-disabled': (s: S) => '' | undefined\n 'data-scope': 'collapsible'\n 'data-part': 'root'\n }\n trigger: {\n type: 'button'\n 'aria-expanded': (s: S) => boolean\n 'aria-controls': string\n id: string\n disabled: (s: S) => boolean\n 'data-state': (s: S) => 'open' | 'closed'\n 'data-disabled': (s: S) => '' | undefined\n 'data-scope': 'collapsible'\n 'data-part': 'trigger'\n onClick: (e: MouseEvent) => void\n }\n content: {\n role: 'region'\n id: string\n 'aria-labelledby': string\n hidden: (s: S) => boolean\n 'data-state': (s: S) => 'open' | 'closed'\n 'data-scope': 'collapsible'\n 'data-part': 'content'\n }\n}\n\nexport interface ConnectOptions {\n id: string\n}\n\nexport function connect<S>(\n get: (s: S) => CollapsibleState,\n send: Send<CollapsibleMsg>,\n opts: ConnectOptions,\n): CollapsibleParts<S> {\n const triggerId = `${opts.id}:trigger`\n const contentId = `${opts.id}:content`\n\n return {\n root: {\n 'data-state': (s) => (get(s).open ? 'open' : 'closed'),\n 'data-disabled': (s) => (get(s).disabled ? '' : undefined),\n 'data-scope': 'collapsible',\n 'data-part': 'root',\n },\n trigger: {\n type: 'button',\n 'aria-expanded': (s) => get(s).open,\n 'aria-controls': contentId,\n id: triggerId,\n disabled: (s) => get(s).disabled,\n 'data-state': (s) => (get(s).open ? 'open' : 'closed'),\n 'data-disabled': (s) => (get(s).disabled ? '' : undefined),\n 'data-scope': 'collapsible',\n 'data-part': 'trigger',\n onClick: tagSend(send, ['toggle'], () => send({ type: 'toggle' })),\n },\n content: {\n role: 'region',\n id: contentId,\n 'aria-labelledby': triggerId,\n hidden: (s) => !get(s).open,\n 'data-state': (s) => (get(s).open ? 'open' : 'closed'),\n 'data-scope': 'collapsible',\n 'data-part': 'content',\n },\n }\n}\n\nexport const collapsible = { init, update, connect }\n"]}
1
+ {"version":3,"file":"collapsible.js","sourceRoot":"","sources":["../../src/components/collapsible.ts"],"names":[],"mappings":"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","sourcesContent":["import { tagSend } from '@llui/dom'\nimport type { Send, Signal } from '@llui/dom'\n\n/**\n * Collapsible — a single expandable/collapsible section. Simpler than\n * accordion (no grouping, no keyboard navigation between siblings).\n */\n\nexport interface CollapsibleState {\n open: boolean\n disabled: boolean\n}\n\nexport type CollapsibleMsg =\n /** @intent(\"Toggle the collapsible panel open/closed\") */\n | { type: 'toggle' }\n /** @intent(\"Expand the collapsible panel\") */\n | { type: 'open' }\n /** @intent(\"Collapse the panel\") */\n | { type: 'close' }\n /** @intent(\"Set the panel's open state to a specific value\") */\n | { type: 'setOpen'; open: boolean }\n\nexport interface CollapsibleInit {\n open?: boolean\n disabled?: boolean\n}\n\nexport function init(opts: CollapsibleInit = {}): CollapsibleState {\n return { open: opts.open ?? false, disabled: opts.disabled ?? false }\n}\n\nexport function update(state: CollapsibleState, msg: CollapsibleMsg): [CollapsibleState, never[]] {\n if (state.disabled) return [state, []]\n switch (msg.type) {\n case 'toggle':\n return [{ ...state, open: !state.open }, []]\n case 'open':\n return [{ ...state, open: true }, []]\n case 'close':\n return [{ ...state, open: false }, []]\n case 'setOpen':\n return [{ ...state, open: msg.open }, []]\n }\n}\n\nexport interface CollapsibleParts {\n root: {\n 'data-state': Signal<'open' | 'closed'>\n 'data-disabled': Signal<'' | undefined>\n 'data-scope': 'collapsible'\n 'data-part': 'root'\n }\n trigger: {\n type: 'button'\n 'aria-expanded': Signal<boolean>\n 'aria-controls': string\n id: string\n disabled: Signal<boolean>\n 'data-state': Signal<'open' | 'closed'>\n 'data-disabled': Signal<'' | undefined>\n 'data-scope': 'collapsible'\n 'data-part': 'trigger'\n onClick: (e: MouseEvent) => void\n }\n content: {\n role: 'region'\n id: string\n 'aria-labelledby': string\n hidden: Signal<boolean>\n 'data-state': Signal<'open' | 'closed'>\n 'data-scope': 'collapsible'\n 'data-part': 'content'\n }\n}\n\nexport interface ConnectOptions {\n id: string\n}\n\nexport function connect(\n state: Signal<CollapsibleState>,\n send: Send<CollapsibleMsg>,\n opts: ConnectOptions,\n): CollapsibleParts {\n const triggerId = `${opts.id}:trigger`\n const contentId = `${opts.id}:content`\n\n return {\n root: {\n 'data-state': state.map((s) => (s.open ? 'open' : 'closed')),\n 'data-disabled': state.map((s) => (s.disabled ? '' : undefined)),\n 'data-scope': 'collapsible',\n 'data-part': 'root',\n },\n trigger: {\n type: 'button',\n 'aria-expanded': state.map((s) => s.open),\n 'aria-controls': contentId,\n id: triggerId,\n disabled: state.map((s) => s.disabled),\n 'data-state': state.map((s) => (s.open ? 'open' : 'closed')),\n 'data-disabled': state.map((s) => (s.disabled ? '' : undefined)),\n 'data-scope': 'collapsible',\n 'data-part': 'trigger',\n onClick: tagSend(send, ['toggle'], () => send({ type: 'toggle' })),\n },\n content: {\n role: 'region',\n id: contentId,\n 'aria-labelledby': triggerId,\n hidden: state.map((s) => !s.open),\n 'data-state': state.map((s) => (s.open ? 'open' : 'closed')),\n 'data-scope': 'collapsible',\n 'data-part': 'content',\n },\n }\n}\n\nexport const collapsible = { init, update, connect }\n"]}