@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
@@ -75,18 +75,18 @@ function thumbPercent(state, index) {
75
75
  return 0;
76
76
  return ((v - state.min) / range) * 100;
77
77
  }
78
- export function connect(get, send) {
78
+ export function connect(state, send) {
79
79
  return {
80
80
  root: {
81
81
  'data-scope': 'slider',
82
82
  'data-part': 'root',
83
- 'data-orientation': (s) => get(s).orientation,
84
- 'data-disabled': (s) => (get(s).disabled ? '' : undefined),
83
+ 'data-orientation': state.map((s) => s.orientation),
84
+ 'data-disabled': state.map((s) => (s.disabled ? '' : undefined)),
85
85
  },
86
86
  control: {
87
87
  'data-scope': 'slider',
88
88
  'data-part': 'control',
89
- 'data-orientation': (s) => get(s).orientation,
89
+ 'data-orientation': state.map((s) => s.orientation),
90
90
  // Consumers attach their own pointer drag logic via onMount, using
91
91
  // `valueFromPoint` + `closestThumbIndex` helpers. The connect layer
92
92
  // preventDefault's to suppress text selection while dragging.
@@ -95,33 +95,33 @@ export function connect(get, send) {
95
95
  track: {
96
96
  'data-scope': 'slider',
97
97
  'data-part': 'track',
98
- 'data-orientation': (s) => get(s).orientation,
98
+ 'data-orientation': state.map((s) => s.orientation),
99
99
  },
100
100
  range: {
101
101
  'data-scope': 'slider',
102
102
  'data-part': 'range',
103
- 'data-orientation': (s) => get(s).orientation,
104
- style: (s) => rangeStyle(get(s)),
103
+ 'data-orientation': state.map((s) => s.orientation),
104
+ style: state.map((s) => rangeStyle(s)),
105
105
  },
106
106
  thumb: (index) => ({
107
107
  thumb: {
108
108
  role: 'slider',
109
- 'aria-valuemin': (s) => get(s).min,
110
- 'aria-valuemax': (s) => get(s).max,
111
- 'aria-valuenow': (s) => get(s).value[index] ?? get(s).min,
112
- 'aria-orientation': (s) => get(s).orientation,
113
- 'aria-disabled': (s) => (get(s).disabled ? 'true' : undefined),
114
- 'data-orientation': (s) => get(s).orientation,
115
- 'data-disabled': (s) => (get(s).disabled ? '' : undefined),
109
+ 'aria-valuemin': state.map((s) => s.min),
110
+ 'aria-valuemax': state.map((s) => s.max),
111
+ 'aria-valuenow': state.map((s) => s.value[index] ?? s.min),
112
+ 'aria-orientation': state.map((s) => s.orientation),
113
+ 'aria-disabled': state.map((s) => (s.disabled ? 'true' : undefined)),
114
+ 'data-orientation': state.map((s) => s.orientation),
115
+ 'data-disabled': state.map((s) => (s.disabled ? '' : undefined)),
116
116
  'data-scope': 'slider',
117
117
  'data-part': 'thumb',
118
118
  'data-index': String(index),
119
- tabIndex: (s) => (get(s).disabled ? -1 : 0),
120
- style: (s) => thumbStyle(get(s), index),
119
+ tabIndex: state.map((s) => (s.disabled ? -1 : 0)),
120
+ style: state.map((s) => thumbStyle(s, index)),
121
121
  onKeyDown: (e) => handleThumbKey(e, index, send),
122
122
  },
123
123
  }),
124
- value: (s) => get(s).value,
124
+ value: state.map((s) => s.value),
125
125
  };
126
126
  }
127
127
  function handleThumbKey(e, index, send) {
@@ -1 +1 @@
1
- {"version":3,"file":"slider.js","sourceRoot":"","sources":["../../src/components/slider.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Send } from '@llui/dom'\nimport { flipArrow } from '../utils/direction.js'\n\n/**\n * Slider — numeric input controlled by drag or keyboard. Supports multiple\n * thumbs (range slider) and horizontal/vertical orientations. The machine is\n * pure; pointer drag handling (pointermove listeners during a drag) is done\n * by the consumer via `startThumbDrag()` helper which returns a cleanup.\n */\n\nexport type Orientation = 'horizontal' | 'vertical'\n\nexport interface SliderState {\n /** One value per thumb. For a single-value slider, a one-element array. */\n value: number[]\n min: number\n max: number\n step: number\n disabled: boolean\n orientation: Orientation\n /** Minimum gap enforced between adjacent thumbs (range slider). */\n minStepsBetweenThumbs: number\n}\n\nexport type SliderMsg =\n /** @intent(\"Replace all thumb values at once\") */\n | { type: 'setValue'; value: number[] }\n /** @intent(\"Set the value of the thumb at the given index\") */\n | { type: 'setThumb'; index: number; value: number }\n /** @intent(\"Move the thumb at the given index up by one step (or step × multiplier)\") */\n | { type: 'increment'; index: number; multiplier?: number }\n /** @intent(\"Move the thumb at the given index down by one step (or step × multiplier)\") */\n | { type: 'decrement'; index: number; multiplier?: number }\n /** @intent(\"Snap the thumb at the given index to the slider's minimum\") */\n | { type: 'toMin'; index: number }\n /** @intent(\"Snap the thumb at the given index to the slider's maximum\") */\n | { type: 'toMax'; index: number }\n /** @humanOnly */\n | { type: 'setDisabled'; disabled: boolean }\n\nexport interface SliderInit {\n value?: number[]\n min?: number\n max?: number\n step?: number\n disabled?: boolean\n orientation?: Orientation\n minStepsBetweenThumbs?: number\n}\n\nexport function init(opts: SliderInit = {}): SliderState {\n return {\n value: opts.value ?? [0],\n min: opts.min ?? 0,\n max: opts.max ?? 100,\n step: opts.step ?? 1,\n disabled: opts.disabled ?? false,\n orientation: opts.orientation ?? 'horizontal',\n minStepsBetweenThumbs: opts.minStepsBetweenThumbs ?? 0,\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 snapToStep(n: number, min: number, step: number): number {\n const steps = Math.round((n - min) / step)\n const snapped = min + steps * step\n // Avoid floating-point drift — round to precision of step\n const decimals = decimalPlaces(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\nfunction setThumbValue(state: SliderState, index: number, rawValue: number): number[] {\n const { min, max, step, minStepsBetweenThumbs } = state\n const snapped = snapToStep(clamp(rawValue, min, max), min, step)\n const value = [...state.value]\n // Enforce gap with neighbors\n const gap = minStepsBetweenThumbs * step\n const lowerBound = index > 0 ? (value[index - 1] ?? min) + gap : min\n const upperBound = index < value.length - 1 ? (value[index + 1] ?? max) - gap : max\n value[index] = clamp(snapped, lowerBound, upperBound)\n return value\n}\n\nexport function update(state: SliderState, msg: SliderMsg): [SliderState, never[]] {\n if (state.disabled && msg.type !== 'setDisabled') return [state, []]\n switch (msg.type) {\n case 'setValue':\n return [{ ...state, value: msg.value }, []]\n case 'setThumb':\n return [{ ...state, value: setThumbValue(state, msg.index, msg.value) }, []]\n case 'increment': {\n const m = msg.multiplier ?? 1\n const current = state.value[msg.index] ?? state.min\n return [{ ...state, value: setThumbValue(state, msg.index, current + state.step * m) }, []]\n }\n case 'decrement': {\n const m = msg.multiplier ?? 1\n const current = state.value[msg.index] ?? state.min\n return [{ ...state, value: setThumbValue(state, msg.index, current - state.step * m) }, []]\n }\n case 'toMin':\n return [{ ...state, value: setThumbValue(state, msg.index, state.min) }, []]\n case 'toMax':\n return [{ ...state, value: setThumbValue(state, msg.index, state.max) }, []]\n case 'setDisabled':\n return [{ ...state, disabled: msg.disabled }, []]\n }\n}\n\nfunction thumbPercent(state: SliderState, index: number): number {\n const v = state.value[index] ?? state.min\n const range = state.max - state.min\n if (range === 0) return 0\n return ((v - state.min) / range) * 100\n}\n\nexport interface SliderThumbParts<S> {\n thumb: {\n role: 'slider'\n 'aria-valuemin': (s: S) => number\n 'aria-valuemax': (s: S) => number\n 'aria-valuenow': (s: S) => number\n 'aria-orientation': (s: S) => Orientation\n 'aria-disabled': (s: S) => 'true' | undefined\n 'data-orientation': (s: S) => Orientation\n 'data-disabled': (s: S) => '' | undefined\n 'data-scope': 'slider'\n 'data-part': 'thumb'\n 'data-index': string\n tabIndex: (s: S) => number\n onKeyDown: (e: KeyboardEvent) => void\n style: (s: S) => string\n }\n}\n\nexport interface SliderParts<S> {\n root: {\n 'data-scope': 'slider'\n 'data-part': 'root'\n 'data-orientation': (s: S) => Orientation\n 'data-disabled': (s: S) => '' | undefined\n }\n control: {\n 'data-scope': 'slider'\n 'data-part': 'control'\n 'data-orientation': (s: S) => Orientation\n onPointerDown: (e: PointerEvent) => void\n }\n track: {\n 'data-scope': 'slider'\n 'data-part': 'track'\n 'data-orientation': (s: S) => Orientation\n }\n range: {\n 'data-scope': 'slider'\n 'data-part': 'range'\n 'data-orientation': (s: S) => Orientation\n style: (s: S) => string\n }\n thumb: (index: number) => SliderThumbParts<S>\n /** Current raw values — accessor convenience. */\n value: (s: S) => number[]\n}\n\nexport function connect<S>(get: (s: S) => SliderState, send: Send<SliderMsg>): SliderParts<S> {\n return {\n root: {\n 'data-scope': 'slider',\n 'data-part': 'root',\n 'data-orientation': (s) => get(s).orientation,\n 'data-disabled': (s) => (get(s).disabled ? '' : undefined),\n },\n control: {\n 'data-scope': 'slider',\n 'data-part': 'control',\n 'data-orientation': (s) => get(s).orientation,\n // Consumers attach their own pointer drag logic via onMount, using\n // `valueFromPoint` + `closestThumbIndex` helpers. The connect layer\n // preventDefault's to suppress text selection while dragging.\n onPointerDown: (e: PointerEvent) => e.preventDefault(),\n },\n track: {\n 'data-scope': 'slider',\n 'data-part': 'track',\n 'data-orientation': (s) => get(s).orientation,\n },\n range: {\n 'data-scope': 'slider',\n 'data-part': 'range',\n 'data-orientation': (s) => get(s).orientation,\n style: (s) => rangeStyle(get(s)),\n },\n thumb: (index: number): SliderThumbParts<S> => ({\n thumb: {\n role: 'slider',\n 'aria-valuemin': (s) => get(s).min,\n 'aria-valuemax': (s) => get(s).max,\n 'aria-valuenow': (s) => get(s).value[index] ?? get(s).min,\n 'aria-orientation': (s) => get(s).orientation,\n 'aria-disabled': (s) => (get(s).disabled ? 'true' : undefined),\n 'data-orientation': (s) => get(s).orientation,\n 'data-disabled': (s) => (get(s).disabled ? '' : undefined),\n 'data-scope': 'slider',\n 'data-part': 'thumb',\n 'data-index': String(index),\n tabIndex: (s) => (get(s).disabled ? -1 : 0),\n style: (s) => thumbStyle(get(s), index),\n onKeyDown: (e: KeyboardEvent) => handleThumbKey(e, index, send),\n },\n }),\n value: (s) => get(s).value,\n }\n}\n\nfunction handleThumbKey(e: KeyboardEvent, index: number, send: Send<SliderMsg>): void {\n const key = flipArrow(e.key, e.currentTarget as Element)\n switch (key) {\n case 'ArrowRight':\n case 'ArrowUp':\n e.preventDefault()\n send({ type: 'increment', index })\n return\n case 'ArrowLeft':\n case 'ArrowDown':\n e.preventDefault()\n send({ type: 'decrement', index })\n return\n case 'PageUp':\n e.preventDefault()\n send({ type: 'increment', index, multiplier: 10 })\n return\n case 'PageDown':\n e.preventDefault()\n send({ type: 'decrement', index, multiplier: 10 })\n return\n case 'Home':\n e.preventDefault()\n send({ type: 'toMin', index })\n return\n case 'End':\n e.preventDefault()\n send({ type: 'toMax', index })\n return\n }\n}\n\nfunction thumbStyle(state: SliderState, index: number): string {\n const pct = thumbPercent(state, index)\n if (state.orientation === 'horizontal') {\n return `position:absolute;left:${pct}%;transform:translateX(-50%);`\n }\n return `position:absolute;bottom:${pct}%;transform:translateY(50%);`\n}\n\nfunction rangeStyle(state: SliderState): string {\n if (state.value.length === 0) return ''\n const sorted = [...state.value].sort((a, b) => a - b)\n const low = sorted[0]!\n const high = sorted[sorted.length - 1]!\n const range = state.max - state.min\n if (range === 0) return ''\n const startPct = ((low - state.min) / range) * 100\n const endPct = ((high - state.min) / range) * 100\n if (state.orientation === 'horizontal') {\n return `position:absolute;left:${startPct}%;right:${100 - endPct}%;`\n }\n return `position:absolute;bottom:${startPct}%;top:${100 - endPct}%;`\n}\n\n/**\n * Compute the slider value at a given pointer position within the control's\n * bounding rect. Returns null if the pointer is outside the track.\n */\nexport function valueFromPoint(\n state: SliderState,\n rect: DOMRect,\n clientX: number,\n clientY: number,\n): number {\n const { min, max, step, orientation } = state\n let pct: number\n if (orientation === 'horizontal') {\n pct = (clientX - rect.left) / rect.width\n } else {\n pct = 1 - (clientY - rect.top) / rect.height\n }\n const raw = min + pct * (max - min)\n return snapToStep(clamp(raw, min, max), min, step)\n}\n\n/** Determine which thumb index is closest to a given raw value. */\nexport function closestThumbIndex(state: SliderState, raw: number): number {\n if (state.value.length === 0) return 0\n let best = 0\n let bestDist = Infinity\n for (let i = 0; i < state.value.length; i++) {\n const d = Math.abs((state.value[i] ?? 0) - raw)\n if (d < bestDist) {\n bestDist = d\n best = i\n }\n }\n return best\n}\n\nexport const slider = { init, update, connect, valueFromPoint, closestThumbIndex }\n"]}
1
+ {"version":3,"file":"slider.js","sourceRoot":"","sources":["../../src/components/slider.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Send, Signal } from '@llui/dom'\nimport { flipArrow } from '../utils/direction.js'\n\n/**\n * Slider — numeric input controlled by drag or keyboard. Supports multiple\n * thumbs (range slider) and horizontal/vertical orientations. The machine is\n * pure; pointer drag handling (pointermove listeners during a drag) is done\n * by the consumer via `startThumbDrag()` helper which returns a cleanup.\n */\n\nexport type Orientation = 'horizontal' | 'vertical'\n\nexport interface SliderState {\n /** One value per thumb. For a single-value slider, a one-element array. */\n value: number[]\n min: number\n max: number\n step: number\n disabled: boolean\n orientation: Orientation\n /** Minimum gap enforced between adjacent thumbs (range slider). */\n minStepsBetweenThumbs: number\n}\n\nexport type SliderMsg =\n /** @intent(\"Replace all thumb values at once\") */\n | { type: 'setValue'; value: number[] }\n /** @intent(\"Set the value of the thumb at the given index\") */\n | { type: 'setThumb'; index: number; value: number }\n /** @intent(\"Move the thumb at the given index up by one step (or step × multiplier)\") */\n | { type: 'increment'; index: number; multiplier?: number }\n /** @intent(\"Move the thumb at the given index down by one step (or step × multiplier)\") */\n | { type: 'decrement'; index: number; multiplier?: number }\n /** @intent(\"Snap the thumb at the given index to the slider's minimum\") */\n | { type: 'toMin'; index: number }\n /** @intent(\"Snap the thumb at the given index to the slider's maximum\") */\n | { type: 'toMax'; index: number }\n /** @humanOnly */\n | { type: 'setDisabled'; disabled: boolean }\n\nexport interface SliderInit {\n value?: number[]\n min?: number\n max?: number\n step?: number\n disabled?: boolean\n orientation?: Orientation\n minStepsBetweenThumbs?: number\n}\n\nexport function init(opts: SliderInit = {}): SliderState {\n return {\n value: opts.value ?? [0],\n min: opts.min ?? 0,\n max: opts.max ?? 100,\n step: opts.step ?? 1,\n disabled: opts.disabled ?? false,\n orientation: opts.orientation ?? 'horizontal',\n minStepsBetweenThumbs: opts.minStepsBetweenThumbs ?? 0,\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 snapToStep(n: number, min: number, step: number): number {\n const steps = Math.round((n - min) / step)\n const snapped = min + steps * step\n // Avoid floating-point drift — round to precision of step\n const decimals = decimalPlaces(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\nfunction setThumbValue(state: SliderState, index: number, rawValue: number): number[] {\n const { min, max, step, minStepsBetweenThumbs } = state\n const snapped = snapToStep(clamp(rawValue, min, max), min, step)\n const value = [...state.value]\n // Enforce gap with neighbors\n const gap = minStepsBetweenThumbs * step\n const lowerBound = index > 0 ? (value[index - 1] ?? min) + gap : min\n const upperBound = index < value.length - 1 ? (value[index + 1] ?? max) - gap : max\n value[index] = clamp(snapped, lowerBound, upperBound)\n return value\n}\n\nexport function update(state: SliderState, msg: SliderMsg): [SliderState, never[]] {\n if (state.disabled && msg.type !== 'setDisabled') return [state, []]\n switch (msg.type) {\n case 'setValue':\n return [{ ...state, value: msg.value }, []]\n case 'setThumb':\n return [{ ...state, value: setThumbValue(state, msg.index, msg.value) }, []]\n case 'increment': {\n const m = msg.multiplier ?? 1\n const current = state.value[msg.index] ?? state.min\n return [{ ...state, value: setThumbValue(state, msg.index, current + state.step * m) }, []]\n }\n case 'decrement': {\n const m = msg.multiplier ?? 1\n const current = state.value[msg.index] ?? state.min\n return [{ ...state, value: setThumbValue(state, msg.index, current - state.step * m) }, []]\n }\n case 'toMin':\n return [{ ...state, value: setThumbValue(state, msg.index, state.min) }, []]\n case 'toMax':\n return [{ ...state, value: setThumbValue(state, msg.index, state.max) }, []]\n case 'setDisabled':\n return [{ ...state, disabled: msg.disabled }, []]\n }\n}\n\nfunction thumbPercent(state: SliderState, index: number): number {\n const v = state.value[index] ?? state.min\n const range = state.max - state.min\n if (range === 0) return 0\n return ((v - state.min) / range) * 100\n}\n\nexport interface SliderThumbParts {\n thumb: {\n role: 'slider'\n 'aria-valuemin': Signal<number>\n 'aria-valuemax': Signal<number>\n 'aria-valuenow': Signal<number>\n 'aria-orientation': Signal<Orientation>\n 'aria-disabled': Signal<'true' | undefined>\n 'data-orientation': Signal<Orientation>\n 'data-disabled': Signal<'' | undefined>\n 'data-scope': 'slider'\n 'data-part': 'thumb'\n 'data-index': string\n tabIndex: Signal<number>\n onKeyDown: (e: KeyboardEvent) => void\n style: Signal<string>\n }\n}\n\nexport interface SliderParts {\n root: {\n 'data-scope': 'slider'\n 'data-part': 'root'\n 'data-orientation': Signal<Orientation>\n 'data-disabled': Signal<'' | undefined>\n }\n control: {\n 'data-scope': 'slider'\n 'data-part': 'control'\n 'data-orientation': Signal<Orientation>\n onPointerDown: (e: PointerEvent) => void\n }\n track: {\n 'data-scope': 'slider'\n 'data-part': 'track'\n 'data-orientation': Signal<Orientation>\n }\n range: {\n 'data-scope': 'slider'\n 'data-part': 'range'\n 'data-orientation': Signal<Orientation>\n style: Signal<string>\n }\n thumb: (index: number) => SliderThumbParts\n /** Current raw values — reactive convenience. */\n value: Signal<number[]>\n}\n\nexport function connect(state: Signal<SliderState>, send: Send<SliderMsg>): SliderParts {\n return {\n root: {\n 'data-scope': 'slider',\n 'data-part': 'root',\n 'data-orientation': state.map((s) => s.orientation),\n 'data-disabled': state.map((s) => (s.disabled ? '' : undefined)),\n },\n control: {\n 'data-scope': 'slider',\n 'data-part': 'control',\n 'data-orientation': state.map((s) => s.orientation),\n // Consumers attach their own pointer drag logic via onMount, using\n // `valueFromPoint` + `closestThumbIndex` helpers. The connect layer\n // preventDefault's to suppress text selection while dragging.\n onPointerDown: (e: PointerEvent) => e.preventDefault(),\n },\n track: {\n 'data-scope': 'slider',\n 'data-part': 'track',\n 'data-orientation': state.map((s) => s.orientation),\n },\n range: {\n 'data-scope': 'slider',\n 'data-part': 'range',\n 'data-orientation': state.map((s) => s.orientation),\n style: state.map((s) => rangeStyle(s)),\n },\n thumb: (index: number): SliderThumbParts => ({\n thumb: {\n role: 'slider',\n 'aria-valuemin': state.map((s) => s.min),\n 'aria-valuemax': state.map((s) => s.max),\n 'aria-valuenow': state.map((s) => s.value[index] ?? s.min),\n 'aria-orientation': state.map((s) => s.orientation),\n 'aria-disabled': state.map((s) => (s.disabled ? 'true' : undefined)),\n 'data-orientation': state.map((s) => s.orientation),\n 'data-disabled': state.map((s) => (s.disabled ? '' : undefined)),\n 'data-scope': 'slider',\n 'data-part': 'thumb',\n 'data-index': String(index),\n tabIndex: state.map((s) => (s.disabled ? -1 : 0)),\n style: state.map((s) => thumbStyle(s, index)),\n onKeyDown: (e: KeyboardEvent) => handleThumbKey(e, index, send),\n },\n }),\n value: state.map((s) => s.value),\n }\n}\n\nfunction handleThumbKey(e: KeyboardEvent, index: number, send: Send<SliderMsg>): void {\n const key = flipArrow(e.key, e.currentTarget as Element)\n switch (key) {\n case 'ArrowRight':\n case 'ArrowUp':\n e.preventDefault()\n send({ type: 'increment', index })\n return\n case 'ArrowLeft':\n case 'ArrowDown':\n e.preventDefault()\n send({ type: 'decrement', index })\n return\n case 'PageUp':\n e.preventDefault()\n send({ type: 'increment', index, multiplier: 10 })\n return\n case 'PageDown':\n e.preventDefault()\n send({ type: 'decrement', index, multiplier: 10 })\n return\n case 'Home':\n e.preventDefault()\n send({ type: 'toMin', index })\n return\n case 'End':\n e.preventDefault()\n send({ type: 'toMax', index })\n return\n }\n}\n\nfunction thumbStyle(state: SliderState, index: number): string {\n const pct = thumbPercent(state, index)\n if (state.orientation === 'horizontal') {\n return `position:absolute;left:${pct}%;transform:translateX(-50%);`\n }\n return `position:absolute;bottom:${pct}%;transform:translateY(50%);`\n}\n\nfunction rangeStyle(state: SliderState): string {\n if (state.value.length === 0) return ''\n const sorted = [...state.value].sort((a, b) => a - b)\n const low = sorted[0]!\n const high = sorted[sorted.length - 1]!\n const range = state.max - state.min\n if (range === 0) return ''\n const startPct = ((low - state.min) / range) * 100\n const endPct = ((high - state.min) / range) * 100\n if (state.orientation === 'horizontal') {\n return `position:absolute;left:${startPct}%;right:${100 - endPct}%;`\n }\n return `position:absolute;bottom:${startPct}%;top:${100 - endPct}%;`\n}\n\n/**\n * Compute the slider value at a given pointer position within the control's\n * bounding rect. Returns null if the pointer is outside the track.\n */\nexport function valueFromPoint(\n state: SliderState,\n rect: DOMRect,\n clientX: number,\n clientY: number,\n): number {\n const { min, max, step, orientation } = state\n let pct: number\n if (orientation === 'horizontal') {\n pct = (clientX - rect.left) / rect.width\n } else {\n pct = 1 - (clientY - rect.top) / rect.height\n }\n const raw = min + pct * (max - min)\n return snapToStep(clamp(raw, min, max), min, step)\n}\n\n/** Determine which thumb index is closest to a given raw value. */\nexport function closestThumbIndex(state: SliderState, raw: number): number {\n if (state.value.length === 0) return 0\n let best = 0\n let bestDist = Infinity\n for (let i = 0; i < state.value.length; i++) {\n const d = Math.abs((state.value[i] ?? 0) - raw)\n if (d < bestDist) {\n bestDist = d\n best = i\n }\n }\n return best\n}\n\nexport const slider = { init, update, connect, valueFromPoint, closestThumbIndex }\n"]}
@@ -1,4 +1,4 @@
1
- import type { Send } from '@llui/dom';
1
+ import type { Send, Signal } from '@llui/dom';
2
2
  /**
3
3
  * Sortable — pointer-based reorderable list.
4
4
  *
@@ -22,7 +22,7 @@ import type { Send } from '@llui/dom';
22
22
  * }
23
23
  *
24
24
  * view: ({ send, each, text }) => {
25
- * const s = sortable.connect<State>(s => s.sort, m => send({ type: 'sort', msg: m }), { id: 'list' })
25
+ * const s = sortable.connect(state.map((s) => s.sort), m => send({ type: 'sort', msg: m }), { id: 'list' })
26
26
  * return [
27
27
  * ul({ ...s.root, class: 'list' }, [
28
28
  * ...each({
@@ -121,12 +121,12 @@ export type SortableMsg =
121
121
  };
122
122
  export declare function init(): SortableState;
123
123
  export declare function update(state: SortableState, msg: SortableMsg): [SortableState, never[]];
124
- export interface SortableParts<S> {
124
+ export interface SortableParts {
125
125
  root: {
126
126
  'data-scope': 'sortable';
127
127
  'data-part': 'root';
128
128
  'data-container-id': string;
129
- 'data-dragging': (s: S) => '' | undefined;
129
+ 'data-dragging': Signal<'' | undefined>;
130
130
  onPointerMove: (e: PointerEvent) => void;
131
131
  onPointerUp: (e: PointerEvent) => void;
132
132
  onPointerCancel: (e: PointerEvent) => void;
@@ -136,18 +136,18 @@ export interface SortableParts<S> {
136
136
  'data-part': 'item';
137
137
  'data-index': string;
138
138
  'data-id': string;
139
- 'data-dragging': (s: S) => '' | undefined;
140
- 'data-over': (s: S) => '' | undefined;
141
- 'data-shift': (s: S) => 'up' | 'down' | undefined;
142
- 'style.transform': (s: S) => string | undefined;
143
- 'style.zIndex': (s: S) => string | undefined;
139
+ 'data-dragging': Signal<'' | undefined>;
140
+ 'data-over': Signal<'' | undefined>;
141
+ 'data-shift': Signal<'up' | 'down' | undefined>;
142
+ 'style.transform': Signal<string | undefined>;
143
+ 'style.zIndex': Signal<string | undefined>;
144
144
  };
145
145
  handle: (id: string, index: number) => {
146
146
  'data-scope': 'sortable';
147
147
  'data-part': 'handle';
148
148
  role: 'button';
149
149
  tabIndex: 0;
150
- 'aria-grabbed': (s: S) => boolean;
150
+ 'aria-grabbed': Signal<boolean>;
151
151
  'aria-label': string;
152
152
  onPointerDown: (e: PointerEvent) => void;
153
153
  onKeyDown: (e: KeyboardEvent) => void;
@@ -182,7 +182,7 @@ export interface ConnectOptions {
182
182
  */
183
183
  layout?: '1d' | '2d';
184
184
  }
185
- export declare function connect<S>(get: (s: S) => SortableState, send: Send<SortableMsg>, opts: ConnectOptions): SortableParts<S>;
185
+ export declare function connect(state: Signal<SortableState>, send: Send<SortableMsg>, opts: ConnectOptions): SortableParts;
186
186
  /**
187
187
  * Move an item in an array from one index to another, returning a new array.
188
188
  * Out-of-range indices are clamped to array bounds.
@@ -1 +1 @@
1
- {"version":3,"file":"sortable.d.ts","sourceRoot":"","sources":["../../src/components/sortable.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sortable.d.ts","sourceRoot":"","sources":["../../src/components/sortable.ts"],"names":[],"mappings":"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"}
@@ -79,7 +79,7 @@ export function update(state, msg) {
79
79
  }
80
80
  }
81
81
  }
82
- export function connect(get, send, opts) {
82
+ export function connect(state, send, opts) {
83
83
  // The connect's `id` doubles as the cross-container identifier
84
84
  const containerId = opts.id;
85
85
  const layout = opts.layout ?? '1d';
@@ -165,7 +165,7 @@ export function connect(get, send, opts) {
165
165
  'data-scope': 'sortable',
166
166
  'data-part': 'root',
167
167
  'data-container-id': containerId,
168
- 'data-dragging': (s) => (get(s).dragging ? '' : undefined),
168
+ 'data-dragging': state.map((s) => (s.dragging ? '' : undefined)),
169
169
  onPointerMove: tagSend(send, ['move'], (e) => {
170
170
  if (!e.buttons)
171
171
  return;
@@ -193,12 +193,12 @@ export function connect(get, send, opts) {
193
193
  'data-part': 'item',
194
194
  'data-index': String(index),
195
195
  'data-id': id,
196
- 'data-dragging': (s) => {
197
- const d = get(s).dragging;
196
+ 'data-dragging': state.map((s) => {
197
+ const d = s.dragging;
198
198
  return d?.id === id && d?.fromContainer === containerId ? '' : undefined;
199
- },
200
- 'data-over': (s) => {
201
- const d = get(s).dragging;
199
+ }),
200
+ 'data-over': state.map((s) => {
201
+ const d = s.dragging;
202
202
  if (!d || d.toContainer !== containerId)
203
203
  return undefined;
204
204
  // Look up this item's CURRENT DOM index via the drag-start snapshot.
@@ -207,7 +207,7 @@ export function connect(get, send, opts) {
207
207
  const snap = snapshots.get(containerId);
208
208
  const liveIndex = snap?.idToIndex.get(id) ?? index;
209
209
  return d.currentIndex === liveIndex ? '' : undefined;
210
- },
210
+ }),
211
211
  // Shift direction for items BETWEEN the source and target (excluding the
212
212
  // dragged item itself). 'down' = item should translate down to make room;
213
213
  // 'up' = item should translate up. CSS controls the actual displacement.
@@ -217,10 +217,10 @@ export function connect(get, send, opts) {
217
217
  // `data-shift` out of the 2D path prevents any author-provided
218
218
  // CSS rule like `[data-shift] { translate: 0 var(--sortable-shift) }`
219
219
  // from fighting with the computed transform.
220
- 'data-shift': (s) => {
220
+ 'data-shift': state.map((s) => {
221
221
  if (layout === '2d')
222
222
  return undefined;
223
- const d = get(s).dragging;
223
+ const d = s.dragging;
224
224
  if (!d || d.fromContainer !== containerId || d.toContainer !== containerId)
225
225
  return undefined;
226
226
  if (d.id === id)
@@ -241,7 +241,7 @@ export function connect(get, send, opts) {
241
241
  return 'down';
242
242
  }
243
243
  return undefined;
244
- },
244
+ }),
245
245
  // The dragged item follows the pointer. In 1D, translateY only; in
246
246
  // 2D, both axes. Non-dragged items in 2D between source and target
247
247
  // get a per-item translate computed from the snapshot — each item's
@@ -249,8 +249,8 @@ export function connect(get, send, opts) {
249
249
  // opens correctly regardless of row wrap. In 1D, non-dragged items
250
250
  // emit `undefined` here and rely on the consumer's CSS `data-shift`
251
251
  // rule.
252
- 'style.transform': (s) => {
253
- const d = get(s).dragging;
252
+ 'style.transform': state.map((s) => {
253
+ const d = s.dragging;
254
254
  if (!d)
255
255
  return undefined;
256
256
  const isDragged = d.id === id && d.fromContainer === containerId;
@@ -301,23 +301,23 @@ export function connect(get, send, opts) {
301
301
  const dx = target.x - own.x;
302
302
  const dy = target.y - own.y;
303
303
  return `translate(${dx}px, ${dy}px)`;
304
- },
305
- 'style.zIndex': (s) => {
306
- const d = get(s).dragging;
304
+ }),
305
+ 'style.zIndex': state.map((s) => {
306
+ const d = s.dragging;
307
307
  if (!d || d.id !== id || d.fromContainer !== containerId)
308
308
  return undefined;
309
309
  return '10';
310
- },
310
+ }),
311
311
  }),
312
312
  handle: (id, index) => ({
313
313
  'data-scope': 'sortable',
314
314
  'data-part': 'handle',
315
315
  role: 'button',
316
316
  tabIndex: 0,
317
- 'aria-grabbed': (s) => {
318
- const d = get(s).dragging;
317
+ 'aria-grabbed': state.map((s) => {
318
+ const d = s.dragging;
319
319
  return d?.id === id && d?.fromContainer === containerId;
320
- },
320
+ }),
321
321
  'aria-label': 'Drag handle. Press space to pick up, arrow keys to move, space again to drop, escape to cancel.',
322
322
  onPointerDown: tagSend(send, ['start'], (e) => {
323
323
  e.preventDefault();
@@ -1 +1 @@
1
- {"version":3,"file":"sortable.js","sourceRoot":"","sources":["../../src/components/sortable.ts"],"names":[],"mappings":"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","sourcesContent":["import { tagSend } from '@llui/dom'\nimport type { Send } from '@llui/dom'\n\n/**\n * Sortable — pointer-based reorderable list.\n *\n * State machine tracks the currently-dragged item and where it's hovering.\n * The app owns the actual array; listen for `drop` and use `reorder(arr, from, to)`\n * to compute the new order, or watch `currentIndex` during drag for live preview.\n *\n * ```ts\n * type State = { items: string[]; sort: SortableState }\n *\n * update: (state, msg) => {\n * switch (msg.type) {\n * case 'sort':\n * return [{ ...state, sort: sortable.update(state.sort, msg.msg)[0] }, []]\n * case 'drop': {\n * const d = state.sort.dragging\n * if (!d) return [state, []]\n * return [{ ...state, items: reorder(state.items, d.startIndex, d.currentIndex) }, []]\n * }\n * }\n * }\n *\n * view: ({ send, each, text }) => {\n * const s = sortable.connect<State>(s => s.sort, m => send({ type: 'sort', msg: m }), { id: 'list' })\n * return [\n * ul({ ...s.root, class: 'list' }, [\n * ...each({\n * items: (st) => st.items,\n * key: (x) => x,\n * render: ({ item, index }) => [\n * li({ ...s.item(item(), index()), class: 'item' }, [\n * div({ ...s.handle(item(), index()), class: 'handle' }, [text('⋮⋮')]),\n * text(item),\n * ]),\n * ],\n * }),\n * ]),\n * ]\n * }\n * ```\n *\n * Hook up pointermove/pointerup at the root (attachPointerHandlers) — or\n * wire them directly via `onPointerMove` / `onPointerUp` on the root part.\n */\n\nexport interface DragState {\n id: string\n startIndex: number\n currentIndex: number\n /**\n * Container the drag originated from. Defaults to the connect's `id` for\n * single-container sortables. Set when multiple sortables share state.\n */\n fromContainer: string\n /**\n * Container the pointer is currently over. Same as `fromContainer` for\n * single-container sortables. Differs when dragging across containers.\n */\n toContainer: string\n /**\n * Pointer X at drag start (viewport coordinates). Used by 2D layouts\n * to compute `deltaX = currentX - startX` alongside the Y axis. In 1D\n * layouts X is tracked but ignored by the renderer.\n */\n startX: number\n /**\n * Pointer Y at drag start (viewport coordinates). Used by CSS / the\n * library's `style.transform` binding to make the dragged item follow\n * the pointer.\n */\n startY: number\n /**\n * Current pointer X (viewport coordinates). `deltaX = currentX - startX`.\n */\n currentX: number\n /**\n * Current pointer Y (viewport coordinates). `deltaY = currentY - startY`.\n */\n currentY: number\n}\n\nexport interface SortableState {\n dragging: DragState | null\n}\n\nexport type SortableMsg =\n /** @humanOnly */\n | { type: 'start'; id: string; index: number; container: string; x: number; y: number }\n /** @humanOnly */\n | { type: 'move'; index: number; container: string; x: number; y: number }\n /** @humanOnly */\n | { type: 'drop' }\n /** @humanOnly */\n | { type: 'cancel' }\n /** @humanOnly */\n | { type: 'toggleGrab'; id: string; index: number; container: string }\n /** @humanOnly */\n | { type: 'moveBy'; delta: number }\n\nexport function init(): SortableState {\n return { dragging: null }\n}\n\nexport function update(state: SortableState, msg: SortableMsg): [SortableState, never[]] {\n switch (msg.type) {\n case 'start':\n return [\n {\n dragging: {\n id: msg.id,\n startIndex: msg.index,\n currentIndex: msg.index,\n fromContainer: msg.container,\n toContainer: msg.container,\n startX: msg.x,\n startY: msg.y,\n currentX: msg.x,\n currentY: msg.y,\n },\n },\n [],\n ]\n case 'move': {\n if (!state.dragging) return [state, []]\n if (\n state.dragging.currentIndex === msg.index &&\n state.dragging.toContainer === msg.container &&\n state.dragging.currentX === msg.x &&\n state.dragging.currentY === msg.y\n ) {\n return [state, []]\n }\n return [\n {\n dragging: {\n ...state.dragging,\n currentIndex: msg.index,\n toContainer: msg.container,\n currentX: msg.x,\n currentY: msg.y,\n },\n },\n [],\n ]\n }\n case 'drop':\n return state.dragging ? [{ dragging: null }, []] : [state, []]\n case 'cancel':\n return state.dragging ? [{ dragging: null }, []] : [state, []]\n case 'toggleGrab':\n if (state.dragging) {\n // Already dragging — drop at current position\n return [{ dragging: null }, []]\n }\n // Pick up (keyboard — no pointer position)\n return [\n {\n dragging: {\n id: msg.id,\n startIndex: msg.index,\n currentIndex: msg.index,\n fromContainer: msg.container,\n toContainer: msg.container,\n startX: 0,\n startY: 0,\n currentX: 0,\n currentY: 0,\n },\n },\n [],\n ]\n case 'moveBy': {\n if (!state.dragging) return [state, []]\n const next = Math.max(0, state.dragging.currentIndex + msg.delta)\n if (next === state.dragging.currentIndex) return [state, []]\n return [{ dragging: { ...state.dragging, currentIndex: next } }, []]\n }\n }\n}\n\nexport interface SortableParts<S> {\n root: {\n 'data-scope': 'sortable'\n 'data-part': 'root'\n 'data-container-id': string\n 'data-dragging': (s: S) => '' | undefined\n onPointerMove: (e: PointerEvent) => void\n onPointerUp: (e: PointerEvent) => void\n onPointerCancel: (e: PointerEvent) => void\n }\n item: (\n id: string,\n index: number,\n ) => {\n 'data-scope': 'sortable'\n 'data-part': 'item'\n 'data-index': string\n 'data-id': string\n 'data-dragging': (s: S) => '' | undefined\n 'data-over': (s: S) => '' | undefined\n 'data-shift': (s: S) => 'up' | 'down' | undefined\n 'style.transform': (s: S) => string | undefined\n 'style.zIndex': (s: S) => string | undefined\n }\n handle: (\n id: string,\n index: number,\n ) => {\n 'data-scope': 'sortable'\n 'data-part': 'handle'\n role: 'button'\n tabIndex: 0\n 'aria-grabbed': (s: S) => boolean\n 'aria-label': string\n onPointerDown: (e: PointerEvent) => void\n onKeyDown: (e: KeyboardEvent) => void\n }\n}\n\nexport interface ConnectOptions {\n id: string\n /**\n * Drag-target selection + render strategy.\n *\n * - `'1d'` (default) — single-axis, Y-only. `findTargetAt` picks\n * by vertical distance; `style.transform` on the dragged item\n * is `translateY(deltaY)`; non-dragged items between source\n * and target emit `data-shift: 'up' | 'down'` so CSS can\n * animate them via `translateY(±var(--sortable-shift))`.\n * Correct for vertical lists; fails for 2D layouts (flex-wrap,\n * grid) because same-row items collapse to the same midpoint\n * distance.\n *\n * - `'2d'` — Euclidean target selection against 2D midpoints;\n * dragged item follows both X and Y (`translate(dx, dy)`);\n * non-dragged items between source and target get a per-item\n * `style.transform = translate(deltaFromSnapshot)` that opens\n * the correct gap regardless of row boundaries. `data-shift`\n * is always `undefined` in 2D so CSS `translateY(var(--...))`\n * rules don't conflict with the per-item transform.\n *\n * Keyboard navigation (`moveBy`) stays linear-array in both modes —\n * arrow keys step through the array indices regardless of visual\n * row, because that's what screen readers announce and what the\n * underlying data order actually is.\n */\n layout?: '1d' | '2d'\n}\n\nexport function connect<S>(\n get: (s: S) => SortableState,\n send: Send<SortableMsg>,\n opts: ConnectOptions,\n): SortableParts<S> {\n // The connect's `id` doubles as the cross-container identifier\n const containerId = opts.id\n const layout = opts.layout ?? '1d'\n\n // Snapshots taken at drag start — stable throughout the drag so computing\n // the target index is not affected by items visually shifting via CSS.\n // Map: container-id → array of midpoint {x, y} pairs for each item's\n // original bounding rect (sorted by index). The handler records this on\n // pointerdown. Always 2D internally; 1D layout's findTargetAt ignores X.\n interface Snapshot {\n mids: Array<{ x: number; y: number }>\n // id → current DOM index at drag start. Used by data-shift / per-item\n // transform to look up an item's live position, since the `index`\n // captured at render time is frozen and goes stale after each()\n // reconciles a reorder.\n idToIndex: Map<string, number>\n }\n const snapshots = new Map<string, Snapshot>()\n\n function snapshotContainer(rootEl: HTMLElement, cid: string): void {\n const items = rootEl.querySelectorAll<HTMLElement>('[data-scope=\"sortable\"][data-part=\"item\"]')\n // Read rects once — they're pre-transform (no drag shifts yet)\n const mids: Array<{ x: number; y: number }> = []\n const idToIndex = new Map<string, number>()\n items.forEach((item, i) => {\n const r = item.getBoundingClientRect()\n mids.push({ x: r.left + r.width / 2, y: r.top + r.height / 2 })\n const itemId = item.dataset.id\n if (itemId !== undefined) idToIndex.set(itemId, i)\n })\n snapshots.set(cid, { mids, idToIndex })\n }\n\n function snapshotAll(): void {\n const roots = document.querySelectorAll<HTMLElement>(\n '[data-scope=\"sortable\"][data-part=\"root\"]',\n )\n for (const root of roots) {\n const cid = root.dataset.containerId\n if (cid) snapshotContainer(root, cid)\n }\n }\n\n // Find the target index under the pointer using the drag-start snapshot.\n // 1D mode: picks by Y-only distance (original behavior). 2D mode: picks\n // by Euclidean distance over {x, y} midpoints — required for flex-wrap\n // / grid layouts where multiple items share a row and collapse to the\n // same Y value. Both modes are stable against items being visually\n // transformed during the drag because midpoints are taken pre-transform.\n function findTargetAt(e: PointerEvent): { container: string; index: number } | null {\n const roots = document.querySelectorAll<HTMLElement>(\n '[data-scope=\"sortable\"][data-part=\"root\"]',\n )\n for (const root of roots) {\n const r = root.getBoundingClientRect()\n if (e.clientX < r.left || e.clientX > r.right) continue\n if (e.clientY < r.top || e.clientY > r.bottom) continue\n const cid = root.dataset.containerId\n if (!cid) continue\n const snap = snapshots.get(cid)\n if (!snap || snap.mids.length === 0) return { container: cid, index: 0 }\n const mids = snap.mids\n let bestIdx = 0\n if (layout === '2d') {\n // Euclidean (squared — monotonic with distance, saves a sqrt).\n const dx0 = e.clientX - mids[0]!.x\n const dy0 = e.clientY - mids[0]!.y\n let bestDist = dx0 * dx0 + dy0 * dy0\n for (let i = 1; i < mids.length; i++) {\n const dx = e.clientX - mids[i]!.x\n const dy = e.clientY - mids[i]!.y\n const d = dx * dx + dy * dy\n if (d < bestDist) {\n bestDist = d\n bestIdx = i\n }\n }\n } else {\n // 1D — Y-only distance. Preserves the original behavior for\n // vertical lists; same-row items in a flex-wrap would tie and\n // the first match wins, which is the bug that motivates 2D.\n let bestDist = Math.abs(e.clientY - mids[0]!.y)\n for (let i = 1; i < mids.length; i++) {\n const d = Math.abs(e.clientY - mids[i]!.y)\n if (d < bestDist) {\n bestDist = d\n bestIdx = i\n }\n }\n }\n return { container: cid, index: bestIdx }\n }\n return null\n }\n\n return {\n root: {\n 'data-scope': 'sortable',\n 'data-part': 'root',\n 'data-container-id': containerId,\n 'data-dragging': (s) => (get(s).dragging ? '' : undefined),\n onPointerMove: tagSend(send, ['move'], (e) => {\n if (!e.buttons) return\n const hit = findTargetAt(e)\n if (hit !== null)\n send({\n type: 'move',\n index: hit.index,\n container: hit.container,\n x: e.clientX,\n y: e.clientY,\n })\n }),\n onPointerUp: tagSend(send, ['drop'], () => {\n snapshots.clear()\n send({ type: 'drop' })\n }),\n onPointerCancel: tagSend(send, ['cancel'], () => {\n snapshots.clear()\n send({ type: 'cancel' })\n }),\n },\n item: (id, index) => ({\n 'data-scope': 'sortable',\n 'data-part': 'item',\n 'data-index': String(index),\n 'data-id': id,\n 'data-dragging': (s) => {\n const d = get(s).dragging\n return d?.id === id && d?.fromContainer === containerId ? '' : undefined\n },\n 'data-over': (s) => {\n const d = get(s).dragging\n if (!d || d.toContainer !== containerId) return undefined\n // Look up this item's CURRENT DOM index via the drag-start snapshot.\n // The `index` closed over here is frozen at initial render and goes\n // stale after each() reconciles a reorder.\n const snap = snapshots.get(containerId)\n const liveIndex = snap?.idToIndex.get(id) ?? index\n return d.currentIndex === liveIndex ? '' : undefined\n },\n // Shift direction for items BETWEEN the source and target (excluding the\n // dragged item itself). 'down' = item should translate down to make room;\n // 'up' = item should translate up. CSS controls the actual displacement.\n //\n // In 2D layout, `data-shift` is always undefined — the per-item\n // `style.transform` below opens the correct gap directly. Keeping\n // `data-shift` out of the 2D path prevents any author-provided\n // CSS rule like `[data-shift] { translate: 0 var(--sortable-shift) }`\n // from fighting with the computed transform.\n 'data-shift': (s) => {\n if (layout === '2d') return undefined\n const d = get(s).dragging\n if (!d || d.fromContainer !== containerId || d.toContainer !== containerId) return undefined\n if (d.id === id) return undefined\n if (d.startIndex === d.currentIndex) return undefined\n // Look up this item's live DOM index — see note on data-over.\n const snap = snapshots.get(containerId)\n const liveIndex = snap?.idToIndex.get(id) ?? index\n if (d.startIndex < d.currentIndex) {\n // Dragging down: items between start+1 and current shift up\n if (liveIndex > d.startIndex && liveIndex <= d.currentIndex) return 'up'\n } else {\n // Dragging up: items between current and start-1 shift down\n if (liveIndex >= d.currentIndex && liveIndex < d.startIndex) return 'down'\n }\n return undefined\n },\n // The dragged item follows the pointer. In 1D, translateY only; in\n // 2D, both axes. Non-dragged items in 2D between source and target\n // get a per-item translate computed from the snapshot — each item's\n // vector is `snapshot[newSlot] - snapshot[ownSlot]` so the gap\n // opens correctly regardless of row wrap. In 1D, non-dragged items\n // emit `undefined` here and rely on the consumer's CSS `data-shift`\n // rule.\n 'style.transform': (s) => {\n const d = get(s).dragging\n if (!d) return undefined\n const isDragged = d.id === id && d.fromContainer === containerId\n if (isDragged) {\n const deltaY = d.currentY - d.startY\n if (layout === '2d') {\n const deltaX = d.currentX - d.startX\n return `translate(${deltaX}px, ${deltaY}px)`\n }\n return `translateY(${deltaY}px)`\n }\n // Non-dragged items: per-item displacement in 2D only.\n if (layout !== '2d') return undefined\n if (d.fromContainer !== containerId || d.toContainer !== containerId) return undefined\n if (d.startIndex === d.currentIndex) return undefined\n const snap = snapshots.get(containerId)\n if (!snap) return undefined\n const liveIndex = snap.idToIndex.get(id)\n if (liveIndex === undefined) return undefined\n // Which slot this item should visually occupy while the drag\n // previews the reorder:\n // drag-down (start < current): items at liveIndex in\n // (start .. current] shift left-by-one in array order, so\n // they take the slot at liveIndex - 1.\n // drag-up (current < start): items at liveIndex in\n // [current .. start) shift right-by-one, take slot\n // liveIndex + 1.\n let targetSlot: number\n if (d.startIndex < d.currentIndex) {\n if (liveIndex <= d.startIndex || liveIndex > d.currentIndex) return undefined\n targetSlot = liveIndex - 1\n } else {\n if (liveIndex < d.currentIndex || liveIndex >= d.startIndex) return undefined\n targetSlot = liveIndex + 1\n }\n const own = snap.mids[liveIndex]\n const target = snap.mids[targetSlot]\n if (!own || !target) return undefined\n const dx = target.x - own.x\n const dy = target.y - own.y\n return `translate(${dx}px, ${dy}px)`\n },\n 'style.zIndex': (s) => {\n const d = get(s).dragging\n if (!d || d.id !== id || d.fromContainer !== containerId) return undefined\n return '10'\n },\n }),\n handle: (id, index) => ({\n 'data-scope': 'sortable',\n 'data-part': 'handle',\n role: 'button',\n tabIndex: 0,\n 'aria-grabbed': (s) => {\n const d = get(s).dragging\n return d?.id === id && d?.fromContainer === containerId\n },\n 'aria-label':\n 'Drag handle. Press space to pick up, arrow keys to move, space again to drop, escape to cancel.',\n onPointerDown: tagSend(send, ['start'], (e) => {\n e.preventDefault()\n const target = e.currentTarget as Element | null\n if (target && 'setPointerCapture' in target) {\n try {\n ;(target as Element & { setPointerCapture: (id: number) => void }).setPointerCapture(\n e.pointerId,\n )\n } catch {\n // Ignore — not all elements support pointer capture\n }\n }\n // Compute the CURRENT DOM index of this handle's item — the captured\n // `index` param is stale after a reorder (each() moves keyed nodes\n // without re-running render, so the closure's index is frozen at\n // initial mount). Walk up to find the containing item, then count its\n // position among sibling items.\n let currentIndex = index\n if (target) {\n const itemEl = (target as Element).closest<HTMLElement>(\n '[data-scope=\"sortable\"][data-part=\"item\"]',\n )\n const rootEl = (target as Element).closest<HTMLElement>(\n '[data-scope=\"sortable\"][data-part=\"root\"]',\n )\n if (itemEl && rootEl) {\n const items = rootEl.querySelectorAll<HTMLElement>(\n '[data-scope=\"sortable\"][data-part=\"item\"]',\n )\n for (let i = 0; i < items.length; i++) {\n if (items[i] === itemEl) {\n currentIndex = i\n break\n }\n }\n }\n }\n // Snapshot positions BEFORE the drag starts, so subsequent pointermove\n // events can resolve the target index against stable (pre-transform)\n // positions. Otherwise items shifting via CSS would cause the target\n // to oscillate as elementFromPoint hits different items.\n snapshotAll()\n send({\n type: 'start',\n id,\n index: currentIndex,\n container: containerId,\n x: e.clientX,\n y: e.clientY,\n })\n }),\n onKeyDown: tagSend(send, ['toggleGrab', 'cancel', 'moveBy'], (e) => {\n switch (e.key) {\n case ' ':\n case 'Enter':\n e.preventDefault()\n send({ type: 'toggleGrab', id, index, container: containerId })\n return\n case 'Escape':\n e.preventDefault()\n send({ type: 'cancel' })\n return\n case 'ArrowDown':\n case 'ArrowRight':\n e.preventDefault()\n send({ type: 'moveBy', delta: 1 })\n return\n case 'ArrowUp':\n case 'ArrowLeft':\n e.preventDefault()\n send({ type: 'moveBy', delta: -1 })\n return\n }\n }),\n }),\n }\n}\n\n// ── Reorder utility ────────────────────────────────────────────\n\n/**\n * Move an item in an array from one index to another, returning a new array.\n * Out-of-range indices are clamped to array bounds.\n */\nexport function reorder<T>(arr: readonly T[], from: number, to: number): T[] {\n const len = arr.length\n if (len === 0) return []\n const f = Math.max(0, Math.min(len - 1, from))\n const t = Math.max(0, Math.min(len - 1, to))\n if (f === t) return arr.slice()\n const result = arr.slice()\n const [item] = result.splice(f, 1)\n result.splice(t, 0, item)\n return result\n}\n\nexport const sortable = { init, update, connect, reorder }\n"]}
1
+ {"version":3,"file":"sortable.js","sourceRoot":"","sources":["../../src/components/sortable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAsGnC,MAAM,UAAU,IAAI;IAClB,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAA;AAC3B,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,KAAoB,EAAE,GAAgB;IAC3D,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;QACjB,KAAK,OAAO;YACV,OAAO;gBACL;oBACE,QAAQ,EAAE;wBACR,EAAE,EAAE,GAAG,CAAC,EAAE;wBACV,UAAU,EAAE,GAAG,CAAC,KAAK;wBACrB,YAAY,EAAE,GAAG,CAAC,KAAK;wBACvB,aAAa,EAAE,GAAG,CAAC,SAAS;wBAC5B,WAAW,EAAE,GAAG,CAAC,SAAS;wBAC1B,MAAM,EAAE,GAAG,CAAC,CAAC;wBACb,MAAM,EAAE,GAAG,CAAC,CAAC;wBACb,QAAQ,EAAE,GAAG,CAAC,CAAC;wBACf,QAAQ,EAAE,GAAG,CAAC,CAAC;qBAChB;iBACF;gBACD,EAAE;aACH,CAAA;QACH,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,IAAI,CAAC,KAAK,CAAC,QAAQ;gBAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;YACvC,IACE,KAAK,CAAC,QAAQ,CAAC,YAAY,KAAK,GAAG,CAAC,KAAK;gBACzC,KAAK,CAAC,QAAQ,CAAC,WAAW,KAAK,GAAG,CAAC,SAAS;gBAC5C,KAAK,CAAC,QAAQ,CAAC,QAAQ,KAAK,GAAG,CAAC,CAAC;gBACjC,KAAK,CAAC,QAAQ,CAAC,QAAQ,KAAK,GAAG,CAAC,CAAC,EACjC,CAAC;gBACD,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;YACpB,CAAC;YACD,OAAO;gBACL;oBACE,QAAQ,EAAE;wBACR,GAAG,KAAK,CAAC,QAAQ;wBACjB,YAAY,EAAE,GAAG,CAAC,KAAK;wBACvB,WAAW,EAAE,GAAG,CAAC,SAAS;wBAC1B,QAAQ,EAAE,GAAG,CAAC,CAAC;wBACf,QAAQ,EAAE,GAAG,CAAC,CAAC;qBAChB;iBACF;gBACD,EAAE;aACH,CAAA;QACH,CAAC;QACD,KAAK,MAAM;YACT,OAAO,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;QAChE,KAAK,QAAQ;YACX,OAAO,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;QAChE,KAAK,YAAY;YACf,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACnB,8CAA8C;gBAC9C,OAAO,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAA;YACjC,CAAC;YACD,2CAA2C;YAC3C,OAAO;gBACL;oBACE,QAAQ,EAAE;wBACR,EAAE,EAAE,GAAG,CAAC,EAAE;wBACV,UAAU,EAAE,GAAG,CAAC,KAAK;wBACrB,YAAY,EAAE,GAAG,CAAC,KAAK;wBACvB,aAAa,EAAE,GAAG,CAAC,SAAS;wBAC5B,WAAW,EAAE,GAAG,CAAC,SAAS;wBAC1B,MAAM,EAAE,CAAC;wBACT,MAAM,EAAE,CAAC;wBACT,QAAQ,EAAE,CAAC;wBACX,QAAQ,EAAE,CAAC;qBACZ;iBACF;gBACD,EAAE;aACH,CAAA;QACH,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,IAAI,CAAC,KAAK,CAAC,QAAQ;gBAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;YACvC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,YAAY,GAAG,GAAG,CAAC,KAAK,CAAC,CAAA;YACjE,IAAI,IAAI,KAAK,KAAK,CAAC,QAAQ,CAAC,YAAY;gBAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;YAC5D,OAAO,CAAC,EAAE,QAAQ,EAAE,EAAE,GAAG,KAAK,CAAC,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;QACtE,CAAC;IACH,CAAC;AACH,CAAC;AAuED,MAAM,UAAU,OAAO,CACrB,KAA4B,EAC5B,IAAuB,EACvB,IAAoB;IAEpB,+DAA+D;IAC/D,MAAM,WAAW,GAAG,IAAI,CAAC,EAAE,CAAA;IAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAA;IAelC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAoB,CAAA;IAE7C,SAAS,iBAAiB,CAAC,MAAmB,EAAE,GAAW;QACzD,MAAM,KAAK,GAAG,MAAM,CAAC,gBAAgB,CAAc,2CAA2C,CAAC,CAAA;QAC/F,+DAA+D;QAC/D,MAAM,IAAI,GAAoC,EAAE,CAAA;QAChD,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAA;QAC3C,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;YACxB,MAAM,CAAC,GAAG,IAAI,CAAC,qBAAqB,EAAE,CAAA;YACtC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,CAAA;YAC/D,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,EAAE,CAAA;YAC9B,IAAI,MAAM,KAAK,SAAS;gBAAE,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;QACpD,CAAC,CAAC,CAAA;QACF,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAA;IACzC,CAAC;IAED,SAAS,WAAW;QAClB,MAAM,KAAK,GAAG,QAAQ,CAAC,gBAAgB,CACrC,2CAA2C,CAC5C,CAAA;QACD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAA;YACpC,IAAI,GAAG;gBAAE,iBAAiB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;QACvC,CAAC;IACH,CAAC;IAED,yEAAyE;IACzE,wEAAwE;IACxE,uEAAuE;IACvE,sEAAsE;IACtE,mEAAmE;IACnE,yEAAyE;IACzE,SAAS,YAAY,CAAC,CAAe;QACnC,MAAM,KAAK,GAAG,QAAQ,CAAC,gBAAgB,CACrC,2CAA2C,CAC5C,CAAA;QACD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,CAAC,GAAG,IAAI,CAAC,qBAAqB,EAAE,CAAA;YACtC,IAAI,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,KAAK;gBAAE,SAAQ;YACvD,IAAI,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,MAAM;gBAAE,SAAQ;YACvD,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAA;YACpC,IAAI,CAAC,GAAG;gBAAE,SAAQ;YAClB,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YAC/B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,CAAA;YACxE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAA;YACtB,IAAI,OAAO,GAAG,CAAC,CAAA;YACf,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;gBACpB,+DAA+D;gBAC/D,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC,CAAA;gBAClC,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC,CAAA;gBAClC,IAAI,QAAQ,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;gBACpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBACrC,MAAM,EAAE,GAAG,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC,CAAA;oBACjC,MAAM,EAAE,GAAG,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC,CAAA;oBACjC,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAA;oBAC3B,IAAI,CAAC,GAAG,QAAQ,EAAE,CAAC;wBACjB,QAAQ,GAAG,CAAC,CAAA;wBACZ,OAAO,GAAG,CAAC,CAAA;oBACb,CAAC;gBACH,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,4DAA4D;gBAC5D,8DAA8D;gBAC9D,4DAA4D;gBAC5D,IAAI,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAA;gBAC/C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBACrC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAA;oBAC1C,IAAI,CAAC,GAAG,QAAQ,EAAE,CAAC;wBACjB,QAAQ,GAAG,CAAC,CAAA;wBACZ,OAAO,GAAG,CAAC,CAAA;oBACb,CAAC;gBACH,CAAC;YACH,CAAC;YACD,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,CAAA;QAC3C,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,OAAO;QACL,IAAI,EAAE;YACJ,YAAY,EAAE,UAAU;YACxB,WAAW,EAAE,MAAM;YACnB,mBAAmB,EAAE,WAAW;YAChC,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,aAAa,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE;gBAC3C,IAAI,CAAC,CAAC,CAAC,OAAO;oBAAE,OAAM;gBACtB,MAAM,GAAG,GAAG,YAAY,CAAC,CAAC,CAAC,CAAA;gBAC3B,IAAI,GAAG,KAAK,IAAI;oBACd,IAAI,CAAC;wBACH,IAAI,EAAE,MAAM;wBACZ,KAAK,EAAE,GAAG,CAAC,KAAK;wBAChB,SAAS,EAAE,GAAG,CAAC,SAAS;wBACxB,CAAC,EAAE,CAAC,CAAC,OAAO;wBACZ,CAAC,EAAE,CAAC,CAAC,OAAO;qBACb,CAAC,CAAA;YACN,CAAC,CAAC;YACF,WAAW,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE;gBACxC,SAAS,CAAC,KAAK,EAAE,CAAA;gBACjB,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAA;YACxB,CAAC,CAAC;YACF,eAAe,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE;gBAC9C,SAAS,CAAC,KAAK,EAAE,CAAA;gBACjB,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAA;YAC1B,CAAC,CAAC;SACH;QACD,IAAI,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;YACpB,YAAY,EAAE,UAAU;YACxB,WAAW,EAAE,MAAM;YACnB,YAAY,EAAE,MAAM,CAAC,KAAK,CAAC;YAC3B,SAAS,EAAE,EAAE;YACb,eAAe,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBAC/B,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAA;gBACpB,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,aAAa,KAAK,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;YAC1E,CAAC,CAAC;YACF,WAAW,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBAC3B,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAA;gBACpB,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,KAAK,WAAW;oBAAE,OAAO,SAAS,CAAA;gBACzD,qEAAqE;gBACrE,oEAAoE;gBACpE,2CAA2C;gBAC3C,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;gBACvC,MAAM,SAAS,GAAG,IAAI,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,KAAK,CAAA;gBAClD,OAAO,CAAC,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;YACtD,CAAC,CAAC;YACF,yEAAyE;YACzE,0EAA0E;YAC1E,yEAAyE;YACzE,EAAE;YACF,gEAAgE;YAChE,kEAAkE;YAClE,+DAA+D;YAC/D,sEAAsE;YACtE,6CAA6C;YAC7C,YAAY,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBAC5B,IAAI,MAAM,KAAK,IAAI;oBAAE,OAAO,SAAS,CAAA;gBACrC,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAA;gBACpB,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,aAAa,KAAK,WAAW,IAAI,CAAC,CAAC,WAAW,KAAK,WAAW;oBAAE,OAAO,SAAS,CAAA;gBAC5F,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE;oBAAE,OAAO,SAAS,CAAA;gBACjC,IAAI,CAAC,CAAC,UAAU,KAAK,CAAC,CAAC,YAAY;oBAAE,OAAO,SAAS,CAAA;gBACrD,8DAA8D;gBAC9D,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;gBACvC,MAAM,SAAS,GAAG,IAAI,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,KAAK,CAAA;gBAClD,IAAI,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,YAAY,EAAE,CAAC;oBAClC,4DAA4D;oBAC5D,IAAI,SAAS,GAAG,CAAC,CAAC,UAAU,IAAI,SAAS,IAAI,CAAC,CAAC,YAAY;wBAAE,OAAO,IAAI,CAAA;gBAC1E,CAAC;qBAAM,CAAC;oBACN,4DAA4D;oBAC5D,IAAI,SAAS,IAAI,CAAC,CAAC,YAAY,IAAI,SAAS,GAAG,CAAC,CAAC,UAAU;wBAAE,OAAO,MAAM,CAAA;gBAC5E,CAAC;gBACD,OAAO,SAAS,CAAA;YAClB,CAAC,CAAC;YACF,mEAAmE;YACnE,mEAAmE;YACnE,oEAAoE;YACpE,+DAA+D;YAC/D,mEAAmE;YACnE,oEAAoE;YACpE,QAAQ;YACR,iBAAiB,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBACjC,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAA;gBACpB,IAAI,CAAC,CAAC;oBAAE,OAAO,SAAS,CAAA;gBACxB,MAAM,SAAS,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,aAAa,KAAK,WAAW,CAAA;gBAChE,IAAI,SAAS,EAAE,CAAC;oBACd,MAAM,MAAM,GAAG,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAA;oBACpC,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;wBACpB,MAAM,MAAM,GAAG,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAA;wBACpC,OAAO,aAAa,MAAM,OAAO,MAAM,KAAK,CAAA;oBAC9C,CAAC;oBACD,OAAO,cAAc,MAAM,KAAK,CAAA;gBAClC,CAAC;gBACD,uDAAuD;gBACvD,IAAI,MAAM,KAAK,IAAI;oBAAE,OAAO,SAAS,CAAA;gBACrC,IAAI,CAAC,CAAC,aAAa,KAAK,WAAW,IAAI,CAAC,CAAC,WAAW,KAAK,WAAW;oBAAE,OAAO,SAAS,CAAA;gBACtF,IAAI,CAAC,CAAC,UAAU,KAAK,CAAC,CAAC,YAAY;oBAAE,OAAO,SAAS,CAAA;gBACrD,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;gBACvC,IAAI,CAAC,IAAI;oBAAE,OAAO,SAAS,CAAA;gBAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;gBACxC,IAAI,SAAS,KAAK,SAAS;oBAAE,OAAO,SAAS,CAAA;gBAC7C,6DAA6D;gBAC7D,wBAAwB;gBACxB,uDAAuD;gBACvD,8DAA8D;gBAC9D,2CAA2C;gBAC3C,qDAAqD;gBACrD,uDAAuD;gBACvD,qBAAqB;gBACrB,IAAI,UAAkB,CAAA;gBACtB,IAAI,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,YAAY,EAAE,CAAC;oBAClC,IAAI,SAAS,IAAI,CAAC,CAAC,UAAU,IAAI,SAAS,GAAG,CAAC,CAAC,YAAY;wBAAE,OAAO,SAAS,CAAA;oBAC7E,UAAU,GAAG,SAAS,GAAG,CAAC,CAAA;gBAC5B,CAAC;qBAAM,CAAC;oBACN,IAAI,SAAS,GAAG,CAAC,CAAC,YAAY,IAAI,SAAS,IAAI,CAAC,CAAC,UAAU;wBAAE,OAAO,SAAS,CAAA;oBAC7E,UAAU,GAAG,SAAS,GAAG,CAAC,CAAA;gBAC5B,CAAC;gBACD,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;gBAChC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;gBACpC,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM;oBAAE,OAAO,SAAS,CAAA;gBACrC,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAA;gBAC3B,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAA;gBAC3B,OAAO,aAAa,EAAE,OAAO,EAAE,KAAK,CAAA;YACtC,CAAC,CAAC;YACF,cAAc,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBAC9B,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAA;gBACpB,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,aAAa,KAAK,WAAW;oBAAE,OAAO,SAAS,CAAA;gBAC1E,OAAO,IAAI,CAAA;YACb,CAAC,CAAC;SACH,CAAC;QACF,MAAM,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;YACtB,YAAY,EAAE,UAAU;YACxB,WAAW,EAAE,QAAQ;YACrB,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,CAAC;YACX,cAAc,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBAC9B,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAA;gBACpB,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,aAAa,KAAK,WAAW,CAAA;YACzD,CAAC,CAAC;YACF,YAAY,EACV,iGAAiG;YACnG,aAAa,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE;gBAC5C,CAAC,CAAC,cAAc,EAAE,CAAA;gBAClB,MAAM,MAAM,GAAG,CAAC,CAAC,aAA+B,CAAA;gBAChD,IAAI,MAAM,IAAI,mBAAmB,IAAI,MAAM,EAAE,CAAC;oBAC5C,IAAI,CAAC;wBACH,CAAC;wBAAC,MAAgE,CAAC,iBAAiB,CAClF,CAAC,CAAC,SAAS,CACZ,CAAA;oBACH,CAAC;oBAAC,MAAM,CAAC;wBACP,oDAAoD;oBACtD,CAAC;gBACH,CAAC;gBACD,qEAAqE;gBACrE,mEAAmE;gBACnE,iEAAiE;gBACjE,sEAAsE;gBACtE,gCAAgC;gBAChC,IAAI,YAAY,GAAG,KAAK,CAAA;gBACxB,IAAI,MAAM,EAAE,CAAC;oBACX,MAAM,MAAM,GAAI,MAAkB,CAAC,OAAO,CACxC,2CAA2C,CAC5C,CAAA;oBACD,MAAM,MAAM,GAAI,MAAkB,CAAC,OAAO,CACxC,2CAA2C,CAC5C,CAAA;oBACD,IAAI,MAAM,IAAI,MAAM,EAAE,CAAC;wBACrB,MAAM,KAAK,GAAG,MAAM,CAAC,gBAAgB,CACnC,2CAA2C,CAC5C,CAAA;wBACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;4BACtC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;gCACxB,YAAY,GAAG,CAAC,CAAA;gCAChB,MAAK;4BACP,CAAC;wBACH,CAAC;oBACH,CAAC;gBACH,CAAC;gBACD,uEAAuE;gBACvE,qEAAqE;gBACrE,qEAAqE;gBACrE,yDAAyD;gBACzD,WAAW,EAAE,CAAA;gBACb,IAAI,CAAC;oBACH,IAAI,EAAE,OAAO;oBACb,EAAE;oBACF,KAAK,EAAE,YAAY;oBACnB,SAAS,EAAE,WAAW;oBACtB,CAAC,EAAE,CAAC,CAAC,OAAO;oBACZ,CAAC,EAAE,CAAC,CAAC,OAAO;iBACb,CAAC,CAAA;YACJ,CAAC,CAAC;YACF,SAAS,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,YAAY,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE;gBACjE,QAAQ,CAAC,CAAC,GAAG,EAAE,CAAC;oBACd,KAAK,GAAG,CAAC;oBACT,KAAK,OAAO;wBACV,CAAC,CAAC,cAAc,EAAE,CAAA;wBAClB,IAAI,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,CAAA;wBAC/D,OAAM;oBACR,KAAK,QAAQ;wBACX,CAAC,CAAC,cAAc,EAAE,CAAA;wBAClB,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAA;wBACxB,OAAM;oBACR,KAAK,WAAW,CAAC;oBACjB,KAAK,YAAY;wBACf,CAAC,CAAC,cAAc,EAAE,CAAA;wBAClB,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAA;wBAClC,OAAM;oBACR,KAAK,SAAS,CAAC;oBACf,KAAK,WAAW;wBACd,CAAC,CAAC,cAAc,EAAE,CAAA;wBAClB,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,CAAA;wBACnC,OAAM;gBACV,CAAC;YACH,CAAC,CAAC;SACH,CAAC;KACH,CAAA;AACH,CAAC;AAED,kEAAkE;AAElE;;;GAGG;AACH,MAAM,UAAU,OAAO,CAAI,GAAiB,EAAE,IAAY,EAAE,EAAU;IACpE,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAA;IACtB,IAAI,GAAG,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IACxB,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,CAAA;IAC9C,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAA;IAC5C,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC,KAAK,EAAE,CAAA;IAC/B,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,EAAE,CAAA;IAC1B,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAClC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAA;IACzB,OAAO,MAAM,CAAA;AACf,CAAC;AAED,MAAM,CAAC,MAAM,QAAQ,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,CAAA","sourcesContent":["import { tagSend } from '@llui/dom'\nimport type { Send, Signal } from '@llui/dom'\n\n/**\n * Sortable — pointer-based reorderable list.\n *\n * State machine tracks the currently-dragged item and where it's hovering.\n * The app owns the actual array; listen for `drop` and use `reorder(arr, from, to)`\n * to compute the new order, or watch `currentIndex` during drag for live preview.\n *\n * ```ts\n * type State = { items: string[]; sort: SortableState }\n *\n * update: (state, msg) => {\n * switch (msg.type) {\n * case 'sort':\n * return [{ ...state, sort: sortable.update(state.sort, msg.msg)[0] }, []]\n * case 'drop': {\n * const d = state.sort.dragging\n * if (!d) return [state, []]\n * return [{ ...state, items: reorder(state.items, d.startIndex, d.currentIndex) }, []]\n * }\n * }\n * }\n *\n * view: ({ send, each, text }) => {\n * const s = sortable.connect(state.map((s) => s.sort), m => send({ type: 'sort', msg: m }), { id: 'list' })\n * return [\n * ul({ ...s.root, class: 'list' }, [\n * ...each({\n * items: (st) => st.items,\n * key: (x) => x,\n * render: ({ item, index }) => [\n * li({ ...s.item(item(), index()), class: 'item' }, [\n * div({ ...s.handle(item(), index()), class: 'handle' }, [text('⋮⋮')]),\n * text(item),\n * ]),\n * ],\n * }),\n * ]),\n * ]\n * }\n * ```\n *\n * Hook up pointermove/pointerup at the root (attachPointerHandlers) — or\n * wire them directly via `onPointerMove` / `onPointerUp` on the root part.\n */\n\nexport interface DragState {\n id: string\n startIndex: number\n currentIndex: number\n /**\n * Container the drag originated from. Defaults to the connect's `id` for\n * single-container sortables. Set when multiple sortables share state.\n */\n fromContainer: string\n /**\n * Container the pointer is currently over. Same as `fromContainer` for\n * single-container sortables. Differs when dragging across containers.\n */\n toContainer: string\n /**\n * Pointer X at drag start (viewport coordinates). Used by 2D layouts\n * to compute `deltaX = currentX - startX` alongside the Y axis. In 1D\n * layouts X is tracked but ignored by the renderer.\n */\n startX: number\n /**\n * Pointer Y at drag start (viewport coordinates). Used by CSS / the\n * library's `style.transform` binding to make the dragged item follow\n * the pointer.\n */\n startY: number\n /**\n * Current pointer X (viewport coordinates). `deltaX = currentX - startX`.\n */\n currentX: number\n /**\n * Current pointer Y (viewport coordinates). `deltaY = currentY - startY`.\n */\n currentY: number\n}\n\nexport interface SortableState {\n dragging: DragState | null\n}\n\nexport type SortableMsg =\n /** @humanOnly */\n | { type: 'start'; id: string; index: number; container: string; x: number; y: number }\n /** @humanOnly */\n | { type: 'move'; index: number; container: string; x: number; y: number }\n /** @humanOnly */\n | { type: 'drop' }\n /** @humanOnly */\n | { type: 'cancel' }\n /** @humanOnly */\n | { type: 'toggleGrab'; id: string; index: number; container: string }\n /** @humanOnly */\n | { type: 'moveBy'; delta: number }\n\nexport function init(): SortableState {\n return { dragging: null }\n}\n\nexport function update(state: SortableState, msg: SortableMsg): [SortableState, never[]] {\n switch (msg.type) {\n case 'start':\n return [\n {\n dragging: {\n id: msg.id,\n startIndex: msg.index,\n currentIndex: msg.index,\n fromContainer: msg.container,\n toContainer: msg.container,\n startX: msg.x,\n startY: msg.y,\n currentX: msg.x,\n currentY: msg.y,\n },\n },\n [],\n ]\n case 'move': {\n if (!state.dragging) return [state, []]\n if (\n state.dragging.currentIndex === msg.index &&\n state.dragging.toContainer === msg.container &&\n state.dragging.currentX === msg.x &&\n state.dragging.currentY === msg.y\n ) {\n return [state, []]\n }\n return [\n {\n dragging: {\n ...state.dragging,\n currentIndex: msg.index,\n toContainer: msg.container,\n currentX: msg.x,\n currentY: msg.y,\n },\n },\n [],\n ]\n }\n case 'drop':\n return state.dragging ? [{ dragging: null }, []] : [state, []]\n case 'cancel':\n return state.dragging ? [{ dragging: null }, []] : [state, []]\n case 'toggleGrab':\n if (state.dragging) {\n // Already dragging — drop at current position\n return [{ dragging: null }, []]\n }\n // Pick up (keyboard — no pointer position)\n return [\n {\n dragging: {\n id: msg.id,\n startIndex: msg.index,\n currentIndex: msg.index,\n fromContainer: msg.container,\n toContainer: msg.container,\n startX: 0,\n startY: 0,\n currentX: 0,\n currentY: 0,\n },\n },\n [],\n ]\n case 'moveBy': {\n if (!state.dragging) return [state, []]\n const next = Math.max(0, state.dragging.currentIndex + msg.delta)\n if (next === state.dragging.currentIndex) return [state, []]\n return [{ dragging: { ...state.dragging, currentIndex: next } }, []]\n }\n }\n}\n\nexport interface SortableParts {\n root: {\n 'data-scope': 'sortable'\n 'data-part': 'root'\n 'data-container-id': string\n 'data-dragging': Signal<'' | undefined>\n onPointerMove: (e: PointerEvent) => void\n onPointerUp: (e: PointerEvent) => void\n onPointerCancel: (e: PointerEvent) => void\n }\n item: (\n id: string,\n index: number,\n ) => {\n 'data-scope': 'sortable'\n 'data-part': 'item'\n 'data-index': string\n 'data-id': string\n 'data-dragging': Signal<'' | undefined>\n 'data-over': Signal<'' | undefined>\n 'data-shift': Signal<'up' | 'down' | undefined>\n 'style.transform': Signal<string | undefined>\n 'style.zIndex': Signal<string | undefined>\n }\n handle: (\n id: string,\n index: number,\n ) => {\n 'data-scope': 'sortable'\n 'data-part': 'handle'\n role: 'button'\n tabIndex: 0\n 'aria-grabbed': Signal<boolean>\n 'aria-label': string\n onPointerDown: (e: PointerEvent) => void\n onKeyDown: (e: KeyboardEvent) => void\n }\n}\n\nexport interface ConnectOptions {\n id: string\n /**\n * Drag-target selection + render strategy.\n *\n * - `'1d'` (default) — single-axis, Y-only. `findTargetAt` picks\n * by vertical distance; `style.transform` on the dragged item\n * is `translateY(deltaY)`; non-dragged items between source\n * and target emit `data-shift: 'up' | 'down'` so CSS can\n * animate them via `translateY(±var(--sortable-shift))`.\n * Correct for vertical lists; fails for 2D layouts (flex-wrap,\n * grid) because same-row items collapse to the same midpoint\n * distance.\n *\n * - `'2d'` — Euclidean target selection against 2D midpoints;\n * dragged item follows both X and Y (`translate(dx, dy)`);\n * non-dragged items between source and target get a per-item\n * `style.transform = translate(deltaFromSnapshot)` that opens\n * the correct gap regardless of row boundaries. `data-shift`\n * is always `undefined` in 2D so CSS `translateY(var(--...))`\n * rules don't conflict with the per-item transform.\n *\n * Keyboard navigation (`moveBy`) stays linear-array in both modes —\n * arrow keys step through the array indices regardless of visual\n * row, because that's what screen readers announce and what the\n * underlying data order actually is.\n */\n layout?: '1d' | '2d'\n}\n\nexport function connect(\n state: Signal<SortableState>,\n send: Send<SortableMsg>,\n opts: ConnectOptions,\n): SortableParts {\n // The connect's `id` doubles as the cross-container identifier\n const containerId = opts.id\n const layout = opts.layout ?? '1d'\n\n // Snapshots taken at drag start — stable throughout the drag so computing\n // the target index is not affected by items visually shifting via CSS.\n // Map: container-id → array of midpoint {x, y} pairs for each item's\n // original bounding rect (sorted by index). The handler records this on\n // pointerdown. Always 2D internally; 1D layout's findTargetAt ignores X.\n interface Snapshot {\n mids: Array<{ x: number; y: number }>\n // id → current DOM index at drag start. Used by data-shift / per-item\n // transform to look up an item's live position, since the `index`\n // captured at render time is frozen and goes stale after each()\n // reconciles a reorder.\n idToIndex: Map<string, number>\n }\n const snapshots = new Map<string, Snapshot>()\n\n function snapshotContainer(rootEl: HTMLElement, cid: string): void {\n const items = rootEl.querySelectorAll<HTMLElement>('[data-scope=\"sortable\"][data-part=\"item\"]')\n // Read rects once — they're pre-transform (no drag shifts yet)\n const mids: Array<{ x: number; y: number }> = []\n const idToIndex = new Map<string, number>()\n items.forEach((item, i) => {\n const r = item.getBoundingClientRect()\n mids.push({ x: r.left + r.width / 2, y: r.top + r.height / 2 })\n const itemId = item.dataset.id\n if (itemId !== undefined) idToIndex.set(itemId, i)\n })\n snapshots.set(cid, { mids, idToIndex })\n }\n\n function snapshotAll(): void {\n const roots = document.querySelectorAll<HTMLElement>(\n '[data-scope=\"sortable\"][data-part=\"root\"]',\n )\n for (const root of roots) {\n const cid = root.dataset.containerId\n if (cid) snapshotContainer(root, cid)\n }\n }\n\n // Find the target index under the pointer using the drag-start snapshot.\n // 1D mode: picks by Y-only distance (original behavior). 2D mode: picks\n // by Euclidean distance over {x, y} midpoints — required for flex-wrap\n // / grid layouts where multiple items share a row and collapse to the\n // same Y value. Both modes are stable against items being visually\n // transformed during the drag because midpoints are taken pre-transform.\n function findTargetAt(e: PointerEvent): { container: string; index: number } | null {\n const roots = document.querySelectorAll<HTMLElement>(\n '[data-scope=\"sortable\"][data-part=\"root\"]',\n )\n for (const root of roots) {\n const r = root.getBoundingClientRect()\n if (e.clientX < r.left || e.clientX > r.right) continue\n if (e.clientY < r.top || e.clientY > r.bottom) continue\n const cid = root.dataset.containerId\n if (!cid) continue\n const snap = snapshots.get(cid)\n if (!snap || snap.mids.length === 0) return { container: cid, index: 0 }\n const mids = snap.mids\n let bestIdx = 0\n if (layout === '2d') {\n // Euclidean (squared — monotonic with distance, saves a sqrt).\n const dx0 = e.clientX - mids[0]!.x\n const dy0 = e.clientY - mids[0]!.y\n let bestDist = dx0 * dx0 + dy0 * dy0\n for (let i = 1; i < mids.length; i++) {\n const dx = e.clientX - mids[i]!.x\n const dy = e.clientY - mids[i]!.y\n const d = dx * dx + dy * dy\n if (d < bestDist) {\n bestDist = d\n bestIdx = i\n }\n }\n } else {\n // 1D — Y-only distance. Preserves the original behavior for\n // vertical lists; same-row items in a flex-wrap would tie and\n // the first match wins, which is the bug that motivates 2D.\n let bestDist = Math.abs(e.clientY - mids[0]!.y)\n for (let i = 1; i < mids.length; i++) {\n const d = Math.abs(e.clientY - mids[i]!.y)\n if (d < bestDist) {\n bestDist = d\n bestIdx = i\n }\n }\n }\n return { container: cid, index: bestIdx }\n }\n return null\n }\n\n return {\n root: {\n 'data-scope': 'sortable',\n 'data-part': 'root',\n 'data-container-id': containerId,\n 'data-dragging': state.map((s) => (s.dragging ? '' : undefined)),\n onPointerMove: tagSend(send, ['move'], (e) => {\n if (!e.buttons) return\n const hit = findTargetAt(e)\n if (hit !== null)\n send({\n type: 'move',\n index: hit.index,\n container: hit.container,\n x: e.clientX,\n y: e.clientY,\n })\n }),\n onPointerUp: tagSend(send, ['drop'], () => {\n snapshots.clear()\n send({ type: 'drop' })\n }),\n onPointerCancel: tagSend(send, ['cancel'], () => {\n snapshots.clear()\n send({ type: 'cancel' })\n }),\n },\n item: (id, index) => ({\n 'data-scope': 'sortable',\n 'data-part': 'item',\n 'data-index': String(index),\n 'data-id': id,\n 'data-dragging': state.map((s) => {\n const d = s.dragging\n return d?.id === id && d?.fromContainer === containerId ? '' : undefined\n }),\n 'data-over': state.map((s) => {\n const d = s.dragging\n if (!d || d.toContainer !== containerId) return undefined\n // Look up this item's CURRENT DOM index via the drag-start snapshot.\n // The `index` closed over here is frozen at initial render and goes\n // stale after each() reconciles a reorder.\n const snap = snapshots.get(containerId)\n const liveIndex = snap?.idToIndex.get(id) ?? index\n return d.currentIndex === liveIndex ? '' : undefined\n }),\n // Shift direction for items BETWEEN the source and target (excluding the\n // dragged item itself). 'down' = item should translate down to make room;\n // 'up' = item should translate up. CSS controls the actual displacement.\n //\n // In 2D layout, `data-shift` is always undefined — the per-item\n // `style.transform` below opens the correct gap directly. Keeping\n // `data-shift` out of the 2D path prevents any author-provided\n // CSS rule like `[data-shift] { translate: 0 var(--sortable-shift) }`\n // from fighting with the computed transform.\n 'data-shift': state.map((s) => {\n if (layout === '2d') return undefined\n const d = s.dragging\n if (!d || d.fromContainer !== containerId || d.toContainer !== containerId) return undefined\n if (d.id === id) return undefined\n if (d.startIndex === d.currentIndex) return undefined\n // Look up this item's live DOM index — see note on data-over.\n const snap = snapshots.get(containerId)\n const liveIndex = snap?.idToIndex.get(id) ?? index\n if (d.startIndex < d.currentIndex) {\n // Dragging down: items between start+1 and current shift up\n if (liveIndex > d.startIndex && liveIndex <= d.currentIndex) return 'up'\n } else {\n // Dragging up: items between current and start-1 shift down\n if (liveIndex >= d.currentIndex && liveIndex < d.startIndex) return 'down'\n }\n return undefined\n }),\n // The dragged item follows the pointer. In 1D, translateY only; in\n // 2D, both axes. Non-dragged items in 2D between source and target\n // get a per-item translate computed from the snapshot — each item's\n // vector is `snapshot[newSlot] - snapshot[ownSlot]` so the gap\n // opens correctly regardless of row wrap. In 1D, non-dragged items\n // emit `undefined` here and rely on the consumer's CSS `data-shift`\n // rule.\n 'style.transform': state.map((s) => {\n const d = s.dragging\n if (!d) return undefined\n const isDragged = d.id === id && d.fromContainer === containerId\n if (isDragged) {\n const deltaY = d.currentY - d.startY\n if (layout === '2d') {\n const deltaX = d.currentX - d.startX\n return `translate(${deltaX}px, ${deltaY}px)`\n }\n return `translateY(${deltaY}px)`\n }\n // Non-dragged items: per-item displacement in 2D only.\n if (layout !== '2d') return undefined\n if (d.fromContainer !== containerId || d.toContainer !== containerId) return undefined\n if (d.startIndex === d.currentIndex) return undefined\n const snap = snapshots.get(containerId)\n if (!snap) return undefined\n const liveIndex = snap.idToIndex.get(id)\n if (liveIndex === undefined) return undefined\n // Which slot this item should visually occupy while the drag\n // previews the reorder:\n // drag-down (start < current): items at liveIndex in\n // (start .. current] shift left-by-one in array order, so\n // they take the slot at liveIndex - 1.\n // drag-up (current < start): items at liveIndex in\n // [current .. start) shift right-by-one, take slot\n // liveIndex + 1.\n let targetSlot: number\n if (d.startIndex < d.currentIndex) {\n if (liveIndex <= d.startIndex || liveIndex > d.currentIndex) return undefined\n targetSlot = liveIndex - 1\n } else {\n if (liveIndex < d.currentIndex || liveIndex >= d.startIndex) return undefined\n targetSlot = liveIndex + 1\n }\n const own = snap.mids[liveIndex]\n const target = snap.mids[targetSlot]\n if (!own || !target) return undefined\n const dx = target.x - own.x\n const dy = target.y - own.y\n return `translate(${dx}px, ${dy}px)`\n }),\n 'style.zIndex': state.map((s) => {\n const d = s.dragging\n if (!d || d.id !== id || d.fromContainer !== containerId) return undefined\n return '10'\n }),\n }),\n handle: (id, index) => ({\n 'data-scope': 'sortable',\n 'data-part': 'handle',\n role: 'button',\n tabIndex: 0,\n 'aria-grabbed': state.map((s) => {\n const d = s.dragging\n return d?.id === id && d?.fromContainer === containerId\n }),\n 'aria-label':\n 'Drag handle. Press space to pick up, arrow keys to move, space again to drop, escape to cancel.',\n onPointerDown: tagSend(send, ['start'], (e) => {\n e.preventDefault()\n const target = e.currentTarget as Element | null\n if (target && 'setPointerCapture' in target) {\n try {\n ;(target as Element & { setPointerCapture: (id: number) => void }).setPointerCapture(\n e.pointerId,\n )\n } catch {\n // Ignore — not all elements support pointer capture\n }\n }\n // Compute the CURRENT DOM index of this handle's item — the captured\n // `index` param is stale after a reorder (each() moves keyed nodes\n // without re-running render, so the closure's index is frozen at\n // initial mount). Walk up to find the containing item, then count its\n // position among sibling items.\n let currentIndex = index\n if (target) {\n const itemEl = (target as Element).closest<HTMLElement>(\n '[data-scope=\"sortable\"][data-part=\"item\"]',\n )\n const rootEl = (target as Element).closest<HTMLElement>(\n '[data-scope=\"sortable\"][data-part=\"root\"]',\n )\n if (itemEl && rootEl) {\n const items = rootEl.querySelectorAll<HTMLElement>(\n '[data-scope=\"sortable\"][data-part=\"item\"]',\n )\n for (let i = 0; i < items.length; i++) {\n if (items[i] === itemEl) {\n currentIndex = i\n break\n }\n }\n }\n }\n // Snapshot positions BEFORE the drag starts, so subsequent pointermove\n // events can resolve the target index against stable (pre-transform)\n // positions. Otherwise items shifting via CSS would cause the target\n // to oscillate as elementFromPoint hits different items.\n snapshotAll()\n send({\n type: 'start',\n id,\n index: currentIndex,\n container: containerId,\n x: e.clientX,\n y: e.clientY,\n })\n }),\n onKeyDown: tagSend(send, ['toggleGrab', 'cancel', 'moveBy'], (e) => {\n switch (e.key) {\n case ' ':\n case 'Enter':\n e.preventDefault()\n send({ type: 'toggleGrab', id, index, container: containerId })\n return\n case 'Escape':\n e.preventDefault()\n send({ type: 'cancel' })\n return\n case 'ArrowDown':\n case 'ArrowRight':\n e.preventDefault()\n send({ type: 'moveBy', delta: 1 })\n return\n case 'ArrowUp':\n case 'ArrowLeft':\n e.preventDefault()\n send({ type: 'moveBy', delta: -1 })\n return\n }\n }),\n }),\n }\n}\n\n// ── Reorder utility ────────────────────────────────────────────\n\n/**\n * Move an item in an array from one index to another, returning a new array.\n * Out-of-range indices are clamped to array bounds.\n */\nexport function reorder<T>(arr: readonly T[], from: number, to: number): T[] {\n const len = arr.length\n if (len === 0) return []\n const f = Math.max(0, Math.min(len - 1, from))\n const t = Math.max(0, Math.min(len - 1, to))\n if (f === t) return arr.slice()\n const result = arr.slice()\n const [item] = result.splice(f, 1)\n result.splice(t, 0, item)\n return result\n}\n\nexport const sortable = { init, update, connect, reorder }\n"]}
@@ -1,4 +1,4 @@
1
- import type { Send } from '@llui/dom';
1
+ import type { Send, Signal } from '@llui/dom';
2
2
  /**
3
3
  * Splitter — resizable panes with a draggable handle. The handle's position
4
4
  * is expressed as a percentage of the container, stored as a number 0..100.
@@ -58,40 +58,40 @@ export declare function init(opts?: SplitterInit): SplitterState;
58
58
  export declare function update(state: SplitterState, msg: SplitterMsg): [SplitterState, never[]];
59
59
  /** Compute position percentage from a pointer event within a container rect. */
60
60
  export declare function positionFromPoint(state: SplitterState, rect: DOMRect, clientX: number, clientY: number): number;
61
- export interface SplitterParts<S> {
61
+ export interface SplitterParts {
62
62
  root: {
63
63
  'data-scope': 'splitter';
64
64
  'data-part': 'root';
65
- 'data-orientation': (s: S) => Orientation;
66
- 'data-disabled': (s: S) => '' | undefined;
67
- 'data-dragging': (s: S) => '' | undefined;
65
+ 'data-orientation': Signal<Orientation>;
66
+ 'data-disabled': Signal<'' | undefined>;
67
+ 'data-dragging': Signal<'' | undefined>;
68
68
  };
69
69
  primaryPanel: {
70
70
  'data-scope': 'splitter';
71
71
  'data-part': 'primary-panel';
72
- style: (s: S) => string;
72
+ style: Signal<string>;
73
73
  };
74
74
  secondaryPanel: {
75
75
  'data-scope': 'splitter';
76
76
  'data-part': 'secondary-panel';
77
- style: (s: S) => string;
77
+ style: Signal<string>;
78
78
  };
79
79
  resizeTrigger: {
80
80
  role: 'separator';
81
- 'aria-orientation': (s: S) => Orientation;
82
- 'aria-valuemin': (s: S) => number;
83
- 'aria-valuemax': (s: S) => number;
84
- 'aria-valuenow': (s: S) => number;
85
- 'aria-disabled': (s: S) => 'true' | undefined;
81
+ 'aria-orientation': Signal<Orientation>;
82
+ 'aria-valuemin': Signal<number>;
83
+ 'aria-valuemax': Signal<number>;
84
+ 'aria-valuenow': Signal<number>;
85
+ 'aria-disabled': Signal<'true' | undefined>;
86
86
  'data-scope': 'splitter';
87
87
  'data-part': 'resize-trigger';
88
- 'data-orientation': (s: S) => Orientation;
89
- tabIndex: (s: S) => number;
88
+ 'data-orientation': Signal<Orientation>;
89
+ tabIndex: Signal<number>;
90
90
  onKeyDown: (e: KeyboardEvent) => void;
91
91
  onPointerDown: (e: PointerEvent) => void;
92
92
  };
93
93
  }
94
- export declare function connect<S>(get: (s: S) => SplitterState, send: Send<SplitterMsg>): SplitterParts<S>;
94
+ export declare function connect(state: Signal<SplitterState>, send: Send<SplitterMsg>): SplitterParts;
95
95
  export declare const splitter: {
96
96
  init: typeof init;
97
97
  update: typeof update;