prime-ui-kit 0.17.0 → 0.19.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 (286) hide show
  1. package/README.md +2 -1
  2. package/dist/chunks/{chunk-PRP4B6OG.js → chunk-IVS3J7AS.js} +1 -1
  3. package/dist/chunks/{chunk-2ODXLPW3.js → chunk-QFHE5GKW.js} +1 -0
  4. package/dist/chunks/{chunk-7WWZYGRC.js → chunk-RZNGLELR.js} +4497 -3896
  5. package/dist/chunks/{chunk-A4WE3UNC.js → chunk-WYCTXD63.js} +18399 -17624
  6. package/dist/chunks/{chunk-SVFWPLNW.js → chunk-ZTZ2ML2B.js} +14 -3
  7. package/dist/color-picker.js +3 -3
  8. package/dist/components/badge/Badge.d.ts +17 -0
  9. package/dist/components/breadcrumb/Breadcrumb.d.ts +11 -2
  10. package/dist/components/button/Button.d.ts +1 -1
  11. package/dist/components/button-group/ButtonGroup.d.ts +1 -1
  12. package/dist/components/card/Card.d.ts +8 -4
  13. package/dist/components/chat/Chat.d.ts +3 -3
  14. package/dist/components/chat/MessageList.d.ts +5 -1
  15. package/dist/components/chat/groupMessages.d.ts +12 -4
  16. package/dist/components/chat-list/ChatList.d.ts +18 -9
  17. package/dist/components/chat-list/formatChatTime.d.ts +3 -3
  18. package/dist/components/checkbox/Checkbox.d.ts +6 -1
  19. package/dist/components/color-field/ColorField.d.ts +1 -1
  20. package/dist/components/color-picker/ColorPicker.d.ts +6 -1
  21. package/dist/components/color-picker/ColorPresets.d.ts +9 -1
  22. package/dist/components/crossfade/Crossfade.d.ts +1 -1
  23. package/dist/components/data-table/ColumnsMenu.d.ts +16 -20
  24. package/dist/components/data-table/DataTable.d.ts +16 -11
  25. package/dist/components/data-table/Head.d.ts +10 -1
  26. package/dist/components/data-table/Row.d.ts +7 -1
  27. package/dist/components/data-table/StateRows.d.ts +3 -1
  28. package/dist/components/data-table/types.d.ts +5 -0
  29. package/dist/components/digit-input/DigitInput.d.ts +1 -1
  30. package/dist/components/drawer/Drawer.d.ts +3 -2
  31. package/dist/components/field-list/FieldList.d.ts +24 -12
  32. package/dist/components/hint/Hint.d.ts +8 -2
  33. package/dist/components/index.d.ts +7 -4
  34. package/dist/components/input/Input.d.ts +27 -5
  35. package/dist/components/input/inputSuggestions.d.ts +39 -0
  36. package/dist/components/kanban/Kanban.d.ts +8 -9
  37. package/dist/components/list/List.d.ts +25 -6
  38. package/dist/components/message/Message.d.ts +15 -3
  39. package/dist/components/message/MessageSticker.d.ts +27 -0
  40. package/dist/components/message/formatMessageTime.d.ts +5 -2
  41. package/dist/components/modal/Modal.d.ts +3 -2
  42. package/dist/components/native-select/NativeSelect.d.ts +1 -1
  43. package/dist/components/radio/Radio.d.ts +11 -2
  44. package/dist/components/rich-text/RichText.d.ts +23 -0
  45. package/dist/components/scroll-container/ScrollContainer.d.ts +1 -1
  46. package/dist/components/scroll-container/scrollGlide.d.ts +26 -0
  47. package/dist/components/scroll-container/useScrollMotion.d.ts +25 -0
  48. package/dist/components/segmented-control/SegmentedControl.d.ts +1 -1
  49. package/dist/components/select/selectContext.d.ts +7 -0
  50. package/dist/components/slider/Slider.d.ts +1 -1
  51. package/dist/components/switch/Switch.d.ts +6 -1
  52. package/dist/components/tag-select/TagSelect.d.ts +1 -1
  53. package/dist/components/textarea/Textarea.d.ts +6 -1
  54. package/dist/components/timeline/Timeline.d.ts +1 -1
  55. package/dist/icon-set.js +2 -2
  56. package/dist/index.css +1 -1
  57. package/dist/index.js +5 -3
  58. package/dist/internal/ChoiceField.d.ts +3 -1
  59. package/dist/internal/FieldFrame.d.ts +8 -2
  60. package/dist/internal/fieldCell.d.ts +7 -1
  61. package/dist/internal/formatClock.d.ts +23 -2
  62. package/dist/internal/leaveGuard.d.ts +27 -0
  63. package/dist/internal/messageList.d.ts +2 -0
  64. package/dist/internal/overlay/DialogGuard.d.ts +3 -2
  65. package/dist/internal/overlay/DialogParts.d.ts +40 -6
  66. package/dist/internal/swatch.d.ts +5 -0
  67. package/dist/internal/tokenDefaults.d.ts +1 -0
  68. package/dist/layout/index.d.ts +1 -1
  69. package/dist/layout/page/Page.d.ts +48 -15
  70. package/dist/skill/anti-slop.md +28 -0
  71. package/dist/skill/api-contract.md +14 -7
  72. package/dist/skill/cheatsheet.md +28 -9
  73. package/dist/skill/checklist.md +9 -0
  74. package/dist/skill/choosing.md +25 -12
  75. package/dist/skill/components.md +1 -0
  76. package/dist/skill/composition.md +88 -16
  77. package/dist/skill/layouts.md +6 -4
  78. package/dist/skill/reference/components/badge/COMPONENT.md +14 -1
  79. package/dist/skill/reference/components/badge/examples/examples.module.css +7 -0
  80. package/dist/skill/reference/components/badge/examples/tag-row.tsx +34 -0
  81. package/dist/skill/reference/components/breadcrumb/COMPONENT.md +9 -4
  82. package/dist/skill/reference/components/breadcrumb/examples/router.tsx +17 -0
  83. package/dist/skill/reference/components/button/COMPONENT.md +1 -1
  84. package/dist/skill/reference/components/button-group/COMPONENT.md +1 -0
  85. package/dist/skill/reference/components/card/COMPONENT.md +7 -1
  86. package/dist/skill/reference/components/card/examples/states.tsx +59 -0
  87. package/dist/skill/reference/components/chat/COMPONENT.md +4 -1
  88. package/dist/skill/reference/components/chat/examples/time-zone.tsx +83 -0
  89. package/dist/skill/reference/components/chat-list/COMPONENT.md +12 -6
  90. package/dist/skill/reference/components/chat-list/examples/links.tsx +1 -1
  91. package/dist/skill/reference/components/chat-list/examples/router.tsx +63 -0
  92. package/dist/skill/reference/components/checkbox/COMPONENT.md +1 -0
  93. package/dist/skill/reference/components/color-field/COMPONENT.md +2 -1
  94. package/dist/skill/reference/components/color-picker/COMPONENT.md +14 -5
  95. package/dist/skill/reference/components/color-picker/examples/presets-custom.tsx +31 -0
  96. package/dist/skill/reference/components/color-swatches/COMPONENT.md +1 -0
  97. package/dist/skill/reference/components/confirm-dialog/COMPONENT.md +1 -1
  98. package/dist/skill/reference/components/crossfade/COMPONENT.md +1 -1
  99. package/dist/skill/reference/components/data-table/COMPONENT.md +46 -41
  100. package/dist/skill/reference/components/data-table/examples/actions-column.tsx +154 -0
  101. package/dist/skill/reference/components/data-table/examples/columns-visibility.tsx +3 -12
  102. package/dist/skill/reference/components/data-table/examples/controlled.tsx +1 -1
  103. package/dist/skill/reference/components/data-table/examples/narrow.tsx +4 -11
  104. package/dist/skill/reference/components/data-table/examples/numeric.tsx +9 -2
  105. package/dist/skill/reference/components/data-table/examples/row-link.tsx +18 -22
  106. package/dist/skill/reference/components/data-table/examples/screen.tsx +12 -1
  107. package/dist/skill/reference/components/data-table/examples/toolbar.tsx +26 -32
  108. package/dist/skill/reference/components/datepicker/COMPONENT.md +3 -1
  109. package/dist/skill/reference/components/datepicker/examples/deadline.tsx +33 -0
  110. package/dist/skill/reference/components/digit-input/COMPONENT.md +1 -0
  111. package/dist/skill/reference/components/dnd/COMPONENT.md +4 -3
  112. package/dist/skill/reference/components/dnd/examples/examples.module.css +4 -3
  113. package/dist/skill/reference/components/dnd/examples/handle.tsx +5 -5
  114. package/dist/skill/reference/components/dnd/examples/locked.tsx +1 -1
  115. package/dist/skill/reference/components/dnd/examples/table.tsx +6 -6
  116. package/dist/skill/reference/components/drawer/COMPONENT.md +38 -9
  117. package/dist/skill/reference/components/drawer/examples/client-card.tsx +32 -8
  118. package/dist/skill/reference/components/drawer/examples/header-actions.tsx +1 -1
  119. package/dist/skill/reference/components/drawer/examples/loading.tsx +58 -0
  120. package/dist/skill/reference/components/field-list/COMPONENT.md +40 -24
  121. package/dist/skill/reference/components/field-list/examples/base-row.tsx +2 -1
  122. package/dist/skill/reference/components/field-list/examples/locked.tsx +11 -11
  123. package/dist/skill/reference/components/field-list/examples/reorder.tsx +1 -1
  124. package/dist/skill/reference/components/field-list/examples/saving.tsx +83 -0
  125. package/dist/skill/reference/components/field-list/examples/screen.module.css +1 -1
  126. package/dist/skill/reference/components/field-list/examples/screen.tsx +168 -162
  127. package/dist/skill/reference/components/field-list/examples/totals.tsx +83 -0
  128. package/dist/skill/reference/components/file-upload/COMPONENT.md +1 -0
  129. package/dist/skill/reference/components/hint/COMPONENT.md +16 -2
  130. package/dist/skill/reference/components/hint/examples/variants.tsx +48 -0
  131. package/dist/skill/reference/components/input/COMPONENT.md +39 -9
  132. package/dist/skill/reference/components/input/examples/affixes.tsx +4 -2
  133. package/dist/skill/reference/components/input/examples/dismiss.tsx +29 -0
  134. package/dist/skill/reference/components/input/examples/suggestions.tsx +26 -0
  135. package/dist/skill/reference/components/input/examples/time.tsx +24 -0
  136. package/dist/skill/reference/components/input/examples/with-select.tsx +44 -0
  137. package/dist/skill/reference/components/kanban/COMPONENT.md +12 -8
  138. package/dist/skill/reference/components/kanban/examples/columns.tsx +4 -2
  139. package/dist/skill/reference/components/kanban/examples/states.tsx +7 -5
  140. package/dist/skill/reference/components/list/COMPONENT.md +39 -13
  141. package/dist/skill/reference/components/list/examples/reorder.tsx +42 -7
  142. package/dist/skill/reference/components/list/examples/row-controls.tsx +80 -0
  143. package/dist/skill/reference/components/list/examples/with-icon.tsx +23 -2
  144. package/dist/skill/reference/components/login-form/COMPONENT.md +8 -7
  145. package/dist/skill/reference/components/login-form/examples/states.tsx +12 -14
  146. package/dist/skill/reference/components/message/COMPONENT.md +30 -9
  147. package/dist/skill/reference/components/message/examples/preview.tsx +28 -0
  148. package/dist/skill/reference/components/message/examples/sticker.tsx +35 -0
  149. package/dist/skill/reference/components/modal/COMPONENT.md +35 -10
  150. package/dist/skill/reference/components/modal/examples/long-content.tsx +37 -18
  151. package/dist/skill/reference/components/native-select/COMPONENT.md +1 -0
  152. package/dist/skill/reference/components/notification/COMPONENT.md +1 -1
  153. package/dist/skill/reference/components/radio/COMPONENT.md +2 -0
  154. package/dist/skill/reference/components/rich-text/COMPONENT.md +93 -0
  155. package/dist/skill/reference/components/rich-text/examples/overview.tsx +19 -0
  156. package/dist/skill/reference/components/scroll-container/COMPONENT.md +8 -5
  157. package/dist/skill/reference/components/segmented-control/COMPONENT.md +4 -2
  158. package/dist/skill/reference/components/segmented-control/examples/in-form.tsx +1 -1
  159. package/dist/skill/reference/components/select/COMPONENT.md +7 -3
  160. package/dist/skill/reference/components/sheet/COMPONENT.md +18 -7
  161. package/dist/skill/reference/components/slider/COMPONENT.md +1 -0
  162. package/dist/skill/reference/components/slider/examples/controlled.tsx +1 -1
  163. package/dist/skill/reference/components/switch/COMPONENT.md +1 -0
  164. package/dist/skill/reference/components/tag-select/COMPONENT.md +1 -0
  165. package/dist/skill/reference/components/textarea/COMPONENT.md +1 -0
  166. package/dist/skill/reference/components/timeline/COMPONENT.md +3 -3
  167. package/dist/skill/reference/components/timeline/examples/structure.tsx +2 -1
  168. package/dist/skill/reference/layout/app-shell/COMPONENT.md +2 -2
  169. package/dist/skill/reference/layout/bottom-nav/COMPONENT.md +1 -0
  170. package/dist/skill/reference/layout/page/COMPONENT.md +42 -20
  171. package/dist/skill/reference/layout/page/examples/examples.module.css +7 -0
  172. package/dist/skill/reference/layout/page/examples/guard.tsx +87 -0
  173. package/dist/skill/reference/layout/page/examples/loading.tsx +57 -0
  174. package/dist/skill/reference/layout/page/examples/screen.module.css +1 -1
  175. package/dist/skill/reference/layout/page/examples/screen.tsx +93 -104
  176. package/dist/skill/reference/layout/page/examples/sections.tsx +2 -15
  177. package/dist/skill/reference/layout/sidebar/COMPONENT.md +1 -0
  178. package/dist/skill/responsive.md +19 -12
  179. package/dist/skill/ux.md +5 -3
  180. package/dist/tokens/semantic.d.ts +3 -1
  181. package/dist/tokens/themes/dark.d.ts +1 -1
  182. package/package.json +2 -2
  183. package/src/components/badge/COMPONENT.md +14 -1
  184. package/src/components/badge/examples/examples.module.css +7 -0
  185. package/src/components/badge/examples/tag-row.tsx +34 -0
  186. package/src/components/breadcrumb/COMPONENT.md +9 -4
  187. package/src/components/breadcrumb/examples/router.tsx +17 -0
  188. package/src/components/button/COMPONENT.md +1 -1
  189. package/src/components/button-group/COMPONENT.md +1 -0
  190. package/src/components/card/COMPONENT.md +7 -1
  191. package/src/components/card/examples/states.tsx +59 -0
  192. package/src/components/chat/COMPONENT.md +4 -1
  193. package/src/components/chat/examples/time-zone.tsx +83 -0
  194. package/src/components/chat-list/COMPONENT.md +12 -6
  195. package/src/components/chat-list/examples/links.tsx +1 -1
  196. package/src/components/chat-list/examples/router.tsx +63 -0
  197. package/src/components/checkbox/COMPONENT.md +1 -0
  198. package/src/components/color-field/COMPONENT.md +2 -1
  199. package/src/components/color-picker/COMPONENT.md +14 -5
  200. package/src/components/color-picker/examples/presets-custom.tsx +31 -0
  201. package/src/components/color-swatches/COMPONENT.md +1 -0
  202. package/src/components/confirm-dialog/COMPONENT.md +1 -1
  203. package/src/components/crossfade/COMPONENT.md +1 -1
  204. package/src/components/data-table/COMPONENT.md +46 -41
  205. package/src/components/data-table/examples/actions-column.tsx +154 -0
  206. package/src/components/data-table/examples/columns-visibility.tsx +3 -12
  207. package/src/components/data-table/examples/controlled.tsx +1 -1
  208. package/src/components/data-table/examples/narrow.tsx +4 -11
  209. package/src/components/data-table/examples/numeric.tsx +9 -2
  210. package/src/components/data-table/examples/row-link.tsx +18 -22
  211. package/src/components/data-table/examples/screen.tsx +12 -1
  212. package/src/components/data-table/examples/toolbar.tsx +26 -32
  213. package/src/components/datepicker/COMPONENT.md +3 -1
  214. package/src/components/datepicker/examples/deadline.tsx +33 -0
  215. package/src/components/digit-input/COMPONENT.md +1 -0
  216. package/src/components/dnd/COMPONENT.md +4 -3
  217. package/src/components/dnd/examples/examples.module.css +4 -3
  218. package/src/components/dnd/examples/handle.tsx +5 -5
  219. package/src/components/dnd/examples/locked.tsx +1 -1
  220. package/src/components/dnd/examples/table.tsx +6 -6
  221. package/src/components/drawer/COMPONENT.md +38 -9
  222. package/src/components/drawer/examples/client-card.tsx +32 -8
  223. package/src/components/drawer/examples/header-actions.tsx +1 -1
  224. package/src/components/drawer/examples/loading.tsx +58 -0
  225. package/src/components/field-list/COMPONENT.md +40 -24
  226. package/src/components/field-list/examples/base-row.tsx +2 -1
  227. package/src/components/field-list/examples/locked.tsx +11 -11
  228. package/src/components/field-list/examples/reorder.tsx +1 -1
  229. package/src/components/field-list/examples/saving.tsx +83 -0
  230. package/src/components/field-list/examples/screen.module.css +1 -1
  231. package/src/components/field-list/examples/screen.tsx +168 -162
  232. package/src/components/field-list/examples/totals.tsx +83 -0
  233. package/src/components/file-upload/COMPONENT.md +1 -0
  234. package/src/components/hint/COMPONENT.md +16 -2
  235. package/src/components/hint/examples/variants.tsx +48 -0
  236. package/src/components/input/COMPONENT.md +39 -9
  237. package/src/components/input/examples/affixes.tsx +4 -2
  238. package/src/components/input/examples/dismiss.tsx +29 -0
  239. package/src/components/input/examples/suggestions.tsx +26 -0
  240. package/src/components/input/examples/time.tsx +24 -0
  241. package/src/components/input/examples/with-select.tsx +44 -0
  242. package/src/components/kanban/COMPONENT.md +12 -8
  243. package/src/components/kanban/examples/columns.tsx +4 -2
  244. package/src/components/kanban/examples/states.tsx +7 -5
  245. package/src/components/list/COMPONENT.md +39 -13
  246. package/src/components/list/examples/reorder.tsx +42 -7
  247. package/src/components/list/examples/row-controls.tsx +80 -0
  248. package/src/components/list/examples/with-icon.tsx +23 -2
  249. package/src/components/login-form/COMPONENT.md +8 -7
  250. package/src/components/login-form/examples/states.tsx +12 -14
  251. package/src/components/message/COMPONENT.md +30 -9
  252. package/src/components/message/examples/preview.tsx +28 -0
  253. package/src/components/message/examples/sticker.tsx +35 -0
  254. package/src/components/modal/COMPONENT.md +35 -10
  255. package/src/components/modal/examples/long-content.tsx +37 -18
  256. package/src/components/native-select/COMPONENT.md +1 -0
  257. package/src/components/notification/COMPONENT.md +1 -1
  258. package/src/components/radio/COMPONENT.md +2 -0
  259. package/src/components/rich-text/COMPONENT.md +93 -0
  260. package/src/components/rich-text/examples/overview.tsx +19 -0
  261. package/src/components/scroll-container/COMPONENT.md +8 -5
  262. package/src/components/segmented-control/COMPONENT.md +4 -2
  263. package/src/components/segmented-control/examples/in-form.tsx +1 -1
  264. package/src/components/select/COMPONENT.md +7 -3
  265. package/src/components/sheet/COMPONENT.md +18 -7
  266. package/src/components/slider/COMPONENT.md +1 -0
  267. package/src/components/slider/examples/controlled.tsx +1 -1
  268. package/src/components/switch/COMPONENT.md +1 -0
  269. package/src/components/tag-select/COMPONENT.md +1 -0
  270. package/src/components/textarea/COMPONENT.md +1 -0
  271. package/src/components/timeline/COMPONENT.md +3 -3
  272. package/src/components/timeline/examples/structure.tsx +2 -1
  273. package/src/layout/app-shell/COMPONENT.md +2 -2
  274. package/src/layout/bottom-nav/COMPONENT.md +1 -0
  275. package/src/layout/page/COMPONENT.md +42 -20
  276. package/src/layout/page/examples/examples.module.css +7 -0
  277. package/src/layout/page/examples/guard.tsx +87 -0
  278. package/src/layout/page/examples/loading.tsx +57 -0
  279. package/src/layout/page/examples/screen.module.css +1 -1
  280. package/src/layout/page/examples/screen.tsx +93 -104
  281. package/src/layout/page/examples/sections.tsx +2 -15
  282. package/src/layout/sidebar/COMPONENT.md +1 -0
  283. package/src/styles/theme-dark.css +1 -1
  284. package/src/styles/theme-light.css +2 -1
  285. package/dist/components/data-table/context.d.ts +0 -14
  286. package/dist/components/scroll-container/useWheelToInline.d.ts +0 -10
package/dist/index.js CHANGED
@@ -46,6 +46,7 @@ import {
46
46
  Pagination,
47
47
  ProgressCircle,
48
48
  Radio,
49
+ RichText,
49
50
  SegmentedControl,
50
51
  Sheet,
51
52
  Sidebar,
@@ -86,7 +87,7 @@ import {
86
87
  useSidebar,
87
88
  useTokenValue,
88
89
  useUploadQueue
89
- } from "./chunks/chunk-A4WE3UNC.js";
90
+ } from "./chunks/chunk-WYCTXD63.js";
90
91
  import {
91
92
  Avatar,
92
93
  Badge,
@@ -121,11 +122,11 @@ import {
121
122
  tierMappings,
122
123
  tones,
123
124
  variants
124
- } from "./chunks/chunk-7WWZYGRC.js";
125
+ } from "./chunks/chunk-RZNGLELR.js";
125
126
  import {
126
127
  ControlSizeProvider,
127
128
  useOptionalControlSize
128
- } from "./chunks/chunk-2ODXLPW3.js";
129
+ } from "./chunks/chunk-QFHE5GKW.js";
129
130
  export {
130
131
  Accordion,
131
132
  AppShell,
@@ -188,6 +189,7 @@ export {
188
189
  ProgressBar,
189
190
  ProgressCircle,
190
191
  Radio,
192
+ RichText,
191
193
  ScrollContainer,
192
194
  SegmentedControl,
193
195
  Select,
@@ -1,4 +1,5 @@
1
1
  import * as React from "react";
2
+ import type { HintTone } from "../components/hint/Hint";
2
3
  import { type FieldIds } from "./FieldFrame";
3
4
  import type { CheckState, ControlSize } from "./states";
4
5
  /** Class of the visually hidden native input that sits on top of the visual control. */
@@ -38,13 +39,14 @@ type ChoiceFieldProps = {
38
39
  */
39
40
  groupOption?: boolean;
40
41
  hint?: React.ReactNode;
42
+ hintTone?: HintTone;
41
43
  error?: React.ReactNode;
42
44
  /** The native input (with `choiceInputClass`) followed by its aria-hidden visual. */
43
45
  control: React.ReactNode;
44
46
  className?: string;
45
47
  children?: React.ReactNode;
46
48
  };
47
- export declare function ChoiceField({ ids, size, state, disabled, readOnly, busy, required, optional, optionalLabel, groupOption, hint, error, control, className, children, }: ChoiceFieldProps): import("react/jsx-runtime").JSX.Element;
49
+ export declare function ChoiceField({ ids, size, state, disabled, readOnly, busy, required, optional, optionalLabel, groupOption, hint, hintTone, error, control, className, children, }: ChoiceFieldProps): import("react/jsx-runtime").JSX.Element;
48
50
  export type ChoiceLabelProps = React.HTMLAttributes<HTMLSpanElement> & {
49
51
  ref?: React.Ref<HTMLSpanElement>;
50
52
  };
@@ -1,4 +1,5 @@
1
1
  import * as React from "react";
2
+ import { type HintTone } from "../components/hint/Hint";
2
3
  import type { ControlSize } from "./states";
3
4
  /** Field props shared by every framed field (the same contract as `Input.Root`). */
4
5
  export type FieldFrameProps = {
@@ -18,6 +19,10 @@ export type FieldFrameProps = {
18
19
  * Support text under the field; linked by `aria-describedby`.
19
20
  */
20
21
  hint?: React.ReactNode;
22
+ /**
23
+ * Status color of `hint` («Осталось 12 дней» in `warning`). The words carry the status, the color repeats it; an `error` replaces the hint and its tone. A validation error is `error`, never a `danger` hint.
24
+ */
25
+ hintTone?: HintTone;
21
26
  /**
22
27
  * Error message; replaces the hint and implies `invalid`.
23
28
  */
@@ -121,10 +126,11 @@ export declare function useLeavingError(showError: boolean, error: React.ReactNo
121
126
  * changes is read, an error the field mounts with is read with the field (`aria-describedby`).
122
127
  * An option of a group (`live={false}`) leaves the announcement to the group.
123
128
  */
124
- export declare function FieldSupport({ ids, size, hint, error, leaving, disabled, live, className, textClassName, }: {
129
+ export declare function FieldSupport({ ids, size, hint, hintTone, error, leaving, disabled, live, className, textClassName, }: {
125
130
  ids: FieldIds;
126
131
  size: ControlSize;
127
132
  hint?: React.ReactNode;
133
+ hintTone?: HintTone;
128
134
  error?: React.ReactNode;
129
135
  /** The error leaving the slot: the frame's `useLeavingError`. */
130
136
  leaving: FieldLeavingError | null;
@@ -166,7 +172,7 @@ type FieldFrameRenderProps = FieldFrameProps & {
166
172
  * spaced by the tier's `--field-label-gap` / `--field-hint-gap`. The support row stays mounted
167
173
  * (empty and without room when it shows nothing), so its text slot is a polite live region.
168
174
  */
169
- export declare function FieldFrame({ size, ids, label, required, optional, hint, error, disabled, optionalLabel, requiredLabel, group, labelEnd, counter, reserveSupportRow, className, children, ...rest }: FieldFrameRenderProps): import("react/jsx-runtime").JSX.Element;
175
+ export declare function FieldFrame({ size, ids, label, required, optional, hint, hintTone, error, disabled, optionalLabel, requiredLabel, group, labelEnd, counter, reserveSupportRow, className, children, ...rest }: FieldFrameRenderProps): import("react/jsx-runtime").JSX.Element;
170
176
  type FieldCounterProps = Omit<React.HTMLAttributes<HTMLSpanElement>, "children"> & {
171
177
  current: number;
172
178
  max: number;
@@ -4,7 +4,7 @@ import * as React from "react";
4
4
  * a framed field without a `label` of its own takes it as its label (and keeps its own `label`, if
5
5
  * any), so every field in a row has a name without a visible label per row. The column heading
6
6
  * shows the name once above the rows; the field's label is read, not shown, until the list stacks
7
- * its rows into blocks in a narrow container (the `prime-field-list` container FieldList sets),
7
+ * its rows into blocks in a narrow container (the size container of the FieldList body),
8
8
  * where each field shows it.
9
9
  */
10
10
  export type FieldCell = {
@@ -17,6 +17,12 @@ export type FieldCell = {
17
17
  hidden: "wide" | "always";
18
18
  /** The column is required: the field in the cell is required too (`useFieldFrame`). */
19
19
  required: boolean;
20
+ /**
21
+ * The row's action the field holds at its end: a one-column list puts each row's remove button
22
+ * inside its field. A text field (`Input.Wrapper`, `Textarea`) renders it as its last action
23
+ * segment; a list whose field holds none keeps the remove in a column of its own.
24
+ */
25
+ action?: React.ReactNode;
20
26
  };
21
27
  export declare const FieldCellContext: React.Context<FieldCell | null>;
22
28
  export declare function useFieldCell(): FieldCell | null;
@@ -1,4 +1,25 @@
1
1
  /** A media position or length: `m:ss`, `h:mm:ss` from an hour on. */
2
2
  export declare function formatClock(seconds: number): string;
3
- /** A time of day: `HH:mm`, 24-hour, in the local zone («09:05»). */
4
- export declare function formatTimeOfDay(date: Date): string;
3
+ /** A calendar day: the month 0–11, as `Date#getMonth`. */
4
+ type CalendarDay = {
5
+ year: number;
6
+ month: number;
7
+ day: number;
8
+ };
9
+ /** The calendar day and the clock of a moment as a time zone reads it. */
10
+ type ZonedParts = CalendarDay & {
11
+ /** 0 (Sunday) – 6, as `Date#getDay`. */
12
+ weekday: number;
13
+ hours: number;
14
+ minutes: number;
15
+ };
16
+ /**
17
+ * The day and the clock of `date` in `timeZone` (an IANA name, `"Asia/Vladivostok"`); without one,
18
+ * in the browser's zone.
19
+ */
20
+ export declare function zonedParts(date: Date, timeZone?: string): ZonedParts;
21
+ /** Whole calendar days from `from` to `to` (both read in one zone); never off by a DST hour. */
22
+ export declare function daysBetween(from: CalendarDay, to: CalendarDay): number;
23
+ /** A time of day: `HH:mm`, 24-hour, in `timeZone` or the browser's zone («09:05»). */
24
+ export declare function formatTimeOfDay(date: Date, timeZone?: string): string;
25
+ export {};
@@ -0,0 +1,27 @@
1
+ import * as React from "react";
2
+ /** What holds a page: a request runs (`busy`), changes are not saved (`dirty`). */
3
+ type LeaveGuardState = {
4
+ busy: boolean;
5
+ dirty: boolean;
6
+ };
7
+ /**
8
+ * The `onClickCapture` of a navigation item (`Sidebar.Item`, `BottomNav.Item`, a `Breadcrumb.Item`
9
+ * level), chained before the consumer's own. While a page guard holds, the click stops before any
10
+ * handler of the item or of its router link runs and before the browser follows `href`: `busy`
11
+ * holds it, `dirty` asks the guard's confirm, which replays the click once the person agrees.
12
+ * Router-agnostic: the replay is the same click. A click that opens a new tab or window, or one on
13
+ * a disabled item, is never held.
14
+ */
15
+ export declare function leaveGuardCapture(onClickCapture?: React.MouseEventHandler<HTMLElement>): React.MouseEventHandler<HTMLElement>;
16
+ /**
17
+ * Registers a page guard while mounted: the navigation items ask it through `holdLeave`, and while
18
+ * it is `busy` or `dirty` the browser asks before the tab closes or reloads (`beforeunload`).
19
+ */
20
+ export declare function useLeaveGuard({ busy, dirty }: LeaveGuardState, ask: (leave: () => void) => void): void;
21
+ /**
22
+ * While `hold` is true the browser asks before the tab closes or reloads (`beforeunload`): a page
23
+ * guard, and a dialog guard (`Modal.Guard`, `Drawer.Guard`, `Sheet.Guard`) whose form is not saved.
24
+ * `released` lets a leave the person already agreed to go without a second prompt.
25
+ */
26
+ export declare function useUnloadGuard(hold: boolean, released?: () => boolean): void;
27
+ export {};
@@ -66,6 +66,8 @@ export type MessageListContextValue = {
66
66
  reactionOptions: readonly MessageReactionOption[] | null;
67
67
  /** The reader: joins a reaction's avatars at once when they put it. */
68
68
  reader: MessageUser | undefined;
69
+ /** The zone a message reads its time in; `undefined` — the browser's zone. */
70
+ timeZone: string | undefined;
69
71
  /** Says `text` in the list's polite live region. */
70
72
  announce: (text: string) => void;
71
73
  };
@@ -10,8 +10,9 @@ export type DialogGuardProps = {
10
10
  };
11
11
  /**
12
12
  * Holds a Modal, Drawer or Sheet from inside its content, where the form state lives: put it anywhere in
13
- * `Content`. Renders nothing but the «discard changes?» confirm when it is asked. Closing from code
14
- * (`open={false}`) is never held.
13
+ * `Content`. Renders nothing but the «discard changes?» confirm when it is asked. While `busy` or
14
+ * `dirty` the browser also asks before the tab closes or reloads, as `Page.Guard` does. Closing from
15
+ * code (`open={false}`) is never held.
15
16
  */
16
17
  export declare function DialogGuard({ busy, dirty }: DialogGuardProps): import("react/jsx-runtime").JSX.Element;
17
18
  export declare namespace DialogGuard {
@@ -148,9 +148,17 @@ export declare namespace DialogTitle {
148
148
  var displayName: string;
149
149
  }
150
150
  export type DialogDescriptionProps = Omit<React.HTMLAttributes<HTMLParagraphElement>, "id"> & {
151
+ /**
152
+ * Its data loads: a `Skeleton` holds the line's place and `aria-busy` is set, so the header never moves; the data fades in.
153
+ */
154
+ loading?: boolean;
151
155
  ref?: React.Ref<HTMLParagraphElement>;
152
156
  };
153
- export declare function DialogDescription({ className, ...rest }: DialogDescriptionProps): import("react/jsx-runtime").JSX.Element;
157
+ /**
158
+ * The line under the title. While its data loads (`loading`) it keeps its place with a Skeleton, so
159
+ * the header never moves when the data arrives; the data then fades in under the same element.
160
+ */
161
+ export declare function DialogDescription({ loading, className, children, ...rest }: DialogDescriptionProps): import("react/jsx-runtime").JSX.Element;
154
162
  export declare namespace DialogDescription {
155
163
  var displayName: string;
156
164
  }
@@ -163,9 +171,10 @@ export type DialogHeaderProps = React.HTMLAttributes<HTMLElement> & {
163
171
  };
164
172
  /**
165
173
  * `[Icon] [Title + Description] [Actions] [close]` in one row. Layout is a CSS grid, so child
166
- * order does not matter; text children stack in the text column.
174
+ * order does not matter; text children stack in the text column. When the row is too narrow for
175
+ * the title beside the actions (a phone), the actions move under the text.
167
176
  */
168
- export declare function DialogHeader({ showClose, className, children, ...rest }: DialogHeaderProps): import("react/jsx-runtime").JSX.Element;
177
+ export declare function DialogHeader({ showClose, className, children, ref, ...rest }: DialogHeaderProps): import("react/jsx-runtime").JSX.Element;
169
178
  export declare namespace DialogHeader {
170
179
  var displayName: string;
171
180
  }
@@ -188,15 +197,40 @@ export declare function DialogBody({ className, ...rest }: DialogBodyProps): imp
188
197
  export declare namespace DialogBody {
189
198
  var displayName: string;
190
199
  }
200
+ export type DialogSectionProps = Omit<React.HTMLAttributes<HTMLElement>, "title"> & {
201
+ /**
202
+ * The heading of the section; it names the `<section>`.
203
+ */
204
+ label: React.ReactNode;
205
+ /**
206
+ * One line of context under the heading (body-s).
207
+ */
208
+ description?: React.ReactNode;
209
+ ref?: React.Ref<HTMLElement>;
210
+ };
211
+ /**
212
+ * A titled group of the dialog body — what `Page.Section` is to a page: an `<h3>` (title-s, one
213
+ * level under the dialog's `<h2>` title) with an optional description and the dialog's `Actions`
214
+ * at the end of the heading row, then the content 16 below. Sections stand further apart than the
215
+ * plain blocks of the body.
216
+ */
217
+ export declare function DialogSection({ label, description, className, children, ref, ...rest }: DialogSectionProps): import("react/jsx-runtime").JSX.Element;
218
+ export declare namespace DialogSection {
219
+ var displayName: string;
220
+ }
191
221
  export type DialogFooterProps = React.HTMLAttributes<HTMLElement> & {
192
222
  /**
193
- * `fill`: equal-width buttons in one row; `end`: auto width, at the end. Stacked on phones (viewport below 640 px) and in a dialog narrower than 360 px.
223
+ * `fill`: equal-width buttons in one row, wrapping rather than cutting a label; `end`: auto width, at the end. Stacked on phones (viewport below 640 px) and in a dialog narrower than 360 px.
194
224
  */
195
225
  layout?: DialogFooterLayout;
196
226
  ref?: React.Ref<HTMLElement>;
197
227
  };
198
- /** Actions in DOM order, primary last. Stacks full width when the dialog is narrower than 360px. */
199
- export declare function DialogFooter({ layout, className, ...rest }: DialogFooterProps): import("react/jsx-runtime").JSX.Element;
228
+ /**
229
+ * Actions in DOM order, primary last. Stacks full width when the dialog is narrower than 360px.
230
+ * With a `Meta` the buttons move as one row: when the line runs short the status text goes above
231
+ * them first, so the buttons never split over two lines while there is room for them in one.
232
+ */
233
+ export declare function DialogFooter({ layout, className, children, ...rest }: DialogFooterProps): import("react/jsx-runtime").JSX.Element;
200
234
  export declare namespace DialogFooter {
201
235
  var displayName: string;
202
236
  }
@@ -86,6 +86,11 @@ type SwatchChipProps = Omit<React.HTMLAttributes<HTMLSpanElement>, "children"> &
86
86
  * host's `--prime-icon-size`, with the faint inner edge; `aria-hidden` — the trigger is named.
87
87
  */
88
88
  export declare function SwatchChip({ value, className, ...rest }: SwatchChipProps): import("react/jsx-runtime").JSX.Element;
89
+ /**
90
+ * A typed hex color as `#rrggbb` (lowercase): `#` optional, 3 or 6 digits, spaces around ignored;
91
+ * `null` for anything else.
92
+ */
93
+ export declare function parseHexColor(text: string): string | null;
89
94
  /** Case- and space-insensitive color comparison; `null` means "no color". */
90
95
  export declare function sameColor(a: string | null, b: string | null): boolean;
91
96
  /**
@@ -6,6 +6,7 @@
6
6
  */
7
7
  export declare const TOKEN_DEFAULTS: {
8
8
  readonly "--prime-gallery-max-size": 360;
9
+ readonly "--prime-message-sticker": 160;
9
10
  readonly "--prime-message-video-note-box": 268;
10
11
  readonly "--prime-motion-duration-base": 380;
11
12
  readonly "--prime-motion-duration-fast": 230;
@@ -2,7 +2,7 @@ export type { AppShellFooterProps, AppShellMainProps, AppShellNavProps, AppShell
2
2
  export { AppShell, useAppShellNav } from "./app-shell/AppShell";
3
3
  export type { BottomNavActionProps, BottomNavItemCountProps, BottomNavItemIconProps, BottomNavItemProps, BottomNavLabels, BottomNavRootProps, } from "./bottom-nav/BottomNav";
4
4
  export { BottomNav } from "./bottom-nav/BottomNav";
5
- export type { PageActionsProps, PageBackButtonProps, PageBodyProps, PageCellProps, PageCellRows, PageCellSpan, PageChipsProps, PageDescriptionProps, PageDetailProps, PageGridProps, PageHeaderProps, PageHeadingProps, PageLabels, PageListProps, PageMaxWidth, PageRootProps, PageSectionLayout, PageSectionProps, PageSplitProps, PageTitleProps, PageToolsProps, PageTopBarProps, } from "./page/Page";
5
+ export type { PageActionsProps, PageBackButtonProps, PageBodyProps, PageCellProps, PageCellRows, PageCellSpan, PageChipsProps, PageDescriptionProps, PageDetailProps, PageGridProps, PageGuardProps, PageHeaderProps, PageHeadingProps, PageLabels, PageListProps, PageMaxWidth, PageRootProps, PageSectionProps, PageSplitProps, PageTitleProps, PageToolsProps, PageTopBarProps, } from "./page/Page";
6
6
  export { Page } from "./page/Page";
7
7
  export type { SidebarAccountProps, SidebarBrandLogoProps, SidebarBrandProps, SidebarContentProps, SidebarFooterProps, SidebarGroupProps, SidebarHeaderProps, SidebarItemActionProps, SidebarItemCountProps, SidebarItemIconProps, SidebarItemProps, SidebarItemShortcutProps, SidebarLabels, SidebarMode, SidebarRootProps, SidebarSubContentProps, SidebarSubProps, SidebarSubTriggerProps, SidebarToggleProps, } from "./sidebar/Sidebar";
8
8
  export { Sidebar, useSidebar } from "./sidebar/Sidebar";
@@ -6,6 +6,14 @@ export type PageLabels = {
6
6
  more: string;
7
7
  /** Name of `Page.BackButton` (back from the detail to the list on a narrow split). */
8
8
  back: string;
9
+ /** Title of the confirm `Page.Guard` opens when a person leaves a `dirty` page. */
10
+ leaveTitle: string;
11
+ /** Its description. */
12
+ leaveDescription: string;
13
+ /** Its confirm button: leave and lose the changes. */
14
+ leaveConfirm: string;
15
+ /** Its cancel button: stay on the page. */
16
+ leaveCancel: string;
9
17
  };
10
18
  export declare const PAGE_LABELS: PageLabels;
11
19
  type DivProps = React.HTMLAttributes<HTMLDivElement> & {
@@ -95,10 +103,14 @@ declare namespace PageTitle {
95
103
  var displayName: string;
96
104
  }
97
105
  export type PageDescriptionProps = React.HTMLAttributes<HTMLParagraphElement> & {
106
+ /**
107
+ * Its data is loading: a Skeleton keeps the line's place, so the title never moves; the data then fades in. Sets `aria-busy`.
108
+ */
109
+ loading?: boolean;
98
110
  ref?: React.Ref<HTMLParagraphElement>;
99
111
  };
100
112
  /** One line of context that carries data (a period, a count): truncates in the bar, wraps in the flow. */
101
- declare function PageDescription({ className, children, ...rest }: PageDescriptionProps): import("react/jsx-runtime").JSX.Element;
113
+ declare function PageDescription({ loading, className, children, ...rest }: PageDescriptionProps): import("react/jsx-runtime").JSX.Element;
102
114
  declare namespace PageDescription {
103
115
  var displayName: string;
104
116
  }
@@ -118,9 +130,10 @@ export type PageToolsProps = DivProps;
118
130
  /**
119
131
  * The page's tools — sections, search and filter, view — as kit controls in the order written.
120
132
  * On the bar's first line each keeps its natural width; on a line of their own they fill it:
121
- * a search (`SmartFilter.Toolbar`, `Input.Root`) takes the room first, switchers share the rest
122
- * (a `SegmentedControl.Root` is `fullWidth` unless set), and they wrap when one line is not
123
- * enough. Named (`aria-label`), it is a `group`.
133
+ * a search (`SmartFilter.Toolbar`, `Input.Root`) takes the room first, switchers and fields share
134
+ * the rest (a `SegmentedControl.Root` and a `Datepicker.Root` are `fullWidth` unless set; a Select
135
+ * trigger fills by itself), and they wrap when one line is not enough. Named (`aria-label`), it is
136
+ * a `group`.
124
137
  */
125
138
  declare function PageTools({ className, children, ref, ...rest }: PageToolsProps): import("react/jsx-runtime").JSX.Element;
126
139
  declare namespace PageTools {
@@ -138,8 +151,6 @@ declare function PageBody({ className, ...rest }: PageBodyProps): import("react/
138
151
  declare namespace PageBody {
139
152
  var displayName: string;
140
153
  }
141
- /** Where the heading of a section stands: over its content or in a column beside it. */
142
- export type PageSectionLayout = "stack" | "aside";
143
154
  export type PageSectionProps = Omit<React.HTMLAttributes<HTMLElement>, "title"> & {
144
155
  /**
145
156
  * The visible heading (`h2`); it also names the section.
@@ -149,10 +160,6 @@ export type PageSectionProps = Omit<React.HTMLAttributes<HTMLElement>, "title">
149
160
  * One line of context under the heading, in secondary body-s.
150
161
  */
151
162
  description?: React.ReactNode;
152
- /**
153
- * `stack` — the heading over the content; `aside` — a ~16rem heading column beside it (a settings page), above it once the content would get narrower than 30rem.
154
- */
155
- layout?: PageSectionLayout;
156
163
  ref?: React.Ref<HTMLElement>;
157
164
  };
158
165
  /**
@@ -160,16 +167,18 @@ export type PageSectionProps = Omit<React.HTMLAttributes<HTMLElement>, "title">
160
167
  * at its end) over its content. Sections stand further apart than the plain blocks of the body,
161
168
  * so the air shows where a new topic starts.
162
169
  */
163
- declare function PageSection({ label, description, layout, className, children, ...rest }: PageSectionProps): import("react/jsx-runtime").JSX.Element;
170
+ declare function PageSection({ label, description, className, children, ...rest }: PageSectionProps): import("react/jsx-runtime").JSX.Element;
164
171
  declare namespace PageSection {
165
172
  var displayName: string;
166
173
  }
167
174
  export type PageGridProps = DivProps;
168
175
  /**
169
176
  * The grid of the page's tiles (KPI cards, charts, panels): 12 columns, one gap on both axes.
170
- * Columns follow the grid's own width, so tiles fold on a narrow panel by themselves.
177
+ * Columns follow the grid's own width, so tiles fold on a narrow panel by themselves. A wide cell
178
+ * (span 7–11) written next to a narrow one (span 4–5) forms a pair that a mid-width grid lays out as
179
+ * 2/3 + 1/3, so the row keeps no hole.
171
180
  */
172
- declare function PageGrid({ className, ...rest }: PageGridProps): import("react/jsx-runtime").JSX.Element;
181
+ declare function PageGrid({ className, children, ...rest }: PageGridProps): import("react/jsx-runtime").JSX.Element;
173
182
  declare namespace PageGrid {
174
183
  var displayName: string;
175
184
  }
@@ -187,11 +196,34 @@ export type PageCellProps = DivProps & {
187
196
  */
188
197
  rows?: PageCellRows;
189
198
  };
190
- /** One tile place in `Page.Grid`; its child (a Card, a ChartFrame) fills it. */
191
- declare function PageCell({ span, rows, className, ...rest }: PageCellProps): import("react/jsx-runtime").JSX.Element;
199
+ /**
200
+ * One tile place in `Page.Grid`; its child (a Card, a ChartFrame) fills it. A `Crossfade` child
201
+ * fills it too (`fill` unless set), so a tile that swaps its states keeps the row's height.
202
+ */
203
+ declare function PageCell({ span, rows, className, children, ...rest }: PageCellProps): import("react/jsx-runtime").JSX.Element;
192
204
  declare namespace PageCell {
193
205
  var displayName: string;
194
206
  }
207
+ export type PageGuardProps = {
208
+ /**
209
+ * A request runs (a save): a press on those items does nothing until it ends; the browser asks before the tab closes.
210
+ */
211
+ busy?: boolean;
212
+ /**
213
+ * Changes are not saved: a press on those items asks «leave without saving?»; its confirm (`labels.leaveConfirm`) repeats the press, its cancel keeps the page. The browser asks before the tab closes.
214
+ */
215
+ dirty?: boolean;
216
+ };
217
+ /**
218
+ * Holds the page from where its form state lives: put it anywhere inside the page. While it holds,
219
+ * a press on a `Sidebar.Item`, a `BottomNav.Item` or a `Breadcrumb.Item` link stops before it
220
+ * navigates — `busy` holds it, `dirty` asks «leave without saving?» and replays the press once the
221
+ * person agrees — and the browser asks before the tab closes or reloads. Renders only the confirm.
222
+ */
223
+ declare function PageGuard({ busy, dirty }: PageGuardProps): import("react/jsx-runtime").JSX.Element;
224
+ declare namespace PageGuard {
225
+ var displayName: string;
226
+ }
195
227
  export type PageSplitProps = DivProps & {
196
228
  /**
197
229
  * The detail is open (a record is chosen), controlled. On a narrow split it takes the place of the list; on a wide one both panes stay.
@@ -255,6 +287,7 @@ export declare const Page: {
255
287
  Section: typeof PageSection;
256
288
  Grid: typeof PageGrid;
257
289
  Cell: typeof PageCell;
290
+ Guard: typeof PageGuard;
258
291
  Split: typeof PageSplit;
259
292
  List: typeof PageList;
260
293
  Detail: typeof PageDetail;
@@ -251,6 +251,11 @@ The same for one value in several units — one heading, the fields in a row, th
251
251
  | bars of dates drawn by hand, or a DataTable of start / end dates | `Gantt` |
252
252
  | a hand-made `<span>` hidden with CSS for screen readers | `<VisuallyHidden>` |
253
253
  | a `div` with `overflow: auto` | `ScrollContainer` (`edges`, `scrollbar="hidden"`, `snap`) |
254
+ | `scroll-snap-type` on a strip of cards | `ScrollContainer snap` (`"mandatory"` only where each child fills most of the view) |
255
+ | a flex row of Badges with its own gap | `Badge.Group` |
256
+ | a Switch or a ⋯ button inside a list row, or the row rebuilt as a `div` to hold them | `List.ItemActions` beside the row's element |
257
+ | a heading row (`Typography as="h3"` + buttons) over a group in a Drawer or a Modal | `Drawer.Section label` / `Modal.Section label` with `Drawer.Actions` / `Modal.Actions` |
258
+ | Markdown turned into HTML (`dangerouslySetInnerHTML`, a Markdown library) | `RichText` |
254
259
  | an `<img>` with your own radius and loading box | `Thumbnail.Root` / `Avatar.Root` |
255
260
  | a lightbox, or a Modal with an `<img>` | `Gallery` (opens `MediaViewer` itself) or `MediaViewer` |
256
261
  | a `position: fixed` bottom tab bar | `BottomNav` in `AppShell.Footer` |
@@ -287,6 +292,29 @@ The same for one value in several units — one heading, the fields in a row, th
287
292
  />
288
293
  ```
289
294
 
295
+ A bar above the table for a single button — the column chooser, an export — wastes a row and splits
296
+ the page's actions ([controls of a table](composition.md#controls-of-a-table)):
297
+
298
+ ```tsx partial
299
+ // bad — a toolbar that holds one control
300
+ <DataTable columns={columns} rows={orders} toolbar={<Button.Root>Колонки</Button.Root>} />
301
+ ```
302
+
303
+ ```tsx good
304
+ // good — the chooser sits in the header row; the page's own actions live in its top bar
305
+ // declare: const orders: { id: string; client: string; total: number }[]
306
+ <DataTable
307
+ columns={[
308
+ { id: "id", header: "Заказ", accessor: "id", hideable: false },
309
+ { id: "client", header: "Клиент", accessor: "client" },
310
+ { id: "total", header: "Сумма", accessor: "total", numeric: true },
311
+ ]}
312
+ rows={orders}
313
+ getRowKey={(row) => row.id}
314
+ columnsMenu
315
+ />
316
+ ```
317
+
290
318
  ## 7b. A top bar out of its groups
291
319
 
292
320
  The bar lays itself out only from its four groups ([the top bar](composition.md#the-top-bar)); a
@@ -26,13 +26,13 @@ import type { ControlSize, PaletteColor, TextTone, Tone, Variant } from "prime-u
26
26
  | Other state | `x` / `defaultX` / `onXChange(x)` | Badge `pressed`; Button `pressed`; ChartFrame `hiddenSeries`; Chat `selected`, `search`; ChatList `search`; ColorPicker `format`; CommandMenu `search`; Composer `recordMode`; DataTable `hiddenColumns`, `page`, `sort`, `selected`, `expanded`, `collapsedGroups`; ExampleFrame `viewport`, `colorScheme`; Gallery `index`; Gantt `scale`; Kanban `columnOrder`; MediaViewer `index`; Message.Media `index`; Select `search`; SmartFilter `search`; VideoNote `playing`, `transcriptExpanded`; VoicePlayer `rate`, `playing`, `transcriptExpanded`; Sidebar `mode`. |
27
27
  | Checked | `checked` / `defaultChecked` / `onCheckedChange(checked)` | Checkbox, Dropdown.CheckboxItem, Switch, Thumbnail. |
28
28
  | Open | `open` / `defaultOpen` / `onOpenChange(open)` | ColorPresets, CommandMenu, ConfirmDialog, Datepicker, Drawer, Dropdown, Gallery, MediaViewer, Message.Media, Modal, Popover, Select, Sheet, TagSelect, Tooltip, Page.Split, Sidebar, Sidebar.Group, Sidebar.Sub. |
29
- | Dismiss | `closeOnOutsideClick` (default `true`), `closeOnEscape` (default `true`) | Both on every overlay that opens a layer: the dialogs, the floating panels, the panels of Select, TagSelect, Datepicker and ColorPresets, the off-canvas Sidebar and the reaction bar of a message. `ConfirmDialog` takes both with `closeOnOutsideClick` default `false` (Escape is held while `onConfirm` runs). Tooltip and Notification take neither. A form holds closing with `Modal.Guard` / `Drawer.Guard` / `Sheet.Guard`. |
29
+ | Dismiss | `closeOnOutsideClick` (default `true`), `closeOnEscape` (default `true`) | Both on every overlay that opens a layer: the dialogs, the floating panels, the panels of Select, TagSelect, Datepicker and ColorPresets, the `suggestions` list of Input, the off-canvas Sidebar and the reaction bar of a message. `ConfirmDialog` takes both with `closeOnOutsideClick` default `false` (Escape is held while `onConfirm` runs). Tooltip and Notification take neither. A form holds closing with `Modal.Guard` / `Drawer.Guard` / `Sheet.Guard`. |
30
30
  | Selection mode | `multiple` | One vs many (Select, Accordion) — never `type`. `mode` only for structurally different values (Datepicker `single \| range`). |
31
31
  | Status words | `selected`, `current`, `pressed` | `current` marks a navigation location (`Sidebar.Item`, `Breadcrumb.Item`) and sets `aria-current`; `pressed` a toggle button. |
32
32
  | Flags | `disabled`, `readOnly`, `required`, `optional`, `loading`, `fullWidth` | Same names everywhere. |
33
33
  | Focus ring | `focusRing` (default `true`) | Fields only; `false` only where focus is obvious otherwise. |
34
34
  | System strings | `labels?: Partial<XLabels>` | aria labels, counters, default texts; Russian defaults; values as `{token}` templates. Visible content goes in children or props. |
35
- | Structure | `X.Root` + `X.Part` | Only for components with parts. Leaves are single exports: `Typography`, `Kbd`, `Divider`, `Spinner`, `Skeleton`, `Crossfade`, `LinkButton`, `NativeSelect`, `DigitInput`, `Slider`, `TagSelect`, `ColorSwatches`, `CodeBlock`, `ProgressBar`, `ProgressCircle`, `Sparkline`, `Pagination`, `DataTable`, `Gantt`, `Fieldset`, `VisuallyHidden`, `ColorField`, `ExampleFrame`, `VoicePlayer`, `VideoNote`, `ScrollContainer`, `Gallery`, `MediaViewer`. This is the one list; other files link here. A group of roots is `X.Group` (`Radio.Group`, `Avatar.Group`). |
35
+ | Structure | `X.Root` + `X.Part` | Only for components with parts. Leaves are single exports: `Typography`, `Kbd`, `Divider`, `Spinner`, `Skeleton`, `Crossfade`, `LinkButton`, `NativeSelect`, `DigitInput`, `Slider`, `TagSelect`, `ColorSwatches`, `CodeBlock`, `ProgressBar`, `ProgressCircle`, `Sparkline`, `Pagination`, `DataTable`, `Gantt`, `Fieldset`, `VisuallyHidden`, `ColorField`, `ExampleFrame`, `VoicePlayer`, `VideoNote`, `ScrollContainer`, `Gallery`, `MediaViewer`, `RichText`. This is the one list; other files link here. A group of roots is `X.Group` (`Radio.Group`, `Avatar.Group`, `Badge.Group`). |
36
36
  | Slots | `X.Trigger`, `X.Close`, `X.Confirm`, `X.Anchor` | Your own button inside, exactly one element child; the slot renders no element and takes no `className` — style the child. A trigger the kit draws itself (`Select.Trigger`, `Accordion.Trigger`) is a real part with `className`. |
37
37
  | Icons in parts | `X.Icon`, `X.ItemIcon` | `Button.Icon`, `Input.Icon`, `Sidebar.ItemIcon`, `Dropdown.ItemIcon`… — never an `icon` prop on a component. Only data arrays (`notify()`, `options`) carry `icon: ReactNode`. |
38
38
  | DOM state | `data-size`, `data-variant`, `data-tone`, `data-color`, `data-invalid`, `data-disabled`, `data-loading`, `data-state` | Style your wrappers from these, not from class names of kit internals. |
@@ -85,7 +85,7 @@ export function PeriodFilter() {
85
85
  resolving. The async events: Input / Textarea `onCommit`, ConfirmDialog `onConfirm`,
86
86
  `EmptyPage.RetryButton` and CommandMenu `onRetry`, Button `onConfirm` (`holdToConfirm`), Slider
87
87
  `onCommit`, DigitInput `onComplete`, Tabs `onRemove`, Switch `onCheckedChange`, Badge `onRemove`,
88
- FileUpload `onValueChange`, TagSelect `onCreate` / `onOptionUpdate` / `onOptionDelete`, DataTable
88
+ FileUpload and FieldList `onValueChange`, TagSelect `onCreate` / `onOptionUpdate` / `onOptionDelete`, DataTable
89
89
  and Dnd `onReorder`, Kanban `onValueChange` / `onColumnOrderChange`, Gantt `onBarChange` /
90
90
  `onBarCreate`, Composer `onSend` / `onSendVoice` / `onSendVideoNote`, `Message.Root`
91
91
  `onReactionToggle` and `onRetry`, the `onRetry` / `onCancel` of `Message.File`, the
@@ -118,8 +118,11 @@ export function PeriodFilter() {
118
118
  - Checkbox, Switch and Radio: [choice controls](#choice-controls) below.
119
119
  - `required` → red `*` after the label + native `required`. `optional` → muted «необязательно».
120
120
  - Placeholder is an example (`name@company.ru`), never the label.
121
- - Units and prefixes in affixes are hidden from screen readers — put the meaning into the label or hint
122
- too («Бюджет, ₽», «Адрес: prime.app/p/…»).
121
+ - `hintTone` (`success` · `warning` · `danger`) colors the `hint` of a field by the status of its
122
+ value («Осталось 12 дней» in `warning`); a lone `Hint.Root` takes `tone`. The words carry the
123
+ status and the color only repeats it; a validation problem is `error`, which replaces the hint.
124
+ - `Input.Affix` and `Input.InlineAffix` describe the input for screen readers (`aria-describedby`),
125
+ so the label never repeats a unit or a prefix ([a unit lives in one place](ux.md#3-label-economy)).
123
126
  - Mark the minority: when most fields are required, mark only the optional ones (`optional`); when most
124
127
  are optional, mark the required ones; on a tie mark the required ones. Validate in code either way.
125
128
  - Show `error` after the user leaves the field or on submit, not while typing the first character.
@@ -249,7 +252,8 @@ place (a `Banner` for the page; for a region `EmptyPage tone="danger"` — it an
249
252
  фильтры»), and the same action keeps the same variant in the header, toolbars and menus. If «Отмена»
250
253
  would clash with the action itself («Отменить заказ»), use an unambiguous label («Не отменять»).
251
254
  - A control that navigates is a link: `LinkButton href`, `Button.Root asChild` with `<a>` / router
252
- `Link`, `Sidebar.Item href` or `asChild`. Never `onClick={() => location.assign(…)}`.
255
+ `Link`, `Sidebar.Item` / `Breadcrumb.Item` / `List.Item` / `ChatList.Item` `href` or `asChild`. Never
256
+ `onClick={() => location.assign(…)}`.
253
257
 
254
258
  ## Destructive actions
255
259
 
@@ -291,7 +295,10 @@ export function DeleteProject({ onDelete }: { onDelete: () => Promise<void> }) {
291
295
 
292
296
  Leaving a form with unsaved changes is the same contract: `Modal.Guard` / `Drawer.Guard` inside the
293
297
  content with `dirty` (any dismiss asks «Не сохранять изменения?») and `busy` (nothing closes it while
294
- it saves).
298
+ it saves); while either holds, the browser also asks before the tab closes or reloads. A form that is the whole page takes `Page.Guard` (`dirty`, `busy`) inside the page: it
299
+ holds a press on `Sidebar.Item`, `BottomNav.Item` and `Breadcrumb.Item` links — router links
300
+ included — and the browser's own close or reload; never a `beforeunload` or a ConfirmDialog on a
301
+ crumb of your own.
295
302
 
296
303
  ## Providers and helpers
297
304