@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,32 @@
1
+ /**
2
+ * "Did this happen inside that?" — the question behind every popup that closes when you click away, asked
3
+ * identically by `useVisibility` and `useDismiss`. `ElementLike` is structural rather than
4
+ * `React.RefObject`, which keeps the file framework-free. Named exports rather than a namespace, for the
5
+ * reason in `environmentUtils.ts`: a namespace object cannot be tree-shaken a function at a time.
6
+ */
7
+ export type ElementLike = {
8
+ readonly current: Element | null;
9
+ } | Element | null | undefined;
10
+ /** The element behind a ref or an element, whichever the caller happens to be holding. */
11
+ export declare function elementOf(value: ElementLike): Element | null;
12
+ /** The same, narrowed to an `HTMLElement` — for callers that need `focus()` or `style`. */
13
+ export declare function htmlElementOf(value: ElementLike): HTMLElement | null;
14
+ /**
15
+ * Whether an event happened inside any of these elements. `composedPath()` first, so an event from a
16
+ * shadow root counts as inside its host; `contains()` as the fallback, since the path is populated only
17
+ * while the event is being dispatched.
18
+ */
19
+ export declare function isEventInside(event: Event, elements: readonly ElementLike[]): boolean;
20
+ /**
21
+ * Whether this element reads right to left — the direction the browser *resolved*, which is the only
22
+ * form of the answer that accounts for a `dir="auto"` or a `<bdi>` above it. Nothing but
23
+ * `getComputedStyle` knows it, and jsdom computes no direction at all, so a test environment reads as
24
+ * left to right — which is the initial value anyway.
25
+ */
26
+ export declare function isRtl(value: ElementLike): boolean;
27
+ /**
28
+ * Drop whatever the document has selected. A double press selects the word under it before any handler
29
+ * runs, so a widget that *replaces* what was pressed leaves a range over content that no longer exists —
30
+ * which the browser repairs to the nearest boundary and then paints over whatever is rendered inside it.
31
+ */
32
+ export declare function clearSelection(element: ElementLike): void;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * "Is there a DOM, and what may I touch?" — asked in seven places and once answered with a hand-written
3
+ * `typeof` in each. The answers are not interchangeable: a server render has no `document`, a `document`
4
+ * may have no `<head>`, and `matchMedia` is missing from environments that look like browsers. Named
5
+ * exports rather than a namespace, which compiles to an IIFE that ships whole, and every chunk imports this.
6
+ */
7
+ /** A browser: a window with a document. What an effect that touches layout needs to exist. */
8
+ export declare function isBrowser(): boolean;
9
+ /** Whether there is a document at all — false during a server render. */
10
+ export declare function hasDocument(): boolean;
11
+ /** The document, or null when there is none, so a caller can `?.` instead of branching. */
12
+ export declare function documentOrNull(): Document | null;
13
+ /** The document root (`<html>`), or null when there is no DOM. */
14
+ export declare function documentRoot(): Element | null;
15
+ /** The `<head>` to write a stylesheet into, or null when there is nothing to write to. */
16
+ export declare function documentHead(): HTMLHeadElement | null;
17
+ /**
18
+ * Whether the browser has the Popover API, which is what puts a floating layer in the top layer. Asked
19
+ * per mount rather than cached, so a test can install the contract and answer for the browser.
20
+ */
21
+ export declare function supportsPopover(): boolean;
22
+ /**
23
+ * Whether the browser owns a `<dialog>`'s light dismiss: `closedby="any"` closes it on a press outside,
24
+ * and `closedby="closerequest"` gives a non-modal one Escape. Asked per mount, like `supportsPopover`.
25
+ */
26
+ export declare function supportsDialogClosedBy(): boolean;
27
+ /** A media query, or null where `matchMedia` does not exist — a server, or a bare jsdom. */
28
+ export declare function matchMedia(query: string): MediaQueryList | null;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * CSV, to RFC 4180, plus the two things a spreadsheet adds to it: a byte-order mark, without which Excel
3
+ * reads UTF-8 as the local code page and mangles every accented name, and the leading characters that
4
+ * make a *value* into a formula.
5
+ */
6
+ declare namespace CsvUtils {
7
+ interface Options {
8
+ /** The field separator. A semicolon is what a spreadsheet expects in a locale using a decimal comma. */
9
+ delimiter?: string;
10
+ /**
11
+ * Prefix a value beginning `=`, `+`, `-` or `@` with a quote, so a spreadsheet reads it as text.
12
+ * On by default: a cell somebody typed is data, and a downloaded file that runs it is CSV injection.
13
+ */
14
+ escapeFormulas?: boolean;
15
+ }
16
+ /** What Excel needs at the top of the file to read the rest of it as UTF-8. */
17
+ const BOM = "\uFEFF";
18
+ /** One value as a field: quoted when it holds a delimiter, a quote or a newline, and never otherwise. */
19
+ function field(value: unknown, options?: Options): string;
20
+ /** The whole file. Rows are joined with CRLF, which is what the RFC specifies and what Excel writes. */
21
+ function csv(rows: unknown[][], options?: Options): string;
22
+ }
23
+ export default CsvUtils;
@@ -0,0 +1,12 @@
1
+ /** Handing a file the page generated to the person looking at it. */
2
+ declare namespace DownloadUtils {
3
+ /**
4
+ * A file the browser saves. There is no API for "save this" — an anchor with a `download` attribute is
5
+ * the mechanism, so the link is created, clicked and removed within the call.
6
+ *
7
+ * The object URL is revoked on the next task rather than immediately: Safari reads it *after* the click
8
+ * handler returns, and a revoke in the same turn leaves the file empty.
9
+ */
10
+ function download(data: BlobPart, fileName: string, type: string): void;
11
+ }
12
+ export default DownloadUtils;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * A spreadsheet, written out. An `.xlsx` is a ZIP of XML parts (ECMA-376), so the whole format is a
3
+ * handful of strings and `ZipUtils` — which is why this library exports Excel with no dependency to
4
+ * install and nothing added to the grid's bundle until somebody presses the button.
5
+ *
6
+ * What is here is the part a table needs: values that keep their type, a number format, a bold header on
7
+ * a fill, column widths, a frozen header row, an auto-filter, and outline levels so a grouped grid opens
8
+ * in Excel grouped. What is not here is everything else a workbook can hold — formulas, several sheets,
9
+ * images, charts, conditional formats. This is a writer for one table, not an Excel implementation.
10
+ */
11
+ declare namespace XlsxUtils {
12
+ /** What a cell can hold. A `Date` is written as Excel's own serial number, with a date format on it. */
13
+ type Value = string | number | boolean | Date | null | undefined;
14
+ /** One cell's appearance. Each distinct combination becomes one entry in the workbook's style table. */
15
+ interface Style {
16
+ bold?: boolean;
17
+ /** `RRGGBB`, the only colour spelling a workbook has — it carries no theme and no palette. */
18
+ color?: string;
19
+ fill?: string;
20
+ /** An Excel number format, `'#,##0.00'` or `'yyyy-mm-dd'`. */
21
+ format?: string;
22
+ align?: 'left' | 'center' | 'right';
23
+ /** Indent steps, which is how a grouped row is stepped in beside its outline level. */
24
+ indent?: number;
25
+ }
26
+ interface Cell {
27
+ value: Value;
28
+ style?: Style;
29
+ }
30
+ interface Row {
31
+ cells: Cell[];
32
+ /** Outline level: 0 is top level, and a row one deeper is a child of the last row above it. */
33
+ level?: number;
34
+ /** Collapsed out of sight, which is how a collapsed group in the grid opens collapsed in Excel. */
35
+ hidden?: boolean;
36
+ /** On the summary row of a collapsed group — the row carrying the outline's own toggle. */
37
+ collapsed?: boolean;
38
+ }
39
+ interface Sheet {
40
+ name: string;
41
+ /** Column widths in characters, one per column; `undefined` leaves Excel's default. */
42
+ widths: (number | undefined)[];
43
+ rows: Row[];
44
+ /** How many rows stay on screen when the sheet is scrolled. */
45
+ freeze?: number;
46
+ /** Whether the header row gets Excel's filter buttons. A grouped sheet is given none. */
47
+ autoFilter?: boolean;
48
+ }
49
+ /** Text as XML content. The control characters XML 1.0 has no spelling for are dropped rather than escaped. */
50
+ function escape(text: string): string;
51
+ /** A column's letters, the way a spreadsheet names one: 0 is `A`, 26 is `AA`. */
52
+ function columnName(index: number): string;
53
+ /** The six parts of a one-sheet workbook, zipped. */
54
+ function workbook(sheet: Sheet): Uint8Array<ArrayBuffer>;
55
+ }
56
+ export default XlsxUtils;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * The half of the ZIP format a spreadsheet needs. An `.xlsx` is a ZIP of XML parts, and the format allows
3
+ * an entry to be *stored* rather than deflated — so a workbook can be written with no compressor and no
4
+ * dependency at all. Excel reads a stored archive exactly as it reads a compressed one; the file is
5
+ * larger, and it is XML, so a gzipped download is the same size either way.
6
+ *
7
+ * Every entry carries the same DOS timestamp (1980-01-01, the epoch the format starts at), which is what
8
+ * makes the same table export byte-for-byte the same file twice.
9
+ */
10
+ declare namespace ZipUtils {
11
+ /** One file in the archive: the path it is stored under, and its bytes. */
12
+ interface Entry {
13
+ name: string;
14
+ data: Uint8Array;
15
+ }
16
+ /** The checksum every ZIP entry carries, in both of its headers. */
17
+ function crc32(data: Uint8Array): number;
18
+ /** A part's text as the bytes it is stored as. Every part of a workbook is UTF-8 XML. */
19
+ function utf8(text: string): Uint8Array;
20
+ /**
21
+ * The archive, as one buffer: every entry's local header and bytes, then a central directory repeating
22
+ * those headers with each entry's offset, then the record saying where the directory starts.
23
+ */
24
+ function zip(entries: Entry[]): Uint8Array<ArrayBuffer>;
25
+ }
26
+ export default ZipUtils;
@@ -0,0 +1,4 @@
1
+ declare namespace FnUtils {
2
+ function throttle<T extends unknown[]>(callback: (...args: T) => void, wait?: number): (...args: T) => void;
3
+ }
4
+ export default FnUtils;
@@ -0,0 +1,8 @@
1
+ type FormValue = string | string[] | number | number[] | boolean;
2
+ interface FormObject {
3
+ [index: string]: FormValue | FormObject;
4
+ }
5
+ declare namespace FormUtils {
6
+ function getFormEntries(form: HTMLFormElement): FormObject;
7
+ }
8
+ export default FormUtils;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Type-to-find over a list, which every APG list pattern asks for and all of them the same way: a
3
+ * listbox, a menu, a tree. Framework-free, so the buffer is a plain object the caller keeps.
4
+ */
5
+ declare namespace TypeaheadUtils {
6
+ /** How long a buffer stays open, per APG. */
7
+ const TIMEOUT = 1000;
8
+ /** What a caller keeps between keystrokes: what has been typed, and when the last key arrived. */
9
+ interface Buffer {
10
+ query: string;
11
+ at: number;
12
+ }
13
+ /** A key that types a character, rather than one that commands something. */
14
+ function isPrintable(event: {
15
+ key: string;
16
+ ctrlKey?: boolean;
17
+ metaKey?: boolean;
18
+ altKey?: boolean;
19
+ }): boolean;
20
+ /** Whether the buffer is still the one the user is typing into. */
21
+ function isOpen(buffer: Buffer, timeStamp: number): boolean;
22
+ /** Adds a keystroke, starting a fresh buffer when the last one has expired, and returns what to search for. */
23
+ function push(buffer: Buffer, key: string, timeStamp: number): string;
24
+ /**
25
+ * The item a query points at, or `-1`. One character — or the same one repeated, which is how a user
26
+ * cycles through a letter — searches from *after* the current item; a longer buffer is a real prefix
27
+ * and searches from it, so further letters narrow instead of skipping.
28
+ */
29
+ function target(query: string, from: number, count: number, textOf: (index: number) => string, isDisabled?: (index: number) => boolean): number;
30
+ }
31
+ export default TypeaheadUtils;
@@ -0,0 +1,10 @@
1
+ export interface Memo<T> {
2
+ value: T;
3
+ clear(): void;
4
+ }
5
+ /**
6
+ * Lazily-computed cached value with explicit dependency edges. Upstream memos go in `deps` as a thunk, so
7
+ * they can reference siblings whatever the declaration order; clearing a dep cascades, so a mutation only
8
+ * has to clear the root that changed.
9
+ */
10
+ export default function memo<T>(action: () => T, deps?: () => Memo<unknown>[]): Memo<T>;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Which item a menu's keyboard lands on, read off the DOM rather than out of a registry: a menu's items
3
+ * are real focusable elements, and their order is the order they are written in — including the ones a
4
+ * consumer wrapped in a group, put behind a condition, or declared in a submenu of its own.
5
+ */
6
+ declare namespace MenuUtils {
7
+ /** The three roles an item can carry. A separator, a group and a label are not items. */
8
+ const ITEM_SELECTOR = "[role=\"menuitem\"],[role=\"menuitemcheckbox\"],[role=\"menuitemradio\"]";
9
+ /** Whether this panel is the menu a node belongs to, rather than one nested inside it. */
10
+ function owns(panel: Element, node: EventTarget | null): boolean;
11
+ /** The items a panel owns, in DOM order. A submenu's items belong to the submenu, however deep it sits. */
12
+ function items(panel: Element): HTMLElement[];
13
+ /**
14
+ * A disabled item, which is `aria-disabled` and never the `disabled` attribute: APG asks that a
15
+ * disabled menu item stay focusable, so that a keyboard user can find out it is there at all.
16
+ */
17
+ function isDisabled(item: Element): boolean;
18
+ /** An item that opens a submenu. */
19
+ function isSubTrigger(item: Element): boolean;
20
+ /** The next item in a direction, wrapping at the ends the way a menu does. Nothing is skipped — see `isDisabled`. */
21
+ function step(items: readonly HTMLElement[], from: number, delta: number): HTMLElement | undefined;
22
+ /** The item a typed prefix points at, on the shared APG rules. */
23
+ function typeaheadTarget(items: readonly HTMLElement[], query: string, from: number): HTMLElement | undefined;
24
+ }
25
+ export default MenuUtils;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Object helpers that know nothing about the prop registry — which is what lets both packages import
3
+ * this file. `mergeDeep` used to live here and does not any more: it reads `pseudo2`, so it belongs in
4
+ * `src/core/mergeDeep.ts` (see the note there).
5
+ */
6
+ declare namespace ObjectUtils {
7
+ function buildProps<T extends {
8
+ props?: object;
9
+ }, TKey extends keyof T>(props: T, keys: Readonly<TKey[]>, extraTagProps?: object): T;
10
+ function isObject(value: unknown): value is object;
11
+ function isKeyOf<T extends object>(key: any, obj: T): key is keyof T;
12
+ }
13
+ export default ObjectUtils;
@@ -0,0 +1,67 @@
1
+ /** Which axis the thumbs run along. Horizontal is the reading axis, so its arrows mirror in a right-to-left page. */
2
+ export type SliderOrientation = 'horizontal' | 'vertical';
3
+ /** What a key means on a thumb: one step, one page, or a jump to an end of the range. */
4
+ export interface SliderMove {
5
+ kind: 'step' | 'page' | 'edge';
6
+ /** `1` towards the maximum, `-1` towards the minimum. */
7
+ delta: number;
8
+ }
9
+ /** The scale a slider measures on. `step` is the grid every value but `min` and `max` lands on. */
10
+ export interface SliderScale {
11
+ min: number;
12
+ max: number;
13
+ step: number;
14
+ }
15
+ /**
16
+ * Where a thumb sits and what a pointer means, with no DOM and no React in it. The geometry is
17
+ * deliberately physical — a rectangle has no reading order — and the one place direction enters is
18
+ * `moveFor`, which is the half of a right-to-left slider no logical property can fix.
19
+ */
20
+ declare namespace SliderUtils {
21
+ /**
22
+ * How many decimals a step carries, so a value snapped onto its grid does not come back as
23
+ * `0.30000000000000004`. An exponent-form step (`1e-7`) has no readable decimals, so it snaps at the
24
+ * float's own precision instead.
25
+ */
26
+ function decimals(step: number): number;
27
+ /** Inside the scale, nothing else. */
28
+ function clamp(value: number, min: number, max: number): number;
29
+ /**
30
+ * The nearest value on the step grid, counted from `min`. A `max` that is not itself on the grid stays
31
+ * out of reach here — End is what puts a thumb on it, the way a native range input does.
32
+ */
33
+ function snap(value: number, scale: SliderScale): number;
34
+ /** Where a value sits on the scale, 0–100. A scale with no width puts everything at its start. */
35
+ function percent(value: number, min: number, max: number): number;
36
+ /** The same as a CSS length, rounded to a hundredth of a percent — finer than any screen, and short enough to compare. */
37
+ function percentage(value: number, min: number, max: number): string;
38
+ /** Whatever shape the consumer gave, as the array the component works in. */
39
+ function thumbs(value: number | readonly number[]): number[];
40
+ /** And back out again, in the shape it arrived as: a number in, a number out. */
41
+ function shaped<T extends number | number[]>(sample: T, values: readonly number[]): T;
42
+ /**
43
+ * One thumb moved, held between its neighbours. A thumb may meet the one beside it and never pass it:
44
+ * crossing would renumber the thumbs under the focus that is on one of them.
45
+ */
46
+ function move(values: readonly number[], index: number, next: number, scale: SliderScale): number[];
47
+ /** Whether two sets of thumbs say the same thing, so a drag that moved nothing costs no render. */
48
+ function same(left: readonly number[], right: readonly number[]): boolean;
49
+ /**
50
+ * Which thumb a press belongs to: the nearest, and the *last* of two equally near ones, so a pair
51
+ * sitting on top of each other at the minimum can still be pulled apart.
52
+ */
53
+ function nearest(values: readonly number[], target: number): number;
54
+ /**
55
+ * The value a pointer is over. Physical coordinates against a physical rectangle: a vertical slider
56
+ * counts up from its bottom edge, and a right-to-left one from its right.
57
+ */
58
+ function valueAt(rect: DOMRect, clientX: number, clientY: number, orientation: SliderOrientation, rtl: boolean): number;
59
+ /**
60
+ * What a key does on a thumb. Both arrow pairs work on both orientations, which is APG's rule — and
61
+ * only the sideways pair mirrors, because the block axis has no reading order to follow.
62
+ */
63
+ function moveFor(key: string, rtl?: boolean): SliderMove | undefined;
64
+ /** Where a move lands, before the neighbours have their say. An edge move ignores the grid: End is `max` itself. */
65
+ function moved(current: number, key: SliderMove, scale: SliderScale, largeStep: number): number;
66
+ }
67
+ export default SliderUtils;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Fuzzy search implementation for text matching.
3
+ * Matches characters in order but not necessarily consecutively.
4
+ */
5
+ export interface FuzzyMatch {
6
+ score: number;
7
+ matches: [number, number][];
8
+ }
9
+ /**
10
+ * Performs fuzzy matching of a pattern against a target string.
11
+ * Returns a match object with score and matched ranges, or null if no match.
12
+ */
13
+ export declare function fuzzyMatch(pattern: string, target: string): FuzzyMatch | null;
14
+ /**
15
+ * Simple fuzzy search that returns true if the pattern matches the target.
16
+ */
17
+ export declare function fuzzySearch(pattern: string, target: string): boolean;
18
+ /**
19
+ * Fuzzy search across multiple fields of an object.
20
+ * Returns true if the pattern matches any of the specified fields.
21
+ */
22
+ export declare function fuzzySearchObject<T extends object>(pattern: string, obj: T, fields?: (keyof T)[]): boolean;
23
+ /**
24
+ * Get the best fuzzy match score across multiple fields.
25
+ * Returns the highest score found, or 0 if no match.
26
+ */
27
+ export declare function fuzzySearchObjectScore<T extends object>(pattern: string, obj: T, fields?: (keyof T)[]): number;
@@ -0,0 +1,4 @@
1
+ declare namespace StringUtils {
2
+ function capitalize(str: string): string;
3
+ }
4
+ export default StringUtils;
@@ -0,0 +1,75 @@
1
+ /** Which way a tablist runs. Horizontal is the reading axis, so its arrows mirror in a right-to-left page. */
2
+ export type TabsOrientation = 'horizontal' | 'vertical';
3
+ /** What a key means in a tablist: a step to the neighbouring tab, or a jump to an end. */
4
+ export interface TabsMove {
5
+ kind: 'step' | 'edge';
6
+ /** `1` forward, `-1` back — and on an `edge` move, the first tab or the last. */
7
+ delta: number;
8
+ }
9
+ /** Where a tab sits inside its list, along the axis the tabs run on. Physical pixels: a measured length has no reading order. */
10
+ export interface TabsBounds {
11
+ /** From the list's own start edge — its left horizontally, its top vertically. */
12
+ start: number;
13
+ /** The tab's own length on that axis. */
14
+ size: number;
15
+ }
16
+ /**
17
+ * Which tab a tablist's keyboard lands on, read off the DOM rather than out of a registry: a tab is a real
18
+ * focusable element and its position is where it was written — including one a consumer wrapped, put
19
+ * behind a condition, or rendered from a list. The measurements the travelling indicator and the resizing
20
+ * panel container need are here for the same reason: what is on screen is the only thing that knows.
21
+ */
22
+ declare namespace TabsUtils {
23
+ const TAB_SELECTOR = "[role=\"tab\"]";
24
+ const LIST_SELECTOR = "[role=\"tablist\"]";
25
+ const PANEL_SELECTOR = "[role=\"tabpanel\"]";
26
+ /** Whether this tablist is the one a node belongs to, rather than one nested inside it. */
27
+ function owns(list: Element, node: EventTarget | null): boolean;
28
+ /** The tabs a tablist owns, in DOM order. A nested set of tabs belongs to its own list. */
29
+ function tabs(list: Element | null | undefined): HTMLElement[];
30
+ /**
31
+ * A tab no selection can land on. Skipped by every movement, unlike a disabled menu item, which APG asks
32
+ * stay reachable: selection follows focus here, so a tab focus could reach and selection could not would
33
+ * leave the pattern with no state to be in.
34
+ */
35
+ function isDisabled(tab: Element): boolean;
36
+ /** What a tab stands for. The one thing the markup has to carry for the model to work. */
37
+ function valueOf(tab: HTMLElement): string | undefined;
38
+ /**
39
+ * A value turned into an id fragment. `aria-controls` is a space-separated list and the id has to survive
40
+ * a CSS selector, so everything but a letter, a digit and a hyphen is escaped by code point rather than
41
+ * dropped — two values differing only in punctuation must not come out naming one element. The `_` that
42
+ * delimits an escape is escaped along with the rest, which is what keeps the mapping one-to-one.
43
+ */
44
+ function token(value: string): string;
45
+ /** The next selectable tab in a direction, or `undefined` when there is none. Disabled tabs are stepped over. */
46
+ function step(tabs: readonly HTMLElement[], from: number, delta: number, loop: boolean): HTMLElement | undefined;
47
+ /** The first (`delta: 1`) or last (`delta: -1`) selectable tab. */
48
+ function edge(tabs: readonly HTMLElement[], delta: number): HTMLElement | undefined;
49
+ /** Where a tab a move should start from sits, or `-1` when the node is not one of these tabs. */
50
+ function indexOf(tabs: readonly HTMLElement[], node: EventTarget | null): number;
51
+ /**
52
+ * What a key does in a tablist of this orientation. The off-axis arrows deliberately mean nothing — APG
53
+ * leaves them to the page, so a horizontal tablist does not eat Up and Down.
54
+ */
55
+ function moveFor(key: string, orientation: TabsOrientation, rtl?: boolean): TabsMove | undefined;
56
+ /** The tab a move arrives at, or `undefined` when there is nowhere to go. */
57
+ function target(tabs: readonly HTMLElement[], from: number, move: TabsMove, loop: boolean): HTMLElement | undefined;
58
+ /** The tab whose panel is showing, read off the attribute the component writes rather than matched on a value. */
59
+ function selectedTab(list: Element | null | undefined): HTMLElement | undefined;
60
+ /**
61
+ * Where the travelling indicator has to be, measured off the two rectangles rather than `offsetLeft` —
62
+ * whose origin is the nearest positioned ancestor, which need not be the list. The scroll offset is
63
+ * added back because scrolling a list that outgrows its container is the consumer's to set up (#140),
64
+ * so a list that does scroll must not drag the indicator off its tab.
65
+ */
66
+ function bounds(list: Element, tab: Element, orientation: TabsOrientation): TabsBounds;
67
+ /** Whether a fresh measurement says anything new, so a reflow that moved nothing costs no render. */
68
+ function sameBounds(left: TabsBounds | undefined, right: TabsBounds | undefined): boolean;
69
+ /**
70
+ * The panel a container is showing: the one that is not hidden, so `keepMounted` measures the panel on
71
+ * screen rather than the first one written.
72
+ */
73
+ function visiblePanel(container: Element | null | undefined): HTMLElement | undefined;
74
+ }
75
+ export default TabsUtils;
@@ -0,0 +1,73 @@
1
+ /** What a toast is saying, which is the only thing that changes its colour and its urgency. */
2
+ export type ToastKind = 'default' | 'success' | 'error' | 'warning' | 'info' | 'loading';
3
+ /** Why a toast went away — the four every dismissal reports, on the shape the rest of the library uses. */
4
+ export type ToastDismissReason = 'timeout' | 'close' | 'action' | 'imperative';
5
+ export interface ToastAction<TContent> {
6
+ label: TContent;
7
+ onClick(): void;
8
+ /** Whether pressing it also dismisses the toast. Default `true` — an action is an answer to it. */
9
+ closeOnClick?: boolean;
10
+ }
11
+ export interface ToastOptions<TContent> {
12
+ /** Reuse an id and the toast already carrying it is updated in place, which is what `toast.promise` does. */
13
+ id?: string;
14
+ kind?: ToastKind;
15
+ description?: TContent;
16
+ /** Milliseconds on screen. `Infinity` stays until something dismisses it, which is what `loading` uses. */
17
+ duration?: number;
18
+ action?: ToastAction<TContent>;
19
+ /** Whether the close button is drawn and Escape reaches it. Default `true`. */
20
+ dismissible?: boolean;
21
+ onDismiss?(reason: ToastDismissReason): void;
22
+ }
23
+ export interface Toast<TContent> {
24
+ id: string;
25
+ kind: ToastKind;
26
+ message: TContent;
27
+ description?: TContent;
28
+ duration: number;
29
+ action?: ToastAction<TContent>;
30
+ dismissible: boolean;
31
+ onDismiss?(reason: ToastDismissReason): void;
32
+ /** False from the moment it is dismissed: the entry is still rendered, because the exit is running. */
33
+ open: boolean;
34
+ /** On screen rather than waiting behind the limit. A queued toast runs no timer — see `syncTimers`. */
35
+ visible: boolean;
36
+ }
37
+ export interface ToastState<TContent> {
38
+ toasts: readonly Toast<TContent>[];
39
+ /** How many open toasts the limit is holding back, which is what the viewport's counter says. */
40
+ overflow: number;
41
+ }
42
+ export interface ToastStore<TContent> {
43
+ subscribe(listener: () => void): () => void;
44
+ getSnapshot(): ToastState<TContent>;
45
+ /** The empty state, always: nothing has been announced on a server. */
46
+ getServerSnapshot(): ToastState<TContent>;
47
+ add(message: TContent, options?: ToastOptions<TContent>): string;
48
+ /** Changes a toast already on screen. An unknown id is ignored rather than added — see `toast.promise`. */
49
+ update(id: string, message: TContent, options?: ToastOptions<TContent>): void;
50
+ /** Starts the exit. The entry stays until `remove`, which is what gives `<Presence>` something to hold. */
51
+ dismiss(id?: string, reason?: ToastDismissReason): void;
52
+ /** Drops the entry for good — what the viewport calls once the exit has finished. */
53
+ remove(id: string): void;
54
+ setLimit(limit: number): void;
55
+ setDefaultDuration(duration: number): void;
56
+ /** Every timer holds where it got to. WCAG 2.2.1: hovering or focusing the stack must stop the clock. */
57
+ pause(): void;
58
+ resume(): void;
59
+ /** Everything gone with no exit and no handler called — for a test, or a route change. */
60
+ reset(): void;
61
+ }
62
+ /**
63
+ * The queue, the timers and the subscription behind `toast()` — with no React in it, because none of that
64
+ * is a rendering question. The component reads a snapshot and draws it; every decision about what is on
65
+ * screen, what is waiting and when something leaves is made here.
66
+ *
67
+ * A toast past the limit is **queued, not dropped, and its timer has not started** — so a message cannot
68
+ * expire while it was never on screen, which is the whole reason the limit is a queue rather than a cap.
69
+ */
70
+ export default function createToastStore<TContent>(options?: {
71
+ limit?: number;
72
+ duration?: number;
73
+ }): ToastStore<TContent>;
@@ -0,0 +1,47 @@
1
+ /** The slice of a long list that is actually rendered, and where it sits in the scroll space. */
2
+ export interface VirtualWindow {
3
+ /** First row to render. */
4
+ startIndex: number;
5
+ /** One past the last row to render. */
6
+ endIndex: number;
7
+ /** How far down the slice starts, in pixels. */
8
+ offsetY: number;
9
+ /** What the whole list measures — what gives the scrollbar its range. */
10
+ totalHeight: number;
11
+ }
12
+ export interface VirtualWindowOptions {
13
+ count: number;
14
+ /** The *pitch* of a row: its height plus whatever sits between two of them. */
15
+ itemHeight: number;
16
+ /** What the scrolling element shows at once. */
17
+ viewHeight: number;
18
+ scrollTop: number;
19
+ /** Rows kept either side of what is visible, so a scroll has something to reveal. */
20
+ overscan?: number;
21
+ /** The row the keyboard is on, or `-1`. The window moves to hold it whatever the scroll says. */
22
+ activeIndex?: number;
23
+ }
24
+ /**
25
+ * Windowing with no React and no DOM in it: which rows of a long list to render for a given scroll
26
+ * position, and where to put them. Pure arithmetic, so the answers are testable in an environment that
27
+ * computes no layout — which is every environment this repo's tests run in.
28
+ */
29
+ declare namespace VirtualUtils {
30
+ /** Rows either side of the viewport. Four is about a frame of fast scrolling at this row height. */
31
+ const DEFAULT_OVERSCAN = 4;
32
+ /** Below this a window costs more than it saves: the arithmetic, the wrapper and the scroll state. */
33
+ const DEFAULT_THRESHOLD = 100;
34
+ /** What a row is taken to measure before anything has been measured — this library's own option height. */
35
+ const DEFAULT_ITEM_HEIGHT = 36;
36
+ /** What the scroller is taken to show before anything has been measured — `combobox.items`' own height. */
37
+ const DEFAULT_VIEW_HEIGHT = 248;
38
+ /** Whether a list is long enough to be worth windowing. `enabled` is the caller overruling the count. */
39
+ function shouldVirtualize(count: number, enabled?: boolean, threshold?: number): boolean;
40
+ /**
41
+ * The rows to render for a scroll position. The window is a fixed number of rows that *moves*, rather
42
+ * than one that stretches to reach the active row: Home on a ten-thousand-row list would otherwise
43
+ * render all ten thousand, which is the cost the window exists to avoid.
44
+ */
45
+ function windowFor(options: VirtualWindowOptions): VirtualWindow;
46
+ }
47
+ export default VirtualUtils;