altitude-design 0.2.1 → 0.3.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 (295) hide show
  1. package/README.md +41 -6
  2. package/dist/adapters/codemirror.cjs +88 -0
  3. package/dist/adapters/codemirror.cjs.map +7 -0
  4. package/dist/adapters/codemirror.js +67 -0
  5. package/dist/adapters/codemirror.js.map +7 -0
  6. package/dist/adapters/react-flow.css +102 -0
  7. package/dist/adapters/tiptap.css +71 -0
  8. package/dist/altitude.css +3121 -244
  9. package/dist/altitude.iife.js +33 -5
  10. package/dist/altitude.no-fonts.css +3121 -244
  11. package/dist/chart-themes.cjs +195 -0
  12. package/dist/chart-themes.cjs.map +7 -0
  13. package/dist/chart-themes.js +165 -0
  14. package/dist/chart-themes.js.map +7 -0
  15. package/dist/cli/altitude.mjs +134 -0
  16. package/dist/guidance/README.md +32 -0
  17. package/dist/guidance/agent-setup.md +22 -0
  18. package/dist/guidance/app-skeleton.md +17 -0
  19. package/dist/guidance/evidence.json +95 -0
  20. package/dist/guidance/index.json +493 -0
  21. package/dist/guidance/llms.txt +20 -0
  22. package/dist/guidance/manifest.json +92 -0
  23. package/dist/guidance/pattern.schema.json +181 -0
  24. package/dist/guidance/patterns/agent-action.json +77 -0
  25. package/dist/guidance/patterns/agent-action.md +39 -0
  26. package/dist/guidance/patterns/assistant-conversation.json +77 -0
  27. package/dist/guidance/patterns/assistant-conversation.md +50 -0
  28. package/dist/guidance/patterns/async-collection.json +71 -0
  29. package/dist/guidance/patterns/async-collection.md +29 -0
  30. package/dist/guidance/patterns/audit-log.json +75 -0
  31. package/dist/guidance/patterns/audit-log.md +27 -0
  32. package/dist/guidance/patterns/auth.json +86 -0
  33. package/dist/guidance/patterns/auth.md +29 -0
  34. package/dist/guidance/patterns/billing.json +80 -0
  35. package/dist/guidance/patterns/billing.md +29 -0
  36. package/dist/guidance/patterns/consequential-action.json +76 -0
  37. package/dist/guidance/patterns/consequential-action.md +27 -0
  38. package/dist/guidance/patterns/developer-settings.json +79 -0
  39. package/dist/guidance/patterns/developer-settings.md +29 -0
  40. package/dist/guidance/patterns/edit-record.json +74 -0
  41. package/dist/guidance/patterns/edit-record.md +51 -0
  42. package/dist/guidance/patterns/import.json +77 -0
  43. package/dist/guidance/patterns/import.md +31 -0
  44. package/dist/guidance/patterns/members.json +77 -0
  45. package/dist/guidance/patterns/members.md +27 -0
  46. package/dist/guidance/patterns/onboarding.json +78 -0
  47. package/dist/guidance/patterns/onboarding.md +31 -0
  48. package/dist/guidance/patterns/review-submit.json +72 -0
  49. package/dist/guidance/patterns/review-submit.md +27 -0
  50. package/dist/guidance/patterns/screen-layout.json +79 -0
  51. package/dist/guidance/patterns/screen-layout.md +40 -0
  52. package/dist/guidance/patterns/settings.json +78 -0
  53. package/dist/guidance/patterns/settings.md +32 -0
  54. package/dist/guidance/patterns/sync.json +77 -0
  55. package/dist/guidance/patterns/sync.md +31 -0
  56. package/dist/guidance/principles.md +23 -0
  57. package/dist/guidance/references/build/checks/agent-action-pattern.mjs +57 -0
  58. package/dist/guidance/references/build/checks/agent-setup.mjs +78 -0
  59. package/dist/guidance/references/build/checks/assistant-conversation-pattern.mjs +49 -0
  60. package/dist/guidance/references/build/checks/audit-log-pattern.mjs +63 -0
  61. package/dist/guidance/references/build/checks/auth-pattern.mjs +67 -0
  62. package/dist/guidance/references/build/checks/billing-pattern.mjs +63 -0
  63. package/dist/guidance/references/build/checks/developer-settings-pattern.mjs +76 -0
  64. package/dist/guidance/references/build/checks/guidance.mjs +71 -0
  65. package/dist/guidance/references/build/checks/import-pattern.mjs +69 -0
  66. package/dist/guidance/references/build/checks/members-pattern.mjs +71 -0
  67. package/dist/guidance/references/build/checks/onboarding-pattern.mjs +54 -0
  68. package/dist/guidance/references/build/checks/pattern-types.mjs +13 -0
  69. package/dist/guidance/references/build/checks/pattern-workflows.mjs +226 -0
  70. package/dist/guidance/references/build/checks/primary-scope.mjs +49 -0
  71. package/dist/guidance/references/build/checks/render-tells.mjs +72 -0
  72. package/dist/guidance/references/build/checks/screen-layout-pattern.mjs +111 -0
  73. package/dist/guidance/references/build/checks/semantics.mjs +72 -0
  74. package/dist/guidance/references/build/checks/settings-pattern.mjs +73 -0
  75. package/dist/guidance/references/build/checks/sync-pattern.mjs +62 -0
  76. package/dist/guidance/references/build/checks/tells-lint.mjs +164 -0
  77. package/dist/guidance/references/build/fixtures/pattern-workflows.tsx +83 -0
  78. package/dist/guidance/references/build/fixtures/patterns/agent-action.jsx +60 -0
  79. package/dist/guidance/references/build/fixtures/patterns/app-skeleton.jsx +94 -0
  80. package/dist/guidance/references/build/fixtures/patterns/assistant-conversation.jsx +79 -0
  81. package/dist/guidance/references/build/fixtures/patterns/audit-log.jsx +81 -0
  82. package/dist/guidance/references/build/fixtures/patterns/auth.jsx +150 -0
  83. package/dist/guidance/references/build/fixtures/patterns/billing.jsx +96 -0
  84. package/dist/guidance/references/build/fixtures/patterns/developer-settings.jsx +95 -0
  85. package/dist/guidance/references/build/fixtures/patterns/import.jsx +102 -0
  86. package/dist/guidance/references/build/fixtures/patterns/members.jsx +106 -0
  87. package/dist/guidance/references/build/fixtures/patterns/onboarding.jsx +70 -0
  88. package/dist/guidance/references/build/fixtures/patterns/screen-layout-decision.jsx +74 -0
  89. package/dist/guidance/references/build/fixtures/patterns/screen-layout-editor.jsx +56 -0
  90. package/dist/guidance/references/build/fixtures/patterns/screen-layout-report.jsx +42 -0
  91. package/dist/guidance/references/build/fixtures/patterns/settings.jsx +73 -0
  92. package/dist/guidance/references/build/fixtures/patterns/sync.jsx +78 -0
  93. package/dist/guidance/references/project/components/src/pattern-async-collection.tsx +57 -0
  94. package/dist/guidance/references/project/components/src/pattern-consequential-action.tsx +77 -0
  95. package/dist/guidance/references/project/components/src/pattern-edit-record.tsx +127 -0
  96. package/dist/guidance/references/project/components/src/pattern-review-submit.tsx +47 -0
  97. package/dist/guidance/references/project/components/src/settings.tsx +79 -0
  98. package/dist/guidance/references/scripts/build-framework-fixture.mjs +20 -0
  99. package/dist/guidance/rules.json +653 -0
  100. package/dist/guidance/visual/Elevation.md +194 -0
  101. package/dist/guidance/visual/Fundamentals.md +83 -0
  102. package/dist/guidance/visual/Research.md +1620 -0
  103. package/dist/index.cjs +18792 -1925
  104. package/dist/index.cjs.map +4 -4
  105. package/dist/index.js +18792 -1925
  106. package/dist/index.js.map +4 -4
  107. package/dist/tokens.css +84 -84
  108. package/dist/tokens.json +301 -128
  109. package/dist/types/adapter-codemirror.d.ts +13 -0
  110. package/dist/types/agent-fleet.d.ts +166 -0
  111. package/dist/types/ai-label.d.ts +30 -0
  112. package/dist/types/app-shell.d.ts +83 -0
  113. package/dist/types/area-chart.d.ts +80 -0
  114. package/dist/types/artifact.d.ts +65 -0
  115. package/dist/types/bar-chart.d.ts +83 -0
  116. package/dist/types/bar-list.d.ts +35 -0
  117. package/dist/types/breadcrumb.d.ts +62 -0
  118. package/dist/types/chart-brush.d.ts +35 -0
  119. package/dist/types/chart-themes.d.ts +229 -0
  120. package/dist/types/chart.d.ts +570 -0
  121. package/dist/types/checklist.d.ts +71 -0
  122. package/dist/types/code-block.d.ts +32 -0
  123. package/dist/types/collections.d.ts +111 -4
  124. package/dist/types/color-picker.d.ts +38 -0
  125. package/dist/types/command.d.ts +6 -3
  126. package/dist/types/comment-thread.d.ts +48 -0
  127. package/dist/types/confirmation.d.ts +60 -0
  128. package/dist/types/context-menu.d.ts +17 -0
  129. package/dist/types/controls.d.ts +100 -17
  130. package/dist/types/conversation.d.ts +130 -0
  131. package/dist/types/copy-button.d.ts +19 -0
  132. package/dist/types/core.d.ts +139 -10
  133. package/dist/types/data-grid.d.ts +76 -0
  134. package/dist/types/date-picker.d.ts +96 -0
  135. package/dist/types/diff-view.d.ts +54 -0
  136. package/dist/types/dot-plot.d.ts +54 -0
  137. package/dist/types/edit-region.d.ts +121 -0
  138. package/dist/types/feature-gate.d.ts +22 -0
  139. package/dist/types/filter-bar.d.ts +65 -0
  140. package/dist/types/formatted-number.d.ts +38 -0
  141. package/dist/types/heatmap.d.ts +64 -0
  142. package/dist/types/in-place.d.ts +24 -0
  143. package/dist/types/index.d.ts +158 -15
  144. package/dist/types/inline-citation.d.ts +35 -0
  145. package/dist/types/inline-edit.d.ts +71 -0
  146. package/dist/types/input-otp.d.ts +37 -0
  147. package/dist/types/item-group.d.ts +104 -0
  148. package/dist/types/line-chart.d.ts +116 -0
  149. package/dist/types/link.d.ts +11 -0
  150. package/dist/types/markdown.d.ts +88 -0
  151. package/dist/types/meter.d.ts +43 -0
  152. package/dist/types/modal-state.d.ts +62 -0
  153. package/dist/types/nav.d.ts +8 -1
  154. package/dist/types/notifications.d.ts +42 -0
  155. package/dist/types/number-input.d.ts +30 -0
  156. package/dist/types/overlays.d.ts +51 -17
  157. package/dist/types/page-header.d.ts +27 -0
  158. package/dist/types/pagination.d.ts +29 -0
  159. package/dist/types/palette.d.ts +64 -0
  160. package/dist/types/password-input.d.ts +22 -0
  161. package/dist/types/pattern-assistant-conversation.d.ts +55 -0
  162. package/dist/types/pattern-async-collection.d.ts +34 -0
  163. package/dist/types/pattern-consequential-action.d.ts +53 -0
  164. package/dist/types/pattern-edit-record.d.ts +72 -0
  165. package/dist/types/pattern-review-submit.d.ts +43 -0
  166. package/dist/types/permission-matrix.d.ts +34 -0
  167. package/dist/types/plan-picker.d.ts +40 -0
  168. package/dist/types/prompt-input.d.ts +106 -0
  169. package/dist/types/property-list.d.ts +67 -0
  170. package/dist/types/question.d.ts +64 -0
  171. package/dist/types/relative-time.d.ts +21 -0
  172. package/dist/types/removal-receipt.d.ts +1180 -0
  173. package/dist/types/resizable.d.ts +48 -0
  174. package/dist/types/roving.d.ts +44 -0
  175. package/dist/types/save-bar.d.ts +38 -0
  176. package/dist/types/saved-views.d.ts +72 -0
  177. package/dist/types/scatter-chart.d.ts +60 -0
  178. package/dist/types/schedule.d.ts +80 -0
  179. package/dist/types/secret-field.d.ts +33 -0
  180. package/dist/types/select.d.ts +44 -2
  181. package/dist/types/separator.d.ts +11 -0
  182. package/dist/types/settings.d.ts +39 -0
  183. package/dist/types/sheet.d.ts +1 -1
  184. package/dist/types/sparkline.d.ts +46 -0
  185. package/dist/types/split-button.d.ts +21 -0
  186. package/dist/types/stat.d.ts +54 -0
  187. package/dist/types/stepper.d.ts +6 -3
  188. package/dist/types/suggestions.d.ts +29 -0
  189. package/dist/types/suspense.d.ts +12 -1
  190. package/dist/types/sync-indicator.d.ts +24 -0
  191. package/dist/types/tag-input.d.ts +65 -0
  192. package/dist/types/terminal.d.ts +33 -0
  193. package/dist/types/thread-list.d.ts +58 -0
  194. package/dist/types/time-input.d.ts +33 -0
  195. package/dist/types/timeline.d.ts +38 -0
  196. package/dist/types/toggle.d.ts +46 -0
  197. package/dist/types/toolbar.d.ts +34 -0
  198. package/dist/types/tour.d.ts +23 -0
  199. package/dist/types/trace.d.ts +65 -0
  200. package/dist/types/tree.d.ts +71 -0
  201. package/dist/types-cjs/adapter-codemirror.d.cts +13 -0
  202. package/dist/types-cjs/agent-fleet.d.cts +166 -0
  203. package/dist/types-cjs/ai-label.d.cts +30 -0
  204. package/dist/types-cjs/app-shell.d.cts +83 -0
  205. package/dist/types-cjs/area-chart.d.cts +80 -0
  206. package/dist/types-cjs/artifact.d.cts +65 -0
  207. package/dist/types-cjs/bar-chart.d.cts +83 -0
  208. package/dist/types-cjs/bar-list.d.cts +35 -0
  209. package/dist/types-cjs/breadcrumb.d.cts +62 -0
  210. package/dist/types-cjs/chart-brush.d.cts +35 -0
  211. package/dist/types-cjs/chart-themes.d.cts +229 -0
  212. package/dist/types-cjs/chart.d.cts +570 -0
  213. package/dist/types-cjs/checklist.d.cts +71 -0
  214. package/dist/types-cjs/code-block.d.cts +32 -0
  215. package/dist/types-cjs/collections.d.cts +246 -0
  216. package/dist/types-cjs/color-picker.d.cts +38 -0
  217. package/dist/types-cjs/command.d.cts +66 -0
  218. package/dist/types-cjs/comment-thread.d.cts +48 -0
  219. package/dist/types-cjs/confirmation.d.cts +60 -0
  220. package/dist/types-cjs/context-menu.d.cts +17 -0
  221. package/dist/types-cjs/controls.d.cts +360 -0
  222. package/dist/types-cjs/conversation.d.cts +130 -0
  223. package/dist/types-cjs/copy-button.d.cts +19 -0
  224. package/dist/types-cjs/core.d.cts +256 -0
  225. package/dist/types-cjs/data-grid.d.cts +76 -0
  226. package/dist/types-cjs/date-picker.d.cts +96 -0
  227. package/dist/types-cjs/diff-view.d.cts +54 -0
  228. package/dist/types-cjs/dot-plot.d.cts +54 -0
  229. package/dist/types-cjs/edit-region.d.cts +121 -0
  230. package/dist/types-cjs/empty.d.cts +24 -0
  231. package/dist/types-cjs/feature-gate.d.cts +22 -0
  232. package/dist/types-cjs/filter-bar.d.cts +65 -0
  233. package/dist/types-cjs/formatted-number.d.cts +38 -0
  234. package/dist/types-cjs/heatmap.d.cts +64 -0
  235. package/dist/types-cjs/in-place.d.cts +24 -0
  236. package/dist/types-cjs/index.d.cts +154 -0
  237. package/dist/types-cjs/inline-citation.d.cts +35 -0
  238. package/dist/types-cjs/inline-edit.d.cts +71 -0
  239. package/dist/types-cjs/input-otp.d.cts +37 -0
  240. package/dist/types-cjs/item-group.d.cts +104 -0
  241. package/dist/types-cjs/line-chart.d.cts +116 -0
  242. package/dist/types-cjs/link.d.cts +11 -0
  243. package/dist/types-cjs/markdown.d.cts +88 -0
  244. package/dist/types-cjs/meter.d.cts +43 -0
  245. package/dist/types-cjs/modal-state.d.cts +62 -0
  246. package/dist/types-cjs/nav.d.cts +25 -0
  247. package/dist/types-cjs/notifications.d.cts +42 -0
  248. package/dist/types-cjs/number-input.d.cts +30 -0
  249. package/dist/types-cjs/overlays.d.cts +170 -0
  250. package/dist/types-cjs/page-header.d.cts +27 -0
  251. package/dist/types-cjs/pagination.d.cts +29 -0
  252. package/dist/types-cjs/palette.d.cts +64 -0
  253. package/dist/types-cjs/password-input.d.cts +22 -0
  254. package/dist/types-cjs/pattern-assistant-conversation.d.cts +55 -0
  255. package/dist/types-cjs/pattern-async-collection.d.cts +34 -0
  256. package/dist/types-cjs/pattern-consequential-action.d.cts +53 -0
  257. package/dist/types-cjs/pattern-edit-record.d.cts +72 -0
  258. package/dist/types-cjs/pattern-review-submit.d.cts +43 -0
  259. package/dist/types-cjs/permission-matrix.d.cts +34 -0
  260. package/dist/types-cjs/pile.d.cts +27 -0
  261. package/dist/types-cjs/plan-picker.d.cts +40 -0
  262. package/dist/types-cjs/prompt-input.d.cts +106 -0
  263. package/dist/types-cjs/property-list.d.cts +67 -0
  264. package/dist/types-cjs/question.d.cts +64 -0
  265. package/dist/types-cjs/relative-time.d.cts +21 -0
  266. package/dist/types-cjs/removal-receipt.d.cts +1180 -0
  267. package/dist/types-cjs/resizable.d.cts +48 -0
  268. package/dist/types-cjs/roving.d.cts +44 -0
  269. package/dist/types-cjs/save-bar.d.cts +38 -0
  270. package/dist/types-cjs/saved-views.d.cts +72 -0
  271. package/dist/types-cjs/scatter-chart.d.cts +60 -0
  272. package/dist/types-cjs/schedule.d.cts +80 -0
  273. package/dist/types-cjs/secret-field.d.cts +33 -0
  274. package/dist/types-cjs/select.d.cts +109 -0
  275. package/dist/types-cjs/separator.d.cts +11 -0
  276. package/dist/types-cjs/settings.d.cts +39 -0
  277. package/dist/types-cjs/sheet.d.cts +27 -0
  278. package/dist/types-cjs/sparkline.d.cts +46 -0
  279. package/dist/types-cjs/split-button.d.cts +21 -0
  280. package/dist/types-cjs/stat.d.cts +54 -0
  281. package/dist/types-cjs/stepper.d.cts +26 -0
  282. package/dist/types-cjs/suggestions.d.cts +29 -0
  283. package/dist/types-cjs/suspense.d.cts +85 -0
  284. package/dist/types-cjs/sync-indicator.d.cts +24 -0
  285. package/dist/types-cjs/tag-input.d.cts +65 -0
  286. package/dist/types-cjs/terminal.d.cts +33 -0
  287. package/dist/types-cjs/thread-list.d.cts +58 -0
  288. package/dist/types-cjs/time-input.d.cts +33 -0
  289. package/dist/types-cjs/timeline.d.cts +38 -0
  290. package/dist/types-cjs/toggle.d.cts +46 -0
  291. package/dist/types-cjs/toolbar.d.cts +34 -0
  292. package/dist/types-cjs/tour.d.cts +23 -0
  293. package/dist/types-cjs/trace.d.cts +65 -0
  294. package/dist/types-cjs/tree.d.cts +71 -0
  295. package/package.json +89 -9
@@ -1,7 +1,12 @@
1
1
  import * as React from 'react';
2
+ import { type Presentation } from './core.js';
3
+ /** The shared warm-up, for floating readouts outside this module (a chart's readout): warm if one closed within 400ms. */
4
+ export declare const tipIsWarm: () => boolean;
5
+ export declare const markTipClosed: () => void;
2
6
  export interface TooltipProps {
3
7
  content: React.ReactNode;
4
- side?: 'top' | 'bottom';
8
+ /** Default 'top'. 'right' is for a rail of icons, where above would cover the next one. */
9
+ side?: 'top' | 'bottom' | 'right';
5
10
  delay?: number;
6
11
  defaultOpen?: boolean;
7
12
  children: React.ReactElement<any>;
@@ -29,6 +34,8 @@ export interface MenuItem {
29
34
  disabled?: boolean;
30
35
  /** Ephemeral adaptation: predicted items appear at once, the rest fade in over dur-onset. Only worth it when predictions are right most of the time. */
31
36
  predicted?: boolean;
37
+ /** A checkable item (role="menuitemcheckbox"), shown with a check when true: a toggle moved into a menu. */
38
+ checked?: boolean;
32
39
  }
33
40
  export type MenuEntry = MenuItem | {
34
41
  type: 'separator';
@@ -43,8 +50,34 @@ export interface DropdownMenuProps {
43
50
  side?: 'top' | 'bottom';
44
51
  defaultOpen?: boolean;
45
52
  className?: string;
53
+ /**
54
+ * 'auto' (default): anchored to the trigger, or on a narrow touch screen a sheet at the bottom edge, with a title and
55
+ * Close, where the thumb is (#249). 'anchored' or 'sheet' forces one.
56
+ */
57
+ presentation?: Presentation;
58
+ /** The sheet's title. Default: the trigger's aria-label or text. */
59
+ title?: string;
46
60
  }
47
- export declare function DropdownMenu({ trigger, items, align, side, defaultOpen, className }: DropdownMenuProps): React.JSX.Element;
61
+ /**
62
+ * The menu itself, shared by DropdownMenu and ContextMenu: its items, the highlight that glides between them, the
63
+ * keyboard, and choosing. `onClose(true)` asks the owner to close and give focus back.
64
+ */
65
+ export declare function MenuPanel({ items, id, state, side, align, className, style, startFirst, onClose, sheet, title }: {
66
+ items: MenuEntry[];
67
+ id: string;
68
+ state: string;
69
+ side?: 'top' | 'bottom';
70
+ align?: 'start' | 'end';
71
+ className?: string;
72
+ style?: React.CSSProperties;
73
+ /** Opened from the keyboard: the first item is active at once. */
74
+ startFirst?: boolean;
75
+ onClose: () => void;
76
+ /** Presented as a bottom sheet (#249), with this title. */
77
+ sheet?: boolean;
78
+ title?: React.ReactNode;
79
+ }): React.JSX.Element;
80
+ export declare function DropdownMenu({ trigger, items, align, side, defaultOpen, className, presentation, title }: DropdownMenuProps): React.JSX.Element;
48
81
  export interface HoverCardProps {
49
82
  /** What you hover or focus: usually a link or an avatar. It must do its own job (navigate, open) without the card. */
50
83
  trigger: React.ReactElement<any>;
@@ -67,33 +100,28 @@ export interface HoverCardProps {
67
100
  * warm-up: once one has shown, a neighbour opens at once. Its content is supplementary, never the only way to reach anything.
68
101
  */
69
102
  export declare function HoverCard({ trigger, children, side, align, openDelay, closeDelay, open, defaultOpen, onOpenChange, className }: HoverCardProps): React.JSX.Element;
70
- export declare const summitTaken: () => boolean;
103
+ /** The summit is shared by every provider in the same document. */
104
+ export declare const summitTaken: (doc?: Document) => boolean;
71
105
  export interface ModalOptions {
72
106
  open: boolean;
73
107
  onDismiss: () => void;
74
- /** How long the closed pose stays mounted (the exit runs at 70% of the entry). */
75
108
  exitMs: number;
76
109
  panel: React.RefObject<HTMLElement | null>;
77
- /** Blocks the page: the stage recedes, scroll locks and Tab is trapped. Default true. */
78
110
  modal?: boolean;
79
- /** Escape closes. Default true. */
80
111
  dismissible?: boolean;
81
- /** Takes level 5 (Dialog, CommandPalette). Default false. */
82
112
  summit?: boolean;
83
- /** Move focus into the panel once it has risen. Default true. */
84
113
  autoFocus?: boolean;
85
114
  focusSelector?: string;
86
- /** Put focus back where it was on close. Default: autoFocus. */
87
115
  restoreFocus?: boolean;
116
+ background?: 'recede' | 'stationary';
117
+ returnFocus?: () => HTMLElement | null;
88
118
  }
89
- /**
90
- * The machinery every layer above the page shares: presence (mount, rise, exit), the receding page,
91
- * scroll lock, focus in and back out, Escape and the Tab trap. Dialog, Sheet and CommandPalette use it.
92
- */
93
119
  export declare const MODAL_FOCUS = "[data-autofocus], input, textarea, select";
94
- export declare function useModal({ open, onDismiss, exitMs, panel, modal, dismissible, summit, autoFocus, focusSelector, restoreFocus }: ModalOptions): {
95
- onKeyDown: (e: React.KeyboardEvent) => void;
120
+ export declare function useModal({ open, onDismiss, exitMs, panel, modal, dismissible, summit, autoFocus, focusSelector, restoreFocus, background, returnFocus }: ModalOptions): {
96
121
  mounted: boolean;
122
+ onKeyDown: (e: React.KeyboardEvent) => void;
123
+ rootRef: (root: HTMLDivElement | null) => void;
124
+ captureInvoker: (el: HTMLElement) => void;
97
125
  state: "open" | "closed";
98
126
  };
99
127
  export interface DialogProps {
@@ -109,13 +137,17 @@ export interface DialogProps {
109
137
  size?: 'sm' | 'md' | 'lg';
110
138
  /** Set false for decisions that must be answered: the scrim and Escape won't close it. */
111
139
  dismissible?: boolean;
112
- /** Where focus goes once it has risen: the first field (the default), the title (for a read surface), or nowhere (you move it yourself). */
140
+ /** Initial focus: the first field (default), the title, or false for a safe panel fallback until the application moves focus inside. */
113
141
  initialFocus?: 'first-field' | 'title' | false;
114
142
  /** What 'first-field' looks for. Default '[data-autofocus], input, textarea, select'; the panel itself if nothing matches. */
115
143
  focusSelector?: string;
144
+ /** Keep the background in place and remove scrim blur; default 'recede'. Modality is unchanged. */
145
+ background?: 'recede' | 'stationary';
146
+ /** Lazy fallback when the captured invoker can no longer receive focus. */
147
+ returnFocus?: () => HTMLElement | null;
116
148
  className?: string;
117
149
  }
118
- export declare function Dialog({ open, defaultOpen, onOpenChange, trigger, title, description, children, footer, size, dismissible, initialFocus, focusSelector, className }: DialogProps): React.JSX.Element;
150
+ export declare function Dialog({ open, defaultOpen, onOpenChange, trigger, title, description, children, footer, size, dismissible, initialFocus, focusSelector, background, returnFocus, className }: DialogProps): React.JSX.Element;
119
151
  export type ToastTone = 'neutral' | 'positive' | 'caution' | 'critical';
120
152
  export interface ToastOptions {
121
153
  title: React.ReactNode;
@@ -126,6 +158,8 @@ export interface ToastOptions {
126
158
  label: string;
127
159
  onClick: () => void;
128
160
  };
161
+ /** false: shown but not announced, because what it says was already announced where it happened. Default true. */
162
+ announce?: boolean;
129
163
  }
130
164
  export declare function toast(input: ToastOptions | string): number;
131
165
  export declare namespace toast {
@@ -0,0 +1,27 @@
1
+ import * as React from 'react';
2
+ import { MenuEntry } from './overlays.js';
3
+ export interface PageHeaderProps extends Omit<React.HTMLAttributes<HTMLElement>, 'title'> {
4
+ /** A Breadcrumb above the title. */
5
+ breadcrumb?: React.ReactNode;
6
+ /** The page's one primary action: a single Button variant="primary". There's one slot, so there's one primary. */
7
+ primary?: React.ReactElement;
8
+ /** Secondary and ghost actions, before the primary. */
9
+ actions?: React.ReactNode;
10
+ /** Actions that don't need to be seen, in a "More actions" menu. */
11
+ overflow?: MenuEntry[];
12
+ /** Tabs under the title, for the page's sections. */
13
+ tabs?: React.ReactNode;
14
+ /** Stays at the top while the page scrolls, and rises one level when content passes under it. */
15
+ sticky?: boolean;
16
+ /** PageHeaderTitle and PageHeaderDescription. */
17
+ children?: React.ReactNode;
18
+ }
19
+ /**
20
+ * The block every page opens with: breadcrumb, title, description, actions and tabs. The page's name is the record, so
21
+ * the block lies on the ground; only its actions are live, and it has one slot for the primary action (law 1).
22
+ */
23
+ export declare function PageHeader({ breadcrumb, primary, actions, overflow, tabs, sticky, className, children, ...rest }: PageHeaderProps): React.JSX.Element;
24
+ /** The page's h1. */
25
+ export declare function PageHeaderTitle({ className, ...rest }: React.HTMLAttributes<HTMLHeadingElement>): React.JSX.Element;
26
+ /** One line saying what the page is for. */
27
+ export declare function PageHeaderDescription({ className, ...rest }: React.HTMLAttributes<HTMLParagraphElement>): React.JSX.Element;
@@ -0,0 +1,29 @@
1
+ import * as React from 'react';
2
+ /** The pages shown: the first, the last, the current one and `siblings` either side, with a gap where pages are skipped. */
3
+ export declare function pageRange(page: number, count: number, siblings?: number): (number | 'gap')[];
4
+ export interface PaginationProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange'> {
5
+ /** The current page, from 1. */
6
+ page: number;
7
+ /** How many pages. Leave it out for cursor paging: Previous and Next, and "Page 3". */
8
+ pageCount?: number;
9
+ onPageChange?: (page: number) => void;
10
+ /** With pageSize: the summary "21–40 of 214". */
11
+ total?: number;
12
+ pageSize?: number;
13
+ /** Pages have URLs: they're links. Without it they're buttons. */
14
+ hrefFor?: (page: number) => string;
15
+ /** For cursor paging: whether there's a next page. Default true. */
16
+ hasNext?: boolean;
17
+ /** Pages either side of the current one. Default 1. */
18
+ siblings?: number;
19
+ /** The next page is loading: the thumb is held pressed until it lands. */
20
+ loading?: boolean;
21
+ /** What's being paged, plural, for the summary ("invoices"). */
22
+ noun?: string;
23
+ locale?: string;
24
+ }
25
+ /**
26
+ * Move through pages of a collection. The page numbers sit in a trench and the current page is one raised thumb that
27
+ * travels to it, as RadioGroup's does: "you are here, among these". They stay links (or buttons) in plain Tab order.
28
+ */
29
+ export declare function Pagination({ page, pageCount, onPageChange, total, pageSize, hrefFor, hasNext, siblings, loading, noun, locale, className, 'aria-label': label, ...rest }: PaginationProps): React.JSX.Element;
@@ -0,0 +1,64 @@
1
+ type Vec = [number, number, number];
2
+ /** [lightness 0–1, chroma, hue in degrees] */
3
+ export declare function oklch(hex: string): Vec;
4
+ /** OKLCH → hex, or null when the colour is outside sRGB. */
5
+ export declare function fromOklch(L: number, C: number, h: number): string | null;
6
+ /** The most chroma (to 0.001) that hue h holds at lightness L inside sRGB. */
7
+ export declare function maxChroma(L: number, h: number): number;
8
+ export type Vision = 'normal' | 'protan' | 'deutan';
9
+ /** OKLab ΔE × 100 between two hex colours, as seen with normal vision or simulated protanopia or deuteranopia. */
10
+ export declare function deltaE(a: string, b: string, kind?: Vision): number;
11
+ /** The smaller of the protan and deutan ΔE. */
12
+ export declare const cvdDeltaE: (a: string, b: string) => number;
13
+ export declare function contrastRatio(a: string, b: string): number;
14
+ export declare const hueGap: (a: number, b: number) => number;
15
+ /** A scheme is dark when its ground is, by the same test deriveAccent uses. */
16
+ export declare const isDarkGround: (ground: string) => boolean;
17
+ export declare const DATA_GATES: {
18
+ reserved: number;
19
+ normal: number;
20
+ hue: number;
21
+ cvd: number;
22
+ cvdAny: number;
23
+ contrast: number;
24
+ chroma: number;
25
+ band: Record<"light" | "dark", [number, number]>;
26
+ rampStep: number;
27
+ pole: number;
28
+ context: {
29
+ chroma: number;
30
+ line: number;
31
+ other: number;
32
+ };
33
+ };
34
+ export declare const DATA_SLOTS: readonly ["data-1", "data-2", "data-3", "data-4", "data-5", "data-6"];
35
+ export declare const DATA_RESERVED: readonly ["accent", "positive", "caution", "critical", "presence-1", "presence-2", "presence-3"];
36
+ export declare const DATA_SEQ: readonly ["data-seq-1", "data-seq-2", "data-seq-3", "data-seq-4", "data-seq-5", "data-seq-6", "data-seq-7"];
37
+ export declare const DATA_DIV_NEG: readonly ["data-div-mid", "data-div-neg-1", "data-div-neg-2", "data-div-neg-3"];
38
+ export declare const DATA_DIV_POS: readonly ["data-div-mid", "data-div-pos-1", "data-div-pos-2", "data-div-pos-3"];
39
+ /** Every data-* token, in tokens.json order. */
40
+ export declare const DATA_TOKENS: readonly ["data-1", "data-2", "data-3", "data-4", "data-5", "data-6", "data-other", "data-context", "data-seq-1", "data-seq-2", "data-seq-3", "data-seq-4", "data-seq-5", "data-seq-6", "data-seq-7", "data-div-neg-3", "data-div-neg-2", "data-div-neg-1", "data-div-mid", "data-div-pos-1", "data-div-pos-2", "data-div-pos-3"];
41
+ /** Magnitude, low to high, in one hue: light schemes darken from near-white; dark schemes start near their ground and climb. */
42
+ export declare function sequentialRamp(h: number, dark: boolean): string[];
43
+ /**
44
+ * Measure the data-* tokens against every gate. `get` returns a token's value by name (without `--`); every value
45
+ * must already be a hex colour. Returns one sentence per problem.
46
+ */
47
+ export declare function checkDataPalette(get: (name: string) => string): string[];
48
+ /**
49
+ * Colours that could be data-1 for a brand accent, best first: the accent's hue (then hues up to 30° either side), at
50
+ * lightnesses nearest the accent's, each clearing the band, chroma, 3:1 on ground and raised, and the reserved hues.
51
+ */
52
+ export declare function accentCandidates(accent: string, get: (name: string) => string): string[];
53
+ /**
54
+ * A scheme's six slots, led by a brand accent. The slot nearest the accent makes way: the first candidate (see
55
+ * accentCandidates) that keeps every pairwise gate with the other five takes its place, or, if none does, that nearest
56
+ * slot leads unchanged. The other five are re-ordered behind data-1: every order is tried and the greatest minimum
57
+ * adjacent CVD ΔE wins, ties keeping the scheme's order; if none clears the adjacent gate, the slot closest to data-1
58
+ * is dropped and the rest tried again. Dropped slots leave the end of the palette to data-other. Deterministic.
59
+ */
60
+ export declare function leadSlots(accent: string, candidates: string[], slots: string[]): {
61
+ slots: string[];
62
+ dropped: string[];
63
+ };
64
+ export {};
@@ -0,0 +1,22 @@
1
+ import * as React from 'react';
2
+ import { InputProps } from './controls.js';
3
+ export interface PasswordRequirement {
4
+ label: string;
5
+ test: (value: string) => boolean;
6
+ }
7
+ export interface PasswordInputProps extends Omit<InputProps, 'type' | 'trailing'> {
8
+ /** Scores a password from 0 (weakest) to 4 (strongest); your app supplies the scoring (zxcvbn, your rules). Shown as a Meter. */
9
+ strength?: (value: string) => number;
10
+ /** The word for each score, 0 to 4. Default "Very weak", "Weak", "Fair", "Good", "Strong". */
11
+ strengthLabels?: [string, string, string, string, string];
12
+ /** Rules shown under the field, each stamped as met or not as the password changes. */
13
+ requirements?: PasswordRequirement[];
14
+ /** The reveal toggle's name. It never changes with its state. Default "Show password". */
15
+ revealLabel?: string;
16
+ }
17
+ /**
18
+ * A password field: an Input with a reveal Toggle in its end cap, a caps-lock notice, and, when creating one, its
19
+ * strength as a reading (a Meter, never a Progress) and its requirements stamped as met. Strength and requirements
20
+ * describe the field and are announced politely once typing pauses.
21
+ */
22
+ export declare const PasswordInput: React.ForwardRefExoticComponent<PasswordInputProps & React.RefAttributes<HTMLInputElement>>;
@@ -0,0 +1,55 @@
1
+ /** What a turn is doing. 'interrupted' is an unfinished answer found after a reload; 'awaiting-input' is a Confirmation or Question open. */
2
+ export type AssistantTurnState = 'ready' | 'submitted' | 'streaming' | 'complete' | 'stopped' | 'failed' | 'interrupted' | 'awaiting-input';
3
+ export type AssistantErrorKind = 'offline' | 'rate-limited' | 'context-full' | 'refused' | 'outage' | 'unknown';
4
+ /** Throw this from `stream` to say what went wrong; anything else is 'unknown' (or 'offline' when the browser is offline). */
5
+ export declare class AssistantError extends Error {
6
+ kind: AssistantErrorKind;
7
+ /** For 'rate-limited': when it can be tried again. */
8
+ retryAt?: Date | number;
9
+ constructor(kind: AssistantErrorKind, message?: string, retryAt?: Date | number);
10
+ }
11
+ export interface AssistantTurnError {
12
+ kind: AssistantErrorKind;
13
+ retryAt?: Date | number;
14
+ message?: string;
15
+ }
16
+ export interface AssistantTurnOptions<I> {
17
+ /** Starts the answer: yield text as it arrives; resolve when the stream says it's complete. Abort on `signal`. */
18
+ stream: (input: I, signal: AbortSignal) => AsyncIterable<string>;
19
+ /** An answer restored after a reload. If it wasn't complete it's 'interrupted', never shown as complete. */
20
+ restored?: {
21
+ input: I;
22
+ text: string;
23
+ complete: boolean;
24
+ };
25
+ locale?: string;
26
+ }
27
+ export interface AssistantTurn<I> {
28
+ state: AssistantTurnState;
29
+ /** The answer so far: kept when stopped, failed or interrupted. */
30
+ text: string;
31
+ /** What was sent, kept until it's answered: put it back in the composer when sending fails. */
32
+ input: I | undefined;
33
+ error: AssistantTurnError | null;
34
+ /** The error in words, with what to do: "You've reached this hour's limit. Try again at 3:40 PM." */
35
+ errorText: string;
36
+ /** Map onto the components. */
37
+ promptStatus: 'ready' | 'submitted' | 'streaming' | 'error';
38
+ messageStatus: 'streaming' | 'complete' | 'stopped' | 'error' | undefined;
39
+ /** Sends unless a turn is already in flight (a double Enter sends once). Returns whether it started. */
40
+ submit: (input: I) => boolean;
41
+ stop: () => void;
42
+ /** Sends the last input again (after a failure, a stop or an interruption). */
43
+ retry: () => boolean;
44
+ /** A Confirmation or Question is open (true) or answered (false): the turn waits for the person. */
45
+ awaitInput: (waiting: boolean) => void;
46
+ }
47
+ /** Each error kind in words, with what to do. */
48
+ export declare function assistantErrorText(error: AssistantTurnError | null, locale?: string): string;
49
+ /**
50
+ * The assistant-conversation contract's turn (project/framework/patterns/assistant-conversation.md, #285): a send that
51
+ * can't happen twice, a stream whose late events from a superseded turn are ignored, Stop that keeps the partial
52
+ * answer, completion only when the stream says so, an unfinished answer after a reload shown as interrupted, and each
53
+ * error kind in words. Map `promptStatus` to PromptInput and `messageStatus` to the answer's Message.
54
+ */
55
+ export declare function useAssistantTurn<I>({ stream, restored, locale }: AssistantTurnOptions<I>): AssistantTurn<I>;
@@ -0,0 +1,34 @@
1
+ export type CollectionPhase = 'loading' | 'refreshing' | 'populated' | 'empty' | 'no-results' | 'failed';
2
+ export interface AsyncCollectionOptions<T, Q> {
3
+ initialQuery: Q;
4
+ /** Own query semantics, permissions, pagination and URL/history in the application. Abort is advisory. */
5
+ load: (query: Q, context: {
6
+ signal: AbortSignal;
7
+ }) => readonly T[] | Promise<readonly T[]>;
8
+ getKey: (item: T) => string;
9
+ isFiltered: (query: Q) => boolean;
10
+ /** preserve deliberately retains keys absent from the current page/filter; reconcile deleted identities in the app. */
11
+ selection: 'clear-on-query' | 'preserve';
12
+ messages?: Partial<{
13
+ loading: string;
14
+ refreshing: string;
15
+ empty: string;
16
+ noResults: string;
17
+ failed: string;
18
+ results: (count: number) => string;
19
+ }>;
20
+ }
21
+ /** Stale-response-safe collection, with explicit selection policy. See altitude-design/guidance/patterns/async-collection.md. */
22
+ export declare function useAsyncCollection<T, Q>(options: AsyncCollectionOptions<T, Q>): {
23
+ setQuery: (query: Q) => void;
24
+ refresh: () => void;
25
+ reset: () => void;
26
+ clearSelection: () => void;
27
+ toggleSelection: (key: string) => void;
28
+ query: Q;
29
+ items: readonly T[];
30
+ phase: CollectionPhase;
31
+ error: string;
32
+ status: string;
33
+ selectedKeys: ReadonlySet<string>;
34
+ };
@@ -0,0 +1,53 @@
1
+ export type ActionResult<T> = {
2
+ ok: true;
3
+ value: T;
4
+ } | {
5
+ ok: false;
6
+ error: string;
7
+ };
8
+ export type UndoResult = {
9
+ ok: true;
10
+ } | {
11
+ ok: false;
12
+ error: string;
13
+ };
14
+ export type ConsequentialPhase = 'idle' | 'confirming' | 'pending' | 'failed' | 'succeeded' | 'undoing' | 'undone';
15
+ interface ActionBase<T> {
16
+ /** Render target and consequence alongside the trigger and in any confirmation. */
17
+ target: string;
18
+ consequence: string;
19
+ execute: () => ActionResult<T> | Promise<ActionResult<T>>;
20
+ /** Connected, visible next logical destination when the original trigger disappears. */
21
+ focusFallback?: () => HTMLElement | null;
22
+ messages?: Partial<{
23
+ pending: string;
24
+ succeeded: string;
25
+ failed: string;
26
+ undoing: string;
27
+ undone: string;
28
+ }>;
29
+ }
30
+ export type ConsequentialActionOptions<T> = ActionBase<T> & ({
31
+ requiresConfirmation: true;
32
+ undo?: (result: T) => UndoResult | Promise<UndoResult>;
33
+ } | {
34
+ requiresConfirmation: false;
35
+ undo: (result: T) => UndoResult | Promise<UndoResult>;
36
+ });
37
+ /** Confirmation records intent; only execute success records completion. Undo is offered only with an application-supplied inverse.
38
+ * Compose Dialog/Alert/Button with the returned content and states. See altitude-design/guidance/patterns/consequential-action.md. */
39
+ export declare function useConsequentialAction<T>(options: ConsequentialActionOptions<T>): {
40
+ target: string;
41
+ consequence: string;
42
+ canUndo: boolean;
43
+ request: () => void;
44
+ confirm: () => void;
45
+ cancel: () => void;
46
+ retry: () => Promise<void> | undefined;
47
+ undo: (() => Promise<void>) | undefined;
48
+ phase: ConsequentialPhase;
49
+ error: string;
50
+ status: string;
51
+ result: T | undefined;
52
+ };
53
+ export {};
@@ -0,0 +1,72 @@
1
+ import * as React from 'react';
2
+ export type FieldErrors<T> = Partial<Record<keyof T, string>>;
3
+ export type EditRecordResult<T> = {
4
+ ok: true;
5
+ value: T;
6
+ } | {
7
+ ok: false;
8
+ error: string;
9
+ errors?: FieldErrors<T>;
10
+ };
11
+ export type EditRecordPhase = 'editing' | 'invalid' | 'submitting' | 'saved' | 'failed';
12
+ export type LeaveReason = 'cancel' | 'back' | 'navigation';
13
+ export interface EditRecordOptions<T extends object> {
14
+ /** Initial snapshot only. Use reset to deliberately adopt another record; keep snapshots immutable. */
15
+ initialValue: T;
16
+ validate: (draft: T) => FieldErrors<T>;
17
+ /** Submit validates every field; blur additionally validates the blurred field. Corrections revalidate visible errors. */
18
+ validationMode: 'submit' | 'blur';
19
+ save: (draft: T, context: {
20
+ previousValue: T;
21
+ }) => EditRecordResult<T> | Promise<EditRecordResult<T>>;
22
+ /** Supply semantic equality for nested values. The default compares top-level fields with Object.is. */
23
+ isEqual?: (a: T, b: T) => boolean;
24
+ messages?: Partial<{
25
+ saving: string;
26
+ saved: string;
27
+ failed: string;
28
+ invalid: string;
29
+ newerEdits: string;
30
+ }>;
31
+ }
32
+ /** Small record workflow. Persistence, concurrency/version checks, authorization and route interception belong to the app.
33
+ * See altitude-design/guidance/patterns/edit-record.md. A response never replaces edits made after dispatch.
34
+ */
35
+ export declare function useEditRecord<T extends object>(options: EditRecordOptions<T>): {
36
+ dirty: boolean;
37
+ setDraft: (draft: T) => void;
38
+ setField: <K extends keyof T>(key: K, value: T[K]) => void;
39
+ validateField: (key: keyof T) => void;
40
+ validateAll: () => boolean;
41
+ submit: () => Promise<EditRecordResult<T> | undefined>;
42
+ reset: (value?: T) => boolean;
43
+ requestLeave: (reason: LeaveReason, confirmDiscard: (context: {
44
+ reason: LeaveReason;
45
+ draft: T;
46
+ }) => boolean | Promise<boolean>) => Promise<boolean>;
47
+ draft: T;
48
+ baseline: T;
49
+ errors: FieldErrors<T>;
50
+ error: string;
51
+ phase: EditRecordPhase;
52
+ status: string;
53
+ submitCount: number;
54
+ };
55
+ export interface ErrorSummaryProps {
56
+ errors: readonly {
57
+ id: string;
58
+ label: string;
59
+ message: string;
60
+ }[];
61
+ title?: string;
62
+ /** Change after an unsuccessful submit to focus the summary. Omit to keep focus where it is. */
63
+ focusKey?: number;
64
+ className?: string;
65
+ }
66
+ /** Render from the same errors passed to Field; use each input's actual id. Inline Field owns alert announcements. */
67
+ export declare function ErrorSummary({ errors, title, focusKey, className }: ErrorSummaryProps): React.JSX.Element | null;
68
+ /** Place outside any aria-busy region so pending and completion remain announced. */
69
+ export declare function WorkflowStatus({ children, className }: {
70
+ children?: React.ReactNode;
71
+ className?: string;
72
+ }): React.JSX.Element;
@@ -0,0 +1,43 @@
1
+ import type { FieldErrors } from './pattern-edit-record.js';
2
+ export type ReviewSubmitResult<T, R> = {
3
+ ok: true;
4
+ receipt: R;
5
+ } | {
6
+ ok: false;
7
+ error: string;
8
+ errors?: FieldErrors<T>;
9
+ };
10
+ export interface ReviewSubmitOptions<T extends object, R> {
11
+ /** Supply any recovered draft here. Durable storage, step dependencies and cross-session resume are application responsibilities. */
12
+ initialValue: T;
13
+ validate: (draft: T) => FieldErrors<T>;
14
+ submit: (draft: T) => ReviewSubmitResult<T, R> | Promise<ReviewSubmitResult<T, R>>;
15
+ isEqual?: (a: T, b: T) => boolean;
16
+ messages?: Partial<{
17
+ submitting: string;
18
+ complete: string;
19
+ failed: string;
20
+ invalid: string;
21
+ }>;
22
+ }
23
+ /** Review/correct/submit composition with a persistent application-provided receipt. No automatic persistence or fabricated resume.
24
+ * See altitude-design/guidance/patterns/review-submit.md. Mount a new workflow to start a distinct transaction after completion. */
25
+ export declare function useReviewSubmit<T extends object, R>(options: ReviewSubmitOptions<T, R>): {
26
+ draft: T;
27
+ errors: Partial<Record<keyof T, string>>;
28
+ error: string;
29
+ status: string;
30
+ submitCount: number;
31
+ dirty: boolean;
32
+ phase: "review" | "editing" | "complete" | "submitting";
33
+ receipt: R | undefined;
34
+ setDraft: (value: T) => void;
35
+ setField: <K extends keyof T>(key: K, value: T[K]) => void;
36
+ review: () => void;
37
+ correct: () => void;
38
+ submit: () => Promise<void>;
39
+ requestLeave: (reason: import("./pattern-edit-record.js").LeaveReason, confirmDiscard: (context: {
40
+ reason: import("./pattern-edit-record.js").LeaveReason;
41
+ draft: T;
42
+ }) => boolean | Promise<boolean>) => Promise<boolean>;
43
+ };
@@ -0,0 +1,34 @@
1
+ import * as React from 'react';
2
+ export interface MatrixRole {
3
+ id: string;
4
+ name: string; /** Every permission is always granted (an owner). */
5
+ locked?: boolean;
6
+ }
7
+ export interface MatrixPermission {
8
+ id: string;
9
+ name: string; /** Rows with the same group sit under its heading. */
10
+ group?: string;
11
+ }
12
+ export interface MatrixInherited {
13
+ granted: boolean; /** Where it comes from ("Admin"). */
14
+ from: string;
15
+ }
16
+ export interface PermissionMatrixProps {
17
+ roles: MatrixRole[];
18
+ permissions: MatrixPermission[];
19
+ /** Grants you can change: value[roleId][permissionId]. */
20
+ value: Record<string, Record<string, boolean>>;
21
+ /** A grant decided elsewhere (a parent role, a group): shown as a stamped mark, not a choice. */
22
+ inherited?: (roleId: string, permissionId: string) => MatrixInherited | undefined;
23
+ /** Called when a choice is toggled. Return a promise and the cell hovers as pending until it settles; a rejection reverts it. */
24
+ onChange?: (roleId: string, permissionId: string, granted: boolean) => void | Promise<unknown>;
25
+ /** Names the grid ("Role permissions"). */
26
+ 'aria-label'?: string;
27
+ className?: string;
28
+ }
29
+ /**
30
+ * Roles against permissions. The grid is settled (the record of who can do what). An editable grant is a choice, built
31
+ * like a Checkbox (a trench the accent pours into); an inherited or fixed grant is already decided, so it's a flush
32
+ * stamped check, not a disabled box. The active cell is a ring, never a height. A grid: arrows move, Space toggles.
33
+ */
34
+ export declare function PermissionMatrix({ roles, permissions, value, inherited, onChange, 'aria-label': label, className }: PermissionMatrixProps): React.JSX.Element;
@@ -0,0 +1,40 @@
1
+ import * as React from 'react';
2
+ export interface Plan {
3
+ id: string;
4
+ name: string;
5
+ description?: React.ReactNode;
6
+ /** In minor units (cents), per period; a single number is the same for both. Null: no price (Contact sales). */
7
+ price: {
8
+ month: number;
9
+ year: number;
10
+ } | number | null;
11
+ /** ISO 4217. Default 'USD'. */
12
+ currency?: string;
13
+ /** What the price is for ("per seat"). */
14
+ unit?: string;
15
+ features?: string[];
16
+ /** Why it can't be chosen ("Contact sales for more than 500 seats"). */
17
+ unavailable?: string;
18
+ }
19
+ export interface PlanPickerProps {
20
+ plans: Plan[];
21
+ value?: string;
22
+ defaultValue?: string;
23
+ onValueChange?: (id: string) => void;
24
+ /** The plan they're on now: a "Current plan" plate. */
25
+ current?: string;
26
+ /** A plan you suggest: a "Recommended" plate, never extra height. */
27
+ recommended?: string;
28
+ /** The billing period, with a Monthly / Annually switch when onPeriodChange is given. Annual prices are per month, billed yearly. */
29
+ period?: 'month' | 'year';
30
+ onPeriodChange?: (period: 'month' | 'year') => void;
31
+ locale?: string;
32
+ 'aria-label'?: string;
33
+ className?: string;
34
+ }
35
+ /**
36
+ * Choose a plan. The plans are positions in one choice, so the cards lie flush and one raised mark travels to the chosen
37
+ * one, as RadioGroup's thumb does. "Current plan" and "Recommended" are plates, not height: marketing emphasis isn't
38
+ * importance. The only level-2 slab is your Continue button, outside it.
39
+ */
40
+ export declare function PlanPicker({ plans, value, defaultValue, onValueChange, current, recommended, period, onPeriodChange, locale, 'aria-label': label, className }: PlanPickerProps): React.JSX.Element;