@k2b/ui 0.32.0 → 0.34.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (292) hide show
  1. package/dist/base.css +14 -1
  2. package/dist/browser/actions/ContextMenu.js +13 -0
  3. package/dist/browser/actions/ContextMenu.js.map +1 -1
  4. package/dist/browser/actions/Dropdown.js +173 -102
  5. package/dist/browser/actions/Dropdown.js.map +1 -1
  6. package/dist/browser/actions/FilterChip.js +113 -56
  7. package/dist/browser/actions/FilterChip.js.map +1 -1
  8. package/dist/browser/actions/SelectionToolbar.js +129 -0
  9. package/dist/browser/actions/SelectionToolbar.js.map +1 -0
  10. package/dist/browser/actions/filter-messages.js +26 -2
  11. package/dist/browser/actions/filter-messages.js.map +1 -1
  12. package/dist/browser/actions/index.js +1 -0
  13. package/dist/browser/actions/index.js.map +1 -1
  14. package/dist/browser/actions/menu-rows.js +23 -3
  15. package/dist/browser/actions/menu-rows.js.map +1 -1
  16. package/dist/browser/actions/menu-sheet.js +2 -7
  17. package/dist/browser/actions/menu-sheet.js.map +1 -1
  18. package/dist/browser/charts.js +6 -0
  19. package/dist/browser/charts.js.map +1 -0
  20. package/dist/browser/chat/ChatComposer.js +616 -421
  21. package/dist/browser/chat/ChatComposer.js.map +1 -1
  22. package/dist/browser/chat/chat-messages.js +18 -0
  23. package/dist/browser/chat/chat-messages.js.map +1 -1
  24. package/dist/browser/chat/composer-document.js +19 -0
  25. package/dist/browser/chat/composer-document.js.map +1 -1
  26. package/dist/browser/chat/index.js.map +1 -1
  27. package/dist/browser/content/Calendar.js +39 -29
  28. package/dist/browser/content/Calendar.js.map +1 -1
  29. package/dist/browser/content/CalendarDayView.js +159 -165
  30. package/dist/browser/content/CalendarDayView.js.map +1 -1
  31. package/dist/browser/content/Chart.js +8 -0
  32. package/dist/browser/content/Chart.js.map +1 -1
  33. package/dist/browser/content/FileGrid.js +231 -9
  34. package/dist/browser/content/FileGrid.js.map +1 -1
  35. package/dist/browser/content/FileTypeIcon.js +15 -0
  36. package/dist/browser/content/FileTypeIcon.js.map +1 -1
  37. package/dist/browser/content/FileView.js +11 -4
  38. package/dist/browser/content/FileView.js.map +1 -1
  39. package/dist/browser/content/MessageRow.js +627 -343
  40. package/dist/browser/content/MessageRow.js.map +1 -1
  41. package/dist/browser/content/ReactionBar.js +20 -1
  42. package/dist/browser/content/ReactionBar.js.map +1 -1
  43. package/dist/browser/content/calendar-day-scroll.js +4 -3
  44. package/dist/browser/content/calendar-day-scroll.js.map +1 -1
  45. package/dist/browser/content/chart-bar.js +476 -0
  46. package/dist/browser/content/chart-bar.js.map +1 -0
  47. package/dist/browser/content/file-list-messages.js +52 -0
  48. package/dist/browser/content/file-list-messages.js.map +1 -0
  49. package/dist/browser/content/index.js +2 -2
  50. package/dist/browser/content/index.js.map +1 -1
  51. package/dist/browser/feedback/Tooltip.js +31 -14
  52. package/dist/browser/feedback/Tooltip.js.map +1 -1
  53. package/dist/browser/feedback/dialog-core.js +6 -0
  54. package/dist/browser/feedback/dialog-core.js.map +1 -1
  55. package/dist/browser/inputs/ChoiceList.js +178 -0
  56. package/dist/browser/inputs/ChoiceList.js.map +1 -0
  57. package/dist/browser/inputs/ChoiceSlider.js +314 -0
  58. package/dist/browser/inputs/ChoiceSlider.js.map +1 -0
  59. package/dist/browser/inputs/ChoiceTiles.js +135 -0
  60. package/dist/browser/inputs/ChoiceTiles.js.map +1 -0
  61. package/dist/browser/inputs/ColorChoices.js +120 -0
  62. package/dist/browser/inputs/ColorChoices.js.map +1 -0
  63. package/dist/browser/inputs/QrScanner.js +95 -13
  64. package/dist/browser/inputs/QrScanner.js.map +1 -1
  65. package/dist/browser/inputs/TextInput.js +19 -14
  66. package/dist/browser/inputs/TextInput.js.map +1 -1
  67. package/dist/browser/inputs/index.js +4 -0
  68. package/dist/browser/inputs/index.js.map +1 -1
  69. package/dist/browser/inputs/qr-messages.js +2 -0
  70. package/dist/browser/inputs/qr-messages.js.map +1 -1
  71. package/dist/browser/internal/radio-keys.js +13 -0
  72. package/dist/browser/internal/radio-keys.js.map +1 -0
  73. package/dist/browser/intl/shortcut-messages.js +4 -0
  74. package/dist/browser/intl/shortcut-messages.js.map +1 -1
  75. package/dist/browser/intl/shortcut.js +4 -0
  76. package/dist/browser/intl/shortcut.js.map +1 -1
  77. package/dist/browser/layout/AnchoredPopover.js +180 -0
  78. package/dist/browser/layout/AnchoredPopover.js.map +1 -0
  79. package/dist/browser/layout/AppWorkspace.js +684 -532
  80. package/dist/browser/layout/AppWorkspace.js.map +1 -1
  81. package/dist/browser/layout/DetailPanel.js +443 -333
  82. package/dist/browser/layout/DetailPanel.js.map +1 -1
  83. package/dist/browser/layout/MobileShell.js +231 -42
  84. package/dist/browser/layout/MobileShell.js.map +1 -1
  85. package/dist/browser/layout/Settings.js +283 -175
  86. package/dist/browser/layout/Settings.js.map +1 -1
  87. package/dist/browser/layout/SidebarRailHint.js +79 -0
  88. package/dist/browser/layout/SidebarRailHint.js.map +1 -0
  89. package/dist/browser/layout/SidebarSwitcher.js +79 -66
  90. package/dist/browser/layout/SidebarSwitcher.js.map +1 -1
  91. package/dist/browser/layout/TabBar.js +18 -4
  92. package/dist/browser/layout/TabBar.js.map +1 -1
  93. package/dist/browser/layout/app-workspace-controller.js +11 -4
  94. package/dist/browser/layout/app-workspace-controller.js.map +1 -1
  95. package/dist/browser/layout/detail-panel-messages.js +4 -2
  96. package/dist/browser/layout/detail-panel-messages.js.map +1 -1
  97. package/dist/browser/layout/index.js +3 -1
  98. package/dist/browser/layout/index.js.map +1 -1
  99. package/dist/browser/layout/scroll-fade.js +32 -5
  100. package/dist/browser/layout/scroll-fade.js.map +1 -1
  101. package/dist/browser/layout/settings-messages.js +26 -2
  102. package/dist/browser/layout/settings-messages.js.map +1 -1
  103. package/dist/browser/surfaces/Avatar.js +2 -14
  104. package/dist/browser/surfaces/Avatar.js.map +1 -1
  105. package/dist/browser/surfaces/DotStrip.js +70 -0
  106. package/dist/browser/surfaces/DotStrip.js.map +1 -0
  107. package/dist/browser/surfaces/NoticeCard.js +46 -30
  108. package/dist/browser/surfaces/NoticeCard.js.map +1 -1
  109. package/dist/browser/surfaces/ProgressRing.js +3 -0
  110. package/dist/browser/surfaces/ProgressRing.js.map +1 -1
  111. package/dist/browser/surfaces/ResourceCard.js +125 -68
  112. package/dist/browser/surfaces/ResourceCard.js.map +1 -1
  113. package/dist/browser/surfaces/index.js +2 -0
  114. package/dist/browser/surfaces/index.js.map +1 -1
  115. package/dist/browser/surfaces/person-color.js +18 -0
  116. package/dist/browser/surfaces/person-color.js.map +1 -0
  117. package/dist/browser/surfaces/resource-messages.js +8 -4
  118. package/dist/browser/surfaces/resource-messages.js.map +1 -1
  119. package/dist/browser/widgets/Widget.js +3 -2
  120. package/dist/browser/widgets/Widget.js.map +1 -1
  121. package/dist/ssr/actions/ContextMenu.js +9 -0
  122. package/dist/ssr/actions/ContextMenu.js.map +1 -1
  123. package/dist/ssr/actions/Dropdown.js +65 -31
  124. package/dist/ssr/actions/Dropdown.js.map +1 -1
  125. package/dist/ssr/actions/FilterChip.js +67 -16
  126. package/dist/ssr/actions/FilterChip.js.map +1 -1
  127. package/dist/ssr/actions/SelectionToolbar.js +104 -0
  128. package/dist/ssr/actions/SelectionToolbar.js.map +1 -0
  129. package/dist/ssr/actions/filter-messages.js +26 -2
  130. package/dist/ssr/actions/filter-messages.js.map +1 -1
  131. package/dist/ssr/actions/index.js +1 -0
  132. package/dist/ssr/actions/index.js.map +1 -1
  133. package/dist/ssr/actions/menu-rows.js +23 -3
  134. package/dist/ssr/actions/menu-rows.js.map +1 -1
  135. package/dist/ssr/actions/menu-sheet.js +2 -7
  136. package/dist/ssr/actions/menu-sheet.js.map +1 -1
  137. package/dist/ssr/charts.js +6 -0
  138. package/dist/ssr/charts.js.map +1 -0
  139. package/dist/ssr/chat/ChatComposer.js +184 -76
  140. package/dist/ssr/chat/ChatComposer.js.map +1 -1
  141. package/dist/ssr/chat/chat-messages.js +18 -0
  142. package/dist/ssr/chat/chat-messages.js.map +1 -1
  143. package/dist/ssr/chat/composer-document.js +19 -0
  144. package/dist/ssr/chat/composer-document.js.map +1 -1
  145. package/dist/ssr/chat/index.js.map +1 -1
  146. package/dist/ssr/content/Calendar.js +40 -31
  147. package/dist/ssr/content/Calendar.js.map +1 -1
  148. package/dist/ssr/content/CalendarDayView.js +40 -48
  149. package/dist/ssr/content/CalendarDayView.js.map +1 -1
  150. package/dist/ssr/content/Chart.js +8 -0
  151. package/dist/ssr/content/Chart.js.map +1 -1
  152. package/dist/ssr/content/FileGrid.js +132 -5
  153. package/dist/ssr/content/FileGrid.js.map +1 -1
  154. package/dist/ssr/content/FileTypeIcon.js +15 -0
  155. package/dist/ssr/content/FileTypeIcon.js.map +1 -1
  156. package/dist/ssr/content/FileView.js +11 -4
  157. package/dist/ssr/content/FileView.js.map +1 -1
  158. package/dist/ssr/content/MessageRow.js +274 -91
  159. package/dist/ssr/content/MessageRow.js.map +1 -1
  160. package/dist/ssr/content/ReactionBar.js +20 -1
  161. package/dist/ssr/content/ReactionBar.js.map +1 -1
  162. package/dist/ssr/content/calendar-day-scroll.js +4 -3
  163. package/dist/ssr/content/calendar-day-scroll.js.map +1 -1
  164. package/dist/ssr/content/chart-bar.js +476 -0
  165. package/dist/ssr/content/chart-bar.js.map +1 -0
  166. package/dist/ssr/content/file-list-messages.js +52 -0
  167. package/dist/ssr/content/file-list-messages.js.map +1 -0
  168. package/dist/ssr/content/index.js +2 -2
  169. package/dist/ssr/content/index.js.map +1 -1
  170. package/dist/ssr/feedback/Tooltip.js +31 -14
  171. package/dist/ssr/feedback/Tooltip.js.map +1 -1
  172. package/dist/ssr/feedback/dialog-core.js +6 -0
  173. package/dist/ssr/feedback/dialog-core.js.map +1 -1
  174. package/dist/ssr/inputs/ChoiceList.js +95 -0
  175. package/dist/ssr/inputs/ChoiceList.js.map +1 -0
  176. package/dist/ssr/inputs/ChoiceSlider.js +191 -0
  177. package/dist/ssr/inputs/ChoiceSlider.js.map +1 -0
  178. package/dist/ssr/inputs/ChoiceTiles.js +61 -0
  179. package/dist/ssr/inputs/ChoiceTiles.js.map +1 -0
  180. package/dist/ssr/inputs/ColorChoices.js +60 -0
  181. package/dist/ssr/inputs/ColorChoices.js.map +1 -0
  182. package/dist/ssr/inputs/QrScanner.js +89 -10
  183. package/dist/ssr/inputs/QrScanner.js.map +1 -1
  184. package/dist/ssr/inputs/TextInput.js +17 -2
  185. package/dist/ssr/inputs/TextInput.js.map +1 -1
  186. package/dist/ssr/inputs/index.js +4 -0
  187. package/dist/ssr/inputs/index.js.map +1 -1
  188. package/dist/ssr/inputs/qr-messages.js +2 -0
  189. package/dist/ssr/inputs/qr-messages.js.map +1 -1
  190. package/dist/ssr/internal/radio-keys.js +13 -0
  191. package/dist/ssr/internal/radio-keys.js.map +1 -0
  192. package/dist/ssr/intl/shortcut-messages.js +4 -0
  193. package/dist/ssr/intl/shortcut-messages.js.map +1 -1
  194. package/dist/ssr/intl/shortcut.js +4 -0
  195. package/dist/ssr/intl/shortcut.js.map +1 -1
  196. package/dist/ssr/layout/AnchoredPopover.js +142 -0
  197. package/dist/ssr/layout/AnchoredPopover.js.map +1 -0
  198. package/dist/ssr/layout/AppWorkspace.js +287 -141
  199. package/dist/ssr/layout/AppWorkspace.js.map +1 -1
  200. package/dist/ssr/layout/DetailPanel.js +181 -108
  201. package/dist/ssr/layout/DetailPanel.js.map +1 -1
  202. package/dist/ssr/layout/MobileShell.js +118 -24
  203. package/dist/ssr/layout/MobileShell.js.map +1 -1
  204. package/dist/ssr/layout/Settings.js +122 -45
  205. package/dist/ssr/layout/Settings.js.map +1 -1
  206. package/dist/ssr/layout/SidebarRailHint.js +79 -0
  207. package/dist/ssr/layout/SidebarRailHint.js.map +1 -0
  208. package/dist/ssr/layout/SidebarSwitcher.js +13 -3
  209. package/dist/ssr/layout/SidebarSwitcher.js.map +1 -1
  210. package/dist/ssr/layout/TabBar.js +11 -3
  211. package/dist/ssr/layout/TabBar.js.map +1 -1
  212. package/dist/ssr/layout/app-workspace-controller.js +11 -4
  213. package/dist/ssr/layout/app-workspace-controller.js.map +1 -1
  214. package/dist/ssr/layout/detail-panel-messages.js +4 -2
  215. package/dist/ssr/layout/detail-panel-messages.js.map +1 -1
  216. package/dist/ssr/layout/index.js +3 -1
  217. package/dist/ssr/layout/index.js.map +1 -1
  218. package/dist/ssr/layout/scroll-fade.js +32 -5
  219. package/dist/ssr/layout/scroll-fade.js.map +1 -1
  220. package/dist/ssr/layout/settings-messages.js +26 -2
  221. package/dist/ssr/layout/settings-messages.js.map +1 -1
  222. package/dist/ssr/surfaces/Avatar.js +2 -14
  223. package/dist/ssr/surfaces/Avatar.js.map +1 -1
  224. package/dist/ssr/surfaces/DotStrip.js +31 -0
  225. package/dist/ssr/surfaces/DotStrip.js.map +1 -0
  226. package/dist/ssr/surfaces/NoticeCard.js +21 -12
  227. package/dist/ssr/surfaces/NoticeCard.js.map +1 -1
  228. package/dist/ssr/surfaces/ProgressRing.js +3 -0
  229. package/dist/ssr/surfaces/ProgressRing.js.map +1 -1
  230. package/dist/ssr/surfaces/ResourceCard.js +40 -15
  231. package/dist/ssr/surfaces/ResourceCard.js.map +1 -1
  232. package/dist/ssr/surfaces/index.js +2 -0
  233. package/dist/ssr/surfaces/index.js.map +1 -1
  234. package/dist/ssr/surfaces/person-color.js +18 -0
  235. package/dist/ssr/surfaces/person-color.js.map +1 -0
  236. package/dist/ssr/surfaces/resource-messages.js +8 -4
  237. package/dist/ssr/surfaces/resource-messages.js.map +1 -1
  238. package/dist/ssr/widgets/Widget.js +3 -2
  239. package/dist/ssr/widgets/Widget.js.map +1 -1
  240. package/dist/styles.css +1 -1
  241. package/dist/types/actions/ContextMenu.d.ts +5 -0
  242. package/dist/types/actions/Dropdown.d.ts +19 -0
  243. package/dist/types/actions/FilterChip.d.ts +11 -0
  244. package/dist/types/actions/SelectionToolbar.d.ts +38 -0
  245. package/dist/types/actions/filter-messages.d.ts +12 -0
  246. package/dist/types/actions/index.d.ts +2 -0
  247. package/dist/types/actions/menu-rows.d.ts +7 -2
  248. package/dist/types/charts.d.ts +5 -0
  249. package/dist/types/chat/ChatComposer.d.ts +28 -0
  250. package/dist/types/chat/chat-messages.d.ts +9 -0
  251. package/dist/types/chat/composer-document.d.ts +5 -0
  252. package/dist/types/chat/index.d.ts +1 -1
  253. package/dist/types/content/Calendar.d.ts +7 -0
  254. package/dist/types/content/Chart.d.ts +2 -1
  255. package/dist/types/content/FileGrid.d.ts +43 -3
  256. package/dist/types/content/FileTypeIcon.d.ts +10 -0
  257. package/dist/types/content/FileView.d.ts +5 -1
  258. package/dist/types/content/MessageRow.d.ts +66 -2
  259. package/dist/types/content/calendar-day-scroll.d.ts +2 -1
  260. package/dist/types/content/chart-bar.d.ts +60 -0
  261. package/dist/types/content/file-list-messages.d.ts +24 -0
  262. package/dist/types/content/index.d.ts +4 -4
  263. package/dist/types/feedback/Tooltip.d.ts +8 -2
  264. package/dist/types/feedback/dialog-core.d.ts +3 -0
  265. package/dist/types/inputs/ChoiceList.d.ts +28 -0
  266. package/dist/types/inputs/ChoiceSlider.d.ts +36 -0
  267. package/dist/types/inputs/ChoiceTiles.d.ts +25 -0
  268. package/dist/types/inputs/ColorChoices.d.ts +19 -0
  269. package/dist/types/inputs/index.d.ts +8 -0
  270. package/dist/types/inputs/qr-messages.d.ts +1 -0
  271. package/dist/types/internal/radio-keys.d.ts +5 -0
  272. package/dist/types/intl/shortcut-messages.d.ts +2 -0
  273. package/dist/types/layout/AnchoredPopover.d.ts +31 -0
  274. package/dist/types/layout/AppWorkspace.d.ts +12 -0
  275. package/dist/types/layout/DetailPanel.d.ts +17 -0
  276. package/dist/types/layout/MobileShell.d.ts +55 -5
  277. package/dist/types/layout/Settings.d.ts +22 -0
  278. package/dist/types/layout/SidebarRailHint.d.ts +26 -0
  279. package/dist/types/layout/TabBar.d.ts +5 -0
  280. package/dist/types/layout/detail-panel-messages.d.ts +1 -0
  281. package/dist/types/layout/index.d.ts +5 -3
  282. package/dist/types/layout/scroll-fade.d.ts +5 -0
  283. package/dist/types/layout/settings-messages.d.ts +12 -0
  284. package/dist/types/surfaces/DotStrip.d.ts +22 -0
  285. package/dist/types/surfaces/NoticeCard.d.ts +3 -0
  286. package/dist/types/surfaces/ProgressRing.d.ts +2 -1
  287. package/dist/types/surfaces/ResourceCard.d.ts +9 -0
  288. package/dist/types/surfaces/index.d.ts +4 -1
  289. package/dist/types/surfaces/person-color.d.ts +10 -0
  290. package/dist/types/surfaces/resource-messages.d.ts +2 -0
  291. package/dist/types/widgets/Widget.d.ts +3 -2
  292. package/package.json +7 -2
@@ -1,18 +1,20 @@
1
1
  import { ssrStyleProperty as _$ssrStyleProperty } from "solid-js/web";
2
- import { createComponent as _$createComponent } from "solid-js/web";
3
- import { ssr as _$ssr } from "solid-js/web";
4
2
  import { ssrAttribute as _$ssrAttribute } from "solid-js/web";
3
+ import { ssr as _$ssr } from "solid-js/web";
5
4
  import { escape as _$escape } from "solid-js/web";
5
+ import { createComponent as _$createComponent } from "solid-js/web";
6
6
  import { memo as _$memo } from "solid-js/web";
7
- var _tmpl$ = ["<i", " aria-hidden=\"true\"></i>"],
7
+ var _tmpl$ = ["<span class=\"k2b-filter-chip__swatches\" aria-hidden=\"true\">", "</span>"],
8
8
  _tmpl$2 = ["<span class=\"k2b-filter-chip__label\">", "", "</span>"],
9
9
  _tmpl$3 = "<i class=\"ti ti-chevron-down k2b-filter-chip__chevron\" aria-hidden=\"true\"></i>",
10
- _tmpl$4 = ["<span class=\"k2b-filter-chip__value\">: ", "", "", "</span>"],
11
- _tmpl$5 = ["<span class=\"k2b-filter-chip__dot\" style=\"", "\" aria-hidden=\"true\"></span>"],
12
- _tmpl$6 = ["<span class=\"k2b-filter-chip__label\">", "</span>"],
13
- _tmpl$7 = ["<a", ">", "</a>"],
14
- _tmpl$8 = ["<button type=\"button\"", "", ">", "</button>"];
15
- import { createMemo, Show } from "solid-js";
10
+ _tmpl$4 = ["<i", " aria-hidden=\"true\"></i>"],
11
+ _tmpl$5 = ["<span class=\"k2b-filter-chip__dot\" style=\"", "\"></span>"],
12
+ _tmpl$6 = ["<span class=\"k2b-filter-chip__value\">: ", "", "", "</span>"],
13
+ _tmpl$7 = ["<span class=\"k2b-filter-chip__dot\" style=\"", "\" aria-hidden=\"true\"></span>"],
14
+ _tmpl$8 = ["<span class=\"k2b-filter-chip__label\">", "</span>"],
15
+ _tmpl$9 = ["<a", ">", "</a>"],
16
+ _tmpl$0 = ["<button type=\"button\"", "", ">", "</button>"];
17
+ import { createMemo, For, Show } from "solid-js";
16
18
  import { useUiMessages } from "../intl/messages";
17
19
  import Dropdown from "./Dropdown";
18
20
  import { useFilterMessages } from "./filter-messages";
@@ -61,6 +63,17 @@ export function FilterChip(props) {
61
63
  };
62
64
  const reset = () => emit(props.defaultValue ? [...props.defaultValue] : []);
63
65
  const showReset = () => hasDefault() && !atDefault() || !hasDefault() && props.value.length > 0;
66
+ const swatches = createMemo(() => props.swatches && !props.iconOnly ? selectedOptions().flatMap(option => option.color ? [option.color] : []).slice(0, 4) : []);
67
+ const onlyValue = value => {
68
+ const kept = props.value.filter(entry => !sectionByValue().get(entry)?.multiple);
69
+ emit([...kept, value]);
70
+ };
71
+ const toggleSection = section => {
72
+ const values = section.options.map(option => option.value);
73
+ const all = values.every(value => selected(value));
74
+ const others = props.value.filter(entry => !values.includes(entry));
75
+ emit(all ? others : [...others, ...values]);
76
+ };
64
77
  const optionItems = createMemo(() => {
65
78
  const result = [];
66
79
  for (const section of props.options) {
@@ -72,11 +85,34 @@ export function FilterChip(props) {
72
85
  closeOnSelect: false,
73
86
  color: option.color,
74
87
  icon: !section.multiple ? option.icon : undefined,
75
- label: option.label
88
+ label: option.label,
89
+ trailing: option.trailing,
90
+ secondary: props.only && section.multiple ? {
91
+ label: filterMessages().only,
92
+ ariaLabel: filterMessages().onlyOption({
93
+ label: option.label
94
+ }),
95
+ action: () => onlyValue(option.value)
96
+ } : undefined
76
97
  }));
98
+ // Read when the row renders, so a change of the choice updates the label without rebuilding the rows.
99
+ const all = () => section.options.every(option => selected(option.value));
100
+ const sectionLabel = section.label;
101
+ const labelAction = section.toggleAll && section.multiple && sectionLabel && section.options.length > 0 ? {
102
+ get label() {
103
+ return all() ? filterMessages().none : filterMessages().all;
104
+ },
105
+ get ariaLabel() {
106
+ return (all() ? filterMessages().noneOf : filterMessages().allOf)({
107
+ label: sectionLabel
108
+ });
109
+ },
110
+ action: () => toggleSection(section)
111
+ } : undefined;
77
112
  if (section.label || section.layout) result.push({
78
113
  sectionLabel: section.label,
79
114
  layout: section.layout,
115
+ labelAction,
80
116
  items
81
117
  });else result.push(...items);
82
118
  }
@@ -135,7 +171,22 @@ export function FilterChip(props) {
135
171
  return triggerLabel();
136
172
  },
137
173
  get children() {
138
- return [_$ssr(_tmpl$, _$ssrAttribute("class", _$escape(props.icon, true), false)), _$createComponent(Show, {
174
+ return [_$createComponent(Show, {
175
+ get when() {
176
+ return swatches().length > 0;
177
+ },
178
+ get fallback() {
179
+ return _$ssr(_tmpl$4, _$ssrAttribute("class", _$escape(props.icon, true), false));
180
+ },
181
+ get children() {
182
+ return _$ssr(_tmpl$, _$escape(_$createComponent(For, {
183
+ get each() {
184
+ return swatches();
185
+ },
186
+ children: color => _$ssr(_tmpl$5, _$ssrStyleProperty("--k2b-filter-color:", _$escape(color, true)))
187
+ })));
188
+ }
189
+ }), _$createComponent(Show, {
139
190
  get when() {
140
191
  return !props.iconOnly;
141
192
  },
@@ -154,11 +205,11 @@ export function FilterChip(props) {
154
205
  }
155
206
  });
156
207
  },
157
- children: first => _$ssr(_tmpl$4, _$escape(_$createComponent(Show, {
208
+ children: first => _$ssr(_tmpl$6, _$escape(_$createComponent(Show, {
158
209
  get when() {
159
210
  return first().color;
160
211
  },
161
- children: color => _$ssr(_tmpl$5, _$ssrStyleProperty("--k2b-filter-color:", _$escape(color(), true)))
212
+ children: color => _$ssr(_tmpl$7, _$ssrStyleProperty("--k2b-filter-color:", _$escape(color(), true)))
162
213
  })), _$escape(first().label), _$escape(_$createComponent(Show, {
163
214
  get when() {
164
215
  return props.value.length > 1;
@@ -181,17 +232,17 @@ export default FilterChip;
181
232
  * `aria-pressed`. Selection changes only colour and background, so neighbouring chips never move.
182
233
  */
183
234
  export function FilterToggle(props) {
184
- const content = () => [_$ssr(_tmpl$, _$ssrAttribute("class", _$escape(props.icon, true), false)), _$ssr(_tmpl$6, _$escape(props.label))];
235
+ const content = () => [_$ssr(_tmpl$4, _$ssrAttribute("class", _$escape(props.icon, true), false)), _$ssr(_tmpl$8, _$escape(props.label))];
185
236
  const className = () => `k2b-filter-chip ${props.class ?? ""}`;
186
237
  return _$createComponent(Show, {
187
238
  get when() {
188
239
  return _$memo(() => props.href !== undefined)() && !props.disabled;
189
240
  },
190
241
  get fallback() {
191
- return _$ssr(_tmpl$8, _$ssrAttribute("class", _$escape(className(), true), false) + _$ssrAttribute("data-active", props.active ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("aria-pressed", _$escape(props.active, true), false) + _$ssrAttribute("title", _$escape(props.title, true), false), _$ssrAttribute("disabled", props.disabled, true), _$escape(content()));
242
+ return _$ssr(_tmpl$0, _$ssrAttribute("class", _$escape(className(), true), false) + _$ssrAttribute("data-active", props.active ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("aria-pressed", _$escape(props.active, true), false) + _$ssrAttribute("title", _$escape(props.title, true), false), _$ssrAttribute("disabled", props.disabled, true), _$escape(content()));
192
243
  },
193
244
  get children() {
194
- return _$ssr(_tmpl$7, _$ssrAttribute("class", _$escape(className(), true), false) + _$ssrAttribute("href", _$escape(props.href, true), false) + _$ssrAttribute("data-active", props.active ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("aria-current", props.active ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("title", _$escape(props.title, true), false), _$escape(content()));
245
+ return _$ssr(_tmpl$9, _$ssrAttribute("class", _$escape(className(), true), false) + _$ssrAttribute("href", _$escape(props.href, true), false) + _$ssrAttribute("data-active", props.active ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("aria-current", props.active ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("title", _$escape(props.title, true), false), _$escape(content()));
195
246
  }
196
247
  });
197
248
  }
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["actions/FilterChip.tsx"],"sourcesContent":["import { createMemo, type JSX, Show } from \"solid-js\";\nimport { useUiMessages } from \"../intl/messages\";\nimport type { ButtonVariant } from \"./Button\";\nimport Dropdown, { type DropdownItem } from \"./Dropdown\";\nimport { useFilterMessages } from \"./filter-messages\";\n\nexport type FilterChipOption = {\n value: string;\n label: string;\n icon?: string;\n color?: string;\n};\n\nexport type FilterChipSection = {\n label?: string;\n options: readonly FilterChipOption[];\n multiple?: boolean;\n /**\n * `row` sets a few short single-select options side by side as one segmented row under its `label`. Selecting the\n * chosen option again keeps it; give the row a value in `defaultValue` so Reset keeps a choice too.\n */\n layout?: \"row\";\n};\n\nexport type FilterChipProps = {\n label: string;\n icon: string;\n options: readonly FilterChipSection[];\n value: readonly string[];\n onValueChange: (value: string[]) => void;\n isActive?: boolean;\n position?: \"bottom-left\" | \"bottom-right\";\n defaultValue?: readonly string[];\n iconOnly?: boolean;\n /** Use a standard button appearance instead of the default filter field. */\n variant?: ButtonVariant;\n /**\n * An active chip names its first value instead of a count: \"Tags: Customer\", \"Tags: Customer +2\". Use it for the\n * chips of `AppWorkspace.Head`; pass only the filter's name as `label`. The chip then grows with its value.\n */\n showValue?: boolean;\n disabled?: boolean;\n class?: string;\n};\n\n/** Section-aware controlled filter with immediate single- and multi-select commits. */\nexport function FilterChip(props: FilterChipProps): JSX.Element {\n const messages = useUiMessages();\n const filterMessages = useFilterMessages();\n const selectedValues = createMemo(() => new Set(props.value));\n const selectedOptions = createMemo(() =>\n props.options.flatMap((section) => section.options).filter((option) => selectedValues().has(option.value)),\n );\n const defaultValues = createMemo(() => new Set(props.defaultValue ?? []));\n const sectionByValue = createMemo(() => {\n const sections = new Map<string, FilterChipSection>();\n for (const section of props.options) {\n for (const option of section.options) sections.set(option.value, section);\n }\n return sections;\n });\n const hasDefault = () => (props.defaultValue?.length ?? 0) > 0;\n const selected = (value: string) => selectedValues().has(value);\n const active = () => props.isActive ?? props.value.length > 0;\n const namedValue = () => (props.showValue && !props.iconOnly && active() ? selectedOptions()[0] : undefined);\n const triggerLabel = () => {\n const first = namedValue();\n if (!first) return props.label;\n return `${props.label}: ${first.label}${props.value.length > 1 ? ` +${props.value.length - 1}` : \"\"}`;\n };\n const atDefault = () => {\n if (!props.defaultValue) return false;\n const current = props.value;\n return current.length === props.defaultValue.length && current.every((value) => defaultValues().has(value));\n };\n const emit = (value: string[]) => props.onValueChange(value);\n const toggle = (value: string) => {\n const section = sectionByValue().get(value);\n if (!section) return;\n const current = props.value;\n if (section.multiple) {\n emit(selected(value) ? current.filter((entry) => entry !== value) : [...current, value]);\n return;\n }\n // A segmented row always keeps one choice, like a SegmentedControl.\n if (section.layout === \"row\" && selected(value)) return;\n const sectionValues = new Set(section.options.map((option) => option.value));\n const otherValues = current.filter((entry) => !sectionValues.has(entry));\n emit(selected(value) ? otherValues : [...otherValues, value]);\n };\n const reset = () => emit(props.defaultValue ? [...props.defaultValue] : []);\n const showReset = () => (hasDefault() && !atDefault()) || (!hasDefault() && props.value.length > 0);\n const optionItems = createMemo<DropdownItem[]>(() => {\n const result: DropdownItem[] = [];\n for (const section of props.options) {\n const items = section.options.map((option) => ({\n action: () => toggle(option.value),\n checked: () => props.value.includes(option.value),\n choice: section.multiple ? (\"checkbox\" as const) : (\"radio\" as const),\n class: \"k2b-filter-chip__option\",\n closeOnSelect: false,\n color: option.color,\n icon: !section.multiple ? option.icon : undefined,\n label: option.label,\n }));\n if (section.label || section.layout) result.push({ sectionLabel: section.label, layout: section.layout, items });\n else result.push(...items);\n }\n return result;\n });\n const items = createMemo<DropdownItem[]>(() => {\n if (!showReset()) return optionItems();\n return [\n ...optionItems(),\n {\n sectionLabel: filterMessages().filterActions,\n items: [\n {\n action: reset,\n icon: hasDefault() ? \"ti ti-refresh\" : \"ti ti-x\",\n label: hasDefault() ? messages().reset : messages().clear,\n variant: \"danger\",\n },\n ],\n },\n ];\n });\n\n return (\n <Dropdown.Root\n disabled={props.disabled}\n items={items()}\n position={props.position ?? \"bottom-left\"}\n menuClass=\"k2b-filter-chip__menu\"\n label={props.label}\n >\n <Dropdown.Trigger\n appearance={props.variant ? \"button\" : \"plain\"}\n variant={props.variant}\n iconOnly={props.iconOnly}\n class={props.variant ? props.class : `k2b-filter-chip ${props.class ?? \"\"}`}\n data-state={active() ? \"active\" : \"idle\"}\n data-active={active() ? \"true\" : undefined}\n data-icon-only={props.iconOnly ? \"true\" : undefined}\n label={triggerLabel()}\n >\n <i class={props.icon} aria-hidden=\"true\" />\n <Show when={!props.iconOnly}>\n <span class=\"k2b-filter-chip__label\">\n {props.label}\n <Show when={namedValue()} fallback={<Show when={!hasDefault() && props.value.length > 0}>{` (${props.value.length})`}</Show>}>\n {(first) => (\n <span class=\"k2b-filter-chip__value\">\n :{\" \"}\n <Show when={first().color}>\n {(color) => <span class=\"k2b-filter-chip__dot\" style={{ \"--k2b-filter-color\": color() }} aria-hidden=\"true\" />}\n </Show>\n {first().label}\n <Show when={props.value.length > 1}>{` +${props.value.length - 1}`}</Show>\n </span>\n )}\n </Show>\n </span>\n <i class=\"ti ti-chevron-down k2b-filter-chip__chevron\" aria-hidden=\"true\" />\n </Show>\n </Dropdown.Trigger>\n </Dropdown.Root>\n );\n}\n\nexport default FilterChip;\n\nexport type FilterToggleProps = {\n label: JSX.Element;\n icon: string;\n /** Whether the filter is on. An active toggle carries the same tint as an active `FilterChip`. */\n active: boolean;\n /** Link to the URL with the filter switched. The link keeps working without JavaScript. */\n href?: string;\n onClick?: (event: MouseEvent) => void;\n title?: string;\n disabled?: boolean;\n class?: string;\n};\n\n/**\n * One on/off filter in the chip look: a link marked `aria-current=\"true\"` while active, or a button with\n * `aria-pressed`. Selection changes only colour and background, so neighbouring chips never move.\n */\nexport function FilterToggle(props: FilterToggleProps): JSX.Element {\n const content = () => (\n <>\n <i class={props.icon} aria-hidden=\"true\" />\n <span class=\"k2b-filter-chip__label\">{props.label}</span>\n </>\n );\n const className = () => `k2b-filter-chip ${props.class ?? \"\"}`;\n return (\n <Show\n when={props.href !== undefined && !props.disabled}\n fallback={\n <button\n type=\"button\"\n class={className()}\n data-active={props.active ? \"true\" : undefined}\n aria-pressed={props.active}\n title={props.title}\n disabled={props.disabled}\n onClick={(event) => props.onClick?.(event)}\n >\n {content()}\n </button>\n }\n >\n <a\n class={className()}\n href={props.href}\n data-active={props.active ? \"true\" : undefined}\n aria-current={props.active ? \"true\" : undefined}\n title={props.title}\n onClick={(event) => props.onClick?.(event)}\n >\n {content()}\n </a>\n </Show>\n );\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["actions/FilterChip.tsx"],"sourcesContent":["import { createMemo, For, type JSX, Show } from \"solid-js\";\nimport { useUiMessages } from \"../intl/messages\";\nimport type { ButtonVariant } from \"./Button\";\nimport Dropdown, { type DropdownItem } from \"./Dropdown\";\nimport { useFilterMessages } from \"./filter-messages\";\n\nexport type FilterChipOption = {\n value: string;\n label: string;\n icon?: string;\n color?: string;\n /** Quiet trailing information about the option, such as a short note or a loading or warning icon with its own label. */\n trailing?: JSX.Element;\n};\n\nexport type FilterChipSection = {\n label?: string;\n options: readonly FilterChipOption[];\n multiple?: boolean;\n /**\n * `row` sets a few short single-select options side by side as one segmented row under its `label`. Selecting the\n * chosen option again keeps it; give the row a value in `defaultValue` so Reset keeps a choice too.\n */\n layout?: \"row\";\n /** A labelled `multiple` section offers \"All\" or, once all its options are chosen, \"None\" beside its label. */\n toggleAll?: boolean;\n};\n\nexport type FilterChipProps = {\n label: string;\n icon: string;\n options: readonly FilterChipSection[];\n value: readonly string[];\n onValueChange: (value: string[]) => void;\n isActive?: boolean;\n position?: \"bottom-left\" | \"bottom-right\";\n defaultValue?: readonly string[];\n iconOnly?: boolean;\n /** Use a standard button appearance instead of the default filter field. */\n variant?: ButtonVariant;\n /**\n * An active chip names its first value instead of a count: \"Tags: Customer\", \"Tags: Customer +2\". Use it for the\n * chips of `AppWorkspace.Head`; pass only the filter's name as `label`. The chip then grows with its value.\n */\n showValue?: boolean;\n /**\n * Each option of a `multiple` section offers \"Only\" at the end of its row: it chooses that option alone among the\n * `multiple` sections and keeps the choices of single-select sections.\n */\n only?: boolean;\n /** The trigger shows the colors of the first four chosen options before its label, as a quiet hint of what is in view. */\n swatches?: boolean;\n disabled?: boolean;\n class?: string;\n};\n\n/** Section-aware controlled filter with immediate single- and multi-select commits. */\nexport function FilterChip(props: FilterChipProps): JSX.Element {\n const messages = useUiMessages();\n const filterMessages = useFilterMessages();\n const selectedValues = createMemo(() => new Set(props.value));\n const selectedOptions = createMemo(() =>\n props.options.flatMap((section) => section.options).filter((option) => selectedValues().has(option.value)),\n );\n const defaultValues = createMemo(() => new Set(props.defaultValue ?? []));\n const sectionByValue = createMemo(() => {\n const sections = new Map<string, FilterChipSection>();\n for (const section of props.options) {\n for (const option of section.options) sections.set(option.value, section);\n }\n return sections;\n });\n const hasDefault = () => (props.defaultValue?.length ?? 0) > 0;\n const selected = (value: string) => selectedValues().has(value);\n const active = () => props.isActive ?? props.value.length > 0;\n const namedValue = () => (props.showValue && !props.iconOnly && active() ? selectedOptions()[0] : undefined);\n const triggerLabel = () => {\n const first = namedValue();\n if (!first) return props.label;\n return `${props.label}: ${first.label}${props.value.length > 1 ? ` +${props.value.length - 1}` : \"\"}`;\n };\n const atDefault = () => {\n if (!props.defaultValue) return false;\n const current = props.value;\n return current.length === props.defaultValue.length && current.every((value) => defaultValues().has(value));\n };\n const emit = (value: string[]) => props.onValueChange(value);\n const toggle = (value: string) => {\n const section = sectionByValue().get(value);\n if (!section) return;\n const current = props.value;\n if (section.multiple) {\n emit(selected(value) ? current.filter((entry) => entry !== value) : [...current, value]);\n return;\n }\n // A segmented row always keeps one choice, like a SegmentedControl.\n if (section.layout === \"row\" && selected(value)) return;\n const sectionValues = new Set(section.options.map((option) => option.value));\n const otherValues = current.filter((entry) => !sectionValues.has(entry));\n emit(selected(value) ? otherValues : [...otherValues, value]);\n };\n const reset = () => emit(props.defaultValue ? [...props.defaultValue] : []);\n const showReset = () => (hasDefault() && !atDefault()) || (!hasDefault() && props.value.length > 0);\n const swatches = createMemo(() =>\n props.swatches && !props.iconOnly\n ? selectedOptions()\n .flatMap((option) => (option.color ? [option.color] : []))\n .slice(0, 4)\n : [],\n );\n const onlyValue = (value: string) => {\n const kept = props.value.filter((entry) => !sectionByValue().get(entry)?.multiple);\n emit([...kept, value]);\n };\n const toggleSection = (section: FilterChipSection) => {\n const values = section.options.map((option) => option.value);\n const all = values.every((value) => selected(value));\n const others = props.value.filter((entry) => !values.includes(entry));\n emit(all ? others : [...others, ...values]);\n };\n const optionItems = createMemo<DropdownItem[]>(() => {\n const result: DropdownItem[] = [];\n for (const section of props.options) {\n const items = section.options.map((option) => ({\n action: () => toggle(option.value),\n checked: () => props.value.includes(option.value),\n choice: section.multiple ? (\"checkbox\" as const) : (\"radio\" as const),\n class: \"k2b-filter-chip__option\",\n closeOnSelect: false,\n color: option.color,\n icon: !section.multiple ? option.icon : undefined,\n label: option.label,\n trailing: option.trailing,\n secondary:\n props.only && section.multiple\n ? {\n label: filterMessages().only,\n ariaLabel: filterMessages().onlyOption({ label: option.label }),\n action: () => onlyValue(option.value),\n }\n : undefined,\n }));\n // Read when the row renders, so a change of the choice updates the label without rebuilding the rows.\n const all = () => section.options.every((option) => selected(option.value));\n const sectionLabel = section.label;\n const labelAction =\n section.toggleAll && section.multiple && sectionLabel && section.options.length > 0\n ? {\n get label() {\n return all() ? filterMessages().none : filterMessages().all;\n },\n get ariaLabel() {\n return (all() ? filterMessages().noneOf : filterMessages().allOf)({ label: sectionLabel });\n },\n action: () => toggleSection(section),\n }\n : undefined;\n if (section.label || section.layout) result.push({ sectionLabel: section.label, layout: section.layout, labelAction, items });\n else result.push(...items);\n }\n return result;\n });\n const items = createMemo<DropdownItem[]>(() => {\n if (!showReset()) return optionItems();\n return [\n ...optionItems(),\n {\n sectionLabel: filterMessages().filterActions,\n items: [\n {\n action: reset,\n icon: hasDefault() ? \"ti ti-refresh\" : \"ti ti-x\",\n label: hasDefault() ? messages().reset : messages().clear,\n variant: \"danger\",\n },\n ],\n },\n ];\n });\n\n return (\n <Dropdown.Root\n disabled={props.disabled}\n items={items()}\n position={props.position ?? \"bottom-left\"}\n menuClass=\"k2b-filter-chip__menu\"\n label={props.label}\n >\n <Dropdown.Trigger\n appearance={props.variant ? \"button\" : \"plain\"}\n variant={props.variant}\n iconOnly={props.iconOnly}\n class={props.variant ? props.class : `k2b-filter-chip ${props.class ?? \"\"}`}\n data-state={active() ? \"active\" : \"idle\"}\n data-active={active() ? \"true\" : undefined}\n data-icon-only={props.iconOnly ? \"true\" : undefined}\n label={triggerLabel()}\n >\n <Show when={swatches().length > 0} fallback={<i class={props.icon} aria-hidden=\"true\" />}>\n <span class=\"k2b-filter-chip__swatches\" aria-hidden=\"true\">\n <For each={swatches()}>{(color) => <span class=\"k2b-filter-chip__dot\" style={{ \"--k2b-filter-color\": color }} />}</For>\n </span>\n </Show>\n <Show when={!props.iconOnly}>\n <span class=\"k2b-filter-chip__label\">\n {props.label}\n <Show when={namedValue()} fallback={<Show when={!hasDefault() && props.value.length > 0}>{` (${props.value.length})`}</Show>}>\n {(first) => (\n <span class=\"k2b-filter-chip__value\">\n :{\" \"}\n <Show when={first().color}>\n {(color) => <span class=\"k2b-filter-chip__dot\" style={{ \"--k2b-filter-color\": color() }} aria-hidden=\"true\" />}\n </Show>\n {first().label}\n <Show when={props.value.length > 1}>{` +${props.value.length - 1}`}</Show>\n </span>\n )}\n </Show>\n </span>\n <i class=\"ti ti-chevron-down k2b-filter-chip__chevron\" aria-hidden=\"true\" />\n </Show>\n </Dropdown.Trigger>\n </Dropdown.Root>\n );\n}\n\nexport default FilterChip;\n\nexport type FilterToggleProps = {\n label: JSX.Element;\n icon: string;\n /** Whether the filter is on. An active toggle carries the same tint as an active `FilterChip`. */\n active: boolean;\n /** Link to the URL with the filter switched. The link keeps working without JavaScript. */\n href?: string;\n onClick?: (event: MouseEvent) => void;\n title?: string;\n disabled?: boolean;\n class?: string;\n};\n\n/**\n * One on/off filter in the chip look: a link marked `aria-current=\"true\"` while active, or a button with\n * `aria-pressed`. Selection changes only colour and background, so neighbouring chips never move.\n */\nexport function FilterToggle(props: FilterToggleProps): JSX.Element {\n const content = () => (\n <>\n <i class={props.icon} aria-hidden=\"true\" />\n <span class=\"k2b-filter-chip__label\">{props.label}</span>\n </>\n );\n const className = () => `k2b-filter-chip ${props.class ?? \"\"}`;\n return (\n <Show\n when={props.href !== undefined && !props.disabled}\n fallback={\n <button\n type=\"button\"\n class={className()}\n data-active={props.active ? \"true\" : undefined}\n aria-pressed={props.active}\n title={props.title}\n disabled={props.disabled}\n onClick={(event) => props.onClick?.(event)}\n >\n {content()}\n </button>\n }\n >\n <a\n class={className()}\n href={props.href}\n data-active={props.active ? \"true\" : undefined}\n aria-current={props.active ? \"true\" : undefined}\n title={props.title}\n onClick={(event) => props.onClick?.(event)}\n >\n {content()}\n </a>\n </Show>\n );\n}\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,104 @@
1
+ import { ssr as _$ssr } from "solid-js/web";
2
+ import { createComponent as _$createComponent } from "solid-js/web";
3
+ import { escape as _$escape } from "solid-js/web";
4
+ var _tmpl$ = ["<div popover=\"manual\" class=\"", "\">", "</div>"];
5
+ import { createEffect, onCleanup } from "solid-js";
6
+ import { isServer } from "solid-js/web";
7
+ import { Toolbar } from "./Toolbar";
8
+ const GAP = 8;
9
+ const EDGE = 8;
10
+
11
+ /** Where the toolbar goes for a selection box: centered on its first line, inside the viewport. */
12
+ export const selectionToolbarPosition = (anchor, toolbar, viewport, placement = "above") => {
13
+ const left = Math.max(EDGE, Math.min(anchor.left + anchor.width / 2 - toolbar.width / 2, viewport.width - toolbar.width - EDGE));
14
+ // A boundary scrolled above the window still leaves the window's top edge as the limit.
15
+ const upper = Math.max(0, viewport.top ?? 0) + EDGE;
16
+ const above = anchor.top - toolbar.height - GAP;
17
+ const below = anchor.bottom + GAP;
18
+ const fitsAbove = above >= upper;
19
+ const fitsBelow = below + toolbar.height <= viewport.height - EDGE;
20
+ // The preferred side when it fits, the other side when only that fits; never on the selected text otherwise.
21
+ const side = placement === "below" ? fitsBelow || !fitsAbove ? "below" : "above" : fitsAbove || !fitsBelow ? "above" : "below";
22
+ if (side === "above") return {
23
+ left,
24
+ top: fitsAbove ? above : upper,
25
+ side
26
+ };
27
+ return {
28
+ left,
29
+ top: fitsBelow ? below : Math.max(upper, viewport.height - EDGE - toolbar.height),
30
+ side
31
+ };
32
+ };
33
+ const keepsFocus = target => target instanceof Element && !!target.closest("input, textarea, select, [contenteditable='true']");
34
+
35
+ /**
36
+ * A toolbar that floats at a text selection, such as formatting and comment actions over selected text. It lies in
37
+ * the top layer, so no scroll container clips it, and pressing its buttons keeps the selection.
38
+ */
39
+ export function SelectionToolbar(props) {
40
+ let root;
41
+ const place = () => {
42
+ const anchor = props.anchor();
43
+ if (!anchor) return false;
44
+ const boundary = props.boundary?.()?.getBoundingClientRect();
45
+ const size = root.getBoundingClientRect();
46
+ const {
47
+ left,
48
+ top,
49
+ side
50
+ } = selectionToolbarPosition(anchor, size, {
51
+ width: document.documentElement.clientWidth,
52
+ height: window.innerHeight,
53
+ top: boundary?.top
54
+ }, props.placement);
55
+ root.style.left = `${Math.round(left)}px`;
56
+ root.style.top = `${Math.round(top)}px`;
57
+ root.dataset.side = side;
58
+ return true;
59
+ };
60
+ if (!isServer) createEffect(() => {
61
+ const open = !!props.anchor();
62
+ if (!open) {
63
+ if (root.matches(":popover-open")) root.hidePopover();
64
+ return;
65
+ }
66
+ if (!root.matches(":popover-open")) root.showPopover();
67
+ place();
68
+ let frame = 0;
69
+ const follow = () => {
70
+ cancelAnimationFrame(frame);
71
+ frame = requestAnimationFrame(() => {
72
+ if (!place() && root.matches(":popover-open")) root.hidePopover();
73
+ });
74
+ };
75
+ window.addEventListener("scroll", follow, {
76
+ capture: true,
77
+ passive: true
78
+ });
79
+ window.addEventListener("resize", follow, {
80
+ passive: true
81
+ });
82
+ const observer = new ResizeObserver(follow);
83
+ observer.observe(root);
84
+ onCleanup(() => {
85
+ cancelAnimationFrame(frame);
86
+ window.removeEventListener("scroll", follow, {
87
+ capture: true
88
+ });
89
+ window.removeEventListener("resize", follow);
90
+ observer.disconnect();
91
+ });
92
+ });
93
+ return (// biome-ignore lint/a11y/noStaticElementInteractions: the toolbar inside is the keyboard target; the frame only keeps the selection on press and forwards Escape.
94
+ _$ssr(_tmpl$, `k2b-selection-toolbar ${_$escape(props.class ?? "", true)}`, _$escape(_$createComponent(Toolbar, {
95
+ get label() {
96
+ return props.label;
97
+ },
98
+ get children() {
99
+ return props.children;
100
+ }
101
+ })))
102
+ );
103
+ }
104
+ //# sourceMappingURL=SelectionToolbar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sources":["actions/SelectionToolbar.tsx"],"sourcesContent":["import { createEffect, type JSX, onCleanup } from \"solid-js\";\nimport { isServer } from \"solid-js/web\";\nimport { Toolbar } from \"./Toolbar\";\n\nexport type SelectionToolbarProps = {\n /**\n * The selection's box in viewport coordinates, or nothing while the toolbar is closed. It is read again on every\n * scroll and resize while the toolbar is open, so a function that measures the selection keeps it attached.\n */\n anchor: () => DOMRect | null | undefined;\n label: string;\n /**\n * `above` (default) places the toolbar over the selection and below it when the space above is too small. `below`\n * always places it below, for touch, where the system's own selection menu sits above.\n */\n placement?: \"above\" | \"below\";\n /** The area the toolbar stays in, such as the editor's scroll area under its toolbar: it goes below the selection when the space above inside this area is too small. */\n boundary?: () => HTMLElement | null | undefined;\n /** Escape inside the toolbar; the application closes it and returns focus to the text. */\n onEscape?: () => void;\n children: JSX.Element;\n class?: string;\n};\n\nconst GAP = 8;\nconst EDGE = 8;\n\n/** Where the toolbar goes for a selection box: centered on its first line, inside the viewport. */\nexport const selectionToolbarPosition = (\n anchor: Pick<DOMRect, \"top\" | \"bottom\" | \"left\" | \"width\">,\n toolbar: { width: number; height: number },\n viewport: { width: number; height: number; top?: number },\n placement: \"above\" | \"below\" = \"above\",\n): { left: number; top: number; side: \"above\" | \"below\" } => {\n const left = Math.max(EDGE, Math.min(anchor.left + anchor.width / 2 - toolbar.width / 2, viewport.width - toolbar.width - EDGE));\n // A boundary scrolled above the window still leaves the window's top edge as the limit.\n const upper = Math.max(0, viewport.top ?? 0) + EDGE;\n const above = anchor.top - toolbar.height - GAP;\n const below = anchor.bottom + GAP;\n const fitsAbove = above >= upper;\n const fitsBelow = below + toolbar.height <= viewport.height - EDGE;\n // The preferred side when it fits, the other side when only that fits; never on the selected text otherwise.\n const side = placement === \"below\" ? (fitsBelow || !fitsAbove ? \"below\" : \"above\") : fitsAbove || !fitsBelow ? \"above\" : \"below\";\n if (side === \"above\") return { left, top: fitsAbove ? above : upper, side };\n return { left, top: fitsBelow ? below : Math.max(upper, viewport.height - EDGE - toolbar.height), side };\n};\n\nconst keepsFocus = (target: EventTarget | null) =>\n target instanceof Element && !!target.closest(\"input, textarea, select, [contenteditable='true']\");\n\n/**\n * A toolbar that floats at a text selection, such as formatting and comment actions over selected text. It lies in\n * the top layer, so no scroll container clips it, and pressing its buttons keeps the selection.\n */\nexport function SelectionToolbar(props: SelectionToolbarProps): JSX.Element {\n let root!: HTMLDivElement;\n const place = () => {\n const anchor = props.anchor();\n if (!anchor) return false;\n const boundary = props.boundary?.()?.getBoundingClientRect();\n const size = root.getBoundingClientRect();\n const { left, top, side } = selectionToolbarPosition(\n anchor,\n size,\n { width: document.documentElement.clientWidth, height: window.innerHeight, top: boundary?.top },\n props.placement,\n );\n root.style.left = `${Math.round(left)}px`;\n root.style.top = `${Math.round(top)}px`;\n root.dataset.side = side;\n return true;\n };\n\n if (!isServer)\n createEffect(() => {\n const open = !!props.anchor();\n if (!open) {\n if (root.matches(\":popover-open\")) root.hidePopover();\n return;\n }\n if (!root.matches(\":popover-open\")) root.showPopover();\n place();\n let frame = 0;\n const follow = () => {\n cancelAnimationFrame(frame);\n frame = requestAnimationFrame(() => {\n if (!place() && root.matches(\":popover-open\")) root.hidePopover();\n });\n };\n window.addEventListener(\"scroll\", follow, { capture: true, passive: true });\n window.addEventListener(\"resize\", follow, { passive: true });\n const observer = new ResizeObserver(follow);\n observer.observe(root);\n onCleanup(() => {\n cancelAnimationFrame(frame);\n window.removeEventListener(\"scroll\", follow, { capture: true });\n window.removeEventListener(\"resize\", follow);\n observer.disconnect();\n });\n });\n\n return (\n // biome-ignore lint/a11y/noStaticElementInteractions: the toolbar inside is the keyboard target; the frame only keeps the selection on press and forwards Escape.\n <div\n ref={root}\n popover=\"manual\"\n class={`k2b-selection-toolbar ${props.class ?? \"\"}`}\n onPointerDown={(event) => {\n // A press on a button would otherwise move focus and clear the selection the actions apply to.\n if (!keepsFocus(event.target)) event.preventDefault();\n }}\n onKeyDown={(event) => {\n if (event.key !== \"Escape\" || !props.onEscape) return;\n event.preventDefault();\n event.stopPropagation();\n props.onEscape();\n }}\n >\n <Toolbar label={props.label}>{props.children}</Toolbar>\n </div>\n );\n}\n"],"mappings":"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","ignoreList":[]}
@@ -6,12 +6,36 @@ const filterMessages = i18n.define({
6
6
  en: {
7
7
  filterActions: "Filter actions",
8
8
  filters: "Filters",
9
- reset: "Reset"
9
+ reset: "Reset",
10
+ all: "All",
11
+ none: "None",
12
+ allOf: ({
13
+ label
14
+ }) => `Choose all of ${label}`,
15
+ noneOf: ({
16
+ label
17
+ }) => `Choose none of ${label}`,
18
+ only: "Only",
19
+ onlyOption: ({
20
+ label
21
+ }) => `Only ${label}`
10
22
  },
11
23
  de: {
12
24
  filterActions: "Filteraktionen",
13
25
  filters: "Filter",
14
- reset: "Zurücksetzen"
26
+ reset: "Zurücksetzen",
27
+ all: "Alle",
28
+ none: "Keine",
29
+ allOf: ({
30
+ label
31
+ }) => `Alle aus ${label} wählen`,
32
+ noneOf: ({
33
+ label
34
+ }) => `Keine aus ${label} wählen`,
35
+ only: "Nur diese",
36
+ onlyOption: ({
37
+ label
38
+ }) => `Nur ${label}`
15
39
  }
16
40
  }
17
41
  });
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["actions/filter-messages.ts"],"sourcesContent":["import { i18n } from \"@k2b/stdlib\";\nimport { useLocale } from \"../intl/locale\";\n\nconst filterMessages = i18n.define({\n baseLocale: \"en\",\n messages: {\n en: {\n filterActions: \"Filter actions\",\n filters: \"Filters\",\n reset: \"Reset\",\n },\n de: {\n filterActions: \"Filteraktionen\",\n filters: \"Filter\",\n reset: \"Zurücksetzen\",\n },\n },\n});\n\nexport type FilterMessages = ReturnType<(typeof filterMessages)[\"resolve\"]>[\"t\"];\n\n/** Resolved from the inherited render locale. */\nexport const useFilterMessages = (): (() => FilterMessages) => {\n const locale = useLocale();\n return () => filterMessages.resolve([locale()]).t;\n};\n\nexport const checkFilterMessages = () => filterMessages.check();\n"],"mappings":"AAAA,SAAS,IAAI,QAAQ,aAAa;AAClC,SAAS,SAAS,QAAQ,gBAAgB;AAE1C,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC;EACjC,UAAU,EAAE,IAAI;EAChB,QAAQ,EAAE;IACR,EAAE,EAAE;MACF,aAAa,EAAE,gBAAgB;MAC/B,OAAO,EAAE,SAAS;MAClB,KAAK,EAAE;IACT,CAAC;IACD,EAAE,EAAE;MACF,aAAa,EAAE,gBAAgB;MAC/B,OAAO,EAAE,QAAQ;MACjB,KAAK,EAAE;IACT;EACF;AACF,CAAC,CAAC;AAIF;AACA,OAAO,MAAM,iBAAiB,GAAG,MAA8B;EAC7D,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC;EAC1B,OAAO,MAAM,cAAc,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACnD,CAAC;AAED,OAAO,MAAM,mBAAmB,GAAG,MAAM,cAAc,CAAC,KAAK,CAAC,CAAC","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["actions/filter-messages.ts"],"sourcesContent":["import { i18n } from \"@k2b/stdlib\";\nimport { useLocale } from \"../intl/locale\";\n\nconst filterMessages = i18n.define({\n baseLocale: \"en\",\n messages: {\n en: {\n filterActions: \"Filter actions\",\n filters: \"Filters\",\n reset: \"Reset\",\n all: \"All\",\n none: \"None\",\n allOf: ({ label }: { label: string }) => `Choose all of ${label}`,\n noneOf: ({ label }: { label: string }) => `Choose none of ${label}`,\n only: \"Only\",\n onlyOption: ({ label }: { label: string }) => `Only ${label}`,\n },\n de: {\n filterActions: \"Filteraktionen\",\n filters: \"Filter\",\n reset: \"Zurücksetzen\",\n all: \"Alle\",\n none: \"Keine\",\n allOf: ({ label }) => `Alle aus ${label} wählen`,\n noneOf: ({ label }) => `Keine aus ${label} wählen`,\n only: \"Nur diese\",\n onlyOption: ({ label }) => `Nur ${label}`,\n },\n },\n});\n\nexport type FilterMessages = ReturnType<(typeof filterMessages)[\"resolve\"]>[\"t\"];\n\n/** Resolved from the inherited render locale. */\nexport const useFilterMessages = (): (() => FilterMessages) => {\n const locale = useLocale();\n return () => filterMessages.resolve([locale()]).t;\n};\n\nexport const checkFilterMessages = () => filterMessages.check();\n"],"mappings":"AAAA,SAAS,IAAI,QAAQ,aAAa;AAClC,SAAS,SAAS,QAAQ,gBAAgB;AAE1C,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC;EACjC,UAAU,EAAE,IAAI;EAChB,QAAQ,EAAE;IACR,EAAE,EAAE;MACF,aAAa,EAAE,gBAAgB;MAC/B,OAAO,EAAE,SAAS;MAClB,KAAK,EAAE,OAAO;MACd,GAAG,EAAE,KAAK;MACV,IAAI,EAAE,MAAM;MACZ,KAAK,EAAE,CAAC;QAAE;MAAyB,CAAC,KAAK,iBAAiB,KAAK,EAAE;MACjE,MAAM,EAAE,CAAC;QAAE;MAAyB,CAAC,KAAK,kBAAkB,KAAK,EAAE;MACnE,IAAI,EAAE,MAAM;MACZ,UAAU,EAAE,CAAC;QAAE;MAAyB,CAAC,KAAK,QAAQ,KAAK;IAC7D,CAAC;IACD,EAAE,EAAE;MACF,aAAa,EAAE,gBAAgB;MAC/B,OAAO,EAAE,QAAQ;MACjB,KAAK,EAAE,cAAc;MACrB,GAAG,EAAE,MAAM;MACX,IAAI,EAAE,OAAO;MACb,KAAK,EAAE,CAAC;QAAE;MAAM,CAAC,KAAK,YAAY,KAAK,SAAS;MAChD,MAAM,EAAE,CAAC;QAAE;MAAM,CAAC,KAAK,aAAa,KAAK,SAAS;MAClD,IAAI,EAAE,WAAW;MACjB,UAAU,EAAE,CAAC;QAAE;MAAM,CAAC,KAAK,OAAO,KAAK;IACzC;EACF;AACF,CAAC,CAAC;AAIF;AACA,OAAO,MAAM,iBAAiB,GAAG,MAA8B;EAC7D,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC;EAC1B,OAAO,MAAM,cAAc,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACnD,CAAC;AAED,OAAO,MAAM,mBAAmB,GAAG,MAAM,cAAc,CAAC,KAAK,CAAC,CAAC","ignoreList":[]}
@@ -8,6 +8,7 @@ export { FilterChip, FilterToggle } from "./FilterChip";
8
8
  export { GestureMenu } from "./GestureMenu";
9
9
  export { RemoveButton } from "./RemoveButton";
10
10
  export { SegmentedControl } from "./SegmentedControl";
11
+ export { SelectionToolbar } from "./SelectionToolbar";
11
12
  export { SplitButton } from "./SplitButton";
12
13
  export { openSpotlightSearch, SpotlightButton } from "./SpotlightSearch";
13
14
  export { Tabs } from "./Tabs";
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["actions/index.ts"],"sourcesContent":["export type { ButtonAlign, ButtonLinkProps, ButtonProps, ButtonSize, ButtonVariant, IconButtonLinkProps, IconButtonProps } from \"./Button\";\nexport { Button, ButtonLink, IconButton, IconButtonLink } from \"./Button\";\nexport type { ContextMenuProps } from \"./ContextMenu\";\nexport { ContextMenu } from \"./ContextMenu\";\nexport type { CopyButtonProps, CopyButtonValue } from \"./CopyButton\";\nexport { CopyButton } from \"./CopyButton\";\nexport type { DisclosureProps } from \"./Disclosure\";\nexport { Disclosure } from \"./Disclosure\";\nexport type { DragPayload, DragSourceProps, DropTargetProps } from \"./DragAndDrop\";\nexport { activeDrag, DragSource, DropTarget, useKeyboardDrag } from \"./DragAndDrop\";\nexport type {\n DropdownAction,\n DropdownActionBase,\n DropdownChoice,\n DropdownItemProps,\n DropdownPosition,\n DropdownProps,\n DropdownSection,\n DropdownTriggerProps,\n} from \"./Dropdown\";\nexport { Dropdown, DropdownItem, dropdownPosition } from \"./Dropdown\";\nexport type { FilterChipOption, FilterChipProps, FilterChipSection, FilterToggleProps } from \"./FilterChip\";\nexport { FilterChip, FilterToggle } from \"./FilterChip\";\nexport type { GestureKind, GestureMenuAction, GestureMenuItem, GestureMenuProps, GestureMenuSection } from \"./GestureMenu\";\nexport { GestureMenu } from \"./GestureMenu\";\nexport type { RemoveButtonProps } from \"./RemoveButton\";\nexport { RemoveButton } from \"./RemoveButton\";\nexport type { SegmentedControlProps, SegmentOption } from \"./SegmentedControl\";\nexport { SegmentedControl } from \"./SegmentedControl\";\nexport type { SplitButtonProps } from \"./SplitButton\";\nexport { SplitButton } from \"./SplitButton\";\nexport type {\n SpotlightButtonProps,\n SpotlightButtonVariant,\n SpotlightSearchOptions,\n SpotlightSearchResolver,\n} from \"./SpotlightSearch\";\nexport {\n openSpotlightSearch,\n SpotlightButton,\n} from \"./SpotlightSearch\";\nexport type { TabOption, TabsItemProps, TabsProps } from \"./Tabs\";\nexport { Tabs } from \"./Tabs\";\nexport type { ToolbarActionProps, ToolbarGroupProps, ToolbarLabelProps, ToolbarProps, ToolbarSeparatorProps } from \"./Toolbar\";\nexport { Toolbar } from \"./Toolbar\";\nexport type { ViewTab, ViewTabsProps } from \"./ViewTabs\";\nexport { ViewTabs } from \"./ViewTabs\";\n"],"mappings":"AACA,SAAS,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,QAAQ,UAAU;AAEzE,SAAS,WAAW,QAAQ,eAAe;AAE3C,SAAS,UAAU,QAAQ,cAAc;AAEzC,SAAS,UAAU,QAAQ,cAAc;AAEzC,SAAS,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,eAAe,QAAQ,eAAe;AAWnF,SAAS,QAAQ,EAAE,YAAY,EAAE,gBAAgB,QAAQ,YAAY;AAErE,SAAS,UAAU,EAAE,YAAY,QAAQ,cAAc;AAEvD,SAAS,WAAW,QAAQ,eAAe;AAE3C,SAAS,YAAY,QAAQ,gBAAgB;AAE7C,SAAS,gBAAgB,QAAQ,oBAAoB;AAErD,SAAS,WAAW,QAAQ,eAAe;AAO3C,SACE,mBAAmB,EACnB,eAAe,QACV,mBAAmB;AAE1B,SAAS,IAAI,QAAQ,QAAQ;AAE7B,SAAS,OAAO,QAAQ,WAAW;AAEnC,SAAS,QAAQ,QAAQ,YAAY","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["actions/index.ts"],"sourcesContent":["export type { ButtonAlign, ButtonLinkProps, ButtonProps, ButtonSize, ButtonVariant, IconButtonLinkProps, IconButtonProps } from \"./Button\";\nexport { Button, ButtonLink, IconButton, IconButtonLink } from \"./Button\";\nexport type { ContextMenuProps } from \"./ContextMenu\";\nexport { ContextMenu } from \"./ContextMenu\";\nexport type { CopyButtonProps, CopyButtonValue } from \"./CopyButton\";\nexport { CopyButton } from \"./CopyButton\";\nexport type { DisclosureProps } from \"./Disclosure\";\nexport { Disclosure } from \"./Disclosure\";\nexport type { DragPayload, DragSourceProps, DropTargetProps } from \"./DragAndDrop\";\nexport { activeDrag, DragSource, DropTarget, useKeyboardDrag } from \"./DragAndDrop\";\nexport type {\n DropdownAction,\n DropdownActionBase,\n DropdownChoice,\n DropdownItemProps,\n DropdownPosition,\n DropdownProps,\n DropdownSection,\n DropdownTriggerProps,\n} from \"./Dropdown\";\nexport { Dropdown, DropdownItem, dropdownPosition } from \"./Dropdown\";\nexport type { FilterChipOption, FilterChipProps, FilterChipSection, FilterToggleProps } from \"./FilterChip\";\nexport { FilterChip, FilterToggle } from \"./FilterChip\";\nexport type { GestureKind, GestureMenuAction, GestureMenuItem, GestureMenuProps, GestureMenuSection } from \"./GestureMenu\";\nexport { GestureMenu } from \"./GestureMenu\";\nexport type { RemoveButtonProps } from \"./RemoveButton\";\nexport { RemoveButton } from \"./RemoveButton\";\nexport type { SegmentedControlProps, SegmentOption } from \"./SegmentedControl\";\nexport { SegmentedControl } from \"./SegmentedControl\";\nexport type { SelectionToolbarProps } from \"./SelectionToolbar\";\nexport { SelectionToolbar } from \"./SelectionToolbar\";\nexport type { SplitButtonProps } from \"./SplitButton\";\nexport { SplitButton } from \"./SplitButton\";\nexport type {\n SpotlightButtonProps,\n SpotlightButtonVariant,\n SpotlightSearchOptions,\n SpotlightSearchResolver,\n} from \"./SpotlightSearch\";\nexport {\n openSpotlightSearch,\n SpotlightButton,\n} from \"./SpotlightSearch\";\nexport type { TabOption, TabsItemProps, TabsProps } from \"./Tabs\";\nexport { Tabs } from \"./Tabs\";\nexport type { ToolbarActionProps, ToolbarGroupProps, ToolbarLabelProps, ToolbarProps, ToolbarSeparatorProps } from \"./Toolbar\";\nexport { Toolbar } from \"./Toolbar\";\nexport type { ViewTab, ViewTabsProps } from \"./ViewTabs\";\nexport { ViewTabs } from \"./ViewTabs\";\n"],"mappings":"AACA,SAAS,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,QAAQ,UAAU;AAEzE,SAAS,WAAW,QAAQ,eAAe;AAE3C,SAAS,UAAU,QAAQ,cAAc;AAEzC,SAAS,UAAU,QAAQ,cAAc;AAEzC,SAAS,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,eAAe,QAAQ,eAAe;AAWnF,SAAS,QAAQ,EAAE,YAAY,EAAE,gBAAgB,QAAQ,YAAY;AAErE,SAAS,UAAU,EAAE,YAAY,QAAQ,cAAc;AAEvD,SAAS,WAAW,QAAQ,eAAe;AAE3C,SAAS,YAAY,QAAQ,gBAAgB;AAE7C,SAAS,gBAAgB,QAAQ,oBAAoB;AAErD,SAAS,gBAAgB,QAAQ,oBAAoB;AAErD,SAAS,WAAW,QAAQ,eAAe;AAO3C,SACE,mBAAmB,EACnB,eAAe,QACV,mBAAmB;AAE1B,SAAS,IAAI,QAAQ,QAAQ;AAE7B,SAAS,OAAO,QAAQ,WAAW;AAEnC,SAAS,QAAQ,QAAQ,YAAY","ignoreList":[]}
@@ -1,15 +1,35 @@
1
1
  /**
2
- * Left and Right cycle through the segments of a row section; Up and Down leave it like any item. Returns whether
3
- * the key moved focus.
2
+ * Left and Right cycle through the segments of a row section, or between a row and its secondary action; Up and Down
3
+ * leave it like any item. Returns whether the key moved focus.
4
4
  */
5
5
  export const focusRowSegment = (items, key) => {
6
6
  if (key !== "ArrowLeft" && key !== "ArrowRight") return false;
7
7
  const active = document.activeElement;
8
- const row = active?.closest(".k2b-dropdown__row");
8
+ const row = active?.closest(".k2b-dropdown__row, .k2b-dropdown__pair");
9
9
  if (!active || !row) return false;
10
10
  const segments = items.filter(item => row.contains(item));
11
11
  const next = segments.indexOf(active) + (key === "ArrowRight" ? 1 : -1);
12
12
  segments[(next + segments.length) % segments.length]?.focus();
13
13
  return true;
14
14
  };
15
+
16
+ /**
17
+ * Moves Up, Down, Home, or End through the rows; a row's secondary action is no stop of its own there, so Down from
18
+ * it goes to the next row. Returns whether the key moved focus.
19
+ */
20
+ export const focusMenuRow = (items, key) => {
21
+ if (!["ArrowDown", "ArrowUp", "Home", "End"].includes(key)) return false;
22
+ const rows = items.filter(item => !item.classList.contains("k2b-dropdown__secondary"));
23
+ if (rows.length === 0) return true;
24
+ if (key === "Home" || key === "End") {
25
+ rows[key === "Home" ? 0 : rows.length - 1]?.focus();
26
+ return true;
27
+ }
28
+ const active = document.activeElement;
29
+ const own = active?.classList.contains("k2b-dropdown__secondary") ? active.closest(".k2b-dropdown__pair")?.querySelector("[role^='menuitem']") : active;
30
+ const current = own ? rows.indexOf(own) : -1;
31
+ const next = current === -1 ? key === "ArrowDown" ? 0 : rows.length - 1 : current + (key === "ArrowDown" ? 1 : -1);
32
+ rows[(next + rows.length) % rows.length]?.focus();
33
+ return true;
34
+ };
15
35
  //# sourceMappingURL=menu-rows.js.map
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["actions/menu-rows.ts"],"sourcesContent":["/**\n * Left and Right cycle through the segments of a row section; Up and Down leave it like any item. Returns whether\n * the key moved focus.\n */\nexport const focusRowSegment = (items: HTMLElement[], key: string): boolean => {\n if (key !== \"ArrowLeft\" && key !== \"ArrowRight\") return false;\n const active = document.activeElement as HTMLElement | null;\n const row = active?.closest(\".k2b-dropdown__row\");\n if (!active || !row) return false;\n const segments = items.filter((item) => row.contains(item));\n const next = segments.indexOf(active) + (key === \"ArrowRight\" ? 1 : -1);\n segments[(next + segments.length) % segments.length]?.focus();\n return true;\n};\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA,OAAO,MAAM,eAAe,GAAG,CAAC,KAAoB,EAAE,GAAW,KAAc;EAC7E,IAAI,GAAG,KAAK,WAAW,IAAI,GAAG,KAAK,YAAY,EAAE,OAAO,KAAK;EAC7D,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAmC;EAC3D,MAAM,GAAG,GAAG,MAAM,EAAE,OAAO,CAAC,oBAAoB,CAAC;EACjD,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG,EAAE,OAAO,KAAK;EACjC,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAE,IAAI,IAAK,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;EAC3D,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,GAAG,KAAK,YAAY,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;EACvE,QAAQ,CAAC,CAAC,IAAI,GAAG,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC;EAC7D,OAAO,IAAI;AACb,CAAC","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["actions/menu-rows.ts"],"sourcesContent":["/**\n * Left and Right cycle through the segments of a row section, or between a row and its secondary action; Up and Down\n * leave it like any item. Returns whether the key moved focus.\n */\nexport const focusRowSegment = (items: HTMLElement[], key: string): boolean => {\n if (key !== \"ArrowLeft\" && key !== \"ArrowRight\") return false;\n const active = document.activeElement as HTMLElement | null;\n const row = active?.closest(\".k2b-dropdown__row, .k2b-dropdown__pair\");\n if (!active || !row) return false;\n const segments = items.filter((item) => row.contains(item));\n const next = segments.indexOf(active) + (key === \"ArrowRight\" ? 1 : -1);\n segments[(next + segments.length) % segments.length]?.focus();\n return true;\n};\n\n/**\n * Moves Up, Down, Home, or End through the rows; a row's secondary action is no stop of its own there, so Down from\n * it goes to the next row. Returns whether the key moved focus.\n */\nexport const focusMenuRow = (items: HTMLElement[], key: string): boolean => {\n if (![\"ArrowDown\", \"ArrowUp\", \"Home\", \"End\"].includes(key)) return false;\n const rows = items.filter((item) => !item.classList.contains(\"k2b-dropdown__secondary\"));\n if (rows.length === 0) return true;\n if (key === \"Home\" || key === \"End\") {\n rows[key === \"Home\" ? 0 : rows.length - 1]?.focus();\n return true;\n }\n const active = document.activeElement as HTMLElement | null;\n const own = active?.classList.contains(\"k2b-dropdown__secondary\")\n ? active.closest(\".k2b-dropdown__pair\")?.querySelector<HTMLElement>(\"[role^='menuitem']\")\n : active;\n const current = own ? rows.indexOf(own) : -1;\n const next = current === -1 ? (key === \"ArrowDown\" ? 0 : rows.length - 1) : current + (key === \"ArrowDown\" ? 1 : -1);\n rows[(next + rows.length) % rows.length]?.focus();\n return true;\n};\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA,OAAO,MAAM,eAAe,GAAG,CAAC,KAAoB,EAAE,GAAW,KAAc;EAC7E,IAAI,GAAG,KAAK,WAAW,IAAI,GAAG,KAAK,YAAY,EAAE,OAAO,KAAK;EAC7D,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAmC;EAC3D,MAAM,GAAG,GAAG,MAAM,EAAE,OAAO,CAAC,yCAAyC,CAAC;EACtE,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG,EAAE,OAAO,KAAK;EACjC,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAE,IAAI,IAAK,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;EAC3D,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,GAAG,KAAK,YAAY,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;EACvE,QAAQ,CAAC,CAAC,IAAI,GAAG,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC;EAC7D,OAAO,IAAI;AACb,CAAC;;AAED;AACA;AACA;AACA;AACA,OAAO,MAAM,YAAY,GAAG,CAAC,KAAoB,EAAE,GAAW,KAAc;EAC1E,IAAI,CAAC,CAAC,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,KAAK;EACxE,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAE,IAAI,IAAK,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,yBAAyB,CAAC,CAAC;EACxF,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,OAAO,IAAI;EAClC,IAAI,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,KAAK,EAAE;IACnC,IAAI,CAAC,GAAG,KAAK,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACnD,OAAO,IAAI;EACb;EACA,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAmC;EAC3D,MAAM,GAAG,GAAG,MAAM,EAAE,SAAS,CAAC,QAAQ,CAAC,yBAAyB,CAAC,GAC7D,MAAM,CAAC,OAAO,CAAC,qBAAqB,CAAC,EAAE,aAAa,CAAc,oBAAoB,CAAC,GACvF,MAAM;EACV,MAAM,OAAO,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;EAC5C,MAAM,IAAI,GAAG,OAAO,KAAK,CAAC,CAAC,GAAI,GAAG,KAAK,WAAW,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,GAAI,OAAO,IAAI,GAAG,KAAK,WAAW,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;EACpH,IAAI,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC;EACjD,OAAO,IAAI;AACb,CAAC","ignoreList":[]}
@@ -7,7 +7,7 @@ import { onCleanup, onMount } from "solid-js";
7
7
  import { dialogCore } from "../feedback/dialog-core";
8
8
  import { LocaleProvider } from "../intl/locale";
9
9
  import BottomSheet, { bottomSheetOptions } from "../layout/BottomSheet";
10
- import { focusRowSegment } from "./menu-rows";
10
+ import { focusMenuRow, focusRowSegment } from "./menu-rows";
11
11
 
12
12
  /** Phones, where a menu opens as a bottom sheet instead of beside its trigger. */
13
13
  export const PHONE_SHEET_QUERY = "(max-width: 47.999rem)";
@@ -65,14 +65,9 @@ const menuItems = menu => Array.from(menu.querySelectorAll("[role^='menuitem']:n
65
65
  */
66
66
  function SheetMenu(props) {
67
67
  let menu;
68
- const focus = index => {
69
- const items = menuItems(menu);
70
- items[(index + items.length) % items.length]?.focus();
71
- };
72
68
  const onKeyDown = event => {
73
69
  const items = menuItems(menu);
74
- const current = items.indexOf(document.activeElement);
75
- if (event.key === "ArrowDown") focus(current + 1);else if (event.key === "ArrowUp") focus(current < 0 ? -1 : current - 1);else if (event.key === "Home" || event.key === "End") focus(event.key === "Home" ? 0 : -1);else if (!focusRowSegment(items, event.key)) return;
70
+ if (!focusMenuRow(items, event.key) && !focusRowSegment(items, event.key)) return;
76
71
  event.preventDefault();
77
72
  };
78
73
  // Keys pressed on the sheet itself, while it is the top level of the shared dialog.
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["actions/menu-sheet.tsx"],"sourcesContent":["import { type JSX, onCleanup, onMount } from \"solid-js\";\nimport { dialogCore } from \"../feedback/dialog-core\";\nimport { LocaleProvider } from \"../intl/locale\";\nimport BottomSheet, { bottomSheetOptions } from \"../layout/BottomSheet\";\nimport type { DropdownAction, DropdownChoice, DropdownItem } from \"./Dropdown\";\nimport { focusRowSegment } from \"./menu-rows\";\n\n/** Phones, where a menu opens as a bottom sheet instead of beside its trigger. */\nexport const PHONE_SHEET_QUERY = \"(max-width: 47.999rem)\";\n\nexport const prefersMenuSheet = (): boolean => typeof matchMedia === \"function\" && matchMedia(PHONE_SHEET_QUERY).matches;\n\ntype SheetEntry = DropdownAction | DropdownChoice;\ntype SheetItem = SheetEntry | { items: readonly SheetEntry[] };\n\n/**\n * Follows a link the way a click on it would, so a page's own link handling, such as progressive navigation, still\n * applies; it runs only after the sheet has left the history.\n */\nconst followLink = (href: string) => {\n const link = document.createElement(\"a\");\n link.href = href;\n link.hidden = true;\n document.body.append(link);\n link.click();\n link.remove();\n};\n\n/**\n * The sheet's items hand their action to `run` instead of running it while the sheet closes: `dialogCore` settles the\n * sheet after it left the history, and only then may an action navigate or open the next dialog.\n * A choice or action that keeps the menu open, or an `immediate` action, runs at once.\n */\nconst afterClose = <T extends DropdownItem>(items: readonly T[], run: (action: () => void) => void): T[] => {\n const entry = (item: SheetEntry): SheetEntry => {\n // A plain link would navigate while the sheet's history entry is still being removed, and that Back could\n // undo the navigation; a plain click instead follows it once the sheet is gone. Modified clicks and external\n // links keep the browser's own behavior.\n if (!item.action && \"href\" in item && item.href && !(\"external\" in item && item.external)) {\n const href = item.href;\n return { ...item, action: () => run(() => followLink(href)) } as SheetEntry;\n }\n const action = item.action;\n if (!action || (\"closeOnSelect\" in item && item.closeOnSelect === false) || (\"immediate\" in item && item.immediate)) return item;\n return { ...item, action: () => run(action) } as SheetEntry;\n };\n return items.map((item) => {\n const sheetItem = item as SheetItem;\n return (\"items\" in sheetItem ? { ...sheetItem, items: sheetItem.items.map(entry) } : entry(sheetItem)) as T;\n });\n};\n\nconst menuItems = (menu: HTMLElement): HTMLElement[] =>\n Array.from(menu.querySelectorAll<HTMLElement>(\"[role^='menuitem']:not([aria-disabled='true'])\"));\n\n/**\n * The menu inside the sheet: the same items, at touch size, with arrow keys for a connected keyboard. Focus starts on\n * the sheet itself, which shows no ring on a phone; the first arrow key moves it into the menu.\n */\nfunction SheetMenu(props: {\n Items: MenuSheetOptions[\"Items\"];\n items: readonly DropdownItem[];\n label: string;\n close: () => void;\n dialog: HTMLDialogElement;\n}): JSX.Element {\n let menu!: HTMLDivElement;\n const focus = (index: number) => {\n const items = menuItems(menu);\n items[(index + items.length) % items.length]?.focus();\n };\n const onKeyDown = (event: KeyboardEvent) => {\n const items = menuItems(menu);\n const current = items.indexOf(document.activeElement as HTMLElement);\n if (event.key === \"ArrowDown\") focus(current + 1);\n else if (event.key === \"ArrowUp\") focus(current < 0 ? -1 : current - 1);\n else if (event.key === \"Home\" || event.key === \"End\") focus(event.key === \"Home\" ? 0 : -1);\n else if (!focusRowSegment(items, event.key)) return;\n event.preventDefault();\n };\n // Keys pressed on the sheet itself, while it is the top level of the shared dialog.\n const onSheetKeyDown = (event: KeyboardEvent) => {\n if (event.target === props.dialog && props.dialog.lastElementChild?.contains(menu)) onKeyDown(event);\n };\n onMount(() => {\n props.dialog.addEventListener(\"keydown\", onSheetKeyDown);\n onCleanup(() => props.dialog.removeEventListener(\"keydown\", onSheetKeyDown));\n });\n return (\n <div ref={menu} class=\"k2b-gesture-menu__sheet-menu\" role=\"menu\" aria-label={props.label} onKeyDown={onKeyDown}>\n <props.Items items={props.items} close={() => props.close()} />\n </div>\n );\n}\n\nexport type MenuSheetOptions = {\n /** Renders the rows: the dropdown's own `DropdownItems`, passed in so this module does not import it back. */\n Items: (props: { items: readonly DropdownItem[]; close: (restoreFocus?: boolean) => void }) => JSX.Element;\n items: readonly DropdownItem[];\n /** Names the sheet and its menu. */\n label: string;\n /** The render locale of the opener; the sheet renders outside its tree. */\n locale: string;\n /** Shown above the menu, for example a row of quick reactions. `close` closes the sheet. */\n top?: (close: () => void) => JSX.Element;\n signal?: AbortSignal;\n};\n\n/** Opens menu items as a bottom sheet; resolves after the sheet closed and the chosen action ran. */\nexport const openMenuSheet = (options: MenuSheetOptions): Promise<void> => {\n let chosen: (() => void) | undefined;\n const choose = (action: () => void) => {\n chosen = action;\n };\n return dialogCore\n .open<void>(\n (close, context) => (\n <LocaleProvider locale={options.locale}>\n <BottomSheet onDismiss={context.requestDismiss}>\n <BottomSheet.Body>\n {options.top?.(() => close())}\n <SheetMenu\n Items={options.Items}\n items={afterClose(options.items, choose)}\n label={options.label}\n close={() => close()}\n dialog={context.dialog}\n />\n </BottomSheet.Body>\n </BottomSheet>\n </LocaleProvider>\n ),\n { ...bottomSheetOptions, ariaLabel: options.label, history: true, signal: options.signal },\n )\n .then(() => chosen?.());\n};\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["actions/menu-sheet.tsx"],"sourcesContent":["import { type JSX, onCleanup, onMount } from \"solid-js\";\nimport { dialogCore } from \"../feedback/dialog-core\";\nimport { LocaleProvider } from \"../intl/locale\";\nimport BottomSheet, { bottomSheetOptions } from \"../layout/BottomSheet\";\nimport type { DropdownAction, DropdownChoice, DropdownItem } from \"./Dropdown\";\nimport { focusMenuRow, focusRowSegment } from \"./menu-rows\";\n\n/** Phones, where a menu opens as a bottom sheet instead of beside its trigger. */\nexport const PHONE_SHEET_QUERY = \"(max-width: 47.999rem)\";\n\nexport const prefersMenuSheet = (): boolean => typeof matchMedia === \"function\" && matchMedia(PHONE_SHEET_QUERY).matches;\n\ntype SheetEntry = DropdownAction | DropdownChoice;\ntype SheetItem = SheetEntry | { items: readonly SheetEntry[] };\n\n/**\n * Follows a link the way a click on it would, so a page's own link handling, such as progressive navigation, still\n * applies; it runs only after the sheet has left the history.\n */\nconst followLink = (href: string) => {\n const link = document.createElement(\"a\");\n link.href = href;\n link.hidden = true;\n document.body.append(link);\n link.click();\n link.remove();\n};\n\n/**\n * The sheet's items hand their action to `run` instead of running it while the sheet closes: `dialogCore` settles the\n * sheet after it left the history, and only then may an action navigate or open the next dialog.\n * A choice or action that keeps the menu open, or an `immediate` action, runs at once.\n */\nconst afterClose = <T extends DropdownItem>(items: readonly T[], run: (action: () => void) => void): T[] => {\n const entry = (item: SheetEntry): SheetEntry => {\n // A plain link would navigate while the sheet's history entry is still being removed, and that Back could\n // undo the navigation; a plain click instead follows it once the sheet is gone. Modified clicks and external\n // links keep the browser's own behavior.\n if (!item.action && \"href\" in item && item.href && !(\"external\" in item && item.external)) {\n const href = item.href;\n return { ...item, action: () => run(() => followLink(href)) } as SheetEntry;\n }\n const action = item.action;\n if (!action || (\"closeOnSelect\" in item && item.closeOnSelect === false) || (\"immediate\" in item && item.immediate)) return item;\n return { ...item, action: () => run(action) } as SheetEntry;\n };\n return items.map((item) => {\n const sheetItem = item as SheetItem;\n return (\"items\" in sheetItem ? { ...sheetItem, items: sheetItem.items.map(entry) } : entry(sheetItem)) as T;\n });\n};\n\nconst menuItems = (menu: HTMLElement): HTMLElement[] =>\n Array.from(menu.querySelectorAll<HTMLElement>(\"[role^='menuitem']:not([aria-disabled='true'])\"));\n\n/**\n * The menu inside the sheet: the same items, at touch size, with arrow keys for a connected keyboard. Focus starts on\n * the sheet itself, which shows no ring on a phone; the first arrow key moves it into the menu.\n */\nfunction SheetMenu(props: {\n Items: MenuSheetOptions[\"Items\"];\n items: readonly DropdownItem[];\n label: string;\n close: () => void;\n dialog: HTMLDialogElement;\n}): JSX.Element {\n let menu!: HTMLDivElement;\n const onKeyDown = (event: KeyboardEvent) => {\n const items = menuItems(menu);\n if (!focusMenuRow(items, event.key) && !focusRowSegment(items, event.key)) return;\n event.preventDefault();\n };\n // Keys pressed on the sheet itself, while it is the top level of the shared dialog.\n const onSheetKeyDown = (event: KeyboardEvent) => {\n if (event.target === props.dialog && props.dialog.lastElementChild?.contains(menu)) onKeyDown(event);\n };\n onMount(() => {\n props.dialog.addEventListener(\"keydown\", onSheetKeyDown);\n onCleanup(() => props.dialog.removeEventListener(\"keydown\", onSheetKeyDown));\n });\n return (\n <div ref={menu} class=\"k2b-gesture-menu__sheet-menu\" role=\"menu\" aria-label={props.label} onKeyDown={onKeyDown}>\n <props.Items items={props.items} close={() => props.close()} />\n </div>\n );\n}\n\nexport type MenuSheetOptions = {\n /** Renders the rows: the dropdown's own `DropdownItems`, passed in so this module does not import it back. */\n Items: (props: { items: readonly DropdownItem[]; close: (restoreFocus?: boolean) => void }) => JSX.Element;\n items: readonly DropdownItem[];\n /** Names the sheet and its menu. */\n label: string;\n /** The render locale of the opener; the sheet renders outside its tree. */\n locale: string;\n /** Shown above the menu, for example a row of quick reactions. `close` closes the sheet. */\n top?: (close: () => void) => JSX.Element;\n signal?: AbortSignal;\n};\n\n/** Opens menu items as a bottom sheet; resolves after the sheet closed and the chosen action ran. */\nexport const openMenuSheet = (options: MenuSheetOptions): Promise<void> => {\n let chosen: (() => void) | undefined;\n const choose = (action: () => void) => {\n chosen = action;\n };\n return dialogCore\n .open<void>(\n (close, context) => (\n <LocaleProvider locale={options.locale}>\n <BottomSheet onDismiss={context.requestDismiss}>\n <BottomSheet.Body>\n {options.top?.(() => close())}\n <SheetMenu\n Items={options.Items}\n items={afterClose(options.items, choose)}\n label={options.label}\n close={() => close()}\n dialog={context.dialog}\n />\n </BottomSheet.Body>\n </BottomSheet>\n </LocaleProvider>\n ),\n { ...bottomSheetOptions, ariaLabel: options.label, history: true, signal: options.signal },\n )\n .then(() => chosen?.());\n};\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Pure chart renderers that share the `Chart` component's drawing without its Solid wrapper, for hosts that draw
3
+ * SVG themselves, such as server previews and app frames.
4
+ */
5
+ export { barChartLayout, renderBarChartSvg } from "./content/chart-bar";
6
+ //# sourceMappingURL=charts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sources":["charts.ts"],"sourcesContent":["/**\n * Pure chart renderers that share the `Chart` component's drawing without its Solid wrapper, for hosts that draw\n * SVG themselves, such as server previews and app frames.\n */\nexport { type BarChartLayout, type BarChartOptions, barChartLayout, renderBarChartSvg } from \"./content/chart-bar\";\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA,SAAoD,cAAc,EAAE,iBAAiB,QAAQ,qBAAqB","ignoreList":[]}