@box-kite/react 0.0.1 → 2.0.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 (280) hide show
  1. package/.claude/rules/box-kite-rules.md +65 -0
  2. package/.claude/skills/box-kite/SKILL.md +138 -0
  3. package/.claude/skills/box-kite/references/components.md +235 -0
  4. package/.claude/skills/box-kite/references/extending.md +42 -0
  5. package/.claude/skills/box-kite/references/patterns.md +27 -0
  6. package/.claude/skills/box-kite/references/styling.md +222 -0
  7. package/.cursor/rules/box-kite.mdc +73 -0
  8. package/AGENTS.md +102 -0
  9. package/BOX_AI_CONTEXT.md +2804 -0
  10. package/BOX_KITE_AI_CONTEXT.md +2804 -0
  11. package/LICENSE +21 -0
  12. package/README.md +744 -7
  13. package/a11y.cjs +1 -0
  14. package/a11y.d.ts +15 -0
  15. package/a11y.mjs +4 -0
  16. package/anchor.cjs +1 -0
  17. package/anchor.d.ts +14 -0
  18. package/anchor.mjs +3 -0
  19. package/behavior.cjs +1 -0
  20. package/behavior.mjs +277 -0
  21. package/box.cjs +1 -0
  22. package/box.d.ts +46 -0
  23. package/box.mjs +23 -0
  24. package/client.cjs +1 -0
  25. package/client.mjs +164 -0
  26. package/components/accordion.cjs +1 -0
  27. package/components/accordion.d.ts +114 -0
  28. package/components/accordion.mjs +251 -0
  29. package/components/baseSvg.cjs +1 -0
  30. package/components/baseSvg.d.ts +5 -0
  31. package/components/baseSvg.mjs +21 -0
  32. package/components/button.cjs +1 -0
  33. package/components/button.d.ts +19 -0
  34. package/components/button.mjs +19 -0
  35. package/components/chart.cjs +1 -0
  36. package/components/chart.d.ts +83 -0
  37. package/components/chart.mjs +236 -0
  38. package/components/checkbox.cjs +1 -0
  39. package/components/checkbox.d.ts +36 -0
  40. package/components/checkbox.mjs +38 -0
  41. package/components/combobox/comboboxChips.d.ts +21 -0
  42. package/components/combobox/comboboxListbox.d.ts +47 -0
  43. package/components/combobox.cjs +1 -0
  44. package/components/combobox.d.ts +121 -0
  45. package/components/combobox.mjs +563 -0
  46. package/components/dataGrid/components/dataGridAggregateValue.d.ts +10 -0
  47. package/components/dataGrid/components/dataGridBody.d.ts +7 -0
  48. package/components/dataGrid/components/dataGridBottomBar.d.ts +6 -0
  49. package/components/dataGrid/components/dataGridCell.d.ts +16 -0
  50. package/components/dataGrid/components/dataGridCellEditor.d.ts +15 -0
  51. package/components/dataGrid/components/dataGridCellPlaceholder.d.ts +14 -0
  52. package/components/dataGrid/components/dataGridCellRowDetail.d.ts +6 -0
  53. package/components/dataGrid/components/dataGridCellRowSelection.d.ts +6 -0
  54. package/components/dataGrid/components/dataGridCellText.d.ts +6 -0
  55. package/components/dataGrid/components/dataGridCellTree.d.ts +16 -0
  56. package/components/dataGrid/components/dataGridColumnFilter.d.ts +9 -0
  57. package/components/dataGrid/components/dataGridColumnGroups.d.ts +7 -0
  58. package/components/dataGrid/components/dataGridContent.d.ts +6 -0
  59. package/components/dataGrid/components/dataGridDataSourceError.d.ts +12 -0
  60. package/components/dataGrid/components/dataGridDetailRow.d.ts +8 -0
  61. package/components/dataGrid/components/dataGridEmptyColumns.d.ts +6 -0
  62. package/components/dataGrid/components/dataGridExport.d.ts +10 -0
  63. package/components/dataGrid/components/dataGridFilterCell.d.ts +11 -0
  64. package/components/dataGrid/components/dataGridFilterRow.d.ts +6 -0
  65. package/components/dataGrid/components/dataGridFooter.d.ts +11 -0
  66. package/components/dataGrid/components/dataGridGlobalFilter.d.ts +6 -0
  67. package/components/dataGrid/components/dataGridGroupRow.d.ts +8 -0
  68. package/components/dataGrid/components/dataGridHeader.d.ts +6 -0
  69. package/components/dataGrid/components/dataGridHeaderCell.d.ts +9 -0
  70. package/components/dataGrid/components/dataGridHeaderCellContextMenu.d.ts +11 -0
  71. package/components/dataGrid/components/dataGridHeaderCellResizer.d.ts +14 -0
  72. package/components/dataGrid/components/dataGridLoader.d.ts +11 -0
  73. package/components/dataGrid/components/dataGridPagination.d.ts +6 -0
  74. package/components/dataGrid/components/dataGridRow.d.ts +8 -0
  75. package/components/dataGrid/components/dataGridTopBar.d.ts +6 -0
  76. package/components/dataGrid/components/dataGridTopBarContextMenu.d.ts +6 -0
  77. package/components/dataGrid/contracts/dataGridContract.d.ts +671 -0
  78. package/components/dataGrid/export/gridExport.d.ts +10 -0
  79. package/components/dataGrid/gridNavigationContext.d.ts +32 -0
  80. package/components/dataGrid/models/aggregateCellModel.d.ts +34 -0
  81. package/components/dataGrid/models/aggregationModel.d.ts +32 -0
  82. package/components/dataGrid/models/cellKeys.d.ts +11 -0
  83. package/components/dataGrid/models/cellModel.d.ts +44 -0
  84. package/components/dataGrid/models/columnModel.d.ts +160 -0
  85. package/components/dataGrid/models/columnVisibilityModel.d.ts +24 -0
  86. package/components/dataGrid/models/dataSourceModel.d.ts +177 -0
  87. package/components/dataGrid/models/detailRowModel.d.ts +22 -0
  88. package/components/dataGrid/models/editModel.d.ts +77 -0
  89. package/components/dataGrid/models/exportModel.d.ts +51 -0
  90. package/components/dataGrid/models/filterModel.d.ts +22 -0
  91. package/components/dataGrid/models/gridModel.d.ts +293 -0
  92. package/components/dataGrid/models/groupRowCellModel.d.ts +34 -0
  93. package/components/dataGrid/models/groupRowModel.d.ts +68 -0
  94. package/components/dataGrid/models/headerCellModel.d.ts +83 -0
  95. package/components/dataGrid/models/paginationModel.d.ts +32 -0
  96. package/components/dataGrid/models/rowModel.d.ts +46 -0
  97. package/components/dataGrid/models/sourceGroupRowModel.d.ts +45 -0
  98. package/components/dataGrid/models/sourceLevel.d.ts +71 -0
  99. package/components/dataGrid/models/sourceRowModel.d.ts +29 -0
  100. package/components/dataGrid/models/sourceTreeRowModel.d.ts +23 -0
  101. package/components/dataGrid/models/treeModel.d.ts +94 -0
  102. package/components/dataGrid/models/treeRow.d.ts +22 -0
  103. package/components/dataGrid/models/treeRowModel.d.ts +50 -0
  104. package/components/dataGrid/models/viewportModel.d.ts +44 -0
  105. package/components/dataGrid/useGrid.d.ts +8 -0
  106. package/components/dataGrid/useGridNavigation.d.ts +21 -0
  107. package/components/dataGrid.cjs +1 -0
  108. package/components/dataGrid.d.ts +4 -0
  109. package/components/dataGrid.mjs +4907 -0
  110. package/components/dialog.cjs +1 -0
  111. package/components/dialog.d.ts +151 -0
  112. package/components/dialog.mjs +223 -0
  113. package/components/dropdown/dropdownContext.d.ts +44 -0
  114. package/components/dropdown/dropdownItems.d.ts +22 -0
  115. package/components/dropdown/dropdownRowRenderer.d.ts +8 -0
  116. package/components/dropdown/dropdownSearch.d.ts +21 -0
  117. package/components/dropdown/utils.d.ts +1 -0
  118. package/components/dropdown.cjs +1 -0
  119. package/components/dropdown.d.ts +77 -0
  120. package/components/dropdown.mjs +491 -0
  121. package/components/flex.cjs +1 -0
  122. package/components/flex.d.ts +6 -0
  123. package/components/flex.mjs +16 -0
  124. package/components/form.cjs +1 -0
  125. package/components/form.d.ts +10 -0
  126. package/components/form.mjs +58 -0
  127. package/components/grid.cjs +1 -0
  128. package/components/grid.d.ts +6 -0
  129. package/components/grid.mjs +16 -0
  130. package/components/icon.cjs +1 -0
  131. package/components/icon.d.ts +37 -0
  132. package/components/icon.mjs +41 -0
  133. package/components/menu.cjs +1 -0
  134. package/components/menu.d.ts +234 -0
  135. package/components/menu.mjs +422 -0
  136. package/components/overlay.cjs +1 -0
  137. package/components/overlay.d.ts +47 -0
  138. package/components/overlay.mjs +52 -0
  139. package/components/popover.cjs +1 -0
  140. package/components/popover.d.ts +100 -0
  141. package/components/popover.mjs +69 -0
  142. package/components/presence.cjs +1 -0
  143. package/components/presence.d.ts +36 -0
  144. package/components/presence.mjs +11 -0
  145. package/components/progress.cjs +1 -0
  146. package/components/progress.d.ts +47 -0
  147. package/components/progress.mjs +28 -0
  148. package/components/radioButton.cjs +1 -0
  149. package/components/radioButton.d.ts +32 -0
  150. package/components/radioButton.mjs +32 -0
  151. package/components/radioGroup.cjs +1 -0
  152. package/components/radioGroup.d.ts +51 -0
  153. package/components/radioGroup.mjs +83 -0
  154. package/components/select.cjs +1 -0
  155. package/components/select.d.ts +51 -0
  156. package/components/select.mjs +36 -0
  157. package/components/semantics.cjs +1 -0
  158. package/components/semantics.d.ts +39 -0
  159. package/components/semantics.mjs +17 -0
  160. package/components/slider.cjs +1 -0
  161. package/components/slider.d.ts +98 -0
  162. package/components/slider.mjs +250 -0
  163. package/components/svg.cjs +1 -0
  164. package/components/svg.d.ts +65 -0
  165. package/components/svg.mjs +141 -0
  166. package/components/switch.cjs +1 -0
  167. package/components/switch.d.ts +29 -0
  168. package/components/switch.mjs +25 -0
  169. package/components/tabs.cjs +1 -0
  170. package/components/tabs.d.ts +87 -0
  171. package/components/tabs.mjs +324 -0
  172. package/components/textarea.cjs +1 -0
  173. package/components/textarea.d.ts +41 -0
  174. package/components/textarea.mjs +33 -0
  175. package/components/textbox.cjs +1 -0
  176. package/components/textbox.d.ts +38 -0
  177. package/components/textbox.mjs +33 -0
  178. package/components/toaster.cjs +1 -0
  179. package/components/toaster.d.ts +106 -0
  180. package/components/toaster.mjs +295 -0
  181. package/components/tooltip.cjs +1 -0
  182. package/components/tooltip.d.ts +98 -0
  183. package/components/tooltip.mjs +110 -0
  184. package/components/visuallyHidden.cjs +1 -0
  185. package/components/visuallyHidden.d.ts +6 -0
  186. package/components/visuallyHidden.mjs +23 -0
  187. package/docs/a11y.md +199 -0
  188. package/docs/anchor.md +139 -0
  189. package/docs/components.md +48 -0
  190. package/docs/index.md +11 -0
  191. package/docs/props.md +1777 -0
  192. package/effects.cjs +1 -0
  193. package/effects.mjs +6 -0
  194. package/forms.cjs +1 -0
  195. package/forms.mjs +21 -0
  196. package/gridExport.cjs +2 -0
  197. package/gridExport.mjs +244 -0
  198. package/icons/dotsIcon.d.ts +2 -0
  199. package/icons/expandIcon.d.ts +2 -0
  200. package/icons/groupingIcon.d.ts +2 -0
  201. package/icons/pinIcon.d.ts +2 -0
  202. package/icons/searchIcon.d.ts +2 -0
  203. package/icons/sortIcon.d.ts +2 -0
  204. package/identity.cjs +1 -0
  205. package/identity.mjs +12 -0
  206. package/keyboard.cjs +1 -0
  207. package/keyboard.mjs +30 -0
  208. package/layer.cjs +1 -0
  209. package/layer.mjs +127 -0
  210. package/motion.cjs +1 -0
  211. package/motion.mjs +66 -0
  212. package/package.json +327 -7
  213. package/placement.cjs +1 -0
  214. package/placement.mjs +180 -0
  215. package/platform.cjs +1 -0
  216. package/platform.mjs +45 -0
  217. package/react/a11y/callbacks.d.ts +12 -0
  218. package/react/a11y/useControllableState.d.ts +25 -0
  219. package/react/a11y/useDismiss.d.ts +25 -0
  220. package/react/a11y/useFocusReturn.d.ts +18 -0
  221. package/react/a11y/useRovingFocus.d.ts +84 -0
  222. package/react/anchor/useAnchorPosition.d.ts +79 -0
  223. package/react/animation/usePresence.d.ts +32 -0
  224. package/react/boxClassNames.d.ts +25 -0
  225. package/react/boxProps.d.ts +49 -0
  226. package/react/boxTagProps.d.ts +7 -0
  227. package/react/clientRuntime.d.ts +11 -0
  228. package/react/dialog/useScrollLock.d.ts +12 -0
  229. package/react/effects.d.ts +10 -0
  230. package/react/forms/labelledControl.d.ts +17 -0
  231. package/react/forms/placeholderProp.d.ts +13 -0
  232. package/react/hooks/usePortalContainer.d.ts +6 -0
  233. package/react/hooks/useVirtualization.d.ts +32 -0
  234. package/react/hooks/useVisibility.d.ts +9 -0
  235. package/react/identity/useIdentifier.d.ts +17 -0
  236. package/react/popover/usePopoverLayer.d.ts +87 -0
  237. package/react/reactTypes.d.ts +10 -0
  238. package/react/resolveStyles.d.ts +18 -0
  239. package/react/styleElements.d.ts +3 -0
  240. package/react/svg/attributesInProps.d.ts +4 -0
  241. package/react/svg/svgNaming.d.ts +15 -0
  242. package/react/theme/theme.d.ts +26 -0
  243. package/react/theme/themeContext.d.ts +7 -0
  244. package/react/useStyles.d.ts +22 -0
  245. package/react-shared.cjs +1 -0
  246. package/react-shared.mjs +122 -0
  247. package/rolldown-runtime.cjs +1 -0
  248. package/rsc.cjs +1 -0
  249. package/rsc.d.ts +27 -0
  250. package/rsc.mjs +18 -0
  251. package/ssg.cjs +1 -0
  252. package/ssg.d.ts +24 -0
  253. package/ssg.mjs +25 -0
  254. package/utils/accordion/accordionUtils.d.ts +48 -0
  255. package/utils/anchor/anchorUtils.d.ts +79 -0
  256. package/utils/animation/animationUtils.d.ts +29 -0
  257. package/utils/array/arrayUtils.d.ts +15 -0
  258. package/utils/array/lazyList.d.ts +10 -0
  259. package/utils/box/boxUtils.d.ts +5 -0
  260. package/utils/chart/chartPalette.d.ts +15 -0
  261. package/utils/chart/chartUtils.d.ts +92 -0
  262. package/utils/combobox/comboboxUtils.d.ts +89 -0
  263. package/utils/dom/domUtils.d.ts +32 -0
  264. package/utils/environment/environmentUtils.d.ts +28 -0
  265. package/utils/export/csvUtils.d.ts +23 -0
  266. package/utils/export/downloadUtils.d.ts +12 -0
  267. package/utils/export/xlsxUtils.d.ts +56 -0
  268. package/utils/export/zipUtils.d.ts +26 -0
  269. package/utils/fn/fnUtils.d.ts +4 -0
  270. package/utils/form/formUtils.d.ts +8 -0
  271. package/utils/keyboard/typeaheadUtils.d.ts +31 -0
  272. package/utils/memo.d.ts +10 -0
  273. package/utils/menu/menuUtils.d.ts +25 -0
  274. package/utils/object/objectUtils.d.ts +13 -0
  275. package/utils/slider/sliderUtils.d.ts +67 -0
  276. package/utils/string/fuzzySearch.d.ts +27 -0
  277. package/utils/string/stringUtils.d.ts +4 -0
  278. package/utils/tabs/tabsUtils.d.ts +75 -0
  279. package/utils/toast/toastStore.d.ts +73 -0
  280. package/utils/virtual/virtualUtils.d.ts +47 -0
@@ -0,0 +1,84 @@
1
+ import { ChangeDetails, ChangeHandler } from './useControllableState';
2
+ export type RovingFocusReason = 'keyboard' | 'typeahead' | 'focus' | 'programmatic';
3
+ export type RovingOrientation = 'vertical' | 'horizontal' | 'both';
4
+ /** A position in grid mode. Both are `-1` when nothing is active. */
5
+ export interface RovingCell {
6
+ row: number;
7
+ column: number;
8
+ }
9
+ export interface RovingFocusOptions {
10
+ /** How many items there are right now — rows, in grid mode. A filtered list may change this. */
11
+ count: number;
12
+ /**
13
+ * Turns the list into a grid and `count` into a count of rows: how many cells the row at `row` holds, a
14
+ * function when rows differ. Grid mode moves in two axes and never wraps (APG), Home/End go to the
15
+ * row's ends, Ctrl+Home/End to the grid's corners, PageUp/PageDown by `pageSize` rows.
16
+ */
17
+ columns?: number | ((row: number) => number);
18
+ /**
19
+ * Where a cell starts in column-index space, for rows whose cells do not line up one-to-one with the
20
+ * grid's columns (a grouped header, a spanning group row). Vertical movement is measured in this space,
21
+ * so a move down out of a cell covering columns 4–6 lands under the column it started in. Identity by default.
22
+ */
23
+ columnIndexOf?: (row: number, cell: number) => number;
24
+ /** Rows a PageUp/PageDown moves. Default 10. Grid mode only. */
25
+ pageSize?: number;
26
+ /** The starting column *index*, when the caller wants one other than the first. Grid mode only. */
27
+ defaultActiveColumn?: number;
28
+ /** The active cell moved. Grid mode only — `onActiveIndexChange` still reports the row. */
29
+ onActiveCellChange?: ChangeHandler<RovingCell, RovingFocusReason>;
30
+ /** Which arrow keys navigate. Default `vertical`. Ignored in grid mode, which uses both axes. */
31
+ orientation?: RovingOrientation;
32
+ /** Wrap around at the ends. Default true. */
33
+ loop?: boolean;
34
+ activeIndex?: number;
35
+ defaultActiveIndex?: number;
36
+ onActiveIndexChange?: ChangeHandler<number, RovingFocusReason>;
37
+ /** Disabled items are skipped by every movement, as APG requires. */
38
+ isDisabled?: (index: number) => boolean;
39
+ /** An item's text. Supplying it turns on typeahead. */
40
+ textOf?: (index: number) => string;
41
+ /**
42
+ * Move real DOM focus onto the active item — the roving-tabindex pattern. `false` is the other half of
43
+ * the APG list patterns: focus stays put (a combobox's trigger) and `aria-activedescendant` names the
44
+ * active item instead. The hook still tracks the index; it just does not take focus.
45
+ */
46
+ focusItems?: boolean;
47
+ /** Enter, and Space when no typeahead buffer is open. */
48
+ onSelect?: (index: number, event: React.KeyboardEvent) => void;
49
+ }
50
+ export interface RovingFocusItemProps {
51
+ ref: (element: HTMLElement | null) => void;
52
+ tabIndex?: number;
53
+ onFocus?: () => void;
54
+ }
55
+ export interface RovingFocus {
56
+ /** Clamped to the current `count`; `-1` when nothing is active. The row, in grid mode. */
57
+ activeIndex: number;
58
+ /**
59
+ * The active cell's ordinal in its row — its column index only while no cell spans more than one column.
60
+ * `-1` outside grid mode.
61
+ */
62
+ activeColumn: number;
63
+ setActiveIndex: (index: number, details: ChangeDetails<RovingFocusReason>) => void;
64
+ /** Grid mode: move both axes at once, `column` being a cell ordinal. Out-of-range values are clamped. */
65
+ setActiveCell: (row: number, column: number, details: ChangeDetails<RovingFocusReason>) => void;
66
+ /** Put this on the element that has focus: the list in roving-tabindex, the trigger otherwise. */
67
+ onKeyDown: (event: React.KeyboardEvent) => void;
68
+ itemProps: (index: number) => RovingFocusItemProps;
69
+ /** Grid mode's `itemProps`: the roving tabindex and the ref for one cell. */
70
+ cellProps: (row: number, column: number) => RovingFocusItemProps;
71
+ /**
72
+ * The active item's element, for `aria-activedescendant` or to scroll it into view. `null` in grid mode
73
+ * whenever the active cell is not rendered, which a virtualized grid is full of: bring the row into view
74
+ * first, then read this on the render that follows.
75
+ */
76
+ activeItem: () => HTMLElement | null;
77
+ }
78
+ /**
79
+ * Arrow-key navigation over a list: the movement half of every APG list pattern (listbox, menu, tabs,
80
+ * radio group), with both focus strategies. It owns which item is active and how the keys move it; the
81
+ * caller owns the roles and the ARIA, because a listbox and a menu navigate alike and are named quite
82
+ * differently. `columns` turns the same movement into APG's grid pattern, and may be a function of the row.
83
+ */
84
+ export default function useRovingFocus(options: RovingFocusOptions): RovingFocus;
@@ -0,0 +1,79 @@
1
+ import { CSSProperties } from 'react';
2
+ import { BoxStyleProps } from '@box-kite/core/types';
3
+ import { AnchorAlign, AnchorSide } from '../../utils/anchor/anchorUtils';
4
+ import { ElementLike } from '../../utils/dom/domUtils';
5
+ export interface AnchorPositionOptions {
6
+ /** Which side of the anchor to sit on. `top`/`bottom` are the block axis, `start`/`end` the inline one. Default `'bottom'`. */
7
+ side?: AnchorSide;
8
+ /** Which of the anchor's edges to line up with along the other axis. Default `'center'`. */
9
+ align?: AnchorAlign;
10
+ /** The gap between anchor and layer, on the ÷4 spacing scale — `offset: 2` is 8px. Default `0`. */
11
+ offset?: number;
12
+ /**
13
+ * Whether the browser may move the layer where it does not fit: the side swapped for its opposite, the
14
+ * alignment mirrored, or both — three candidates, since a candidate has to fit on both axes. Default `true`.
15
+ */
16
+ flip?: boolean;
17
+ /** Whether the layer is at least as wide as its anchor, the way a select popup is. Default `false`. */
18
+ matchWidth?: boolean;
19
+ /** The anchor's name. Generated per instance when omitted, which is what keeps two layers apart. */
20
+ name?: string;
21
+ /**
22
+ * The anchor as an element rather than props to spread — for a caller handed a trigger it does not
23
+ * render itself. The name is written onto it in a layout effect, so a ref is read when the layer mounts.
24
+ */
25
+ anchor?: ElementLike;
26
+ /**
27
+ * Whether `side` reports where the layer ended up rather than where it was asked to go. Off by default,
28
+ * because on the CSS path it costs the one thing that path otherwise never does: a read after layout.
29
+ */
30
+ trackSide?: boolean;
31
+ }
32
+ /** The two anchor-positioning properties, which csstype does not know yet. An inline style, deliberately — see the hook. */
33
+ type AnchorStyle = CSSProperties & {
34
+ anchorName?: string;
35
+ positionAnchor?: string;
36
+ };
37
+ /** What goes on the anchor: its name, and — where the browser cannot place the layer — a ref to measure it by. */
38
+ export interface AnchorElementProps {
39
+ ref?: (element: HTMLElement | null) => void;
40
+ style: AnchorStyle;
41
+ }
42
+ /** What goes on the floating layer. The geometry is shared props; only the identity and the fallback's coordinates are inline. */
43
+ export interface AnchorLayerProps extends Pick<BoxStyleProps, 'position' | 'positionArea' | 'positionTryFallbacks' | 'minWidth' | 'mt' | 'mb' | 'ms' | 'me'> {
44
+ ref?: (element: HTMLElement | null) => void;
45
+ style: AnchorStyle;
46
+ }
47
+ export interface AnchorPosition {
48
+ /** Whether the browser is placing the layer. `false` means this hook measured it instead. */
49
+ css: boolean;
50
+ /** The side the layer is on: the requested one, unless `trackSide` is on and a flip moved it. */
51
+ side: AnchorSide;
52
+ anchorProps: AnchorElementProps;
53
+ layerProps: AnchorLayerProps;
54
+ }
55
+ /**
56
+ * A floating layer placed against an anchor — in CSS where the browser has anchor positioning, and by
57
+ * measurement where it does not. Spread `anchorProps` on the trigger and `layerProps` on the layer;
58
+ * nothing else is needed, and on the CSS path nothing runs at all: no scroll listener, no state, no
59
+ * measurement, because `position-area` and `position-try-fallbacks` are the flip a positioning library
60
+ * ships JS for.
61
+ *
62
+ * ```tsx
63
+ * const { anchorProps, layerProps } = useAnchorPosition({ side: 'bottom', offset: 2, matchWidth: true });
64
+ *
65
+ * <Button {...anchorProps} onClick={toggle}>Options</Button>
66
+ * {open && <Box {...layerProps} component="menu">…</Box>}
67
+ * ```
68
+ *
69
+ * Two things worth knowing. The layer is `position: fixed`, so it escapes every `overflow: hidden`
70
+ * ancestor without a portal — but not a *transformed* one, which is a fixed element's containing block in
71
+ * either path, and not the stacking order, which is still the page's. And the anchor's **name is an inline
72
+ * style rather than a prop**: an identity is per-instance, so a class for it would be a rule per instance
73
+ * that is never freed — the same rule that makes a sparkline's `d` an attribute and its stroke a class.
74
+ *
75
+ * @a11y None of it. A layer is not a pattern: the role, the dismissal and the focus belong to whatever
76
+ * renders one — `useDismiss` and `useFocusReturn` from `@box-kite/react/a11y` are the other half.
77
+ */
78
+ export default function useAnchorPosition(options?: AnchorPositionOptions): AnchorPosition;
79
+ export {};
@@ -0,0 +1,32 @@
1
+ import { RefCallback } from 'react';
2
+ /** The Radix / Base UI attribute value, so a `[data-state]` selector written for either works here too. */
3
+ export type PresenceState = 'open' | 'closed';
4
+ export interface PresenceOptions {
5
+ /** Whether the subtree should be there. The exit starts the moment this goes false. */
6
+ present: boolean;
7
+ }
8
+ export interface Presence {
9
+ /** Whether to render anything at all: true for the whole exit, false once it has finished. */
10
+ mounted: boolean;
11
+ /** False from the first frame of the exit — the flag the leaving styles hang off. */
12
+ present: boolean;
13
+ state: PresenceState;
14
+ /** Goes on the element that carries the transition: its computed style is what the wait is measured from. */
15
+ ref: RefCallback<HTMLElement>;
16
+ /** `{ 'data-state': … }`, ready to spread into a Box's `props`. */
17
+ props: {
18
+ 'data-state': PresenceState;
19
+ };
20
+ }
21
+ /**
22
+ * Holds a subtree long enough for its exit to run, then lets it go. React removes a node the instant it
23
+ * stops rendering it, which is why `startingStyle` can animate an entrance with no JavaScript and nothing
24
+ * can animate an exit: by the time the styles would change, the element is already gone.
25
+ *
26
+ * **The wait is the duration the element's own CSS declares**, read off the node the moment the exit
27
+ * starts. `transitionend` would be more precise but fires once per property with no way to know how many
28
+ * are coming, so the first one cuts a two-property exit short — and a transition that never starts fires
29
+ * nothing at all, so an event-driven wait needs this timer as a backstop anyway. One mechanism, sized from
30
+ * the real CSS: a zero duration (nothing declared, or `prefers-reduced-motion`) unmounts in the same commit.
31
+ */
32
+ export default function usePresence(options: PresenceOptions): Presence;
@@ -0,0 +1,25 @@
1
+ import { ClassNameType } from '@box-kite/core';
2
+ import { ResolvedBoxStyles } from './resolveStyles';
3
+ /**
4
+ * What `useClassNames` hands back: the class attribute for an element this library does not render
5
+ * itself, and — in element mode only — the `<style>` elements those classes need.
6
+ */
7
+ export interface BoxClassNames {
8
+ /** The whole `class` attribute, the engine's classes and the caller's own, already joined. */
9
+ className: string;
10
+ /**
11
+ * Element mode only: the hoistable `<style>` elements the classes need. Render them beside the
12
+ * element (React 19 lifts them into `<head>`). Undefined in every other mode, where the CSS has
13
+ * already gone to a stylesheet and there is nothing left to render.
14
+ */
15
+ styles?: ResolvedBoxStyles['styleElements'];
16
+ }
17
+ /**
18
+ * The resolved styles as a class attribute. Hook-free, so the client entry and the Server-Component
19
+ * one give `useClassNames` the same shape — the only difference between them is whether resolving
20
+ * the styles scheduled a flush effect.
21
+ */
22
+ export default function boxClassNames({ classNames: styleClasses, styleElements }: ResolvedBoxStyles, userClassName?: ClassNameType): {
23
+ className: string;
24
+ styles: import('react').ReactElement<unknown, string | import('react').JSXElementConstructor<any>>[] | undefined;
25
+ };
@@ -0,0 +1,49 @@
1
+ import { default as React } from 'react';
2
+ import { ClassNameType } from '@box-kite/core';
3
+ import { BoxStyleProps, ComponentsAndVariants } from '@box-kite/core/types';
4
+ /**
5
+ * The prop shape of Box, shared by the client component and the Server-Component one so the public
6
+ * surface cannot drift between them.
7
+ */
8
+ type AllProps<TTag extends keyof React.JSX.IntrinsicElements> = React.ComponentProps<TTag>;
9
+ /** `data-*`, which React's own attribute types allow only in JSX position and never in a props bag. */
10
+ type DataAttributes = {
11
+ [attribute: `data-${string}`]: string | number | boolean | undefined;
12
+ };
13
+ type TagProps<TTag extends keyof React.JSX.IntrinsicElements> = Omit<AllProps<TTag>, 'className' | 'style' | 'ref' | 'disabled' | 'required' | 'checked' | 'id'>;
14
+ /**
15
+ * Every attribute the tag takes, plus `data-*` (bug #99: `props={{ 'data-state': 'open' }}` did not
16
+ * typecheck, and `<Box data-state>` did but was dropped, since Box forwards nothing but `props`). A union
17
+ * rather than an intersection: an index signature in the target makes every *interface* passed as a bag
18
+ * unassignable, and `TooltipTrigger.props` is one. Anything else unknown still fails.
19
+ */
20
+ export type TagPropsType<TTag extends keyof React.JSX.IntrinsicElements> = TagProps<TTag> | (TagProps<TTag> & DataAttributes);
21
+ /**
22
+ * `Omit` one union member at a time, for a component claiming attributes of its own. A plain `Omit` over
23
+ * a union keeps only the keys every member shares, so it collapsed the two above into one and dropped
24
+ * `data-*` again — bug #99 one layer up, on every pre-built component.
25
+ */
26
+ export type OmitTagProps<TProps, TKeys extends PropertyKey> = TProps extends unknown ? Omit<TProps, TKeys> : never;
27
+ /**
28
+ * The style props plus the `className` the engine's classes are merged with — everything the
29
+ * resolution needs and nothing about a tag. `useClassNames` takes this, which is why it can style
30
+ * an element this library does not render.
31
+ */
32
+ export interface BoxClassNameProps<TKey extends keyof ComponentsAndVariants = never> extends BoxStyleProps<TKey> {
33
+ /** classNames. supports conditional classNames. */
34
+ className?: ClassNameType;
35
+ }
36
+ export interface BoxCoreProps<TTag extends keyof React.JSX.IntrinsicElements, TKey extends keyof ComponentsAndVariants> extends BoxClassNameProps<TKey> {
37
+ children?: React.ReactNode | ((props: {
38
+ isHover: boolean;
39
+ }) => React.ReactNode);
40
+ /** html tag element */
41
+ tag?: TTag;
42
+ /** props (attributes) related to html tag */
43
+ props?: TagPropsType<TTag>;
44
+ /** CSSProperties */
45
+ style?: React.ComponentProps<TTag>['style'];
46
+ /** The HTML id attribute is used to specify a unique id for an HTML element. */
47
+ id?: string;
48
+ }
49
+ export {};
@@ -0,0 +1,7 @@
1
+ import { BoxStyleProps } from '@box-kite/core/types';
2
+ /**
3
+ * The props that reach the HTML tag: whatever the caller put in `props`, the resolved class list,
4
+ * and the handful of attributes Box lifts to its own top level. Hook-free, so the client Box and
5
+ * the Server-Component Box assemble their markup through the same code.
6
+ */
7
+ export default function buildTagProps(source: BoxStyleProps<any>, styleClasses: string[]): Record<string, any>;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * The client half of the library needs React APIs the server build does not have. Under the `react-server`
3
+ * condition they are absent, so the first one touched at import time throws `createContext is not a
4
+ * function` — no file, no component, nothing to act on (bug #43). The published build prevents that; this
5
+ * is for the ways around it: a deep import, a bundler with no condition, a framework mixing the graphs.
6
+ */
7
+ export declare const CLIENT_RUNTIME_MESSAGE: string;
8
+ /** Throws with something readable if `react` is the server build. Called where the first one is needed. */
9
+ export default function assertClientRuntime(react: {
10
+ createContext?: unknown;
11
+ }): void;
@@ -0,0 +1,12 @@
1
+ import { default as React } from 'react';
2
+ /**
3
+ * Stop the page behind a layer from scrolling, with a class rather than an inline style — so it is one
4
+ * shared rule like every other value this library writes, and a consumer can see what did it. Returns
5
+ * the style elements to render, which is element mode's way of getting a rule onto the page at all.
6
+ *
7
+ * `overflow: hidden` on `<html>` is the whole mechanism, which means two things worth knowing: the
8
+ * scrollbar's width leaves the page as it is applied, so a document that wants no shift should carry
9
+ * `scrollbarGutter="stable"`; and iOS Safari scrolls anyway, where nothing short of `position: fixed`
10
+ * on the body holds it.
11
+ */
12
+ export default function useScrollLock(enabled: boolean): React.ReactElement[] | undefined;
@@ -0,0 +1,10 @@
1
+ import { default as React, useLayoutEffect } from 'react';
2
+ /** A layout effect on the browser, a passive one everywhere else. */
3
+ export declare const useIsomorphicLayoutEffect: typeof React.useEffect;
4
+ /**
5
+ * An insertion effect on the browser, falling back to a layout effect on React 16/17 — React's own
6
+ * recommendation for injecting CSS-in-JS. Insertion effects run during the commit ahead of *every* layout
7
+ * effect, so a component measuring its DOM already sees the styles. Off the browser nothing paints and
8
+ * `getStyles()` flushes for itself, so `useEffect` keeps React quiet.
9
+ */
10
+ export declare const useIsomorphicInsertionEffect: typeof useLayoutEffect;
@@ -0,0 +1,17 @@
1
+ import { BoxProps } from '../../box';
2
+ export interface LabelledControlProps {
3
+ /** The text beside the control. Nothing is wrapped while this is absent. */
4
+ label?: React.ReactNode;
5
+ /** Styles for the `<label>` that wraps the pair — layout, not the control's own appearance. */
6
+ labelProps?: BoxProps<'label'>;
7
+ /** The control itself: an `<input>` that must end up *inside* the label element. */
8
+ children: React.ReactNode;
9
+ }
10
+ /**
11
+ * A form control and its text inside the one `<label>` that ties them together, implicitly: nothing has to
12
+ * be unique (an explicit `for`/`id` pair needs `useId`, a hook, so `RadioButton` would stop rendering on a
13
+ * server) and there is one element to click, so the whole row is a hit target. The text is a bare child
14
+ * rather than a `<Span>`, because a module several chunks share must not import a component chunk — that
15
+ * cycle left `StringUtils` undefined as soon as `semantics.mjs` loaded.
16
+ */
17
+ export default function LabelledControl({ label, labelProps, children }: LabelledControlProps): React.ReactNode;
@@ -0,0 +1,13 @@
1
+ import { BoxPseudoElementStyles } from '@box-kite/core/types';
2
+ /**
3
+ * `placeholder` is an attribute on an `<input>` and a pseudo-element on a Box, and both readings are
4
+ * right — the same collision `Rect`'s `width` and `Path`'s `d` have, settled per element. A string is the
5
+ * text, an object is the `::placeholder` styles, and both at once means the text goes in `props`, where
6
+ * every other attribute already goes.
7
+ */
8
+ export type PlaceholderProp = string | BoxPseudoElementStyles;
9
+ /** The prop split into the two things it can be: `text` for the attribute, `styles` for the Box prop. */
10
+ export default function splitPlaceholder(placeholder: PlaceholderProp | undefined): {
11
+ text?: string;
12
+ styles?: BoxPseudoElementStyles;
13
+ };
@@ -0,0 +1,6 @@
1
+ /**
2
+ * The container every portalled layer shares, created on first use. Pass `false` on the top-layer path,
3
+ * where nothing is portalled: the container is a DOM node plus a theme-class subscription, and a layer
4
+ * that stays where it was declared inherits the theme instead of needing one copied onto it.
5
+ */
6
+ export default function usePortalContainer(enabled?: boolean): HTMLElement | null;
@@ -0,0 +1,32 @@
1
+ import { VirtualWindow } from '../../utils/virtual/virtualUtils';
2
+ export interface UseVirtualizationOptions {
3
+ /** How many rows there are in total — not how many are rendered. */
4
+ count: number;
5
+ /** The scrolling element: what it shows at once is the viewport, and its own rows are the pitch. */
6
+ scrollerRef: React.RefObject<HTMLElement | null>;
7
+ /** The pitch of a row, when it should be declared rather than measured. */
8
+ itemHeight?: number;
9
+ /** What the scroller shows, when it should be declared rather than measured. */
10
+ viewHeight?: number;
11
+ overscan?: number;
12
+ threshold?: number;
13
+ /** Forces windowing on or off. Left off, it follows the row count against `threshold`. */
14
+ enabled?: boolean;
15
+ /** The row the keyboard is on. Always rendered, whatever the scroll position says. */
16
+ activeIndex?: number;
17
+ }
18
+ export interface UseVirtualizationResult extends VirtualWindow {
19
+ /** Whether the list is being windowed at all. `false` means render every row and ignore the rest. */
20
+ virtualized: boolean;
21
+ /** Goes on the element that holds the rendered rows — the one the pitch is measured from. */
22
+ contentRef: (element: HTMLElement | null) => void;
23
+ /** Goes on the scrolling element. */
24
+ onScroll: (event: React.UIEvent<HTMLElement>) => void;
25
+ }
26
+ /**
27
+ * Renders a window of a long list instead of all of it, over the framework-free arithmetic in
28
+ * `VirtualUtils`. The two measurements it needs are taken from the DOM rather than declared, so a row
29
+ * restyled by the caller still windows correctly; until something has been laid out (a first render, or
30
+ * a test environment that computes none) the defaults in the model stand in.
31
+ */
32
+ export default function useVirtualization(options: UseVirtualizationOptions): UseVirtualizationResult;
@@ -0,0 +1,9 @@
1
+ interface Props<T extends HTMLElement = HTMLDivElement> {
2
+ node?: T | null;
3
+ event?: 'mousedown' | 'click';
4
+ hideOnScroll?: boolean;
5
+ hideOnResize?: boolean;
6
+ hideOnEscape?: boolean;
7
+ }
8
+ export default function useVisibility<T extends HTMLElement = HTMLDivElement>(props?: Props<T>): [boolean, React.Dispatch<React.SetStateAction<boolean>>, React.RefObject<T | null>];
9
+ export {};
@@ -0,0 +1,17 @@
1
+ /**
2
+ * A stable, unique id for wiring one element to another — `aria-labelledby`, `aria-controls`,
3
+ * `aria-activedescendant`, `<label for>`.
4
+ *
5
+ * Stable means: the same across renders, the same on the server and on the client (so hydration
6
+ * does not throw the markup away), and different for every instance of a component. Derive related
7
+ * ids from one call rather than calling the hook per element:
8
+ *
9
+ * ```ts
10
+ * const id = useIdentifier('select');
11
+ * // `${id}-trigger`, `${id}-listbox`
12
+ * ```
13
+ *
14
+ * On React 16/17 the fallback is a module counter, which cannot match between a server render and
15
+ * the client one — pass ids in explicitly there if the tree is hydrated.
16
+ */
17
+ export default function useIdentifier(prefix?: string): string;
@@ -0,0 +1,87 @@
1
+ import { ElementLike } from '../../utils/dom/domUtils';
2
+ import { ChangeHandler, SetControllableState } from '../a11y/useControllableState';
3
+ /** Why a layer opened or closed — every component built on this reports the same four. */
4
+ export type PopoverReason = 'trigger' | 'escape' | 'outside-pointer' | 'imperative';
5
+ /** What a trigger says it opens, which is the one thing the layers built on this disagree about. */
6
+ export type PopoverHasPopup = 'dialog' | 'menu';
7
+ /** The DOM attributes a trigger has to carry, whatever it opens. */
8
+ export interface PopoverTriggerAttributes<THasPopup extends PopoverHasPopup = PopoverHasPopup> {
9
+ 'aria-expanded': boolean;
10
+ 'aria-haspopup': THasPopup;
11
+ 'aria-controls'?: string;
12
+ /** Only where the browser has no Popover API. On the platform path `popovertarget` does the toggling. */
13
+ onClick?(event: React.MouseEvent): void;
14
+ }
15
+ /**
16
+ * What the trigger has to carry: spread it onto the control itself, not a wrapper. The `ref` is what the
17
+ * layer is anchored to, so it is not optional decoration.
18
+ *
19
+ * It must be a **button**: `popovertarget` is what the browser toggles on, and it only reads it off one.
20
+ */
21
+ export interface PopoverTrigger<THasPopup extends PopoverHasPopup = PopoverHasPopup> {
22
+ ref: React.RefCallback<HTMLElement>;
23
+ props: PopoverTriggerAttributes<THasPopup>;
24
+ }
25
+ export interface PopoverLayerOptions<THasPopup extends PopoverHasPopup = PopoverHasPopup, TReason extends string = never> {
26
+ /** What the trigger says it opens. */
27
+ haspopup: THasPopup;
28
+ /** A consumer id wins over the generated one, and everything that names the layer follows it. */
29
+ id?: string;
30
+ /** What the generated id is prefixed with, so a debugger says which component it belongs to. */
31
+ idPrefix: string;
32
+ open?: boolean;
33
+ defaultOpen?: boolean;
34
+ onOpenChange?: ChangeHandler<boolean, PopoverReason | TReason>;
35
+ /**
36
+ * The layer is open *and* laid out — the only moment focus can be moved into it. On the platform path
37
+ * this is the `toggle` event rather than an effect on the open state, and the difference is not
38
+ * academic: `beforetoggle` fires before the panel opens and a discrete event is flushed synchronously,
39
+ * so an effect would run while `:popover-open` still does not match, which is `display: none` — and
40
+ * focusing a hidden element does nothing at all (measured).
41
+ */
42
+ onOpened?(panel: HTMLElement): void;
43
+ /**
44
+ * It is about to close, and `heldFocus` says whether it has focus. Fired from `beforetoggle`, while the
45
+ * panel is still shown, because that is the last moment focus can be moved without a flash: the platform
46
+ * returns focus to whatever had it before the **outermost** layer opened, and for a nested one it does
47
+ * nothing at all — focus drops to `<body>` (both measured in Chrome 152). A submenu puts focus back on
48
+ * its own item from here.
49
+ */
50
+ onClosing?(heldFocus: boolean, trigger: HTMLElement | null): void;
51
+ /**
52
+ * More elements a press inside counts as inside, for the portal path only: a nested layer is portalled
53
+ * out of the DOM it was declared in, so nothing about the tree says a press in it is a press in this
54
+ * one. The platform answers that question itself, by the popover nesting rules.
55
+ */
56
+ inside?: readonly ElementLike[];
57
+ }
58
+ export interface PopoverLayer<THasPopup extends PopoverHasPopup = PopoverHasPopup, TReason extends string = never> {
59
+ /** Whether the browser's Popover API is placing the layer in the top layer. `false` is the portal path. */
60
+ platform: boolean;
61
+ isOpen: boolean;
62
+ setOpen: SetControllableState<boolean, PopoverReason | TReason>;
63
+ id: string;
64
+ /** What the trigger render prop is handed. */
65
+ trigger: PopoverTrigger<THasPopup>;
66
+ triggerElement: HTMLElement | null;
67
+ /**
68
+ * The trigger's id — what names a layer after the control that opened it, which is what APG asks of a
69
+ * menu. One is written onto the trigger when it has none of its own.
70
+ */
71
+ triggerId?: string;
72
+ /** Goes on the panel, on both paths. */
73
+ setPanel: React.RefCallback<HTMLElement>;
74
+ panelElement: HTMLElement | null;
75
+ }
76
+ /**
77
+ * One conversation with the Popover API, for every component that opens a layer on it: the open state,
78
+ * the platform mirror, the dismissal reasons, and the two primitives that stand in where the browser has
79
+ * no popover at all. `Popover` is this plus a `role="dialog"` panel; `Menu` is this three times over —
80
+ * once for the menu and once per open submenu.
81
+ *
82
+ * What the platform owns, measured in Chrome 152: the top layer, light dismiss (Escape and an outside
83
+ * press), the toggle from a `popovertarget` trigger — including the press that closes an open layer from
84
+ * its own trigger, with no reopen — and focus return for the outermost layer. What it does not own is
85
+ * focus *into* the layer, focus return for a nested one, and any of the ARIA.
86
+ */
87
+ export default function usePopoverLayer<THasPopup extends PopoverHasPopup, TReason extends string = never>(options: PopoverLayerOptions<THasPopup, TReason>): PopoverLayer<THasPopup, TReason>;
@@ -0,0 +1,10 @@
1
+ import { default as React } from 'react';
2
+ /**
3
+ * React-only type helpers. These live in the adapter rather than in `src/core/coreTypes.ts`
4
+ * because they are expressed in React's own JSX types — the style definitions themselves stay
5
+ * framework-free so every adapter can share them.
6
+ */
7
+ /** The DOM element type behind a set of React props (`HTMLAttributes<E>` / `SVGProps<E>` → `E`). */
8
+ export type ExtractElementType<T> = T extends React.DetailedHTMLProps<React.HTMLAttributes<infer E>, infer E> ? E : T extends React.SVGProps<infer E> ? E : never;
9
+ /** The DOM element type behind an intrinsic tag name (`'input'` → `HTMLInputElement`). */
10
+ export type ExtractElementFromTag<T extends keyof React.JSX.IntrinsicElements> = ExtractElementType<React.JSX.IntrinsicElements[T]>;
@@ -0,0 +1,18 @@
1
+ import { default as React } from 'react';
2
+ import { BoxStyleProps } from '@box-kite/core/types';
3
+ export interface ResolvedBoxStyles {
4
+ classNames: string[];
5
+ /**
6
+ * Element mode only: the hoistable `<style>` elements this Box's classes need, the engine's base
7
+ * element first. Undefined in every other mode, where the CSS has already gone to a stylesheet.
8
+ */
9
+ styleElements?: React.ReactElement[];
10
+ }
11
+ /**
12
+ * Resolve a Box's classes with no hook at all — the render path a Server Component takes. In element mode
13
+ * what those classes need comes back as elements to render, so there is nothing to flush. Its own module
14
+ * for that reason: the RSC entry must reach this without pulling in `useStyles` and its flush effect.
15
+ */
16
+ export default function resolveStyles(props: BoxStyleProps<any>, isSvg: boolean): ResolvedBoxStyles & {
17
+ signature: string | null;
18
+ };
@@ -0,0 +1,3 @@
1
+ import { default as React } from 'react';
2
+ import { StyleElementDescriptor } from '@box-kite/core';
3
+ export default function styleElementsOf(descriptors: readonly StyleElementDescriptor[] | undefined): React.ReactElement[] | undefined;
@@ -0,0 +1,4 @@
1
+ /** Marks a component of this library's own: its DOM attributes belong in `props`, not on top. */
2
+ export declare function withAttributesInProps<TComponent>(component: TComponent): TComponent;
3
+ /** Whether an element's `type` is one of those components. Anything else takes attributes on top. */
4
+ export declare function hasAttributesInProps(type: unknown): boolean;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * A drawing nobody named is decoration, which `aria-hidden` says and silence leaves ambiguous; `label` is
3
+ * the opt-in that makes it `role="img"`. The same rule for every `<svg>` this library puts on a page,
4
+ * whether it renders the element (`Svg`) or hands the attributes to one somebody else renders (`Icon`).
5
+ * `given` is naming the caller wrote by hand — if there is any, the decision was theirs.
6
+ */
7
+ export default function svgNaming(label: string | undefined, given: object | undefined): {
8
+ role: string;
9
+ 'aria-label': string;
10
+ 'aria-hidden'?: undefined;
11
+ } | {
12
+ 'aria-hidden': boolean;
13
+ role?: undefined;
14
+ 'aria-label'?: undefined;
15
+ } | undefined;
@@ -0,0 +1,26 @@
1
+ import { default as React } from 'react';
2
+ import { BoxStyleProps } from '@box-kite/core/types';
3
+ interface ThemeProps {
4
+ children: React.ReactNode;
5
+ theme?: string;
6
+ use?: 'global' | 'local';
7
+ /** When provided, persists the user-selected theme to localStorage under this key. */
8
+ storageKey?: string;
9
+ /**
10
+ * App-wide Box style props applied to the document root (`<html>`). Only takes effect when `use="global"`.
11
+ * Supports the same shape as Box props, including theme-keyed values:
12
+ * `globalStyles={{ scrollbarColor: ['violet-500', 'transparent'], theme: { dark: { scrollbarColor: [...] } } }}`.
13
+ */
14
+ globalStyles?: BoxStyleProps;
15
+ }
16
+ /**
17
+ * The React binding for the theme system. Everything that actually touches the platform — reading
18
+ * and watching `prefers-color-scheme`, persisting the choice, writing the theme onto an element —
19
+ * lives in the framework-free `core/theme/themeRuntime`; this component only holds the React state
20
+ * and context around it.
21
+ */
22
+ declare function Theme(props: ThemeProps): React.JSX.Element;
23
+ declare namespace Theme {
24
+ function useTheme(): [string, (theme: string | null) => void];
25
+ }
26
+ export default Theme;
@@ -0,0 +1,7 @@
1
+ import { default as React } from 'react';
2
+ interface ThemeContextProps {
3
+ theme: string;
4
+ setTheme(theme: string | null): void;
5
+ }
6
+ declare const ThemeContext: React.Context<ThemeContextProps>;
7
+ export default ThemeContext;
@@ -0,0 +1,22 @@
1
+ import { StylesConfiguration } from '@box-kite/core';
2
+ import { BoxStyleProps } from '@box-kite/core/types';
3
+ import { ResolvedBoxStyles } from './resolveStyles';
4
+ export type { StylesConfiguration };
5
+ export default function useStyles(props: BoxStyleProps<any>, isSvg: boolean): ResolvedBoxStyles;
6
+ /**
7
+ * Rules that target a root selector (`html`) instead of a class. Returns their style elements in
8
+ * element mode — global styles belong to no Box, so the caller has to render them itself.
9
+ */
10
+ export declare function useGlobalStyles(props: BoxStyleProps<any> | undefined, selector: string): React.ReactElement[] | undefined;
11
+ /** Engine controls for the default instance. For an isolated engine use `createStyleEngine()`. */
12
+ export declare namespace StylesContext {
13
+ /** Write every pending rule now. The React binding calls this from an insertion effect. */
14
+ function flushSync(): void;
15
+ function clear(): void;
16
+ /** The CSS emitted so far, as text. Flushes first — see `StyleEngine.getStyles`. */
17
+ function getStyles(): string;
18
+ /** The id of the `<style>` element the default engine writes to. */
19
+ function styleElementId(): string;
20
+ /** Apply explicit engine configuration. Call before the first render — cached class names are dropped when the configuration changes. */
21
+ function configure(config: StylesConfiguration): void;
22
+ }