@kerfjs/ui 5.0.0-beta.106 → 5.0.0-beta.107

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 (226) hide show
  1. package/README.md +2 -1
  2. package/ai/application-ui-diagnostic-ids-v1.json +1 -0
  3. package/ai/application-ui-profile.defaults.json +6 -1
  4. package/ai/component-catalog.json +160 -27
  5. package/ai/component-composition-rules.json +20 -2
  6. package/ai/component-composition.d.ts +11 -0
  7. package/ai/component-composition.json +118 -19
  8. package/ai/component-composition.schema.json +32 -0
  9. package/ai/components/README.md +3 -2
  10. package/ai/components/button.md +4 -1
  11. package/ai/components/checkbox-group.md +89 -0
  12. package/ai/components/checkbox.md +3 -2
  13. package/ai/components/color-picker.md +10 -7
  14. package/ai/components/disclosure.md +6 -1
  15. package/ai/components/foundation.md +1 -1
  16. package/ai/components/list-detail-dialog.md +1 -1
  17. package/ai/components/message-composer.md +2 -1
  18. package/ai/components/radio-group.md +4 -3
  19. package/ai/components/split-button.md +5 -2
  20. package/ai/components/surface-scaffold.md +2 -1
  21. package/ai/components/switch.md +1 -1
  22. package/ai/components/text.md +2 -0
  23. package/ai/components/wa-checkbox-group.md +5 -5
  24. package/ai/components/workbench-dialog.md +1 -1
  25. package/ai/public-api-signatures-v1.md +196 -24
  26. package/ai/skill.md +73 -62
  27. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  28. package/dist/browser/checkbox-group.js +5 -0
  29. package/dist/button.d.ts +15 -2
  30. package/dist/button.js +1 -1
  31. package/dist/catalog.js +9 -8
  32. package/dist/catalog.js.map +1 -1
  33. package/dist/checkbox-group.d.ts +70 -0
  34. package/dist/checkbox-group.js +7 -0
  35. package/dist/checkbox-group.js.map +1 -0
  36. package/dist/{chunk-SQ2Q3OQI.js → chunk-2LM3PYHA.js} +2 -2
  37. package/dist/{chunk-SQ2Q3OQI.js.map → chunk-2LM3PYHA.js.map} +1 -1
  38. package/dist/{chunk-HYORKKYP.js → chunk-3VZ6SFD4.js} +1 -1
  39. package/dist/chunk-3VZ6SFD4.js.map +1 -0
  40. package/dist/{chunk-EKBMUXFV.js → chunk-3Z7N2NAZ.js} +141 -54
  41. package/dist/chunk-3Z7N2NAZ.js.map +1 -0
  42. package/dist/{chunk-FKKJHGN5.js → chunk-AZ3WT77F.js} +2 -2
  43. package/dist/{chunk-FKKJHGN5.js.map → chunk-AZ3WT77F.js.map} +1 -1
  44. package/dist/{chunk-FG6U7KQQ.js → chunk-DNWWF6UN.js} +2 -2
  45. package/dist/{chunk-FG6U7KQQ.js.map → chunk-DNWWF6UN.js.map} +1 -1
  46. package/dist/{chunk-C3RLKKFQ.js → chunk-EYDXFOSH.js} +13 -8
  47. package/dist/chunk-EYDXFOSH.js.map +1 -0
  48. package/dist/{chunk-TAHR457X.js → chunk-G4DRH4A5.js} +3 -1
  49. package/dist/chunk-G4DRH4A5.js.map +1 -0
  50. package/dist/{chunk-PE2KPZDW.js → chunk-HDXUHLTQ.js} +7 -2
  51. package/dist/chunk-HDXUHLTQ.js.map +1 -0
  52. package/dist/chunk-HU5IHXCI.js +73 -0
  53. package/dist/chunk-HU5IHXCI.js.map +1 -0
  54. package/dist/{chunk-DF2YKGIX.js → chunk-JCCN3U6X.js} +2 -2
  55. package/dist/{chunk-DF2YKGIX.js.map → chunk-JCCN3U6X.js.map} +1 -1
  56. package/dist/{chunk-GCAK23PU.js → chunk-MVKHSAKE.js} +2 -2
  57. package/dist/{chunk-GCAK23PU.js.map → chunk-MVKHSAKE.js.map} +1 -1
  58. package/dist/{chunk-DDSCVEO5.js → chunk-NLMEDZRM.js} +5 -5
  59. package/dist/{chunk-DDSCVEO5.js.map → chunk-NLMEDZRM.js.map} +1 -1
  60. package/dist/{chunk-ECFCAKWE.js → chunk-NR6O74ST.js} +5 -1
  61. package/dist/chunk-NR6O74ST.js.map +1 -0
  62. package/dist/{chunk-7W3GKMN4.js → chunk-OQP3PFKQ.js} +7 -4
  63. package/dist/chunk-OQP3PFKQ.js.map +1 -0
  64. package/dist/{chunk-WJKHLOP5.js → chunk-TI2GV36S.js} +8 -2
  65. package/dist/chunk-TI2GV36S.js.map +1 -0
  66. package/dist/{chunk-UTCAOOXU.js → chunk-TXRKCGT3.js} +8 -2
  67. package/dist/chunk-TXRKCGT3.js.map +1 -0
  68. package/dist/{chunk-ACUKTVS3.js → chunk-XWNXGFX3.js} +52 -42
  69. package/dist/chunk-XWNXGFX3.js.map +1 -0
  70. package/dist/{chunk-ZXZAECHZ.js → chunk-Z4DS77U2.js} +2 -2
  71. package/dist/{chunk-ZXZAECHZ.js.map → chunk-Z4DS77U2.js.map} +1 -1
  72. package/dist/collapsible-panel.js +2 -2
  73. package/dist/color-picker.d.ts +30 -5
  74. package/dist/color-picker.js +1 -1
  75. package/dist/disclosure.d.ts +13 -4
  76. package/dist/disclosure.js.map +1 -1
  77. package/dist/help-tags-register.js +1 -1
  78. package/dist/index.d.ts +2 -1
  79. package/dist/index.js +20 -19
  80. package/dist/list-action-row.js +1 -1
  81. package/dist/list-detail-dialog.d.ts +7 -1
  82. package/dist/list-detail-dialog.js +6 -4
  83. package/dist/list-detail-dialog.js.map +1 -1
  84. package/dist/list-header.d.ts +8 -1
  85. package/dist/list-header.js +1 -1
  86. package/dist/nav-stack.js +1 -1
  87. package/dist/popup-menu-register.js +2 -2
  88. package/dist/popup-menu.d.ts +15 -5
  89. package/dist/popup-menu.js +1 -1
  90. package/dist/select-register.js +3 -3
  91. package/dist/split-button.d.ts +14 -2
  92. package/dist/split-button.js +1 -1
  93. package/dist/split-view.js +1 -1
  94. package/dist/styles/anchored-surface.css +3 -0
  95. package/dist/styles/button.css +29 -0
  96. package/dist/styles/catalog/components/catalog-example.css +55 -18
  97. package/dist/styles/checkbox-group.css +63 -0
  98. package/dist/styles/checkbox.css +7 -6
  99. package/dist/styles/color-picker.css +69 -34
  100. package/dist/styles/components/actions/button/button.css +29 -0
  101. package/dist/styles/components/actions/split-button/split-button.css +51 -5
  102. package/dist/styles/components/collections/framed-list/framed-list.css +4 -0
  103. package/dist/styles/components/collections/list/list.css +6 -0
  104. package/dist/styles/components/collections/list-header/list-header.css +7 -0
  105. package/dist/styles/components/feedback/anchored-surface/anchored-surface.css +3 -0
  106. package/dist/styles/components/forms/checkbox/checkbox.css +7 -6
  107. package/dist/styles/components/forms/checkbox-group/checkbox-group.css +63 -0
  108. package/dist/styles/components/forms/color-picker/color-picker.css +69 -34
  109. package/dist/styles/components/forms/radio-group/radio-group.css +7 -5
  110. package/dist/styles/components/forms/select/select.css +6 -2
  111. package/dist/styles/components/forms/switch/switch.css +3 -3
  112. package/dist/styles/components/layout/pane/pane.css +9 -0
  113. package/dist/styles/components/layout/workbench/workbench.css +4 -0
  114. package/dist/styles/components/navigation/nav-stack/nav-stack.css +64 -1
  115. package/dist/styles/components/navigation/tab-navigator/tab-navigator.css +1 -0
  116. package/dist/styles/components/surfaces/content-item/content-item.css +30 -0
  117. package/dist/styles/components/surfaces/disclosure/disclosure.css +38 -0
  118. package/dist/styles/components/surfaces/sunken-panel/sunken-panel.css +3 -0
  119. package/dist/styles/components/surfaces/surface-scaffold/surface-scaffold.css +6 -0
  120. package/dist/styles/components/typography/text/text.css +10 -0
  121. package/dist/styles/content-item.css +30 -0
  122. package/dist/styles/disclosure.css +38 -0
  123. package/dist/styles/foundation.css +21 -0
  124. package/dist/styles/framed-list.css +4 -0
  125. package/dist/styles/list-header.css +7 -0
  126. package/dist/styles/list.css +6 -0
  127. package/dist/styles/nav-stack.css +64 -1
  128. package/dist/styles/pane.css +9 -0
  129. package/dist/styles/radio-group.css +7 -5
  130. package/dist/styles/select.css +6 -2
  131. package/dist/styles/split-button.css +51 -5
  132. package/dist/styles/styles.css +1 -0
  133. package/dist/styles/sunken-panel.css +3 -0
  134. package/dist/styles/surface-scaffold.css +6 -0
  135. package/dist/styles/switch.css +3 -3
  136. package/dist/styles/tab-navigator.css +1 -0
  137. package/dist/styles/text.css +10 -0
  138. package/dist/styles/webawesome.css +45 -9
  139. package/dist/styles/workbench.css +4 -0
  140. package/dist/surface-scaffold.d.ts +7 -1
  141. package/dist/surface-scaffold.js +1 -1
  142. package/dist/wire-color-fields.js +2 -2
  143. package/dist/wire-color-pickers.d.ts +4 -3
  144. package/dist/wire-color-pickers.js +1 -1
  145. package/dist/wire-comboboxes.js +1 -1
  146. package/dist/workbench-dialog.d.ts +11 -2
  147. package/dist/workbench-dialog.js +5 -2
  148. package/dist/workbench-dialog.js.map +1 -1
  149. package/dist/workbench.js +1 -1
  150. package/docs/accessibility.md +40 -1
  151. package/docs/anchored-surface.md +6 -1
  152. package/docs/catalog.md +26 -1
  153. package/docs/color-picker.md +39 -8
  154. package/docs/component-contract.md +33 -2
  155. package/docs/component-selection.md +20 -9
  156. package/docs/design/templates/button/full-width-dark.svg +1 -0
  157. package/docs/design/templates/button/full-width.svg +1 -0
  158. package/docs/design/templates/button-dark.svg +1 -1
  159. package/docs/design/templates/button.svg +1 -1
  160. package/docs/design/templates/checkbox/error-dark.svg +1 -1
  161. package/docs/design/templates/checkbox/error.svg +1 -1
  162. package/docs/design/templates/checkbox/states-dark.svg +1 -1
  163. package/docs/design/templates/checkbox/states.svg +1 -1
  164. package/docs/design/templates/checkbox-dark.svg +1 -1
  165. package/docs/design/templates/checkbox-group/horizontal-dark.svg +1 -0
  166. package/docs/design/templates/checkbox-group/horizontal.svg +1 -0
  167. package/docs/design/templates/checkbox-group/vertical-dark.svg +1 -0
  168. package/docs/design/templates/checkbox-group/vertical.svg +1 -0
  169. package/docs/design/templates/checkbox-group-dark.svg +1 -0
  170. package/docs/design/templates/checkbox-group.svg +1 -0
  171. package/docs/design/templates/checkbox.svg +1 -1
  172. package/docs/design/templates/color-picker/gray-dark.svg +1 -1
  173. package/docs/design/templates/color-picker/gray.svg +1 -1
  174. package/docs/design/templates/color-picker/hsb-dark.svg +1 -0
  175. package/docs/design/templates/color-picker/hsb.svg +1 -0
  176. package/docs/design/templates/color-picker/rgb-dark.svg +1 -1
  177. package/docs/design/templates/color-picker/rgb.svg +1 -1
  178. package/docs/design/templates/color-picker-dark.svg +1 -1
  179. package/docs/design/templates/color-picker.svg +1 -1
  180. package/docs/design/templates/disclosure/embedded-dark.svg +1 -0
  181. package/docs/design/templates/disclosure/embedded.svg +1 -0
  182. package/docs/design/templates/disclosure-dark.svg +1 -1
  183. package/docs/design/templates/disclosure.svg +1 -1
  184. package/docs/design/templates/radio-group/horizontal-dark.svg +1 -1
  185. package/docs/design/templates/radio-group/horizontal.svg +1 -1
  186. package/docs/design/templates/radio-group/vertical-dark.svg +1 -1
  187. package/docs/design/templates/radio-group/vertical.svg +1 -1
  188. package/docs/design/templates/radio-group-dark.svg +1 -1
  189. package/docs/design/templates/radio-group.svg +1 -1
  190. package/docs/design/templates/split-button/full-width-dark.svg +1 -0
  191. package/docs/design/templates/split-button/full-width.svg +1 -0
  192. package/docs/design/templates/split-button/pill-dark.svg +1 -0
  193. package/docs/design/templates/split-button/pill.svg +1 -0
  194. package/docs/design/templates/split-button/states-dark.svg +1 -0
  195. package/docs/design/templates/split-button/states.svg +1 -0
  196. package/docs/design/templates/split-button/tones-dark.svg +1 -0
  197. package/docs/design/templates/split-button/tones.svg +1 -0
  198. package/docs/design/templates/split-button-dark.svg +1 -0
  199. package/docs/design/templates/split-button.svg +1 -0
  200. package/docs/design/templates/switch/states-dark.svg +1 -1
  201. package/docs/design/templates/switch/states.svg +1 -1
  202. package/docs/design/templates/switch-dark.svg +1 -1
  203. package/docs/design/templates/switch.svg +1 -1
  204. package/docs/design/templates.md +10 -3
  205. package/docs/disclosure.md +34 -0
  206. package/docs/list-detail-dialog.md +4 -0
  207. package/docs/nav-stack.md +6 -2
  208. package/docs/surface-scaffold.md +6 -2
  209. package/docs/ui-doctor.md +16 -4
  210. package/docs/webawesome-migration.md +1 -1
  211. package/docs/webawesome-theme.md +48 -16
  212. package/docs/workbench-dialog.md +4 -1
  213. package/docs/writing.md +3 -3
  214. package/doctor/copy-capitalization-checks.mjs +10 -7
  215. package/llms.txt +50 -20
  216. package/package.json +7 -1
  217. package/dist/chunk-7W3GKMN4.js.map +0 -1
  218. package/dist/chunk-ACUKTVS3.js.map +0 -1
  219. package/dist/chunk-C3RLKKFQ.js.map +0 -1
  220. package/dist/chunk-ECFCAKWE.js.map +0 -1
  221. package/dist/chunk-EKBMUXFV.js.map +0 -1
  222. package/dist/chunk-HYORKKYP.js.map +0 -1
  223. package/dist/chunk-PE2KPZDW.js.map +0 -1
  224. package/dist/chunk-TAHR457X.js.map +0 -1
  225. package/dist/chunk-UTCAOOXU.js.map +0 -1
  226. package/dist/chunk-WJKHLOP5.js.map +0 -1
@@ -1,10 +1,84 @@
1
- import { hsvToRgb, grayLevel, rgbToHsl, formatHex, parseColor, rgbToHsv } from './chunk-TNJLNLVE.js';
1
+ import { grayLevel, hsvToRgb, rgbToHsl, rgbToHsv, formatHex, parseColor, hslToRgb } from './chunk-TNJLNLVE.js';
2
2
  import { ColorSwatches } from './chunk-IO27YTL3.js';
3
3
  import { LucideIcon } from './chunk-HJXVVFBT.js';
4
4
  import { filterDataAttributes } from './chunk-KH4KEMSP.js';
5
5
  import { ChevronsUpDown, Pipette, Plus } from 'lucide';
6
6
  import { jsxs, jsx } from 'kerfjs/jsx-runtime';
7
7
 
8
+ // src/components/forms/color-picker/model/color-channels.ts
9
+ function colorChannelValues(mode, hsv) {
10
+ switch (mode) {
11
+ case "rgb": {
12
+ const { r, g, b } = hsvToRgb(hsv);
13
+ return [r, g, b].map(Math.round);
14
+ }
15
+ case "hsl": {
16
+ const hsl = rgbToHsl(hsvToRgb(hsv));
17
+ return [hsv.h, hsl.s * 100, hsl.l * 100];
18
+ }
19
+ case "hsb":
20
+ return [hsv.h, hsv.s * 100, hsv.v * 100];
21
+ case "gray":
22
+ return [grayLevel(hsvToRgb(hsv)) * 100];
23
+ }
24
+ }
25
+ function rgbOf(mode, values) {
26
+ const [first = 0, second = 0, third = 0] = values;
27
+ switch (mode) {
28
+ case "rgb":
29
+ return { r: first, g: second, b: third, a: 1 };
30
+ case "hsl":
31
+ return hslToRgb({ h: first, s: second / 100, l: third / 100, a: 1 });
32
+ case "hsb":
33
+ return hsvToRgb({ h: first, s: second / 100, v: third / 100, a: 1 });
34
+ case "gray": {
35
+ const level = first / 100 * 255;
36
+ return { r: level, g: level, b: level, a: 1 };
37
+ }
38
+ }
39
+ }
40
+ function hsvFromChannels(mode, values, current) {
41
+ const { a } = current;
42
+ switch (mode) {
43
+ case "hsb":
44
+ return { h: values[0], s: values[1] / 100, v: values[2] / 100, a };
45
+ case "gray":
46
+ return { h: current.h, s: 0, v: values[0] / 100, a };
47
+ case "rgb":
48
+ case "hsl": {
49
+ const hsv = { ...rgbToHsv(rgbOf(mode, values)), a };
50
+ if (mode === "hsl") hsv.h = values[0];
51
+ else if (hsv.s === 0) hsv.h = current.h;
52
+ if (hsv.v === 0) hsv.s = current.s;
53
+ return hsv;
54
+ }
55
+ }
56
+ }
57
+ function trackStops(mode, index) {
58
+ switch (mode) {
59
+ case "rgb":
60
+ return [0, 255];
61
+ case "gray":
62
+ return [0, 100];
63
+ case "hsl":
64
+ case "hsb":
65
+ if (index === 0) return [0, 60, 120, 180, 240, 300, 360];
66
+ return mode === "hsl" && index === 2 ? [0, 50, 100] : [0, 100];
67
+ }
68
+ }
69
+ function colorChannelColor(mode, values) {
70
+ return formatHex(rgbOf(mode, values));
71
+ }
72
+ function colorChannelTrack(mode, index, values) {
73
+ const hue = index === 0 && (mode === "hsl" || mode === "hsb");
74
+ const stops = trackStops(mode, index).map((stop) => {
75
+ if (hue) return formatHex(rgbOf("hsb", [stop, 100, 100]));
76
+ const next = [...values];
77
+ next[index] = stop;
78
+ return formatHex(rgbOf(mode, next));
79
+ });
80
+ return `linear-gradient(var(--_kui-color-picker-track-direction,to right),${stops.join(",")})`;
81
+ }
8
82
  var COLOR_PICKER_PROTECTED = /* @__PURE__ */ new Set([
9
83
  "data-component",
10
84
  "data-value",
@@ -21,36 +95,39 @@ var MODE_LABELS = {
21
95
  };
22
96
  var COLOR_PICKER_CHANNELS = {
23
97
  rgb: [
24
- { short: "R", name: "Red", max: 255 },
25
- { short: "G", name: "Green", max: 255 },
26
- { short: "B", name: "Blue", max: 255 }
98
+ { short: "R", name: "Red", max: 255, unit: "" },
99
+ { short: "G", name: "Green", max: 255, unit: "" },
100
+ { short: "B", name: "Blue", max: 255, unit: "" }
27
101
  ],
28
102
  hsl: [
29
- { short: "H", name: "Hue", max: 360 },
30
- { short: "S", name: "Saturation", max: 100 },
31
- { short: "L", name: "Lightness", max: 100 }
103
+ { short: "H", name: "Hue", max: 360, unit: "\xB0" },
104
+ { short: "S", name: "Saturation", max: 100, unit: "%" },
105
+ { short: "L", name: "Lightness", max: 100, unit: "%" }
32
106
  ],
33
107
  hsb: [
34
- { short: "H", name: "Hue", max: 360 },
35
- { short: "S", name: "Saturation", max: 100 },
36
- { short: "B", name: "Brightness", max: 100 }
108
+ { short: "H", name: "Hue", max: 360, unit: "\xB0" },
109
+ { short: "S", name: "Saturation", max: 100, unit: "%" },
110
+ { short: "B", name: "Brightness", max: 100, unit: "%" }
37
111
  ],
38
- gray: [{ short: "W", name: "Gray Level", max: 100 }]
112
+ gray: [{ short: "W", name: "Gray Level", max: 100, unit: "%" }]
39
113
  };
40
114
  function colorPickerChannels(mode, hsv) {
41
- const rgba = hsvToRgb(hsv);
42
- switch (mode) {
43
- case "rgb":
44
- return [rgba.r, rgba.g, rgba.b].map(Math.round);
45
- case "hsl": {
46
- const hsl = rgbToHsl(rgba);
47
- return [hsv.h, hsl.s * 100, hsl.l * 100].map(Math.round);
48
- }
49
- case "hsb":
50
- return [hsv.h, hsv.s * 100, hsv.v * 100].map(Math.round);
51
- case "gray":
52
- return [Math.round(grayLevel(rgba) * 100)];
53
- }
115
+ return colorChannelValues(mode, hsv).map(Math.round);
116
+ }
117
+ function colorPickerSlider(mode, index, values) {
118
+ const channel = COLOR_PICKER_CHANNELS[mode][index];
119
+ if (channel === void 0) return void 0;
120
+ const value = String(Math.round(values[index]));
121
+ return {
122
+ max: channel.max,
123
+ value,
124
+ label: channel.name,
125
+ valueText: `${value}${channel.unit}`,
126
+ style: [
127
+ `--_kui-color-picker-track:${colorChannelTrack(mode, index, values)}`,
128
+ `--_kui-color-picker-thumb-color:${colorChannelColor(mode, values)}`
129
+ ].join(";")
130
+ };
54
131
  }
55
132
  function colorPickerAreaText(hsv) {
56
133
  return `Saturation ${Math.round(hsv.s * 100)}%, brightness ${Math.round(hsv.v * 100)}%`;
@@ -87,7 +164,8 @@ function ColorPicker({
87
164
  const hsv = rgbToHsv(rgba);
88
165
  const hex = formatHex(rgba);
89
166
  const channels = COLOR_PICKER_CHANNELS[mode];
90
- const channelValues = colorPickerChannels(mode, hsv);
167
+ const exact = colorChannelValues(mode, hsv);
168
+ const channelValues = exact.map(Math.round);
91
169
  const opacity = `${Math.round(hsv.a * 100)}%`;
92
170
  return /* @__PURE__ */ jsxs(
93
171
  "div",
@@ -127,33 +205,42 @@ function ColorPicker({
127
205
  children: /* @__PURE__ */ jsx("span", { class: "kui-color-picker__area-thumb" })
128
206
  }
129
207
  ),
130
- /* @__PURE__ */ jsx(
131
- "input",
132
- {
133
- class: "kui-color-picker__hue",
134
- type: "range",
135
- min: "0",
136
- max: "360",
137
- step: "1",
138
- value: String(Math.round(hsv.h)),
139
- "aria-label": "Hue",
140
- disabled
141
- }
142
- ),
143
- alpha ? /* @__PURE__ */ jsx(
144
- "input",
145
- {
146
- class: "kui-color-picker__opacity",
147
- type: "range",
148
- min: "0",
149
- max: "100",
150
- step: "1",
151
- value: String(Math.round(hsv.a * 100)),
152
- "aria-label": "Opacity",
153
- "aria-valuetext": opacity,
154
- disabled
155
- }
156
- ) : null,
208
+ /* @__PURE__ */ jsxs("div", { class: "kui-color-picker__sliders", children: [
209
+ [0, 1, 2].map((index) => {
210
+ const slider = colorPickerSlider(mode, index, exact);
211
+ return /* @__PURE__ */ jsx(
212
+ "input",
213
+ {
214
+ class: "kui-color-picker__slider",
215
+ type: "range",
216
+ "data-slider": String(index),
217
+ min: "0",
218
+ max: String(slider?.max ?? 100),
219
+ step: "1",
220
+ value: slider?.value ?? "0",
221
+ "aria-label": slider?.label,
222
+ "aria-valuetext": slider?.valueText,
223
+ style: slider?.style,
224
+ hidden: slider === void 0,
225
+ disabled
226
+ }
227
+ );
228
+ }),
229
+ alpha ? /* @__PURE__ */ jsx(
230
+ "input",
231
+ {
232
+ class: "kui-color-picker__opacity",
233
+ type: "range",
234
+ min: "0",
235
+ max: "100",
236
+ step: "1",
237
+ value: String(Math.round(hsv.a * 100)),
238
+ "aria-label": "Opacity",
239
+ "aria-valuetext": opacity,
240
+ disabled
241
+ }
242
+ ) : null
243
+ ] }),
157
244
  /* @__PURE__ */ jsxs("div", { class: "kui-color-picker__controls", children: [
158
245
  /* @__PURE__ */ jsxs("span", { class: "kui-color-picker__mode-wrap", children: [
159
246
  /* @__PURE__ */ jsx(
@@ -293,6 +380,6 @@ function ColorPicker({
293
380
  );
294
381
  }
295
382
 
296
- export { COLOR_PICKER_CHANNELS, COLOR_PICKER_SWATCH_ACTION, ColorPicker, colorPickerAreaText, colorPickerChannels, colorPickerStyle };
383
+ export { COLOR_PICKER_CHANNELS, COLOR_PICKER_SWATCH_ACTION, ColorPicker, colorChannelValues, colorPickerAreaText, colorPickerChannels, colorPickerSlider, colorPickerStyle, hsvFromChannels };
297
384
 
298
- //# sourceMappingURL=chunk-EKBMUXFV.js.map
385
+ //# sourceMappingURL=chunk-3Z7N2NAZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/forms/color-picker/model/color-channels.ts","../src/components/forms/color-picker/color-picker.tsx"],"names":[],"mappings":"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","file":"chunk-3Z7N2NAZ.js","sourcesContent":["/**\n * Channel math for the ColorPicker's color models: the unrounded channel\n * values a model shows for the picker's HSV state, the HSV a set of channel\n * values produces, and the gradient each channel's slider track paints. The\n * model's sliders and fields both edit through these, so a channel change\n * replaces only that channel and every other one keeps its exact value.\n */\nimport type { ColorPickerMode } from '../color-picker.js';\nimport {\n formatHex,\n grayLevel,\n hslToRgb,\n type Hsva,\n hsvToRgb,\n type Rgba,\n rgbToHsl,\n rgbToHsv,\n} from './color-model.js';\n\n/**\n * The channel values a model shows for an HSV color, before rounding: RGB\n * 0–255 (rounded, since hex and the fields carry whole bytes), hue 0–360,\n * and every other channel 0–100.\n */\nexport function colorChannelValues(mode: ColorPickerMode, hsv: Hsva): number[] {\n switch (mode) {\n case 'rgb': {\n const { r, g, b } = hsvToRgb(hsv);\n return [r, g, b].map(Math.round);\n }\n case 'hsl': {\n const hsl = rgbToHsl(hsvToRgb(hsv));\n return [hsv.h, hsl.s * 100, hsl.l * 100];\n }\n case 'hsb':\n return [hsv.h, hsv.s * 100, hsv.v * 100];\n case 'gray':\n return [grayLevel(hsvToRgb(hsv)) * 100];\n }\n}\n\n/** The opaque color a model's channel values describe. */\nfunction rgbOf(mode: ColorPickerMode, values: readonly number[]): Rgba {\n const [first = 0, second = 0, third = 0] = values;\n switch (mode) {\n case 'rgb':\n return { r: first, g: second, b: third, a: 1 };\n case 'hsl':\n return hslToRgb({ h: first, s: second / 100, l: third / 100, a: 1 });\n case 'hsb':\n return hsvToRgb({ h: first, s: second / 100, v: third / 100, a: 1 });\n case 'gray': {\n const level = (first / 100) * 255;\n return { r: level, g: level, b: level, a: 1 };\n }\n }\n}\n\n/**\n * The HSV a model's channel values produce, keeping `current`'s alpha. Where\n * the result cannot carry a hue (a gray) or a saturation (black), `current`'s\n * is kept, so the area and the other models do not jump.\n */\nexport function hsvFromChannels(\n mode: ColorPickerMode,\n values: readonly number[],\n current: Hsva,\n): Hsva {\n const { a } = current;\n switch (mode) {\n case 'hsb':\n return { h: values[0]!, s: values[1]! / 100, v: values[2]! / 100, a };\n case 'gray':\n return { h: current.h, s: 0, v: values[0]! / 100, a };\n case 'rgb':\n case 'hsl': {\n const hsv = { ...rgbToHsv(rgbOf(mode, values)), a };\n if (mode === 'hsl') hsv.h = values[0]!;\n else if (hsv.s === 0) hsv.h = current.h;\n if (hsv.v === 0) hsv.s = current.s;\n return hsv;\n }\n }\n}\n\n/**\n * The evenly spaced stop values a channel's track needs to be exact: the\n * models are piecewise linear in RGB, so hue breaks every 60° and HSL\n * lightness at 50%.\n */\nfunction trackStops(mode: ColorPickerMode, index: number): number[] {\n switch (mode) {\n case 'rgb':\n return [0, 255];\n case 'gray':\n return [0, 100];\n case 'hsl':\n case 'hsb':\n if (index === 0) return [0, 60, 120, 180, 240, 300, 360];\n return mode === 'hsl' && index === 2 ? [0, 50, 100] : [0, 100];\n }\n}\n\n/**\n * The opaque `#rrggbb` a model's channel values describe: the color under\n * every channel slider's thumb (a gray level for the grayscale model, which\n * shows the gray its slider would set rather than the current color).\n */\nexport function colorChannelColor(\n mode: ColorPickerMode,\n values: readonly number[],\n): string {\n return formatHex(rgbOf(mode, values));\n}\n\n/**\n * The gradient a channel's slider track paints: the colors that channel\n * produces from its minimum to its maximum while every other channel keeps\n * its value. The HSL and HSB hue track is the exception: it is always the\n * full-saturation, full-brightness rainbow, so a dark or gray color still\n * shows which hue each position picks. The gradient runs in the slider's writing direction (its\n * `--_kui-color-picker-track-direction`, `to left` in right-to-left text),\n * so the minimum always sits where the native range puts it.\n */\nexport function colorChannelTrack(\n mode: ColorPickerMode,\n index: number,\n values: readonly number[],\n): string {\n const hue = index === 0 && (mode === 'hsl' || mode === 'hsb');\n const stops = trackStops(mode, index).map((stop) => {\n if (hue) return formatHex(rgbOf('hsb', [stop, 100, 100]));\n const next = [...values];\n next[index] = stop;\n return formatHex(rgbOf(mode, next));\n });\n return `linear-gradient(var(--_kui-color-picker-track-direction,to right),${stops.join(',')})`;\n}\n","import { ChevronsUpDown, Pipette, Plus } from 'lucide';\n\nimport { filterDataAttributes } from '../../../shared/dom/extension-attributes.js';\nimport { LucideIcon } from '../../media/lucide-icon/lucide-icon.js';\nimport {\n type ColorSwatch,\n ColorSwatches,\n} from '../color-swatches/color-swatches.js';\nimport {\n colorChannelColor,\n colorChannelTrack,\n colorChannelValues,\n} from './model/color-channels.js';\nimport {\n formatHex,\n type Hsva,\n hsvToRgb,\n parseColor,\n rgbToHsv,\n} from './model/color-model.js';\n\n/** The channel fields the picker shows: RGB, HSL, HSB (HSV), or one gray level. */\nexport type ColorPickerMode = 'rgb' | 'hsl' | 'hsb' | 'gray';\n\n/** A titled group of app-owned colors, such as \"Document Colors\". */\nexport interface ColorPickerSamples {\n title: string;\n swatches: readonly ColorSwatch[];\n}\n\n/** Application `data-*` metadata; the picker's own markers stay protected. */\nexport type ColorPickerRootAttributes = Readonly<\n Record<`data-${string}`, string | undefined>\n>;\n\nconst COLOR_PICKER_PROTECTED = new Set([\n 'data-component',\n 'data-value',\n 'data-mode',\n 'data-alpha',\n 'data-color-picker-id',\n]);\n\n/** The delegated action every preset and sample swatch carries. */\nexport const COLOR_PICKER_SWATCH_ACTION = 'kui-color-picker-swatch';\n\nexport interface ColorPickerProps {\n /** The picker's id; it also prefixes its inner ids. */\n id: string;\n /** The picker's accessible name. */\n label: string;\n /**\n * The color, as CSS color text (`#rrggbb[aa]`, `rgb()`, `hsl()`); invalid\n * text shows black. The picker reports `#rrggbb`, or `#rrggbbaa` below\n * full opacity.\n */\n value: string;\n /** The channel fields shown (default `rgb`). */\n mode?: ColorPickerMode;\n /** Offer opacity: an alpha slider and field (default true). */\n alpha?: boolean;\n /** A form field name the hex value submits under. */\n name?: string;\n /** Associate the hidden input with a form outside its ancestor chain. */\n form?: string;\n /**\n * Offer a button that samples a color from the screen, where the browser\n * provides the EyeDropper API (default true; hidden elsewhere).\n */\n eyedropper?: boolean;\n /** A preset row of swatches under the controls. */\n presets?: readonly ColorSwatch[];\n /** Titled groups of app-owned colors under the presets. */\n samples?: readonly ColorPickerSamples[];\n /**\n * A `data-action` for an \"Add to Samples\" button in the controls row; the\n * app reads the picker's current value and adds it to its samples.\n */\n addSampleAction?: string;\n disabled?: boolean;\n className?: string;\n rootAttributes?: ColorPickerRootAttributes;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\nconst MODE_LABELS: Record<ColorPickerMode, [string, string]> = {\n rgb: ['RGB', 'RGBA'],\n hsl: ['HSL', 'HSLA'],\n hsb: ['HSB', 'HSBA'],\n gray: ['Grayscale', 'Grayscale'],\n};\n\n/**\n * The labels, accessible names, maximum, and spoken unit of each channel per\n * mode; the mode's sliders and fields both follow it.\n */\nexport const COLOR_PICKER_CHANNELS: Record<\n ColorPickerMode,\n readonly { short: string; name: string; max: number; unit: '' | '%' | '°' }[]\n> = {\n rgb: [\n { short: 'R', name: 'Red', max: 255, unit: '' },\n { short: 'G', name: 'Green', max: 255, unit: '' },\n { short: 'B', name: 'Blue', max: 255, unit: '' },\n ],\n hsl: [\n { short: 'H', name: 'Hue', max: 360, unit: '°' },\n { short: 'S', name: 'Saturation', max: 100, unit: '%' },\n { short: 'L', name: 'Lightness', max: 100, unit: '%' },\n ],\n hsb: [\n { short: 'H', name: 'Hue', max: 360, unit: '°' },\n { short: 'S', name: 'Saturation', max: 100, unit: '%' },\n { short: 'B', name: 'Brightness', max: 100, unit: '%' },\n ],\n gray: [{ short: 'W', name: 'Gray Level', max: 100, unit: '%' }],\n};\n\n/** The rounded channel values a mode shows for an HSV color. */\nexport function colorPickerChannels(\n mode: ColorPickerMode,\n hsv: Hsva,\n): number[] {\n return colorChannelValues(mode, hsv).map(Math.round);\n}\n\n/** One channel slider's attributes; see {@link colorPickerSlider}. */\nexport interface ColorPickerSliderState {\n max: number;\n value: string;\n label: string;\n valueText: string;\n style: string;\n}\n\n/**\n * The attributes of one channel slider for a mode's exact channel values:\n * its range, value, accessible name and spoken value, and an inline style\n * with the track gradient of the colors that channel produces while the\n * others hold (the full rainbow for the HSL and HSB hue) and the color under\n * the thumb.\n * `undefined` for a slot the mode does not use.\n */\nexport function colorPickerSlider(\n mode: ColorPickerMode,\n index: number,\n values: readonly number[],\n): ColorPickerSliderState | undefined {\n const channel = COLOR_PICKER_CHANNELS[mode][index];\n if (channel === undefined) return undefined;\n const value = String(Math.round(values[index]!));\n return {\n max: channel.max,\n value,\n label: channel.name,\n valueText: `${value}${channel.unit}`,\n style: [\n `--_kui-color-picker-track:${colorChannelTrack(mode, index, values)}`,\n `--_kui-color-picker-thumb-color:${colorChannelColor(mode, values)}`,\n ].join(';'),\n };\n}\n\n/** The area's spoken value. */\nexport function colorPickerAreaText(hsv: Hsva): string {\n return `Saturation ${Math.round(hsv.s * 100)}%, brightness ${Math.round(hsv.v * 100)}%`;\n}\n\n/** The CSS custom properties that place the thumbs and paint the tracks. */\nexport function colorPickerStyle(hsv: Hsva): string {\n const opaque = formatHex({ ...hsvToRgb(hsv), a: 1 });\n return [\n `--_kui-color-picker-h:${hsv.h.toFixed(2)}`,\n `--_kui-color-picker-s:${(hsv.s * 100).toFixed(2)}%`,\n `--_kui-color-picker-v:${(hsv.v * 100).toFixed(2)}%`,\n `--_kui-color-picker-a:${(hsv.a * 100).toFixed(2)}%`,\n `--_kui-color-picker-color:${opaque}`,\n ].join(';');\n}\n\n/**\n * A full color picker panel: a saturation and brightness area; a slider for\n * each channel of the color model (red, green, and blue; hue, saturation, and\n * lightness or brightness; or one gray level), each track painting the colors\n * that channel produces while the others hold (the hue track the full\n * rainbow); an optional opacity slider on\n * a checkerboard; a color-model menu (RGB, HSL, HSB, Grayscale) with its\n * channel fields, a hex field (8 digits below full\n * opacity) and an opacity field, an optional screen sampler (EyeDropper), and\n * optional preset and sample swatches. The controlled `value` renders it;\n * wire `wireColorPickers` from `@kerfjs/ui/wire-color-pickers` to make it\n * interactive. The interactive surface belongs to that wiring after the first\n * render, so a drag never fights a re-render; a new `value` from the app\n * resynchronizes it.\n */\nexport function ColorPicker({\n id,\n label,\n value,\n mode = 'rgb',\n alpha = true,\n name,\n form,\n eyedropper = true,\n presets,\n samples,\n addSampleAction,\n disabled = false,\n className = '',\n rootAttributes = {},\n slot,\n}: ColorPickerProps) {\n const parsed = parseColor(value) ?? { r: 0, g: 0, b: 0, a: 1 };\n const rgba = alpha ? parsed : { ...parsed, a: 1 };\n const hsv = rgbToHsv(rgba);\n const hex = formatHex(rgba);\n const channels = COLOR_PICKER_CHANNELS[mode];\n const exact = colorChannelValues(mode, hsv);\n const channelValues = exact.map(Math.round);\n const opacity = `${Math.round(hsv.a * 100)}%`;\n return (\n <div\n {...filterDataAttributes(rootAttributes, COLOR_PICKER_PROTECTED)}\n id={id}\n class={`kui-color-picker ${className}`.trim()}\n role=\"group\"\n aria-label={label}\n data-component=\"color-picker\"\n data-color-picker-id={id}\n data-value={hex}\n data-mode={mode}\n data-alpha={alpha ? '' : undefined}\n data-disabled={disabled ? '' : undefined}\n slot={slot}\n >\n <div\n class=\"kui-color-picker__surface\"\n data-morph-skip\n style={colorPickerStyle(hsv)}\n >\n <div\n class=\"kui-color-picker__area\"\n role=\"slider\"\n tabindex={disabled ? -1 : 0}\n aria-label=\"Saturation and Brightness\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n aria-valuenow={String(Math.round(hsv.s * 100))}\n aria-valuetext={colorPickerAreaText(hsv)}\n aria-disabled={disabled ? 'true' : undefined}\n >\n <span class=\"kui-color-picker__area-thumb\" />\n </div>\n <div class=\"kui-color-picker__sliders\">\n {[0, 1, 2].map((index) => {\n const slider = colorPickerSlider(mode, index, exact);\n return (\n <input\n class=\"kui-color-picker__slider\"\n type=\"range\"\n data-slider={String(index)}\n min=\"0\"\n max={String(slider?.max ?? 100)}\n step=\"1\"\n value={slider?.value ?? '0'}\n aria-label={slider?.label}\n aria-valuetext={slider?.valueText}\n style={slider?.style}\n hidden={slider === undefined}\n disabled={disabled}\n />\n );\n })}\n {alpha ? (\n <input\n class=\"kui-color-picker__opacity\"\n type=\"range\"\n min=\"0\"\n max=\"100\"\n step=\"1\"\n value={String(Math.round(hsv.a * 100))}\n aria-label=\"Opacity\"\n aria-valuetext={opacity}\n disabled={disabled}\n />\n ) : null}\n </div>\n <div class=\"kui-color-picker__controls\">\n <span class=\"kui-color-picker__mode-wrap\">\n <select\n class=\"kui-color-picker__mode\"\n aria-label=\"Color Model\"\n disabled={disabled}\n >\n {(Object.keys(MODE_LABELS) as ColorPickerMode[]).map((option) => (\n <option value={option} selected={option === mode}>\n {MODE_LABELS[option][alpha ? 1 : 0]}\n </option>\n ))}\n </select>\n <span class=\"kui-color-picker__mode-icon\" aria-hidden=\"true\">\n <LucideIcon\n icon={ChevronsUpDown}\n name=\"chevrons-up-down\"\n size=\"s\"\n />\n </span>\n </span>\n {eyedropper ? (\n <button\n type=\"button\"\n class=\"kui-color-picker__tool kui-color-picker__eyedropper\"\n aria-label=\"Pick a Color from the Screen\"\n title=\"Pick a Color from the Screen\"\n hidden\n disabled={disabled}\n >\n <LucideIcon icon={Pipette} name=\"pipette\" size=\"m\" />\n </button>\n ) : null}\n {addSampleAction === undefined ? null : (\n <button\n type=\"button\"\n class=\"kui-color-picker__tool\"\n data-action={addSampleAction}\n aria-label=\"Add to Samples\"\n title=\"Add to Samples\"\n disabled={disabled}\n >\n <LucideIcon icon={Plus} name=\"plus\" size=\"m\" />\n </button>\n )}\n </div>\n <div\n class=\"kui-color-picker__channels\"\n data-count={String(channels.length)}\n >\n {[0, 1, 2].map((index) => {\n const channel = channels[index];\n return (\n <label\n class=\"kui-color-picker__field\"\n hidden={channel === undefined}\n >\n <span class=\"kui-color-picker__field-label\" aria-hidden=\"true\">\n {channel?.short ?? ''}\n </span>\n <input\n class=\"kui-color-picker__channel\"\n data-channel={String(index)}\n inputMode=\"numeric\"\n value={channel ? String(channelValues[index]) : ''}\n aria-label={channel?.name}\n disabled={disabled}\n />\n </label>\n );\n })}\n </div>\n <div class=\"kui-color-picker__hex-row\">\n <label class=\"kui-color-picker__field kui-color-picker__field--hex\">\n <span class=\"kui-color-picker__field-label\" aria-hidden=\"true\">\n #\n </span>\n <input\n class=\"kui-color-picker__hex\"\n value={hex.slice(1).toUpperCase()}\n maxLength={8}\n spellcheck=\"false\"\n autocomplete=\"off\"\n aria-label=\"Hex Color\"\n disabled={disabled}\n />\n </label>\n {alpha ? (\n <label class=\"kui-color-picker__field\">\n <span class=\"kui-color-picker__field-label\" aria-hidden=\"true\">\n A\n </span>\n <input\n class=\"kui-color-picker__opacity-field\"\n inputMode=\"numeric\"\n value={opacity}\n aria-label=\"Opacity\"\n disabled={disabled}\n />\n </label>\n ) : null}\n </div>\n {name === undefined ? null : (\n <input type=\"hidden\" name={name} value={hex} form={form} />\n )}\n </div>\n {presets === undefined ? null : (\n <ColorSwatches\n name={`${id}-presets`}\n ariaLabel=\"Presets\"\n swatches={presets}\n value={presets.find((swatch) => swatch.value === hex)?.value}\n size=\"compact\"\n disabled={disabled}\n action={COLOR_PICKER_SWATCH_ACTION}\n />\n )}\n {(samples ?? []).map((group, index) => (\n <ColorSwatches\n name={`${id}-samples-${index}`}\n label={group.title}\n swatches={group.swatches}\n value={group.swatches.find((swatch) => swatch.value === hex)?.value}\n size=\"compact\"\n disabled={disabled}\n action={COLOR_PICKER_SWATCH_ACTION}\n />\n ))}\n </div>\n );\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { NavStack } from './chunk-ZXZAECHZ.js';
1
+ import { NavStack } from './chunk-Z4DS77U2.js';
2
2
  import { ResizableRegion } from './chunk-Y6KT7ZTR.js';
3
3
  import { remify, pct } from './chunk-IQSRHXZR.js';
4
4
  import { jsx, jsxs } from 'kerfjs/jsx-runtime';
@@ -144,4 +144,4 @@ function SplitView({
144
144
 
145
145
  export { SplitView };
146
146
 
147
- //# sourceMappingURL=chunk-FKKJHGN5.js.map
147
+ //# sourceMappingURL=chunk-AZ3WT77F.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/layout/split-view/split-view.tsx"],"names":[],"mappings":"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","file":"chunk-FKKJHGN5.js","sourcesContent":["import type { KerfUiContent } from '../../../shared/content/semantic-content.js';\nimport { pct, remify } from '../../../shared/styles/css-values.js';\nimport {\n NavStack,\n type NavStackProps,\n type NavStackView,\n} from '../../navigation/nav-stack/nav-stack.js';\nimport {\n ResizableRegion,\n type ResizableRegionProps,\n} from '../resizable-region/resizable-region.js';\n\n/**\n * The roomy list pane's `ResizableRegion`: its committed `size` and `min` /\n * `max` limits, plus the region configuration that forwards unchanged\n * (`separator`, `handleIcon`, `contentOverflow`, and collapse:\n * `collapsed`, `transitioning`, `collapseMotion`, `restoreControl`,\n * `restorePosition`). Omitted options keep the region's defaults.\n */\nexport interface SplitViewResizable extends Pick<\n ResizableRegionProps,\n | 'separator'\n | 'handleIcon'\n | 'contentOverflow'\n | 'collapsed'\n | 'transitioning'\n | 'collapseMotion'\n | 'restoreControl'\n | 'restorePosition'\n> {\n size: number;\n min: number;\n max: number;\n}\n\n/**\n * One compact view's top- and bottom-toolbar content and pinned footer (see\n * `NavStackView`).\n */\nexport type SplitViewCompactViewToolbars = Pick<\n NavStackView,\n 'toolbar' | 'bottomToolbar' | 'footer'\n>;\n\n/**\n * The compact `NavStack`'s configuration: its toolbar configuration, back\n * control, persistent bottom toolbar, chrome dividers, and chrome and\n * bottom-toolbar presentations forward to the stack, and `list` / `detail`\n * give each view its own toolbar groups.\n */\nexport interface SplitViewCompactStack extends Pick<\n NavStackProps,\n | 'toolbarConfig'\n | 'backIcon'\n | 'backText'\n | 'hideToolbar'\n | 'bottomToolbar'\n | 'chromeDividers'\n | 'chromePresentation'\n | 'bottomToolbarPresentation'\n> {\n /** Toolbar content for the list (root) view. */\n list?: SplitViewCompactViewToolbars;\n /** Toolbar content for the pushed detail view. */\n detail?: SplitViewCompactViewToolbars;\n}\n\n/**\n * The fixed list column's width: a size in CSS pixels, or that size capped\n * at a fraction of the SplitView's own width so a narrow container (a\n * dialog, a small window) always leaves the detail in view.\n */\nexport type SplitViewListWidth =\n | number\n | {\n /** Preferred width in CSS pixels. */\n size: number;\n /** Largest share of the SplitView's width, greater than 0 and at most 1. */\n maxFraction?: number;\n };\n\n/** The list-width custom property value for a fixed split. */\nfunction listWidthValue(listWidth: SplitViewListWidth): string {\n const { size, maxFraction } =\n typeof listWidth === 'number'\n ? { size: listWidth, maxFraction: undefined }\n : listWidth;\n if (!Number.isFinite(size) || size <= 0)\n throw new RangeError(\n 'SplitView listWidth size must be a positive number of pixels',\n );\n if (\n maxFraction !== undefined &&\n (!Number.isFinite(maxFraction) || maxFraction <= 0 || maxFraction > 1)\n )\n throw new RangeError(\n 'SplitView listWidth maxFraction must be greater than 0 and at most 1',\n );\n const preferred = remify(size);\n return maxFraction === undefined\n ? preferred\n : `min(${preferred}, ${pct(maxFraction * 100)})`;\n}\n\nexport interface SplitViewProps {\n id: string;\n label: string;\n /** The list (primary) pane. */\n list: KerfUiContent;\n /** The detail (secondary) pane. */\n detail: KerfUiContent;\n /**\n * Compact (\"one pane at a time\") classes — a handset or portrait tablet.\n * Derive from `deviceClass().value.compact`. When true the split collapses to\n * a `NavStack`: the list is the root and the detail is pushed over it.\n */\n compact?: boolean;\n /** In compact mode, whether the detail is currently pushed over the list. */\n detailActive?: boolean;\n /** Title/label for the list (compact NavStack root + region label). */\n listTitle?: string;\n /** Title/label for the detail (compact NavStack pushed view + region label). */\n detailTitle?: string;\n /** Back label for the compact NavStack (default \"Back\"). */\n backLabel?: string;\n /** Compact NavStack configuration and per-view toolbars. */\n compactStack?: SplitViewCompactStack;\n /** A resizable separator on roomy classes (min/max px). Omit for a fixed split. */\n resizable?: SplitViewResizable;\n /**\n * The fixed split's list column width (default 320px). A number is CSS\n * pixels; `{ size, maxFraction }` caps it at that share of the SplitView's\n * width. A resizable split sizes its list with `resizable` instead.\n */\n listWidth?: SplitViewListWidth;\n className?: string;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\n/**\n * A list-detail split. On roomy classes it shows both panes side\n * by side with an optional resizable separator; on compact classes it collapses\n * to a `NavStack` (list → detail). See `docs/23-app-layouts.md` §3.2. Compose the\n * resizable wiring with `wireResizableRegions` and the compact back with\n * `wireNavStack`.\n */\nexport function SplitView({\n id,\n label,\n list,\n detail,\n compact = false,\n detailActive = false,\n listTitle = '',\n detailTitle = '',\n backLabel = 'Back',\n compactStack = {},\n resizable,\n listWidth,\n className = '',\n slot,\n}: SplitViewProps) {\n if (listWidth !== undefined && resizable)\n throw new RangeError(\n 'SplitView listWidth applies to a fixed split; size a resizable list with resizable.size, min, and max',\n );\n const listWidthStyle =\n listWidth === undefined\n ? undefined\n : `--kui-split-view-list-width:${listWidthValue(listWidth)}`;\n if (compact) {\n const listView: NavStackView = {\n ...compactStack.list,\n key: 'list',\n toolbar: { ...compactStack.list?.toolbar, title: listTitle },\n content: list,\n };\n const views: NavStackView[] = detailActive\n ? [\n listView,\n {\n ...compactStack.detail,\n key: 'detail',\n toolbar: { ...compactStack.detail?.toolbar, title: detailTitle },\n content: detail,\n },\n ]\n : [listView];\n return (\n <div\n class={`kui-split-view kui-split-view--compact ${className}`.trim()}\n id={id}\n data-component=\"split-view\"\n data-split-mode=\"compact\"\n slot={slot}\n >\n <NavStack\n id={`${id}-stack`}\n label={label}\n views={views}\n backLabel={backLabel}\n backIcon={compactStack.backIcon}\n backText={compactStack.backText}\n toolbarConfig={compactStack.toolbarConfig}\n hideToolbar={compactStack.hideToolbar}\n bottomToolbar={compactStack.bottomToolbar}\n chromeDividers={compactStack.chromeDividers}\n chromePresentation={compactStack.chromePresentation}\n bottomToolbarPresentation={compactStack.bottomToolbarPresentation}\n />\n </div>\n );\n }\n const listPane = resizable ? (\n <ResizableRegion\n id={`${id}-list`}\n label={listTitle || 'List'}\n size={resizable.size}\n min={resizable.min}\n max={resizable.max}\n separator={resizable.separator}\n handleIcon={resizable.handleIcon}\n contentOverflow={resizable.contentOverflow}\n collapsed={resizable.collapsed}\n transitioning={resizable.transitioning}\n collapseMotion={resizable.collapseMotion}\n restoreControl={resizable.restoreControl}\n restorePosition={resizable.restorePosition}\n >\n <div\n class=\"kui-split-view__list kui-pane\"\n data-split-list\n data-resizable=\"true\"\n >\n {list}\n </div>\n </ResizableRegion>\n ) : (\n <div\n class=\"kui-split-view__list kui-pane\"\n data-split-list\n data-resizable=\"false\"\n >\n {list}\n </div>\n );\n return (\n <div\n class={`kui-split-view ${className}`.trim()}\n id={id}\n data-component=\"split-view\"\n data-split-mode=\"split\"\n aria-label={label}\n style={listWidthStyle}\n slot={slot}\n >\n {listPane}\n <div\n class=\"kui-split-view__detail kui-pane\"\n data-split-detail\n aria-label={detailTitle || undefined}\n >\n {detail}\n </div>\n </div>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/components/layout/split-view/split-view.tsx"],"names":[],"mappings":"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","file":"chunk-AZ3WT77F.js","sourcesContent":["import type { KerfUiContent } from '../../../shared/content/semantic-content.js';\nimport { pct, remify } from '../../../shared/styles/css-values.js';\nimport {\n NavStack,\n type NavStackProps,\n type NavStackView,\n} from '../../navigation/nav-stack/nav-stack.js';\nimport {\n ResizableRegion,\n type ResizableRegionProps,\n} from '../resizable-region/resizable-region.js';\n\n/**\n * The roomy list pane's `ResizableRegion`: its committed `size` and `min` /\n * `max` limits, plus the region configuration that forwards unchanged\n * (`separator`, `handleIcon`, `contentOverflow`, and collapse:\n * `collapsed`, `transitioning`, `collapseMotion`, `restoreControl`,\n * `restorePosition`). Omitted options keep the region's defaults.\n */\nexport interface SplitViewResizable extends Pick<\n ResizableRegionProps,\n | 'separator'\n | 'handleIcon'\n | 'contentOverflow'\n | 'collapsed'\n | 'transitioning'\n | 'collapseMotion'\n | 'restoreControl'\n | 'restorePosition'\n> {\n size: number;\n min: number;\n max: number;\n}\n\n/**\n * One compact view's top- and bottom-toolbar content and pinned footer (see\n * `NavStackView`).\n */\nexport type SplitViewCompactViewToolbars = Pick<\n NavStackView,\n 'toolbar' | 'bottomToolbar' | 'footer'\n>;\n\n/**\n * The compact `NavStack`'s configuration: its toolbar configuration, back\n * control, persistent bottom toolbar, chrome dividers, and chrome and\n * bottom-toolbar presentations forward to the stack, and `list` / `detail`\n * give each view its own toolbar groups.\n */\nexport interface SplitViewCompactStack extends Pick<\n NavStackProps,\n | 'toolbarConfig'\n | 'backIcon'\n | 'backText'\n | 'hideToolbar'\n | 'bottomToolbar'\n | 'chromeDividers'\n | 'chromePresentation'\n | 'bottomToolbarPresentation'\n> {\n /** Toolbar content for the list (root) view. */\n list?: SplitViewCompactViewToolbars;\n /** Toolbar content for the pushed detail view. */\n detail?: SplitViewCompactViewToolbars;\n}\n\n/**\n * The fixed list column's width: a size in CSS pixels, or that size capped\n * at a fraction of the SplitView's own width so a narrow container (a\n * dialog, a small window) always leaves the detail in view.\n */\nexport type SplitViewListWidth =\n | number\n | {\n /** Preferred width in CSS pixels. */\n size: number;\n /** Largest share of the SplitView's width, greater than 0 and at most 1. */\n maxFraction?: number;\n };\n\n/** The list-width custom property value for a fixed split. */\nfunction listWidthValue(listWidth: SplitViewListWidth): string {\n const { size, maxFraction } =\n typeof listWidth === 'number'\n ? { size: listWidth, maxFraction: undefined }\n : listWidth;\n if (!Number.isFinite(size) || size <= 0)\n throw new RangeError(\n 'SplitView listWidth size must be a positive number of pixels',\n );\n if (\n maxFraction !== undefined &&\n (!Number.isFinite(maxFraction) || maxFraction <= 0 || maxFraction > 1)\n )\n throw new RangeError(\n 'SplitView listWidth maxFraction must be greater than 0 and at most 1',\n );\n const preferred = remify(size);\n return maxFraction === undefined\n ? preferred\n : `min(${preferred}, ${pct(maxFraction * 100)})`;\n}\n\nexport interface SplitViewProps {\n id: string;\n label: string;\n /** The list (primary) pane. */\n list: KerfUiContent;\n /** The detail (secondary) pane. */\n detail: KerfUiContent;\n /**\n * Compact (\"one pane at a time\") classes — a handset or portrait tablet.\n * Derive from `deviceClass().value.compact`. When true the split collapses to\n * a `NavStack`: the list is the root and the detail is pushed over it.\n */\n compact?: boolean;\n /** In compact mode, whether the detail is currently pushed over the list. */\n detailActive?: boolean;\n /** Title/label for the list (compact NavStack root + region label). */\n listTitle?: string;\n /** Title/label for the detail (compact NavStack pushed view + region label). */\n detailTitle?: string;\n /** Back label for the compact NavStack (default \"Back\"). */\n backLabel?: string;\n /** Compact NavStack configuration and per-view toolbars. */\n compactStack?: SplitViewCompactStack;\n /** A resizable separator on roomy classes (min/max px). Omit for a fixed split. */\n resizable?: SplitViewResizable;\n /**\n * The fixed split's list column width (default 320px). A number is CSS\n * pixels; `{ size, maxFraction }` caps it at that share of the SplitView's\n * width. A resizable split sizes its list with `resizable` instead.\n */\n listWidth?: SplitViewListWidth;\n className?: string;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\n/**\n * A list-detail split. On roomy classes it shows both panes side\n * by side with an optional resizable separator; on compact classes it collapses\n * to a `NavStack` (list → detail). See `docs/23-app-layouts.md` §3.2. Compose the\n * resizable wiring with `wireResizableRegions` and the compact back with\n * `wireNavStack`.\n */\nexport function SplitView({\n id,\n label,\n list,\n detail,\n compact = false,\n detailActive = false,\n listTitle = '',\n detailTitle = '',\n backLabel = 'Back',\n compactStack = {},\n resizable,\n listWidth,\n className = '',\n slot,\n}: SplitViewProps) {\n if (listWidth !== undefined && resizable)\n throw new RangeError(\n 'SplitView listWidth applies to a fixed split; size a resizable list with resizable.size, min, and max',\n );\n const listWidthStyle =\n listWidth === undefined\n ? undefined\n : `--kui-split-view-list-width:${listWidthValue(listWidth)}`;\n if (compact) {\n const listView: NavStackView = {\n ...compactStack.list,\n key: 'list',\n toolbar: { ...compactStack.list?.toolbar, title: listTitle },\n content: list,\n };\n const views: NavStackView[] = detailActive\n ? [\n listView,\n {\n ...compactStack.detail,\n key: 'detail',\n toolbar: { ...compactStack.detail?.toolbar, title: detailTitle },\n content: detail,\n },\n ]\n : [listView];\n return (\n <div\n class={`kui-split-view kui-split-view--compact ${className}`.trim()}\n id={id}\n data-component=\"split-view\"\n data-split-mode=\"compact\"\n slot={slot}\n >\n <NavStack\n id={`${id}-stack`}\n label={label}\n views={views}\n backLabel={backLabel}\n backIcon={compactStack.backIcon}\n backText={compactStack.backText}\n toolbarConfig={compactStack.toolbarConfig}\n hideToolbar={compactStack.hideToolbar}\n bottomToolbar={compactStack.bottomToolbar}\n chromeDividers={compactStack.chromeDividers}\n chromePresentation={compactStack.chromePresentation}\n bottomToolbarPresentation={compactStack.bottomToolbarPresentation}\n />\n </div>\n );\n }\n const listPane = resizable ? (\n <ResizableRegion\n id={`${id}-list`}\n label={listTitle || 'List'}\n size={resizable.size}\n min={resizable.min}\n max={resizable.max}\n separator={resizable.separator}\n handleIcon={resizable.handleIcon}\n contentOverflow={resizable.contentOverflow}\n collapsed={resizable.collapsed}\n transitioning={resizable.transitioning}\n collapseMotion={resizable.collapseMotion}\n restoreControl={resizable.restoreControl}\n restorePosition={resizable.restorePosition}\n >\n <div\n class=\"kui-split-view__list kui-pane\"\n data-split-list\n data-resizable=\"true\"\n >\n {list}\n </div>\n </ResizableRegion>\n ) : (\n <div\n class=\"kui-split-view__list kui-pane\"\n data-split-list\n data-resizable=\"false\"\n >\n {list}\n </div>\n );\n return (\n <div\n class={`kui-split-view ${className}`.trim()}\n id={id}\n data-component=\"split-view\"\n data-split-mode=\"split\"\n aria-label={label}\n style={listWidthStyle}\n slot={slot}\n >\n {listPane}\n <div\n class=\"kui-split-view__detail kui-pane\"\n data-split-detail\n aria-label={detailTitle || undefined}\n >\n {detail}\n </div>\n </div>\n );\n}\n"]}
@@ -1,8 +1,8 @@
1
1
  import { paneConfigProps } from './chunk-CTQUDCY5.js';
2
2
  import { ToolbarControlGroup, isRelocatableGroup } from './chunk-2PXZBFEC.js';
3
+ import { Toolbar } from './chunk-CMLPFIC5.js';
3
4
  import { Pane } from './chunk-HQZG3OFL.js';
4
5
  import { List } from './chunk-OY2MXIBB.js';
5
- import { Toolbar } from './chunk-CMLPFIC5.js';
6
6
  import { LucideIcon } from './chunk-HJXVVFBT.js';
7
7
  import { PanelLeftOpen, PanelLeftClose, PanelRightOpen, PanelRightClose, PanelBottomOpen, PanelBottomClose } from 'lucide';
8
8
  import { jsx, jsxs, Fragment } from 'kerfjs/jsx-runtime';
@@ -159,4 +159,4 @@ function relocatedPanelGroups(toolbar, side, collapsed, attributes, size = "defa
159
159
 
160
160
  export { collapsiblePanelToggleIcon, composedPanelBody, groupSizeFor, panelToggleGroup, relocatedPanelGroups };
161
161
 
162
- //# sourceMappingURL=chunk-FG6U7KQQ.js.map
162
+ //# sourceMappingURL=chunk-DNWWF6UN.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/shared/panels/panel-toolbar.tsx"],"names":[],"mappings":"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","file":"chunk-FG6U7KQQ.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\nimport {\n PanelBottomClose,\n PanelBottomOpen,\n PanelLeftClose,\n PanelLeftOpen,\n PanelRightClose,\n PanelRightOpen,\n} from 'lucide';\n\nimport {\n Toolbar,\n type ToolbarConfig,\n} from '../../components/actions/toolbar/toolbar.js';\nimport {\n ToolbarControlGroup,\n type ToolbarControlGroupSize,\n} from '../../components/actions/toolbar-control-group/toolbar-control-group.js';\nimport {\n List,\n type ListConfig,\n} from '../../components/collections/list/list.js';\nimport { paneConfigProps } from '../../components/layout/pane/internal/pane-config-props.js';\nimport { Pane, type PaneConfig } from '../../components/layout/pane/pane.js';\nimport { LucideIcon } from '../../components/media/lucide-icon/lucide-icon.js';\nimport type { KerfUiContent } from '../content/semantic-content.js';\nimport { isRelocatableGroup } from './panel-toolbar-group.js';\n\n/** Which edge a collapsible panel docks to. */\nexport type PanelSide = 'left' | 'right' | 'bottom';\n\n/**\n * The standard collapse/expand icon for a panel `side` and `collapsed` state,\n * so every app's sidebars and drawers use one recognizable convention:\n * `PanelLeft*` for a left rail, `PanelRight*` for a right rail, `PanelBottom*`\n * for a bottom drawer — the `Close` glyph while open, the `Open` glyph while\n * collapsed. Exposed so an app can render its own toggle affordance.\n */\nexport function collapsiblePanelToggleIcon(\n side: PanelSide,\n collapsed: boolean,\n): { icon: Parameters<typeof LucideIcon>[0]['icon']; name: string } {\n if (side === 'left')\n return collapsed\n ? { icon: PanelLeftOpen, name: 'panel-left-open' }\n : { icon: PanelLeftClose, name: 'panel-left-close' };\n if (side === 'right')\n return collapsed\n ? { icon: PanelRightOpen, name: 'panel-right-open' }\n : { icon: PanelRightClose, name: 'panel-right-close' };\n return collapsed\n ? { icon: PanelBottomOpen, name: 'panel-bottom-open' }\n : { icon: PanelBottomClose, name: 'panel-bottom-close' };\n}\n\n/**\n * The standard collapse toggle a panel toolbar renders. The app handles the\n * button's `data-action` and flips its own `collapsed` flag.\n */\nexport interface PanelToggle {\n /** The `data-action` the toggle button carries. */\n action: string;\n /**\n * The panel's short title-style name (\"Navigator\", \"Build Output\"). It is\n * the toggle group's accessible name and completes the default \"Show …\" /\n * \"Hide …\" label (\"Show Navigator\"), so it follows the title-style rule in\n * `docs/writing.md`; it is never recapitalized.\n */\n name: string;\n /** Accessible label while the panel is collapsed. Defaults to `Show {name}`. */\n showLabel?: string;\n /** Accessible label while the panel is open. Defaults to `Hide {name}`. */\n hideLabel?: string;\n}\n\n/**\n * A collapsible panel's top toolbar, composed so its groups follow the\n * panel's open state.\n *\n * - `title` precedes the `leading` zone. Groups may appear in any of the\n * `leading`, `center`, and `trailing` zones while the panel is open.\n * - Groups marked `relocateOnCollapse` move to the work area's toolbar while\n * the panel is collapsed, preserving their order across the three zones.\n * - `toggle` is always the last group: in the panel's toolbar while it is\n * open, and right after the relocated groups in the work area's toolbar\n * while it is collapsed.\n *\n * Relocated content renders in both places while the panel is collapsed (the\n * panel's copy is inert), so give it no `id`s. Pass groups directly or in\n * arrays so their render-time annotation remains available to the panel.\n *\n * The toolbar's configuration (`dividerSides`, `centerAlign`, `responsive`,\n * `responsiveAt`, `safeAreaEdges`) forwards to its `Toolbar`. It draws no\n * divider of its own: the panel's `Pane` draws the line under it while the\n * content is scrolled (its `chromeDividers`, wired by `wireScrollDividers`).\n */\nexport interface PanelToolbar extends ToolbarConfig {\n /** Accessible name of the panel's toolbar. */\n label: string;\n title?: KerfUiContent;\n leading?: KerfUiContent;\n center?: KerfUiContent;\n trailing?: KerfUiContent;\n toggle?: PanelToggle;\n}\n\n/** A panel's fixed bottom toolbar, below its optional footer content. */\nexport interface PanelBottomToolbar extends ToolbarConfig {\n label: string;\n leading?: KerfUiContent;\n center?: KerfUiContent;\n trailing?: KerfUiContent;\n}\n\n/** Whether panel chrome stays fixed, scrolls, or follows Pane's auto rule. */\nexport type PanelChromePlacement = 'fixed' | 'scroll' | 'auto';\n\nfunction panelChromeList(content: KerfUiContent, config?: ListConfig) {\n return (\n <List\n dividerSides={config?.dividerSides}\n gap={config?.gap}\n hAlign={config?.hAlign}\n vAlign={config?.vAlign}\n textInsets={config?.textInsets}\n controlInsets={config?.controlInsets}\n >\n {content}\n </List>\n );\n}\n\n/** Owner-specific attributes a toggle button carries (its wiring hooks). */\nexport type PanelToggleAttributes = Readonly<Record<string, string>>;\n\n/** The group size that fits a toolbar of this density. */\nexport function groupSizeFor(\n density: ToolbarConfig['density'],\n): ToolbarControlGroupSize {\n return density === 'compact' ? 'compact' : 'default';\n}\n\n/** The standard toggle, alone in a borderless group. */\nexport function panelToggleGroup(\n side: PanelSide,\n toggle: PanelToggle,\n collapsed: boolean,\n attributes: PanelToggleAttributes,\n size: ToolbarControlGroupSize = 'default',\n): SafeHtml {\n const glyph = collapsiblePanelToggleIcon(side, collapsed);\n return (\n <ToolbarControlGroup\n label={toggle.name}\n appearance=\"borderless\"\n size={size}\n single\n >\n <button\n type=\"button\"\n {...attributes}\n data-action={toggle.action}\n aria-expanded={String(!collapsed)}\n aria-label={\n collapsed\n ? (toggle.showLabel ?? `Show ${toggle.name}`)\n : (toggle.hideLabel ?? `Hide ${toggle.name}`)\n }\n >\n <LucideIcon icon={glyph.icon} name={glyph.name} />\n </button>\n </ToolbarControlGroup>\n );\n}\n\n/**\n * The panel's own toolbar: content keeps its chosen zones and the toggle trails.\n */\nexport function composedPanelToolbar(\n toolbar: PanelToolbar,\n side: PanelSide,\n collapsed: boolean,\n attributes: PanelToggleAttributes,\n): SafeHtml {\n return (\n <Toolbar\n label={toolbar.label}\n density={toolbar.density}\n dividerSides={toolbar.dividerSides}\n centerAlign={toolbar.centerAlign}\n responsive={toolbar.responsive}\n responsiveAt={toolbar.responsiveAt}\n safeAreaEdges={toolbar.safeAreaEdges}\n center={toolbar.center}\n leading={\n <>\n {toolbar.title}\n {toolbar.leading}\n </>\n }\n trailing={\n <>\n {toolbar.trailing}\n {toolbar.toggle\n ? panelToggleGroup(\n side,\n toolbar.toggle,\n collapsed,\n attributes,\n groupSizeFor(toolbar.density),\n )\n : null}\n </>\n }\n />\n );\n}\n\n/**\n * A toolbar panel's body: its content in a `Pane` under its composed toolbar,\n * with its optional `footer` below. The panel's `pane` configuration forwards\n * to that `Pane`; an omitted or `undefined` field keeps the `Pane` default.\n */\nexport function composedPanelBody({\n toolbar,\n side,\n collapsed,\n attributes,\n pane,\n header,\n headerList,\n headerPlacement = 'fixed',\n footer,\n footerList,\n bottomToolbar,\n footerPlacement = 'fixed',\n content,\n}: {\n toolbar: PanelToolbar;\n side: PanelSide;\n collapsed: boolean;\n attributes: PanelToggleAttributes;\n pane: PaneConfig | undefined;\n header?: KerfUiContent;\n headerList?: ListConfig;\n headerPlacement?: PanelChromePlacement;\n footer?: KerfUiContent;\n footerList?: ListConfig;\n bottomToolbar?: PanelBottomToolbar;\n footerPlacement?: PanelChromePlacement;\n content: KerfUiContent;\n}): SafeHtml {\n const panelHeader = (\n <>\n {composedPanelToolbar(toolbar, side, collapsed, attributes)}\n {header ? panelChromeList(header, headerList) : null}\n </>\n );\n const panelFooter =\n footer || bottomToolbar ? (\n <>\n {footer ? panelChromeList(footer, footerList) : null}\n {bottomToolbar ? (\n <Toolbar\n position=\"footer\"\n label={bottomToolbar.label}\n density={bottomToolbar.density}\n dividerSides={bottomToolbar.dividerSides}\n centerAlign={bottomToolbar.centerAlign}\n responsive={bottomToolbar.responsive}\n responsiveAt={bottomToolbar.responsiveAt}\n safeAreaEdges={bottomToolbar.safeAreaEdges}\n leading={bottomToolbar.leading}\n center={bottomToolbar.center}\n trailing={bottomToolbar.trailing}\n />\n ) : null}\n </>\n ) : undefined;\n const scrollHeader = headerPlacement === 'scroll';\n const scrollFooter = footerPlacement === 'scroll';\n return (\n <Pane\n header={scrollHeader ? undefined : panelHeader}\n footer={scrollFooter ? undefined : panelFooter}\n chromePlacement={\n headerPlacement === 'auto' || footerPlacement === 'auto'\n ? 'auto'\n : 'fixed'\n }\n {...paneConfigProps(pane)}\n >\n {scrollHeader ? panelHeader : null}\n {content}\n {scrollFooter ? panelFooter : null}\n </Pane>\n );\n}\n\n/**\n * The groups a collapsed panel hands to the work area, in zone order, then its\n * toggle. Empty while the panel is open or has no toolbar.\n */\nexport function relocatedPanelGroups(\n toolbar: PanelToolbar | undefined,\n side: PanelSide,\n collapsed: boolean,\n attributes: PanelToggleAttributes,\n size: ToolbarControlGroupSize = 'default',\n): KerfUiContent[] {\n if (!collapsed || !toolbar) return [];\n const groups: KerfUiContent[] = [];\n const collect = (content: KerfUiContent): void => {\n if (Array.isArray(content)) {\n for (const item of content) collect(item);\n } else if (isRelocatableGroup(content)) {\n groups.push(content);\n }\n };\n collect(toolbar.leading);\n collect(toolbar.center);\n collect(toolbar.trailing);\n return [\n ...groups,\n toolbar.toggle\n ? panelToggleGroup(side, toolbar.toggle, true, attributes, size)\n : null,\n ].filter((group) => group !== undefined && group !== null && group !== false);\n}\n"]}
1
+ {"version":3,"sources":["../src/shared/panels/panel-toolbar.tsx"],"names":[],"mappings":"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","file":"chunk-DNWWF6UN.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\nimport {\n PanelBottomClose,\n PanelBottomOpen,\n PanelLeftClose,\n PanelLeftOpen,\n PanelRightClose,\n PanelRightOpen,\n} from 'lucide';\n\nimport {\n Toolbar,\n type ToolbarConfig,\n} from '../../components/actions/toolbar/toolbar.js';\nimport {\n ToolbarControlGroup,\n type ToolbarControlGroupSize,\n} from '../../components/actions/toolbar-control-group/toolbar-control-group.js';\nimport {\n List,\n type ListConfig,\n} from '../../components/collections/list/list.js';\nimport { paneConfigProps } from '../../components/layout/pane/internal/pane-config-props.js';\nimport { Pane, type PaneConfig } from '../../components/layout/pane/pane.js';\nimport { LucideIcon } from '../../components/media/lucide-icon/lucide-icon.js';\nimport type { KerfUiContent } from '../content/semantic-content.js';\nimport { isRelocatableGroup } from './panel-toolbar-group.js';\n\n/** Which edge a collapsible panel docks to. */\nexport type PanelSide = 'left' | 'right' | 'bottom';\n\n/**\n * The standard collapse/expand icon for a panel `side` and `collapsed` state,\n * so every app's sidebars and drawers use one recognizable convention:\n * `PanelLeft*` for a left rail, `PanelRight*` for a right rail, `PanelBottom*`\n * for a bottom drawer — the `Close` glyph while open, the `Open` glyph while\n * collapsed. Exposed so an app can render its own toggle affordance.\n */\nexport function collapsiblePanelToggleIcon(\n side: PanelSide,\n collapsed: boolean,\n): { icon: Parameters<typeof LucideIcon>[0]['icon']; name: string } {\n if (side === 'left')\n return collapsed\n ? { icon: PanelLeftOpen, name: 'panel-left-open' }\n : { icon: PanelLeftClose, name: 'panel-left-close' };\n if (side === 'right')\n return collapsed\n ? { icon: PanelRightOpen, name: 'panel-right-open' }\n : { icon: PanelRightClose, name: 'panel-right-close' };\n return collapsed\n ? { icon: PanelBottomOpen, name: 'panel-bottom-open' }\n : { icon: PanelBottomClose, name: 'panel-bottom-close' };\n}\n\n/**\n * The standard collapse toggle a panel toolbar renders. The app handles the\n * button's `data-action` and flips its own `collapsed` flag.\n */\nexport interface PanelToggle {\n /** The `data-action` the toggle button carries. */\n action: string;\n /**\n * The panel's short title-style name (\"Navigator\", \"Build Output\"). It is\n * the toggle group's accessible name and completes the default \"Show …\" /\n * \"Hide …\" label (\"Show Navigator\"), so it follows the title-style rule in\n * `docs/writing.md`; it is never recapitalized.\n */\n name: string;\n /** Accessible label while the panel is collapsed. Defaults to `Show {name}`. */\n showLabel?: string;\n /** Accessible label while the panel is open. Defaults to `Hide {name}`. */\n hideLabel?: string;\n}\n\n/**\n * A collapsible panel's top toolbar, composed so its groups follow the\n * panel's open state.\n *\n * - `title` precedes the `leading` zone. Groups may appear in any of the\n * `leading`, `center`, and `trailing` zones while the panel is open.\n * - Groups marked `relocateOnCollapse` move to the work area's toolbar while\n * the panel is collapsed, preserving their order across the three zones.\n * - `toggle` is always the last group: in the panel's toolbar while it is\n * open, and right after the relocated groups in the work area's toolbar\n * while it is collapsed.\n *\n * Relocated content renders in both places while the panel is collapsed (the\n * panel's copy is inert), so give it no `id`s. Pass groups directly or in\n * arrays so their render-time annotation remains available to the panel.\n *\n * The toolbar's configuration (`dividerSides`, `centerAlign`, `responsive`,\n * `responsiveAt`, `safeAreaEdges`) forwards to its `Toolbar`. It draws no\n * divider of its own: the panel's `Pane` draws the line under it while the\n * content is scrolled (its `chromeDividers`, wired by `wireScrollDividers`).\n */\nexport interface PanelToolbar extends ToolbarConfig {\n /** Accessible name of the panel's toolbar. */\n label: string;\n title?: KerfUiContent;\n leading?: KerfUiContent;\n center?: KerfUiContent;\n trailing?: KerfUiContent;\n toggle?: PanelToggle;\n}\n\n/** A panel's fixed bottom toolbar, below its optional footer content. */\nexport interface PanelBottomToolbar extends ToolbarConfig {\n label: string;\n leading?: KerfUiContent;\n center?: KerfUiContent;\n trailing?: KerfUiContent;\n}\n\n/** Whether panel chrome stays fixed, scrolls, or follows Pane's auto rule. */\nexport type PanelChromePlacement = 'fixed' | 'scroll' | 'auto';\n\nfunction panelChromeList(content: KerfUiContent, config?: ListConfig) {\n return (\n <List\n dividerSides={config?.dividerSides}\n gap={config?.gap}\n hAlign={config?.hAlign}\n vAlign={config?.vAlign}\n textInsets={config?.textInsets}\n controlInsets={config?.controlInsets}\n >\n {content}\n </List>\n );\n}\n\n/** Owner-specific attributes a toggle button carries (its wiring hooks). */\nexport type PanelToggleAttributes = Readonly<Record<string, string>>;\n\n/** The group size that fits a toolbar of this density. */\nexport function groupSizeFor(\n density: ToolbarConfig['density'],\n): ToolbarControlGroupSize {\n return density === 'compact' ? 'compact' : 'default';\n}\n\n/** The standard toggle, alone in a borderless group. */\nexport function panelToggleGroup(\n side: PanelSide,\n toggle: PanelToggle,\n collapsed: boolean,\n attributes: PanelToggleAttributes,\n size: ToolbarControlGroupSize = 'default',\n): SafeHtml {\n const glyph = collapsiblePanelToggleIcon(side, collapsed);\n return (\n <ToolbarControlGroup\n label={toggle.name}\n appearance=\"borderless\"\n size={size}\n single\n >\n <button\n type=\"button\"\n {...attributes}\n data-action={toggle.action}\n aria-expanded={String(!collapsed)}\n aria-label={\n collapsed\n ? (toggle.showLabel ?? `Show ${toggle.name}`)\n : (toggle.hideLabel ?? `Hide ${toggle.name}`)\n }\n >\n <LucideIcon icon={glyph.icon} name={glyph.name} />\n </button>\n </ToolbarControlGroup>\n );\n}\n\n/**\n * The panel's own toolbar: content keeps its chosen zones and the toggle trails.\n */\nexport function composedPanelToolbar(\n toolbar: PanelToolbar,\n side: PanelSide,\n collapsed: boolean,\n attributes: PanelToggleAttributes,\n): SafeHtml {\n return (\n <Toolbar\n label={toolbar.label}\n density={toolbar.density}\n dividerSides={toolbar.dividerSides}\n centerAlign={toolbar.centerAlign}\n responsive={toolbar.responsive}\n responsiveAt={toolbar.responsiveAt}\n safeAreaEdges={toolbar.safeAreaEdges}\n center={toolbar.center}\n leading={\n <>\n {toolbar.title}\n {toolbar.leading}\n </>\n }\n trailing={\n <>\n {toolbar.trailing}\n {toolbar.toggle\n ? panelToggleGroup(\n side,\n toolbar.toggle,\n collapsed,\n attributes,\n groupSizeFor(toolbar.density),\n )\n : null}\n </>\n }\n />\n );\n}\n\n/**\n * A toolbar panel's body: its content in a `Pane` under its composed toolbar,\n * with its optional `footer` below. The panel's `pane` configuration forwards\n * to that `Pane`; an omitted or `undefined` field keeps the `Pane` default.\n */\nexport function composedPanelBody({\n toolbar,\n side,\n collapsed,\n attributes,\n pane,\n header,\n headerList,\n headerPlacement = 'fixed',\n footer,\n footerList,\n bottomToolbar,\n footerPlacement = 'fixed',\n content,\n}: {\n toolbar: PanelToolbar;\n side: PanelSide;\n collapsed: boolean;\n attributes: PanelToggleAttributes;\n pane: PaneConfig | undefined;\n header?: KerfUiContent;\n headerList?: ListConfig;\n headerPlacement?: PanelChromePlacement;\n footer?: KerfUiContent;\n footerList?: ListConfig;\n bottomToolbar?: PanelBottomToolbar;\n footerPlacement?: PanelChromePlacement;\n content: KerfUiContent;\n}): SafeHtml {\n const panelHeader = (\n <>\n {composedPanelToolbar(toolbar, side, collapsed, attributes)}\n {header ? panelChromeList(header, headerList) : null}\n </>\n );\n const panelFooter =\n footer || bottomToolbar ? (\n <>\n {footer ? panelChromeList(footer, footerList) : null}\n {bottomToolbar ? (\n <Toolbar\n position=\"footer\"\n label={bottomToolbar.label}\n density={bottomToolbar.density}\n dividerSides={bottomToolbar.dividerSides}\n centerAlign={bottomToolbar.centerAlign}\n responsive={bottomToolbar.responsive}\n responsiveAt={bottomToolbar.responsiveAt}\n safeAreaEdges={bottomToolbar.safeAreaEdges}\n leading={bottomToolbar.leading}\n center={bottomToolbar.center}\n trailing={bottomToolbar.trailing}\n />\n ) : null}\n </>\n ) : undefined;\n const scrollHeader = headerPlacement === 'scroll';\n const scrollFooter = footerPlacement === 'scroll';\n return (\n <Pane\n header={scrollHeader ? undefined : panelHeader}\n footer={scrollFooter ? undefined : panelFooter}\n chromePlacement={\n headerPlacement === 'auto' || footerPlacement === 'auto'\n ? 'auto'\n : 'fixed'\n }\n {...paneConfigProps(pane)}\n >\n {scrollHeader ? panelHeader : null}\n {content}\n {scrollFooter ? panelFooter : null}\n </Pane>\n );\n}\n\n/**\n * The groups a collapsed panel hands to the work area, in zone order, then its\n * toggle. Empty while the panel is open or has no toolbar.\n */\nexport function relocatedPanelGroups(\n toolbar: PanelToolbar | undefined,\n side: PanelSide,\n collapsed: boolean,\n attributes: PanelToggleAttributes,\n size: ToolbarControlGroupSize = 'default',\n): KerfUiContent[] {\n if (!collapsed || !toolbar) return [];\n const groups: KerfUiContent[] = [];\n const collect = (content: KerfUiContent): void => {\n if (Array.isArray(content)) {\n for (const item of content) collect(item);\n } else if (isRelocatableGroup(content)) {\n groups.push(content);\n }\n };\n collect(toolbar.leading);\n collect(toolbar.center);\n collect(toolbar.trailing);\n return [\n ...groups,\n toolbar.toggle\n ? panelToggleGroup(side, toolbar.toggle, true, attributes, size)\n : null,\n ].filter((group) => group !== undefined && group !== null && group !== false);\n}\n"]}
@@ -1,5 +1,5 @@
1
- import { pointAnchor, followAnchor, positionPopup, PHONE_SUBMENU_QUERY, phoneSubmenuPosition } from './chunk-PE2KPZDW.js';
2
- import { POPUP_MENU_OPEN_EVENT, POPUP_MENU_CLOSE_EVENT, POPUP_MENU_SELECT_EVENT } from './chunk-HYORKKYP.js';
1
+ import { pointAnchor, followAnchor, positionPopup, PHONE_SUBMENU_QUERY, phoneSubmenuPosition } from './chunk-HDXUHLTQ.js';
2
+ import { POPUP_MENU_OPEN_EVENT, POPUP_MENU_CLOSE_EVENT, POPUP_MENU_SELECT_EVENT } from './chunk-3VZ6SFD4.js';
3
3
 
4
4
  // src/components/actions/popup-menu/internal/reveal-in-menu.ts
5
5
  function revealInMenu(item, menu) {
@@ -116,15 +116,20 @@ function installPopupMenus(doc = document) {
116
116
  crossOffset: SUBMENU_CROSS_OFFSET
117
117
  });
118
118
  };
119
- const openRoot = (root, { point, focus }) => {
119
+ const openRoot = (root, {
120
+ point,
121
+ placement: pointPlacement,
122
+ focus
123
+ }) => {
120
124
  const opener = rootOpenerOf(root);
121
125
  const menu = rootMenuOf(root);
122
126
  if (!opener || !menu) return;
123
127
  if (opener instanceof HTMLButtonElement && opener.disabled) return;
124
128
  if (isOpen(menu)) closeMenu(menu, false);
125
129
  const context = root.getAttribute("data-trigger") === "context";
126
- const anchor = point && !context ? pointAnchor(point.x, point.y) : opener;
127
- const placement = point || context ? "bottom-start" : root.getAttribute("data-placement") ?? "bottom-start";
130
+ const pointOpened = point !== void 0 && !context;
131
+ const anchor = pointOpened ? pointAnchor(point.x, point.y) : opener;
132
+ const placement = (point !== void 0 ? pointPlacement : void 0) ?? (pointOpened ? "bottom-start" : root.getAttribute("data-placement") ?? "bottom-start");
128
133
  try {
129
134
  menu.showPopover();
130
135
  } catch {
@@ -431,8 +436,8 @@ function installPopupMenus(doc = document) {
431
436
  (event) => {
432
437
  const root = event.target;
433
438
  if (!(root instanceof HTMLElement) || !root.matches(ROOT)) return;
434
- const { point } = event.detail;
435
- openRoot(root, { point, focus: "first" });
439
+ const { point, placement } = event.detail;
440
+ openRoot(root, { point, placement, focus: "first" });
436
441
  },
437
442
  true
438
443
  );
@@ -449,4 +454,4 @@ function installPopupMenus(doc = document) {
449
454
 
450
455
  export { installPopupMenus };
451
456
 
452
- //# sourceMappingURL=chunk-C3RLKKFQ.js.map
457
+ //# sourceMappingURL=chunk-EYDXFOSH.js.map