prime-ui-kit 0.13.0 → 0.14.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 (215) hide show
  1. package/README.md +7 -6
  2. package/dist/chunks/{chunk-ZSJMNA46.js → chunk-P6ZO37JM.js} +1 -1
  3. package/dist/chunks/{chunk-Z3WKKAS6.js → chunk-SYEX7OVT.js} +3572 -2865
  4. package/dist/chunks/{chunk-E6SQBSDF.js → chunk-WXKRUVSE.js} +199 -162
  5. package/dist/color-picker.js +2 -2
  6. package/dist/components/banner/Banner.d.ts +5 -2
  7. package/dist/components/chart-frame/ChartFrame.d.ts +19 -6
  8. package/dist/components/chat/Chat.d.ts +2 -2
  9. package/dist/components/chat/ChatPinned.d.ts +2 -2
  10. package/dist/components/chat/MessageList.d.ts +1 -1
  11. package/dist/components/chat/chatContext.d.ts +1 -1
  12. package/dist/components/field-list/FieldList.d.ts +90 -0
  13. package/dist/components/index.d.ts +3 -1
  14. package/dist/components/input/Input.d.ts +2 -2
  15. package/dist/components/kanban/Kanban.d.ts +6 -3
  16. package/dist/components/page-content/PageContent.d.ts +55 -4
  17. package/dist/components/sparkline/Sparkline.d.ts +64 -15
  18. package/dist/components/sparkline/geometry.d.ts +26 -0
  19. package/dist/components/tooltip/Tooltip.d.ts +5 -2
  20. package/dist/hooks/usePosition.d.ts +15 -4
  21. package/dist/index.css +1 -1
  22. package/dist/index.js +4 -2
  23. package/dist/internal/ChartTooltip.d.ts +26 -0
  24. package/dist/internal/FieldAction.d.ts +6 -7
  25. package/dist/internal/fieldCell.d.ts +21 -0
  26. package/dist/internal/messageList.d.ts +2 -2
  27. package/dist/internal/palette.d.ts +7 -0
  28. package/dist/skill/SKILL.md +24 -14
  29. package/dist/skill/anti-slop.md +77 -4
  30. package/dist/skill/cheatsheet.md +24 -5
  31. package/dist/skill/checklist.md +19 -1
  32. package/dist/skill/choosing.md +10 -5
  33. package/dist/skill/components.md +4 -3
  34. package/dist/skill/composition.md +28 -15
  35. package/dist/skill/foundations.md +8 -6
  36. package/dist/skill/layouts.md +6 -6
  37. package/dist/skill/patterns/app-shell.module.css +1 -8
  38. package/dist/skill/patterns/app-shell.tsx +11 -9
  39. package/dist/skill/patterns/chat.tsx +23 -5
  40. package/dist/skill/patterns/dashboard.module.css +1 -31
  41. package/dist/skill/patterns/dashboard.tsx +150 -136
  42. package/dist/skill/patterns/detail-page.module.css +0 -3
  43. package/dist/skill/patterns/detail-page.tsx +4 -7
  44. package/dist/skill/patterns/form-drawer.tsx +2 -2
  45. package/dist/skill/patterns/kanban-board.tsx +4 -2
  46. package/dist/skill/patterns/list-page.tsx +2 -2
  47. package/dist/skill/patterns/media-library.module.css +0 -22
  48. package/dist/skill/patterns/media-library.tsx +17 -18
  49. package/dist/skill/patterns/record-editor.module.css +18 -0
  50. package/dist/skill/patterns/record-editor.tsx +356 -0
  51. package/dist/skill/patterns/screen-states.module.css +3 -17
  52. package/dist/skill/patterns/screen-states.tsx +70 -69
  53. package/dist/skill/patterns/settings-page.module.css +1 -21
  54. package/dist/skill/patterns/settings-page.tsx +58 -79
  55. package/dist/skill/reference/components/avatar/COMPONENT.md +4 -4
  56. package/dist/skill/reference/components/avatar/examples/presence.tsx +1 -1
  57. package/dist/skill/reference/components/avatar/examples/states.tsx +1 -1
  58. package/dist/skill/reference/components/banner/COMPONENT.md +6 -6
  59. package/dist/skill/reference/components/banner/examples/dismissible.tsx +22 -11
  60. package/dist/skill/reference/components/banner/examples/examples.module.css +3 -3
  61. package/dist/skill/reference/components/banner/examples/narrow.tsx +1 -1
  62. package/dist/skill/reference/components/breadcrumb/COMPONENT.md +1 -1
  63. package/dist/skill/reference/components/breadcrumb/examples/overflow.tsx +1 -1
  64. package/dist/skill/reference/components/card/COMPONENT.md +5 -4
  65. package/dist/skill/reference/components/card/examples/examples.module.css +0 -28
  66. package/dist/skill/reference/components/card/examples/kpi-media.tsx +13 -11
  67. package/dist/skill/reference/components/card/examples/narrow.tsx +1 -1
  68. package/dist/skill/reference/components/card/examples/panel-chart.tsx +45 -22
  69. package/dist/skill/reference/components/chart-frame/COMPONENT.md +10 -7
  70. package/dist/skill/reference/components/chart-frame/examples/tooltip.tsx +20 -24
  71. package/dist/skill/reference/components/chat/COMPONENT.md +3 -3
  72. package/dist/skill/reference/components/chat/examples/search.tsx +1 -1
  73. package/dist/skill/reference/components/chat-list/COMPONENT.md +1 -1
  74. package/dist/skill/reference/components/checkbox/examples/indicator.tsx +24 -2
  75. package/dist/skill/reference/components/color-picker/COMPONENT.md +2 -2
  76. package/dist/skill/reference/components/color-swatches/COMPONENT.md +1 -0
  77. package/dist/skill/reference/components/datepicker/COMPONENT.md +1 -0
  78. package/dist/skill/reference/components/dnd/COMPONENT.md +3 -3
  79. package/dist/skill/reference/components/field-list/COMPONENT.md +164 -0
  80. package/dist/skill/reference/components/field-list/examples/base-row.tsx +76 -0
  81. package/dist/skill/reference/components/field-list/examples/controlled.tsx +72 -0
  82. package/dist/skill/reference/components/field-list/examples/errors.tsx +85 -0
  83. package/dist/skill/reference/components/field-list/examples/examples.module.css +34 -0
  84. package/dist/skill/reference/components/field-list/examples/limits.tsx +55 -0
  85. package/dist/skill/reference/components/field-list/examples/locked.tsx +139 -0
  86. package/dist/skill/reference/components/field-list/examples/narrow.tsx +68 -0
  87. package/dist/skill/reference/components/field-list/examples/overview.tsx +66 -0
  88. package/dist/skill/reference/components/field-list/examples/reorder.tsx +42 -0
  89. package/dist/skill/reference/components/field-list/examples/sizes.tsx +42 -0
  90. package/dist/skill/reference/components/field-list/examples/states.tsx +51 -0
  91. package/dist/skill/reference/components/input/examples/examples.module.css +2 -7
  92. package/dist/skill/reference/components/kanban/COMPONENT.md +13 -9
  93. package/dist/skill/reference/components/kanban/examples/limits.tsx +2 -1
  94. package/dist/skill/reference/components/kanban/examples/variants.tsx +16 -8
  95. package/dist/skill/reference/components/list/COMPONENT.md +1 -1
  96. package/dist/skill/reference/components/media-viewer/COMPONENT.md +2 -2
  97. package/dist/skill/reference/components/message/COMPONENT.md +2 -2
  98. package/dist/skill/reference/components/notification/COMPONENT.md +1 -0
  99. package/dist/skill/reference/components/page-content/COMPONENT.md +70 -14
  100. package/dist/skill/reference/components/page-content/examples/grid.tsx +107 -0
  101. package/dist/skill/reference/components/page-content/examples/overview.tsx +2 -2
  102. package/dist/skill/reference/components/page-content/examples/sections.tsx +81 -0
  103. package/dist/skill/reference/components/page-toolbar/COMPONENT.md +1 -1
  104. package/dist/skill/reference/components/segmented-control/COMPONENT.md +1 -0
  105. package/dist/skill/reference/components/select/COMPONENT.md +4 -2
  106. package/dist/skill/reference/components/select/examples/icon-only.tsx +38 -0
  107. package/dist/skill/reference/components/sparkline/COMPONENT.md +83 -30
  108. package/dist/skill/reference/components/sparkline/examples/compact.tsx +1 -1
  109. package/dist/skill/reference/components/sparkline/examples/curve.tsx +28 -0
  110. package/dist/skill/reference/components/sparkline/examples/gaps.tsx +33 -0
  111. package/dist/skill/reference/components/sparkline/examples/overview.tsx +11 -2
  112. package/dist/skill/reference/components/sparkline/examples/period.tsx +7 -2
  113. package/dist/skill/reference/components/sparkline/examples/reference.tsx +37 -0
  114. package/dist/skill/reference/components/sparkline/examples/variants.tsx +2 -2
  115. package/dist/skill/reference/components/tabs/examples/examples.module.css +0 -6
  116. package/dist/skill/reference/components/tabs/examples/in-drawer.tsx +11 -13
  117. package/dist/skill/reference/components/timeline/examples/examples.module.css +0 -8
  118. package/dist/skill/reference/components/timeline/examples/narrow.tsx +2 -2
  119. package/dist/skill/reference/components/timeline/examples/sizes.tsx +3 -3
  120. package/dist/skill/reference/components/timeline/examples/variants.tsx +4 -4
  121. package/dist/skill/reference/components/tooltip/COMPONENT.md +6 -4
  122. package/dist/skill/reference/components/tooltip/examples/placement.tsx +2 -1
  123. package/dist/skill/reference/components/video-note/COMPONENT.md +1 -1
  124. package/dist/skill/reference/components/voice-player/COMPONENT.md +1 -1
  125. package/dist/skill/reference/layout/app-header/examples/in-app-shell.tsx +2 -2
  126. package/dist/skill/reference/layout/app-shell/COMPONENT.md +1 -1
  127. package/dist/skill/reference/layout/app-shell/examples/footer.tsx +2 -2
  128. package/dist/skill/reference/layout/app-shell/examples/overview.tsx +2 -2
  129. package/dist/skill/reference/layout/app-shell/examples/template.tsx +2 -2
  130. package/dist/skill/reference/layout/bottom-nav/examples/floating-action.tsx +2 -2
  131. package/dist/skill/reference/layout/bottom-nav/examples/floating.tsx +2 -2
  132. package/dist/skill/reference/layout/bottom-nav/examples/in-app-shell.tsx +2 -2
  133. package/dist/skill/responsive.md +5 -3
  134. package/dist/skill/ux.md +145 -0
  135. package/dist/tokens/semantic.d.ts +2 -0
  136. package/package.json +1 -1
  137. package/src/components/avatar/COMPONENT.md +4 -4
  138. package/src/components/avatar/examples/presence.tsx +1 -1
  139. package/src/components/avatar/examples/states.tsx +1 -1
  140. package/src/components/banner/COMPONENT.md +6 -6
  141. package/src/components/banner/examples/dismissible.tsx +22 -11
  142. package/src/components/banner/examples/examples.module.css +3 -3
  143. package/src/components/banner/examples/narrow.tsx +1 -1
  144. package/src/components/breadcrumb/COMPONENT.md +1 -1
  145. package/src/components/breadcrumb/examples/overflow.tsx +1 -1
  146. package/src/components/card/COMPONENT.md +5 -4
  147. package/src/components/card/examples/examples.module.css +0 -28
  148. package/src/components/card/examples/kpi-media.tsx +13 -11
  149. package/src/components/card/examples/narrow.tsx +1 -1
  150. package/src/components/card/examples/panel-chart.tsx +45 -22
  151. package/src/components/chart-frame/COMPONENT.md +10 -7
  152. package/src/components/chart-frame/examples/tooltip.tsx +20 -24
  153. package/src/components/chat/COMPONENT.md +3 -3
  154. package/src/components/chat/examples/search.tsx +1 -1
  155. package/src/components/chat-list/COMPONENT.md +1 -1
  156. package/src/components/checkbox/examples/indicator.tsx +24 -2
  157. package/src/components/color-picker/COMPONENT.md +2 -2
  158. package/src/components/color-swatches/COMPONENT.md +1 -0
  159. package/src/components/datepicker/COMPONENT.md +1 -0
  160. package/src/components/dnd/COMPONENT.md +3 -3
  161. package/src/components/field-list/COMPONENT.md +164 -0
  162. package/src/components/field-list/examples/base-row.tsx +76 -0
  163. package/src/components/field-list/examples/controlled.tsx +72 -0
  164. package/src/components/field-list/examples/errors.tsx +85 -0
  165. package/src/components/field-list/examples/examples.module.css +34 -0
  166. package/src/components/field-list/examples/limits.tsx +55 -0
  167. package/src/components/field-list/examples/locked.tsx +139 -0
  168. package/src/components/field-list/examples/narrow.tsx +68 -0
  169. package/src/components/field-list/examples/overview.tsx +66 -0
  170. package/src/components/field-list/examples/reorder.tsx +42 -0
  171. package/src/components/field-list/examples/sizes.tsx +42 -0
  172. package/src/components/field-list/examples/states.tsx +51 -0
  173. package/src/components/input/examples/examples.module.css +2 -7
  174. package/src/components/kanban/COMPONENT.md +13 -9
  175. package/src/components/kanban/examples/limits.tsx +2 -1
  176. package/src/components/kanban/examples/variants.tsx +16 -8
  177. package/src/components/list/COMPONENT.md +1 -1
  178. package/src/components/media-viewer/COMPONENT.md +2 -2
  179. package/src/components/message/COMPONENT.md +2 -2
  180. package/src/components/notification/COMPONENT.md +1 -0
  181. package/src/components/page-content/COMPONENT.md +70 -14
  182. package/src/components/page-content/examples/grid.tsx +107 -0
  183. package/src/components/page-content/examples/overview.tsx +2 -2
  184. package/src/components/page-content/examples/sections.tsx +81 -0
  185. package/src/components/page-toolbar/COMPONENT.md +1 -1
  186. package/src/components/segmented-control/COMPONENT.md +1 -0
  187. package/src/components/select/COMPONENT.md +4 -2
  188. package/src/components/select/examples/icon-only.tsx +38 -0
  189. package/src/components/sparkline/COMPONENT.md +83 -30
  190. package/src/components/sparkline/examples/compact.tsx +1 -1
  191. package/src/components/sparkline/examples/curve.tsx +28 -0
  192. package/src/components/sparkline/examples/gaps.tsx +33 -0
  193. package/src/components/sparkline/examples/overview.tsx +11 -2
  194. package/src/components/sparkline/examples/period.tsx +7 -2
  195. package/src/components/sparkline/examples/reference.tsx +37 -0
  196. package/src/components/sparkline/examples/variants.tsx +2 -2
  197. package/src/components/tabs/examples/examples.module.css +0 -6
  198. package/src/components/tabs/examples/in-drawer.tsx +11 -13
  199. package/src/components/timeline/examples/examples.module.css +0 -8
  200. package/src/components/timeline/examples/narrow.tsx +2 -2
  201. package/src/components/timeline/examples/sizes.tsx +3 -3
  202. package/src/components/timeline/examples/variants.tsx +4 -4
  203. package/src/components/tooltip/COMPONENT.md +6 -4
  204. package/src/components/tooltip/examples/placement.tsx +2 -1
  205. package/src/components/video-note/COMPONENT.md +1 -1
  206. package/src/components/voice-player/COMPONENT.md +1 -1
  207. package/src/layout/app-header/examples/in-app-shell.tsx +2 -2
  208. package/src/layout/app-shell/COMPONENT.md +1 -1
  209. package/src/layout/app-shell/examples/footer.tsx +2 -2
  210. package/src/layout/app-shell/examples/overview.tsx +2 -2
  211. package/src/layout/app-shell/examples/template.tsx +2 -2
  212. package/src/layout/bottom-nav/examples/floating-action.tsx +2 -2
  213. package/src/layout/bottom-nav/examples/floating.tsx +2 -2
  214. package/src/layout/bottom-nav/examples/in-app-shell.tsx +2 -2
  215. package/src/styles/theme-light.css +1 -0
@@ -567,16 +567,16 @@ function MorphText({ children: text, className }) {
567
567
  React6.useLayoutEffect(() => {
568
568
  if (!morph) return;
569
569
  const root = rootRef.current;
570
- const segment = segmentRef.current;
570
+ const segment2 = segmentRef.current;
571
571
  const sizer = sizerRef.current;
572
- if (!root || !segment || !sizer) return;
572
+ if (!root || !segment2 || !sizer) return;
573
573
  const target = sizer.getBoundingClientRect().width;
574
574
  const still = root.getBoundingClientRect().width - target;
575
575
  const from = Math.max(0, morph.width - still);
576
576
  if (target !== from) {
577
- segment.style.width = `${from}px`;
578
- segment.getBoundingClientRect();
579
- segment.style.width = `${target}px`;
577
+ segment2.style.width = `${from}px`;
578
+ segment2.getBoundingClientRect();
579
+ segment2.style.width = `${target}px`;
580
580
  }
581
581
  const changed = splitChange(morph.from, morph.to);
582
582
  const longest = changed.in.length > changed.out.length ? changed.in : changed.out;
@@ -1272,6 +1272,9 @@ function readCssLengthPx(name, fallbackPx) {
1272
1272
  function getViewportPadPx() {
1273
1273
  return readCssLengthPx("--prime-space-2", FALLBACK_VIEWPORT_PAD_PX);
1274
1274
  }
1275
+ function pointRect(x, y) {
1276
+ return { left: x, right: x, top: y, bottom: y, width: 0, height: 0 };
1277
+ }
1275
1278
  var clamp = (value, min, max) => Math.max(min, Math.min(value, Math.max(min, max)));
1276
1279
  function computeFloatingPosition(anchor, contentW, contentH, vw, vh, opts) {
1277
1280
  const { align, offset, flip, matchAnchorWidth, arrowInset: arrowInset2, boundary } = opts;
@@ -1346,13 +1349,16 @@ function usePosition(enabled, anchorRef, layerRef, {
1346
1349
  align = DEFAULT_ALIGN,
1347
1350
  matchAnchorWidth = false,
1348
1351
  offsetToken = "--prime-panel-offset",
1349
- arrowInset: arrowInset2
1352
+ arrowInset: arrowInset2,
1353
+ anchorPoint = null
1350
1354
  } = {}) {
1351
1355
  const [attached, setAttached] = React12.useState(false);
1352
1356
  const [resolvedSide, setResolvedSide] = React12.useState(preferredSide);
1353
1357
  const resolveAnchorRect = useAnchorRectResolver();
1354
1358
  const resolveBoundary = useFloatingBoundaryResolver();
1355
1359
  const metricsRef = React12.useRef(null);
1360
+ const pointRef = React12.useRef(anchorPoint);
1361
+ pointRef.current = anchorPoint;
1356
1362
  const update = React12.useCallback(
1357
1363
  (remeasure) => {
1358
1364
  const anchor = anchorRef.current;
@@ -1366,36 +1372,44 @@ function usePosition(enabled, anchorRef, layerRef, {
1366
1372
  };
1367
1373
  }
1368
1374
  const { offset, pad, arrow } = metricsRef.current;
1369
- const rect = anchor.getBoundingClientRect();
1370
- const pos = computeFloatingPosition(
1371
- resolveAnchorRect ? resolveAnchorRect(anchor, rect) : rect,
1372
- layer.offsetWidth,
1373
- layer.offsetHeight,
1374
- window.innerWidth,
1375
- window.innerHeight,
1376
- {
1377
- side: preferredSide,
1378
- align,
1379
- offset,
1380
- viewportPad: pad,
1381
- flip: true,
1382
- matchAnchorWidth,
1383
- arrowInset: arrow,
1384
- boundary: resolveBoundary?.(anchor) ?? void 0
1385
- }
1386
- );
1387
- setResolvedSide(pos.side);
1375
+ const rawRect = anchor.getBoundingClientRect();
1376
+ const point = pointRef.current;
1377
+ const rect = point ? pointRect(rawRect.left + point.x, rawRect.top + point.y) : resolveAnchorRect ? resolveAnchorRect(anchor, rawRect) : rawRect;
1378
+ const boundary = resolveBoundary?.(anchor) ?? void 0;
1379
+ const compute = (width2, height2) => computeFloatingPosition(rect, width2, height2, window.innerWidth, window.innerHeight, {
1380
+ side: preferredSide,
1381
+ align,
1382
+ offset,
1383
+ viewportPad: pad,
1384
+ flip: true,
1385
+ matchAnchorWidth,
1386
+ arrowInset: arrow,
1387
+ boundary
1388
+ });
1388
1389
  const set = (name, value) => {
1389
1390
  if (layer.style.getPropertyValue(name) !== value) layer.style.setProperty(name, value);
1390
1391
  };
1391
1392
  const px = (n) => n === void 0 ? "" : `${n}px`;
1392
1393
  set("position", "fixed");
1394
+ let width = layer.offsetWidth;
1395
+ let height = layer.offsetHeight;
1396
+ let pos = compute(width, height);
1397
+ for (let pass = 0; pass < 3; pass++) {
1398
+ set(FLOAT_MIN_WIDTH_VAR, px(pos.minWidth));
1399
+ set(FLOAT_MAX_WIDTH_VAR, px(pos.maxWidth));
1400
+ set(FLOAT_MAX_HEIGHT_VAR, px(pos.maxHeight));
1401
+ const nextWidth = layer.offsetWidth;
1402
+ const nextHeight = layer.offsetHeight;
1403
+ if (nextWidth === width && nextHeight === height) break;
1404
+ width = nextWidth;
1405
+ height = nextHeight;
1406
+ pos = compute(width, height);
1407
+ }
1408
+ setResolvedSide(pos.side);
1393
1409
  set("top", px(pos.top));
1394
1410
  set("left", px(pos.left));
1395
- set(FLOAT_MIN_WIDTH_VAR, px(pos.minWidth));
1396
- set(FLOAT_MAX_WIDTH_VAR, px(pos.maxWidth));
1397
- set(FLOAT_MAX_HEIGHT_VAR, px(pos.maxHeight));
1398
1411
  set(FLOAT_ARROW_VAR, px(pos.arrow));
1412
+ delete layer.dataset.floatPending;
1399
1413
  },
1400
1414
  [
1401
1415
  anchorRef,
@@ -1411,9 +1425,12 @@ function usePosition(enabled, anchorRef, layerRef, {
1411
1425
  );
1412
1426
  const updateRef = React12.useRef(update);
1413
1427
  updateRef.current = update;
1428
+ const enabledRef = React12.useRef(enabled);
1429
+ enabledRef.current = enabled;
1414
1430
  const attachLayer = React12.useCallback(
1415
1431
  (node) => {
1416
1432
  layerRef.current = node;
1433
+ if (node && enabledRef.current) node.dataset.floatPending = "";
1417
1434
  setAttached(node !== null);
1418
1435
  },
1419
1436
  [layerRef]
@@ -1422,6 +1439,11 @@ function usePosition(enabled, anchorRef, layerRef, {
1422
1439
  React12.useLayoutEffect(() => {
1423
1440
  if (active2) update(true);
1424
1441
  }, [active2, update]);
1442
+ const pointX = anchorPoint?.x;
1443
+ const pointY = anchorPoint?.y;
1444
+ React12.useLayoutEffect(() => {
1445
+ if (active2 && pointX !== void 0 && pointY !== void 0) updateRef.current(false);
1446
+ }, [active2, pointX, pointY]);
1425
1447
  React12.useLayoutEffect(() => {
1426
1448
  if (!active2) return;
1427
1449
  let frame2 = 0;
@@ -1442,7 +1464,10 @@ function usePosition(enabled, anchorRef, layerRef, {
1442
1464
  target.addEventListener("scroll", follow, { passive: true });
1443
1465
  }
1444
1466
  window.visualViewport?.addEventListener("resize", resize);
1445
- const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(follow);
1467
+ const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(() => {
1468
+ cancelAnimationFrame(frame2);
1469
+ updateRef.current(false);
1470
+ });
1446
1471
  if (layerRef.current) observer?.observe(layerRef.current);
1447
1472
  if (anchorRef.current) observer?.observe(anchorRef.current);
1448
1473
  return () => {
@@ -3917,8 +3942,8 @@ function resolveValue(value, max) {
3917
3942
  percent: Math.round(clamped / top * 100)
3918
3943
  };
3919
3944
  }
3920
- function segmentFill(segment) {
3921
- return segment.color ? { tone: void 0, color: segment.color } : { tone: segment.tone ?? "accent", color: void 0 };
3945
+ function segmentFill(segment2) {
3946
+ return segment2.color ? { tone: void 0, color: segment2.color } : { tone: segment2.tone ?? "accent", color: void 0 };
3922
3947
  }
3923
3948
  function resolveRows(input, scale, max) {
3924
3949
  const segments = input.map((s) => ({ ...s, value: nonNegative(s.value) }));
@@ -3928,10 +3953,10 @@ function resolveRows(input, scale, max) {
3928
3953
  const first = segments[0]?.value ?? 0;
3929
3954
  const lengthBase = scale === "max" ? largest : scale === "first" ? first : sum;
3930
3955
  const shareBase = scale === "first" ? first : sum;
3931
- return segments.map((segment) => ({
3932
- segment,
3933
- ratio: lengthBase > 0 ? Math.min(1, segment.value / lengthBase) : 0,
3934
- percent: shareBase > 0 ? Math.round(segment.value / shareBase * 100) : 0
3956
+ return segments.map((segment2) => ({
3957
+ segment: segment2,
3958
+ ratio: lengthBase > 0 ? Math.min(1, segment2.value / lengthBase) : 0,
3959
+ percent: shareBase > 0 ? Math.round(segment2.value / shareBase * 100) : 0
3935
3960
  }));
3936
3961
  }
3937
3962
  var NUMBER = new Intl.NumberFormat("ru-RU");
@@ -3976,9 +4001,9 @@ function ProgressLegend({
3976
4001
  className
3977
4002
  }) {
3978
4003
  if (segments.length === 0) return null;
3979
- return /* @__PURE__ */ jsx23("ul", { id, className: cx(ProgressLegend_default.legend, className), "data-size": size, children: segments.map((segment, index) => {
3980
- const { tone, color } = segmentFill(segment);
3981
- const share = scale > 0 ? Math.round(segment.value / scale * 100) : 0;
4004
+ return /* @__PURE__ */ jsx23("ul", { id, className: cx(ProgressLegend_default.legend, className), "data-size": size, children: segments.map((segment2, index) => {
4005
+ const { tone, color } = segmentFill(segment2);
4006
+ const share = scale > 0 ? Math.round(segment2.value / scale * 100) : 0;
3982
4007
  return (
3983
4008
  // biome-ignore lint/suspicious/noArrayIndexKey: parts in source order, like the bar
3984
4009
  /* @__PURE__ */ jsxs11("li", { className: ProgressLegend_default.item, children: [
@@ -3990,8 +4015,8 @@ function ProgressLegend({
3990
4015
  ...toDataAttributes({ tone, color })
3991
4016
  }
3992
4017
  ),
3993
- /* @__PURE__ */ jsx23("span", { className: ProgressLegend_default.name, children: segment.label }),
3994
- /* @__PURE__ */ jsx23("span", { className: ProgressLegend_default.value, children: formatValue(segment.value) }),
4018
+ /* @__PURE__ */ jsx23("span", { className: ProgressLegend_default.name, children: segment2.label }),
4019
+ /* @__PURE__ */ jsx23("span", { className: ProgressLegend_default.value, children: formatValue(segment2.value) }),
3995
4020
  /* @__PURE__ */ jsxs11("span", { className: ProgressLegend_default.share, children: [
3996
4021
  share,
3997
4022
  "%"
@@ -4113,12 +4138,12 @@ function ProgressBar(props) {
4113
4138
  /* @__PURE__ */ jsx24(ProgressLegendSkeleton, { rows: 1, size, className: ProgressBar_default.rowSkeletonText }),
4114
4139
  barSkeleton
4115
4140
  ] }, i)
4116
- )) }, "loading") : /* @__PURE__ */ jsx24("ol", { className: cx(ProgressBar_default.rows, swapClass), ...nameProps, children: rows.map(({ segment, ratio, percent: share }, i) => (
4141
+ )) }, "loading") : /* @__PURE__ */ jsx24("ol", { className: cx(ProgressBar_default.rows, swapClass), ...nameProps, children: rows.map(({ segment: segment2, ratio, percent: share }, i) => (
4117
4142
  // biome-ignore lint/suspicious/noArrayIndexKey: rows in source order
4118
4143
  /* @__PURE__ */ jsxs12("li", { className: ProgressBar_default.row, children: [
4119
4144
  /* @__PURE__ */ jsxs12("div", { className: ProgressBar_default.rowHeader, children: [
4120
- /* @__PURE__ */ jsx24("span", { className: ProgressBar_default.rowLabel, children: segment.label }),
4121
- /* @__PURE__ */ jsx24("span", { className: ProgressBar_default.rowValue, children: formatValue(segment.value) }),
4145
+ /* @__PURE__ */ jsx24("span", { className: ProgressBar_default.rowLabel, children: segment2.label }),
4146
+ /* @__PURE__ */ jsx24("span", { className: ProgressBar_default.rowValue, children: formatValue(segment2.value) }),
4122
4147
  /* @__PURE__ */ jsxs12("span", { className: ProgressBar_default.rowShare, children: [
4123
4148
  share,
4124
4149
  "%"
@@ -4129,7 +4154,7 @@ function ProgressBar(props) {
4129
4154
  {
4130
4155
  className: cx(palette_default.hue, ProgressBar_default.fill),
4131
4156
  style: { "--pb-ratio": ratio },
4132
- ...toDataAttributes(segmentFill(segment))
4157
+ ...toDataAttributes(segmentFill(segment2))
4133
4158
  }
4134
4159
  ) })
4135
4160
  ] }, i)
@@ -4239,7 +4264,7 @@ function getPasswordStrength(value) {
4239
4264
  }
4240
4265
 
4241
4266
  // src/components/input/Input.tsx
4242
- import * as React41 from "react";
4267
+ import * as React42 from "react";
4243
4268
 
4244
4269
  // src/internal/FieldAction.tsx
4245
4270
  import * as React38 from "react";
@@ -4253,7 +4278,7 @@ var FieldAction_default = {
4253
4278
  // src/internal/FieldAction.tsx
4254
4279
  import { Fragment as Fragment5, jsx as jsx25, jsxs as jsxs13 } from "react/jsx-runtime";
4255
4280
  var fieldActionClass = cx(FieldAction_default.action, touchTargetBlockClass);
4256
- function FieldActionButton({
4281
+ function segment({
4257
4282
  label,
4258
4283
  asChild = false,
4259
4284
  className,
@@ -4269,17 +4294,15 @@ function FieldActionButton({
4269
4294
  "aria-label": label,
4270
4295
  "data-field-action": ""
4271
4296
  };
4297
+ return asChild ? /* @__PURE__ */ jsx25(Slot, { ...shared, ref, "aria-disabled": disabled || void 0, children }) : /* @__PURE__ */ jsx25("button", { ...shared, ref, type, disabled, children });
4298
+ }
4299
+ function FieldActionSegment(props) {
4300
+ return segment(props);
4301
+ }
4302
+ function FieldActionButton(props) {
4272
4303
  return /* @__PURE__ */ jsxs13(Tooltip.Root, { children: [
4273
- /* @__PURE__ */ jsx25(Tooltip.Trigger, { children: asChild ? /* @__PURE__ */ jsx25(
4274
- Slot,
4275
- {
4276
- ...shared,
4277
- ref,
4278
- "aria-disabled": disabled || void 0,
4279
- children
4280
- }
4281
- ) : /* @__PURE__ */ jsx25("button", { ...shared, ref, type, disabled, children }) }),
4282
- /* @__PURE__ */ jsx25(Tooltip.Content, { children: label })
4304
+ /* @__PURE__ */ jsx25(Tooltip.Trigger, { children: segment(props) }),
4305
+ /* @__PURE__ */ jsx25(Tooltip.Content, { children: props.label })
4283
4306
  ] });
4284
4307
  }
4285
4308
  var COPY_FEEDBACK_MS = 1600;
@@ -4443,7 +4466,14 @@ function FieldCommitStatus({
4443
4466
  }
4444
4467
 
4445
4468
  // src/internal/FieldFrame.tsx
4469
+ import * as React41 from "react";
4470
+
4471
+ // src/internal/fieldCell.ts
4446
4472
  import * as React40 from "react";
4473
+ var FieldCellContext = React40.createContext(null);
4474
+ function useFieldCell() {
4475
+ return React40.useContext(FieldCellContext);
4476
+ }
4447
4477
 
4448
4478
  // src/internal/formatLabel.ts
4449
4479
  function formatLabel(template, values) {
@@ -4457,6 +4487,8 @@ function formatLabel(template, values) {
4457
4487
  var FieldFrame_default = {
4458
4488
  root: "FieldFrame_root",
4459
4489
  label: "FieldFrame_label",
4490
+ cellLabel: "FieldFrame_cellLabel",
4491
+ "prime-field-list": "FieldFrame_prime-field-list",
4460
4492
  labelRow: "FieldFrame_labelRow",
4461
4493
  labelEnd: "FieldFrame_labelEnd",
4462
4494
  body: "FieldFrame_body",
@@ -4481,7 +4513,8 @@ function useFieldFrame(explicitId, {
4481
4513
  error,
4482
4514
  invalid
4483
4515
  }, ariaDescribedBy) {
4484
- const generated = React40.useId();
4516
+ const generated = React41.useId();
4517
+ const cell = useFieldCell();
4485
4518
  const controlId = explicitId ?? generated;
4486
4519
  const labelId = `${controlId}-label`;
4487
4520
  const hintId = `${controlId}-hint`;
@@ -4495,7 +4528,8 @@ function useFieldFrame(explicitId, {
4495
4528
  hintId,
4496
4529
  errorId,
4497
4530
  describedBy,
4498
- labelledBy: hasContent(label) ? labelId : void 0,
4531
+ // In a FieldList cell the frame renders the column heading as the label when there is none.
4532
+ labelledBy: hasContent(label) || cell ? labelId : void 0,
4499
4533
  showHint,
4500
4534
  showError,
4501
4535
  invalid: Boolean(invalid) || showError
@@ -4503,9 +4537,9 @@ function useFieldFrame(explicitId, {
4503
4537
  }
4504
4538
  function useErrorShake(invalid, error) {
4505
4539
  const key = !invalid ? null : typeof error === "string" || typeof error === "number" ? String(error) : "invalid";
4506
- const previous = React40.useRef(key);
4507
- const [count, setCount] = React40.useState(0);
4508
- React40.useEffect(() => {
4540
+ const previous = React41.useRef(key);
4541
+ const [count, setCount] = React41.useState(0);
4542
+ React41.useEffect(() => {
4509
4543
  if (key !== null && key !== previous.current) setCount((n) => n + 1);
4510
4544
  previous.current = key;
4511
4545
  }, [key]);
@@ -4513,7 +4547,7 @@ function useErrorShake(invalid, error) {
4513
4547
  return count % 2 ? "odd" : "even";
4514
4548
  }
4515
4549
  function useLeavingError(showError, error) {
4516
- const last = React40.useRef(error);
4550
+ const last = React41.useRef(error);
4517
4551
  if (showError) last.current = error;
4518
4552
  const presence = usePresence(showError, { exitDuration: "fast" });
4519
4553
  if (showError || !presence.mounted) return null;
@@ -4542,7 +4576,9 @@ function FieldFrame({
4542
4576
  const leaving = useLeavingError(showError, error);
4543
4577
  const showSupport = showError || showHint || leaving != null || counter != null || reserveSupportRow;
4544
4578
  const shake = useErrorShake(ids.invalid, error);
4545
- const labelNode = hasContent(label) ? /* @__PURE__ */ jsx27(
4579
+ const cell = useFieldCell();
4580
+ const shownLabel = hasContent(label) ? label : cell?.label;
4581
+ const labelNode = hasContent(shownLabel) ? /* @__PURE__ */ jsx27(
4546
4582
  Label.Root,
4547
4583
  {
4548
4584
  id: ids.labelId,
@@ -4552,8 +4588,12 @@ function FieldFrame({
4552
4588
  optional,
4553
4589
  disabled,
4554
4590
  labels: { optional: optionalLabel },
4555
- className: FieldFrame_default.label,
4556
- children: label
4591
+ className: cx(
4592
+ FieldFrame_default.label,
4593
+ cell && visuallyHiddenClass,
4594
+ cell?.hidden === "wide" && FieldFrame_default.cellLabel
4595
+ ),
4596
+ children: shownLabel
4557
4597
  }
4558
4598
  ) : null;
4559
4599
  return /* @__PURE__ */ jsxs15(
@@ -4688,17 +4728,17 @@ function InputRoot({
4688
4728
  className,
4689
4729
  ...rest
4690
4730
  }) {
4691
- const [strengthValue, setStrengthValue] = React41.useState("");
4731
+ const [strengthValue, setStrengthValue] = React42.useState("");
4692
4732
  const size = useControlSize(sizeProp);
4693
4733
  const ids = useFieldFrame(id, { label, hint, error, invalid });
4694
- const labels = React41.useMemo(() => ({ ...INPUT_LABELS, ...labelsProp }), [labelsProp]);
4734
+ const labels = React42.useMemo(() => ({ ...INPUT_LABELS, ...labelsProp }), [labelsProp]);
4695
4735
  const { invalid: isInvalid, controlId: inputId, describedBy } = ids;
4696
- const inputRef = React41.useRef(null);
4736
+ const inputRef = React42.useRef(null);
4697
4737
  const commit = useFieldCommit(inputRef, onCommit);
4698
4738
  const hasCommit = onCommit !== void 0;
4699
- const [revealed, setRevealed] = React41.useState(false);
4700
- const selectionRef = React41.useRef(null);
4701
- const contextValue = React41.useMemo(
4739
+ const [revealed, setRevealed] = React42.useState(false);
4740
+ const selectionRef = React42.useRef(null);
4741
+ const contextValue = React42.useMemo(
4702
4742
  () => ({
4703
4743
  size,
4704
4744
  invalid: isInvalid,
@@ -4826,7 +4866,7 @@ function InputField({
4826
4866
  } = useInputContext();
4827
4867
  const setRefs = useMergedRefs(inputRef, ref);
4828
4868
  const disabled = useInheritedDisabled(disabledProp);
4829
- React41.useLayoutEffect(() => {
4869
+ React42.useLayoutEffect(() => {
4830
4870
  const selection = selectionRef.current;
4831
4871
  const input = inputRef.current;
4832
4872
  if (!selection || !input) return;
@@ -4834,7 +4874,7 @@ function InputField({
4834
4874
  input.setSelectionRange(selection[0], selection[1]);
4835
4875
  }, [revealed, selectionRef, inputRef]);
4836
4876
  const controlled = rest.value;
4837
- React41.useEffect(() => {
4877
+ React42.useEffect(() => {
4838
4878
  if (!reportValue) return;
4839
4879
  if (controlled !== void 0) reportValue(String(controlled));
4840
4880
  else if (inputRef.current) reportValue(inputRef.current.value);
@@ -4897,17 +4937,14 @@ function InputInlineAffix({ side, children, className, ...rest }) {
4897
4937
  );
4898
4938
  }
4899
4939
  InputInlineAffix.displayName = "Input.InlineAffix";
4900
- function InputClearButton({ className, onClick: onClick2, ref, ...rest }) {
4940
+ function InputClearButton({ onClick: onClick2, ref, ...rest }) {
4901
4941
  const { inputId, inputRef, labels } = useInputContext();
4902
4942
  return /* @__PURE__ */ jsx28(
4903
- "button",
4943
+ FieldActionSegment,
4904
4944
  {
4905
4945
  ...rest,
4906
4946
  ref,
4907
- type: "button",
4908
- className: cx(fieldActionClass, className),
4909
- "data-field-action": "",
4910
- "aria-label": labels.clear,
4947
+ label: labels.clear,
4911
4948
  "aria-controls": inputId,
4912
4949
  onClick: (event) => {
4913
4950
  onClick2?.(event);
@@ -4934,23 +4971,14 @@ function InputCopyButton({ value, ...rest }) {
4934
4971
  );
4935
4972
  }
4936
4973
  InputCopyButton.displayName = "Input.CopyButton";
4937
- function InputRevealButton({
4938
- className,
4939
- onClick: onClick2,
4940
- onMouseDown,
4941
- ref,
4942
- ...rest
4943
- }) {
4974
+ function InputRevealButton({ onClick: onClick2, onMouseDown, ref, ...rest }) {
4944
4975
  const { inputId, inputRef, labels, revealed, setRevealed, selectionRef } = useInputContext();
4945
4976
  return /* @__PURE__ */ jsx28(
4946
- "button",
4977
+ FieldActionSegment,
4947
4978
  {
4948
4979
  ...rest,
4949
4980
  ref,
4950
- type: "button",
4951
- className: cx(fieldActionClass, className),
4952
- "data-field-action": "",
4953
- "aria-label": labels.reveal,
4981
+ label: labels.reveal,
4954
4982
  "aria-pressed": revealed,
4955
4983
  "aria-controls": inputId,
4956
4984
  onMouseDown: (event) => {
@@ -4993,7 +5021,7 @@ var Input = {
4993
5021
  };
4994
5022
 
4995
5023
  // src/components/checkbox/Checkbox.tsx
4996
- import * as React42 from "react";
5024
+ import * as React43 from "react";
4997
5025
 
4998
5026
  // src/internal/CheckMark.module.css
4999
5027
  var CheckMark_default = {
@@ -5132,9 +5160,9 @@ function CheckboxRoot({
5132
5160
  defaultValue: defaultChecked,
5133
5161
  onChange: onCheckedChange
5134
5162
  });
5135
- const internalRef = React42.useRef(null);
5163
+ const internalRef = React43.useRef(null);
5136
5164
  const mergedRef = useMergedRefs(internalRef, ref);
5137
- React42.useEffect(() => {
5165
+ React43.useEffect(() => {
5138
5166
  if (internalRef.current) internalRef.current.indeterminate = indeterminate;
5139
5167
  }, [indeterminate]);
5140
5168
  return /* @__PURE__ */ jsx31(
@@ -5231,7 +5259,7 @@ var Checkbox = {
5231
5259
  };
5232
5260
 
5233
5261
  // src/components/thumbnail/Thumbnail.tsx
5234
- import * as React44 from "react";
5262
+ import * as React45 from "react";
5235
5263
 
5236
5264
  // src/internal/formatClock.ts
5237
5265
  function formatClock(seconds) {
@@ -5260,7 +5288,7 @@ function firstFrame(src) {
5260
5288
  }
5261
5289
 
5262
5290
  // src/internal/mediaSession.ts
5263
- import * as React43 from "react";
5291
+ import * as React44 from "react";
5264
5292
  var active = null;
5265
5293
  var audible = (media) => !media.muted && media.volume > 0;
5266
5294
  function claimPlayback(media) {
@@ -5272,7 +5300,7 @@ function releasePlayback(media) {
5272
5300
  if (active === media) active = null;
5273
5301
  }
5274
5302
  function useMediaSession(ref) {
5275
- React43.useEffect(() => {
5303
+ React44.useEffect(() => {
5276
5304
  const media = ref.current;
5277
5305
  if (!media) return;
5278
5306
  const claim = () => claimPlayback(media);
@@ -5402,22 +5430,22 @@ function ThumbnailVideoInner({
5402
5430
  ...rest
5403
5431
  }) {
5404
5432
  const report = slot2.useReportStatus();
5405
- const mute = React44.useCallback(
5433
+ const mute = React45.useCallback(
5406
5434
  (node) => {
5407
5435
  if (node) node.muted = autoPlay && !controls;
5408
5436
  },
5409
5437
  [autoPlay, controls]
5410
5438
  );
5411
- const sessionRef = React44.useRef(null);
5439
+ const sessionRef = React45.useRef(null);
5412
5440
  useMediaSession(sessionRef);
5413
5441
  const videoRef = useMergedRefs(mute, sessionRef, ref);
5414
5442
  const media = useImageStatus(report, {
5415
5443
  onLoad: onLoadedData,
5416
5444
  onError
5417
5445
  });
5418
- const [duration, setDuration] = React44.useState(null);
5419
- const [playing, setPlaying] = React44.useState(false);
5420
- const [still] = React44.useState(prefersReducedMotion);
5446
+ const [duration, setDuration] = React45.useState(null);
5447
+ const [playing, setPlaying] = React45.useState(false);
5448
+ const [still] = React45.useState(prefersReducedMotion);
5421
5449
  const loops = autoPlay && !still && !controls;
5422
5450
  return /* @__PURE__ */ jsxs20(Fragment9, { children: [
5423
5451
  /* @__PURE__ */ jsx33(
@@ -5468,7 +5496,7 @@ var Thumbnail = {
5468
5496
  };
5469
5497
 
5470
5498
  // src/internal/swatch.tsx
5471
- import * as React45 from "react";
5499
+ import * as React46 from "react";
5472
5500
 
5473
5501
  // src/internal/swatch.module.css
5474
5502
  var swatch_default = {
@@ -5501,7 +5529,7 @@ var COLOR_PRESETS = [
5501
5529
  { value: "#be185d", label: "\u0422\u0451\u043C\u043D\u043E-\u0440\u043E\u0437\u043E\u0432\u044B\u0439" }
5502
5530
  ];
5503
5531
  function useSwatchOptions(presets, allowEmpty, emptyLabel) {
5504
- return React45.useMemo(
5532
+ return React46.useMemo(
5505
5533
  () => [
5506
5534
  ...presets.map((preset) => ({ ...preset, contrast: markContrast(preset.value) })),
5507
5535
  ...allowEmpty ? [{ value: null, label: emptyLabel, contrast: "dark" }] : []
@@ -5566,7 +5594,7 @@ function markContrast(value) {
5566
5594
  }
5567
5595
 
5568
5596
  // src/components/color-swatches/ColorSwatches.tsx
5569
- import * as React46 from "react";
5597
+ import * as React47 from "react";
5570
5598
 
5571
5599
  // src/internal/rovingFocus.ts
5572
5600
  var PREV = {
@@ -5633,8 +5661,8 @@ function balancedColumns(count, width, cell, gap) {
5633
5661
  return Math.ceil(count / rows);
5634
5662
  }
5635
5663
  function useBalancedColumns(gridRef, count) {
5636
- const [columns, setColumns] = React46.useState();
5637
- React46.useLayoutEffect(() => {
5664
+ const [columns, setColumns] = React47.useState();
5665
+ React47.useLayoutEffect(() => {
5638
5666
  const grid = gridRef.current;
5639
5667
  if (!grid || typeof ResizeObserver === "undefined") return;
5640
5668
  const measure = () => {
@@ -5685,8 +5713,8 @@ function ColorSwatches({
5685
5713
  const options = useSwatchOptions(presets, allowEmpty, labels.empty);
5686
5714
  const selectedIndex = options.findIndex((option) => sameColor(option.value, value));
5687
5715
  const focusIndex = Math.max(0, selectedIndex);
5688
- const itemRefs = React46.useRef([]);
5689
- const gridRef = React46.useRef(null);
5716
+ const itemRefs = React47.useRef([]);
5717
+ const gridRef = React47.useRef(null);
5690
5718
  const columns = useBalancedColumns(gridRef, options.length);
5691
5719
  const labelledBy = ariaLabelledBy ?? ids.labelledBy;
5692
5720
  const onKeyDown2 = (event) => {
@@ -5778,10 +5806,10 @@ function ColorSwatches({
5778
5806
  }
5779
5807
 
5780
5808
  // src/components/select/Select.tsx
5781
- import * as React51 from "react";
5809
+ import * as React52 from "react";
5782
5810
 
5783
5811
  // src/internal/listbox.ts
5784
- import * as React47 from "react";
5812
+ import * as React48 from "react";
5785
5813
  var optionDomId = (listboxId, value) => `${listboxId}-opt-${value.replace(/\s+/g, "_")}`;
5786
5814
  function enabledOptions(container) {
5787
5815
  if (!container) return [];
@@ -5806,11 +5834,11 @@ function createStore(initial) {
5806
5834
  };
5807
5835
  }
5808
5836
  function useCreateStore(initial) {
5809
- return React47.useState(() => createStore(initial))[0];
5837
+ return React48.useState(() => createStore(initial))[0];
5810
5838
  }
5811
5839
  function useStoreSlice(store, select) {
5812
5840
  const read = () => select(store.get());
5813
- return React47.useSyncExternalStore(store.subscribe, read, read);
5841
+ return React48.useSyncExternalStore(store.subscribe, read, read);
5814
5842
  }
5815
5843
  function handleListboxKeyDown(event, { items, highlight, onSelect }) {
5816
5844
  if (items.length === 0) return;
@@ -5832,10 +5860,10 @@ function handleListboxKeyDown(event, { items, highlight, onSelect }) {
5832
5860
  }
5833
5861
  var TYPEAHEAD_RESET_MS = 500;
5834
5862
  function useTypeahead() {
5835
- const state = React47.useRef({ buffer: "", timer: 0 });
5836
- React47.useEffect(() => () => window.clearTimeout(state.current.timer), []);
5837
- const isTyping = React47.useCallback(() => state.current.buffer !== "", []);
5838
- const find = React47.useCallback(
5863
+ const state = React48.useRef({ buffer: "", timer: 0 });
5864
+ React48.useEffect(() => () => window.clearTimeout(state.current.timer), []);
5865
+ const isTyping = React48.useCallback(() => state.current.buffer !== "", []);
5866
+ const find = React48.useCallback(
5839
5867
  (key, items, highlighted) => {
5840
5868
  const s = state.current;
5841
5869
  window.clearTimeout(s.timer);
@@ -5857,19 +5885,19 @@ function useTypeahead() {
5857
5885
  }
5858
5886
  var LOAD_MORE_ROOT_MARGIN = "0px 0px 48px 0px";
5859
5887
  function useLoadMore({ enabled, onLoadMore, scrollRef, rearm }) {
5860
- const sentinelRef = React47.useRef(null);
5861
- const handlerRef = React47.useRef(onLoadMore);
5888
+ const sentinelRef = React48.useRef(null);
5889
+ const handlerRef = React48.useRef(onLoadMore);
5862
5890
  handlerRef.current = onLoadMore;
5863
- const askedRef = React47.useRef(false);
5864
- React47.useLayoutEffect(() => {
5891
+ const askedRef = React48.useRef(false);
5892
+ React48.useLayoutEffect(() => {
5865
5893
  askedRef.current = false;
5866
5894
  }, [enabled, rearm]);
5867
- const request = React47.useCallback(() => {
5895
+ const request = React48.useCallback(() => {
5868
5896
  if (!enabled || askedRef.current) return;
5869
5897
  askedRef.current = true;
5870
5898
  void handlerRef.current?.();
5871
5899
  }, [enabled]);
5872
- React47.useEffect(() => {
5900
+ React48.useEffect(() => {
5873
5901
  const root = scrollRef.current;
5874
5902
  const target = sentinelRef.current;
5875
5903
  if (!enabled || !root || !target || typeof IntersectionObserver === "undefined") return;
@@ -5886,7 +5914,7 @@ function useLoadMore({ enabled, onLoadMore, scrollRef, rearm }) {
5886
5914
  }
5887
5915
 
5888
5916
  // src/internal/MenuGroup.tsx
5889
- import * as React48 from "react";
5917
+ import * as React49 from "react";
5890
5918
 
5891
5919
  // src/internal/menu.module.css
5892
5920
  var menu_default = {
@@ -5908,7 +5936,7 @@ var menu_default = {
5908
5936
  // src/internal/MenuGroup.tsx
5909
5937
  import { jsx as jsx36, jsxs as jsxs23 } from "react/jsx-runtime";
5910
5938
  function MenuGroup({ label, className, children, ...rest }) {
5911
- const labelId = React48.useId();
5939
+ const labelId = React49.useId();
5912
5940
  return (
5913
5941
  // biome-ignore lint/a11y/useSemanticElements: role="group" inside a menu / listbox; <fieldset> is not allowed there
5914
5942
  /* @__PURE__ */ jsxs23(
@@ -5951,10 +5979,10 @@ var Select_default = {
5951
5979
  };
5952
5980
 
5953
5981
  // src/components/select/SelectItem.tsx
5954
- import * as React50 from "react";
5982
+ import * as React51 from "react";
5955
5983
 
5956
5984
  // src/internal/HighlightMatch.tsx
5957
- import * as React49 from "react";
5985
+ import * as React50 from "react";
5958
5986
 
5959
5987
  // src/internal/HighlightMatch.module.css
5960
5988
  var HighlightMatch_default = {
@@ -5998,7 +6026,7 @@ function HighlightMatch({
5998
6026
  }
5999
6027
  function highlightChildren(children, query) {
6000
6028
  if (!query.trim()) return children;
6001
- return React49.Children.map(
6029
+ return React50.Children.map(
6002
6030
  children,
6003
6031
  (child) => typeof child === "string" || typeof child === "number" ? /* @__PURE__ */ jsx37(HighlightMatch, { text: String(child), query }) : child
6004
6032
  );
@@ -6040,7 +6068,7 @@ function textOf(node) {
6040
6068
  if (node == null || typeof node === "boolean") return "";
6041
6069
  if (typeof node === "string" || typeof node === "number") return String(node);
6042
6070
  if (Array.isArray(node)) return node.map(textOf).join("");
6043
- if (React50.isValidElement(node))
6071
+ if (React51.isValidElement(node))
6044
6072
  return textOf(node.props.children);
6045
6073
  return "";
6046
6074
  }
@@ -6048,9 +6076,9 @@ function SelectItemIcon({ className, ...rest }) {
6048
6076
  return /* @__PURE__ */ jsx38("span", { "aria-hidden": "true", className: cx(menu_default.itemIcon, className), ...rest });
6049
6077
  }
6050
6078
  SelectItemIcon.displayName = "Select.ItemIcon";
6051
- var OptionQueryContext = React50.createContext("");
6079
+ var OptionQueryContext = React51.createContext("");
6052
6080
  function SelectItemText({ children, className, ...rest }) {
6053
- const query = React50.useContext(OptionQueryContext);
6081
+ const query = React51.useContext(OptionQueryContext);
6054
6082
  return /* @__PURE__ */ jsx38("span", { ...rest, className: cx(Select_default.itemTitle, className), children: highlightChildren(children, query) });
6055
6083
  }
6056
6084
  SelectItemText.displayName = "Select.ItemText";
@@ -6059,7 +6087,7 @@ function SelectItemDescription({
6059
6087
  className,
6060
6088
  ...rest
6061
6089
  }) {
6062
- const query = React50.useContext(OptionQueryContext);
6090
+ const query = React51.useContext(OptionQueryContext);
6063
6091
  return /* @__PURE__ */ jsx38("span", { ...rest, className: cx(Select_default.itemDescription, className), children: highlightChildren(children, query) });
6064
6092
  }
6065
6093
  SelectItemDescription.displayName = "Select.ItemDescription";
@@ -6077,11 +6105,11 @@ function splitItemChildren(children) {
6077
6105
  description: ""
6078
6106
  };
6079
6107
  let plain = "";
6080
- for (const child of React50.Children.toArray(children)) {
6081
- if (!React50.isValidElement(child)) {
6108
+ for (const child of React51.Children.toArray(children)) {
6109
+ if (!React51.isValidElement(child)) {
6082
6110
  plain += textOf(child);
6083
6111
  parts.body.push(child);
6084
- } else if (child.type === React50.Fragment) {
6112
+ } else if (child.type === React51.Fragment) {
6085
6113
  const inner = splitItemChildren(child.props.children);
6086
6114
  parts.leading.push(...inner.leading);
6087
6115
  parts.body.push(...inner.body);
@@ -6111,7 +6139,7 @@ function splitItemChildren(children) {
6111
6139
  }
6112
6140
  function sizeMedia(leading, size) {
6113
6141
  return leading.map(
6114
- (node) => React50.isValidElement(node) && (node.type === Thumbnail.Root || node.type === Avatar.Root) ? React50.cloneElement(node, {
6142
+ (node) => React51.isValidElement(node) && (node.type === Thumbnail.Root || node.type === Avatar.Root) ? React51.cloneElement(node, {
6115
6143
  size: node.props.size ?? MEDIA_SIZE[size],
6116
6144
  className: cx(Select_default.media, node.props.className),
6117
6145
  "aria-hidden": true
@@ -6133,7 +6161,7 @@ function SelectItem({
6133
6161
  const haystack = normalize(`${resolvedLabel} ${parts.description} ${keywords ?? ""}`);
6134
6162
  const isSelected = selected.includes(value);
6135
6163
  const isHighlighted = useStoreSlice(highlight, (current) => current === value);
6136
- React50.useLayoutEffect(
6164
+ React51.useLayoutEffect(
6137
6165
  () => registry.register(value, resolvedLabel, haystack),
6138
6166
  [registry, value, resolvedLabel, haystack]
6139
6167
  );
@@ -6190,7 +6218,7 @@ function SelectAction({
6190
6218
  ...rest
6191
6219
  }) {
6192
6220
  const { highlight, listboxId, setOpen, size } = useSelectContext();
6193
- const value = `${ACTION_PREFIX}${React50.useId()}`;
6221
+ const value = `${ACTION_PREFIX}${React51.useId()}`;
6194
6222
  const isHighlighted = useStoreSlice(highlight, (current) => current === value);
6195
6223
  const parts = splitItemChildren(children);
6196
6224
  return (
@@ -6282,7 +6310,7 @@ function SelectRoot(props) {
6282
6310
  } = props;
6283
6311
  const multiple = props.multiple === true;
6284
6312
  const disabled = useInheritedDisabled(disabledProp);
6285
- const labels = React51.useMemo(() => ({ ...SELECT_LABELS, ...labelsProp }), [labelsProp]);
6313
+ const labels = React52.useMemo(() => ({ ...SELECT_LABELS, ...labelsProp }), [labelsProp]);
6286
6314
  const ids = useFieldFrame(id, { hint, error, invalid });
6287
6315
  const [stored, setStored] = useControllableState({
6288
6316
  value: props.value,
@@ -6291,7 +6319,7 @@ function SelectRoot(props) {
6291
6319
  const changes = usePendingChanges(stored, takeNext);
6292
6320
  const value = changes.shown;
6293
6321
  const saving = changes.pending.length > 0;
6294
- const [announcement, setAnnouncement] = React51.useState("");
6322
+ const [announcement, setAnnouncement] = React52.useState("");
6295
6323
  const onValueChange = props.onValueChange;
6296
6324
  const commit = (next) => {
6297
6325
  if (saving || Object.is(next, value)) return;
@@ -6306,9 +6334,9 @@ function SelectRoot(props) {
6306
6334
  onReject: () => setAnnouncement(labels.changeFailed)
6307
6335
  });
6308
6336
  };
6309
- const commitRef = React51.useRef(commit);
6337
+ const commitRef = React52.useRef(commit);
6310
6338
  commitRef.current = commit;
6311
- const selected = React51.useMemo(
6339
+ const selected = React52.useMemo(
6312
6340
  () => Array.isArray(value) ? value : value ? [value] : [],
6313
6341
  [value]
6314
6342
  );
@@ -6318,19 +6346,19 @@ function SelectRoot(props) {
6318
6346
  onChange: onOpenChange
6319
6347
  });
6320
6348
  const highlight = useCreateStore(void 0);
6321
- const [registry] = React51.useState(createItemRegistry);
6349
+ const [registry] = React52.useState(createItemRegistry);
6322
6350
  const [query, setQuery] = useControllableState({
6323
6351
  value: search,
6324
6352
  defaultValue: defaultSearch,
6325
6353
  onChange: onSearchChange
6326
6354
  });
6327
- const triggerRef = React51.useRef(null);
6328
- const wasOpenRef = React51.useRef(isOpen);
6329
- React51.useEffect(() => {
6355
+ const triggerRef = React52.useRef(null);
6356
+ const wasOpenRef = React52.useRef(isOpen);
6357
+ React52.useEffect(() => {
6330
6358
  if (wasOpenRef.current && !isOpen) setQuery("");
6331
6359
  wasOpenRef.current = isOpen;
6332
6360
  }, [isOpen, setQuery]);
6333
- const pick = React51.useCallback(
6361
+ const pick = React52.useCallback(
6334
6362
  (optionValue) => {
6335
6363
  if (multiple) {
6336
6364
  const list = Array.isArray(value) ? value : [];
@@ -6344,8 +6372,8 @@ function SelectRoot(props) {
6344
6372
  },
6345
6373
  [multiple, value, setOpen]
6346
6374
  );
6347
- const clear = React51.useCallback(() => commitRef.current(multiple ? [] : ""), [multiple]);
6348
- const context = React51.useMemo(
6375
+ const clear = React52.useCallback(() => commitRef.current(multiple ? [] : ""), [multiple]);
6376
+ const context = React52.useMemo(
6349
6377
  () => ({
6350
6378
  size,
6351
6379
  invalid: ids.invalid,
@@ -6462,6 +6490,8 @@ function SelectTrigger({
6462
6490
  labels
6463
6491
  } = useSelectContext();
6464
6492
  const mergedRef = useMergedRefs(triggerRef, ref);
6493
+ const parts = React52.Children.toArray(children);
6494
+ const iconOnly = parts.some((node) => React52.isValidElement(node) && node.type === SelectTriggerIcon) && !parts.some((node) => React52.isValidElement(node) && node.type === SelectValue);
6465
6495
  const busy = loading || saving;
6466
6496
  const showClear = clearable && selected.length > 0 && !disabled && !busy;
6467
6497
  return /* @__PURE__ */ jsxs26(
@@ -6502,17 +6532,22 @@ function SelectTrigger({
6502
6532
  invalid: invalid || void 0,
6503
6533
  loading: busy || void 0,
6504
6534
  disabled: disabled || void 0,
6505
- "focus-ring": focusRing ? void 0 : false
6535
+ "focus-ring": focusRing ? void 0 : false,
6536
+ "icon-only": iconOnly || void 0
6506
6537
  }),
6507
6538
  children: [
6508
- /* @__PURE__ */ jsx39("span", { className: Select_default.triggerMain, children }),
6539
+ /* @__PURE__ */ jsxs26("span", { className: Select_default.triggerMain, children: [
6540
+ children,
6541
+ iconOnly ? /* @__PURE__ */ jsx39(SelectValue, { className: visuallyHiddenClass }) : null
6542
+ ] }),
6509
6543
  showClear ? (
6510
6544
  // A segment, not a button: interactive content inside a <button> is invalid. The keyboard
6511
- // clears with Delete / Backspace on the trigger.
6545
+ // clears with Delete / Backspace on the trigger. A touch target in height, like the clear
6546
+ // segment of a field (`FieldAction`).
6512
6547
  /* @__PURE__ */ jsx39(
6513
6548
  "span",
6514
6549
  {
6515
- className: Select_default.clear,
6550
+ className: cx(Select_default.clear, touchTargetBlockClass),
6516
6551
  "aria-hidden": "true",
6517
6552
  title: labels.clear,
6518
6553
  "data-select-clear": "",
@@ -6608,11 +6643,11 @@ function SelectContent({ searchable = false, className, children, ...rest }) {
6608
6643
  labels,
6609
6644
  registry
6610
6645
  } = useSelectContext();
6611
- const listboxRef = React51.useRef(null);
6646
+ const listboxRef = React52.useRef(null);
6612
6647
  const items = [];
6613
6648
  const actions = [];
6614
- for (const child of React51.Children.toArray(children)) {
6615
- (React51.isValidElement(child) && child.type === SelectAction ? actions : items).push(child);
6649
+ for (const child of React52.Children.toArray(children)) {
6650
+ (React52.isValidElement(child) && child.type === SelectAction ? actions : items).push(child);
6616
6651
  }
6617
6652
  const actionsId = `${listboxId}-actions`;
6618
6653
  const floating = useFloatingLayer({
@@ -6637,12 +6672,12 @@ function SelectContent({ searchable = false, className, children, ...rest }) {
6637
6672
  scrollRef: listboxRef,
6638
6673
  rearm: version
6639
6674
  });
6640
- React51.useEffect(() => {
6675
+ React52.useEffect(() => {
6641
6676
  if (highlighted === void 0) return;
6642
6677
  if (enabledOptions(listboxRef.current).at(-1)?.dataset.value === highlighted) requestMore();
6643
6678
  }, [highlighted, requestMore]);
6644
6679
  const panelRef = floating.contentRef;
6645
- React51.useEffect(() => {
6680
+ React52.useEffect(() => {
6646
6681
  const panel = panelRef.current;
6647
6682
  if (isOpen && swapped && panel && !panel.contains(document.activeElement)) focusInto(panel);
6648
6683
  }, [region, swapped, isOpen, panelRef]);
@@ -6765,10 +6800,10 @@ function HighlightOnOpen({
6765
6800
  highlight
6766
6801
  }) {
6767
6802
  const { isOpen, query, selected, registry } = useSelectContext();
6768
- const selectedRef = React51.useRef(selected);
6803
+ const selectedRef = React52.useRef(selected);
6769
6804
  selectedRef.current = selected;
6770
6805
  const version = useStoreSlice(registry.version, (value) => value);
6771
- React51.useLayoutEffect(() => {
6806
+ React52.useLayoutEffect(() => {
6772
6807
  if (!isOpen) return;
6773
6808
  const options = enabledOptions(listboxRef.current);
6774
6809
  const first = options.find((item) => selectedRef.current.includes(item.dataset.value ?? ""));
@@ -6776,10 +6811,10 @@ function HighlightOnOpen({
6776
6811
  first?.scrollIntoView?.({ block: "nearest" });
6777
6812
  return () => highlight.set(void 0);
6778
6813
  }, [isOpen, listboxRef, highlight]);
6779
- React51.useLayoutEffect(() => {
6814
+ React52.useLayoutEffect(() => {
6780
6815
  if (query !== "") highlight.set(enabledOptions(panelRef.current)[0]?.dataset.value);
6781
6816
  }, [query, panelRef, highlight]);
6782
- React51.useLayoutEffect(() => {
6817
+ React52.useLayoutEffect(() => {
6783
6818
  if (query === "") return;
6784
6819
  const options = enabledOptions(listboxRef.current);
6785
6820
  if (!options.some((item) => item.dataset.value === highlight.get())) {
@@ -6896,6 +6931,8 @@ export {
6896
6931
  enterMotion_default,
6897
6932
  Hint,
6898
6933
  Label,
6934
+ FieldCellContext,
6935
+ useFieldCell,
6899
6936
  formatLabel,
6900
6937
  useFieldFrame,
6901
6938
  FieldFrame,