@sesamehr/react-design-system 2.0.0-beta.2 → 2.0.0-beta.21

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 (136) hide show
  1. package/README.md +34 -0
  2. package/dist/Button/ActionItem/ActionItem.d.ts +40 -0
  3. package/dist/Button/ActionItem/index.d.ts +1 -0
  4. package/dist/Button/IconButton/IconButton.d.ts +32 -0
  5. package/dist/Button/IconButton/index.d.ts +27 -0
  6. package/dist/Data/Table/Table.d.ts +1 -1
  7. package/dist/Data/Table/TableBody/TableBody.d.ts +3 -0
  8. package/dist/Data/Table/TableHead/TableHead.d.ts +25 -1
  9. package/dist/Data/Table/TableScrollbar/TableScrollbar.d.ts +21 -0
  10. package/dist/Data/Table/TableSelectCell/TableSelectCell.d.ts +8 -0
  11. package/dist/Data/Table/TableVirtualized/TableVirtualized.d.ts +45 -0
  12. package/dist/Data/Table/TableVirtualized/index.d.ts +2 -0
  13. package/dist/Data/Table/hooks/index.d.ts +3 -0
  14. package/dist/Data/Table/hooks/useDragToScroll/useDragToScroll.d.ts +12 -2
  15. package/dist/Data/Table/hooks/useTableVirtual/context.d.ts +16 -0
  16. package/dist/Data/Table/hooks/useTableVirtual/index.d.ts +3 -0
  17. package/dist/Data/Table/hooks/useTableVirtual/useTableVirtual.d.ts +36 -0
  18. package/dist/Data/Table/hooks/useTableVirtual/useTableVirtual.types.d.ts +74 -0
  19. package/dist/Data/Table/index.d.ts +2 -2
  20. package/dist/Display/Avatar/AvatarSkeleton/AvatarSkeleton.d.ts +30 -0
  21. package/dist/Display/Avatar/index.d.ts +2 -0
  22. package/dist/Display/AvatarDetails/AvatarDetails.d.ts +68 -0
  23. package/dist/Display/AvatarDetails/index.d.ts +1 -0
  24. package/dist/Display/AvatarGroup/AvatarGroup.d.ts +3 -0
  25. package/dist/Display/Badge/Badge.d.ts +3 -2
  26. package/dist/Display/Badge/index.d.ts +10 -1
  27. package/dist/Display/ChatBubble/ChatBubble.d.ts +28 -0
  28. package/dist/Display/ChatBubble/ChatBubbleStatus/ChatBubbleStatus.d.ts +8 -0
  29. package/dist/Display/ChatBubble/ChatBubbleStatus/index.d.ts +10 -0
  30. package/dist/Display/ChatBubble/index.d.ts +44 -0
  31. package/dist/Display/Chip/Chip.d.ts +21 -5
  32. package/dist/Display/Chip/index.d.ts +19 -10
  33. package/dist/Display/FileCard/FileCard.d.ts +66 -0
  34. package/dist/Display/FileCard/index.d.ts +1 -0
  35. package/dist/Display/FilePreviewCard/FilePreviewCard.d.ts +49 -0
  36. package/dist/Display/FilePreviewCard/index.d.ts +1 -0
  37. package/dist/Feedback/Alert/AlertIcon.d.ts +1 -1
  38. package/dist/Feedback/Dialog/DialogBody.d.ts +18 -0
  39. package/dist/Feedback/Dialog/index.d.ts +1 -0
  40. package/dist/Feedback/Loader/Loader.d.ts +16 -0
  41. package/dist/Feedback/Loader/index.d.ts +2 -0
  42. package/dist/Feedback/Popover/PopoverContent.d.ts +0 -1
  43. package/dist/Feedback/Progress/Progress.d.ts +3 -0
  44. package/dist/Feedback/Progress/index.d.ts +17 -0
  45. package/dist/Feedback/Skeleton/Skeleton.d.ts +21 -0
  46. package/dist/Feedback/Skeleton/index.d.ts +2 -0
  47. package/dist/Feedback/Tooltip/TooltipContent.d.ts +0 -1
  48. package/dist/Forms/Field/Counter/Counter.d.ts +9 -0
  49. package/dist/Forms/Field/Counter/index.d.ts +13 -0
  50. package/dist/Forms/Field/FieldGroup/FieldGroup.d.ts +16 -1
  51. package/dist/Forms/Field/FieldLabel/FieldLabel.d.ts +16 -0
  52. package/dist/Forms/Field/FieldMessage/FieldMessage.d.ts +22 -2
  53. package/dist/Forms/Field/index.d.ts +1 -0
  54. package/dist/Forms/Field/useFieldGroup.d.ts +108 -0
  55. package/dist/Forms/Inputs/Calendar/Calendar.d.ts +55 -0
  56. package/dist/Forms/Inputs/Calendar/CalendarDay.d.ts +37 -0
  57. package/dist/Forms/Inputs/Calendar/CalendarRange.d.ts +56 -0
  58. package/dist/Forms/Inputs/Calendar/constraints.d.ts +19 -0
  59. package/dist/Forms/Inputs/Calendar/date.d.ts +28 -0
  60. package/dist/Forms/Inputs/Calendar/index.d.ts +21 -0
  61. package/dist/Forms/Inputs/Calendar/nav.d.ts +34 -0
  62. package/dist/Forms/Inputs/Calendar/testids.d.ts +28 -0
  63. package/dist/Forms/Inputs/Calendar/useCalendarLocale.d.ts +40 -0
  64. package/dist/Forms/Inputs/ChatInput/ChatInput.d.ts +68 -0
  65. package/dist/Forms/Inputs/ChatInput/index.d.ts +46 -0
  66. package/dist/Forms/Inputs/Combobox/Combobox.d.ts +19 -0
  67. package/dist/Forms/Inputs/Combobox/ComboboxCancel.d.ts +14 -0
  68. package/dist/Forms/Inputs/Combobox/ComboboxChipsInput.d.ts +11 -0
  69. package/dist/Forms/Inputs/Combobox/ComboboxContent.d.ts +0 -6
  70. package/dist/Forms/Inputs/Combobox/ComboboxGroup.d.ts +6 -2
  71. package/dist/Forms/Inputs/Combobox/ComboboxInput.d.ts +6 -1
  72. package/dist/Forms/Inputs/Combobox/ComboboxItem.d.ts +4 -0
  73. package/dist/Forms/Inputs/Combobox/ComboboxItemEdit.d.ts +134 -0
  74. package/dist/Forms/Inputs/Combobox/context.d.ts +21 -1
  75. package/dist/Forms/Inputs/Combobox/index.d.ts +2 -0
  76. package/dist/Forms/Inputs/Combobox/useChipOverflow.d.ts +30 -0
  77. package/dist/Forms/Inputs/Combobox/useComboboxEditing.d.ts +40 -0
  78. package/dist/Forms/Inputs/Combobox/useComboboxLabels.d.ts +21 -0
  79. package/dist/Forms/Inputs/Combobox/useComboboxSearch.d.ts +20 -0
  80. package/dist/Forms/Inputs/DatePicker/DatePicker.d.ts +51 -0
  81. package/dist/Forms/Inputs/DatePicker/DatePickerHeader.d.ts +65 -0
  82. package/dist/Forms/Inputs/DatePicker/DatePickerMonthSelect.d.ts +27 -0
  83. package/dist/Forms/Inputs/DatePicker/DatePickerTrigger.d.ts +29 -0
  84. package/dist/Forms/Inputs/DatePicker/DatePickerYearSelect.d.ts +25 -0
  85. package/dist/Forms/Inputs/DatePicker/DateRangePicker.d.ts +61 -0
  86. package/dist/Forms/Inputs/DatePicker/format.d.ts +44 -0
  87. package/dist/Forms/Inputs/DatePicker/index.d.ts +6 -0
  88. package/dist/Forms/Inputs/DatePicker/month.d.ts +28 -0
  89. package/dist/Forms/Inputs/DatePicker/useDatePickerHeader.d.ts +23 -0
  90. package/dist/Forms/Inputs/InputOtp/InputOtp.d.ts +7 -0
  91. package/dist/Forms/Inputs/InputPassword/InputPassword.d.ts +9 -1
  92. package/dist/Forms/Inputs/InputText/InputText.d.ts +9 -0
  93. package/dist/Forms/Inputs/SearchBar/SearchBar.d.ts +35 -0
  94. package/dist/Forms/Inputs/SearchBar/index.d.ts +20 -0
  95. package/dist/Forms/Inputs/SearchPanel/SearchPanel.d.ts +71 -0
  96. package/dist/Forms/Inputs/SearchPanel/SearchPanelEmpty.d.ts +16 -0
  97. package/dist/Forms/Inputs/SearchPanel/SearchPanelGroup.d.ts +14 -0
  98. package/dist/Forms/Inputs/SearchPanel/SearchPanelInput.d.ts +31 -0
  99. package/dist/Forms/Inputs/SearchPanel/SearchPanelItem.d.ts +20 -0
  100. package/dist/Forms/Inputs/SearchPanel/SearchPanelList.d.ts +11 -0
  101. package/dist/Forms/Inputs/SearchPanel/context.d.ts +11 -0
  102. package/dist/Forms/Inputs/SearchPanel/index.d.ts +6 -0
  103. package/dist/Forms/Inputs/Select/SelectContent.d.ts +0 -4
  104. package/dist/Forms/Inputs/Select/SelectGroup.d.ts +6 -2
  105. package/dist/Forms/Inputs/Select/SelectItem.d.ts +6 -0
  106. package/dist/Forms/Inputs/Textarea/Textarea.d.ts +69 -0
  107. package/dist/Forms/Inputs/Textarea/index.d.ts +21 -0
  108. package/dist/Forms/Inputs/Toggle/RadioButton/RadioGroup.d.ts +5 -0
  109. package/dist/Forms/Inputs/Toggle/ToggleLabel/ToggleLabel.d.ts +10 -1
  110. package/dist/Forms/Inputs/index.d.ts +6 -0
  111. package/dist/Layout/Card/Card.d.ts +4 -1
  112. package/dist/Layout/Card/index.d.ts +10 -4
  113. package/dist/Layout/Scrollbar/Scrollbar.d.ts +46 -0
  114. package/dist/Layout/Scrollbar/index.d.ts +2 -0
  115. package/dist/Layout/Scrollbar/useScrollbar.d.ts +52 -0
  116. package/dist/Navigation/ToggleTabs/useToggleTabsPill.d.ts +27 -0
  117. package/dist/hooks/index.d.ts +14 -0
  118. package/dist/hooks/useAutoGrow/useAutoGrow.d.ts +22 -0
  119. package/dist/hooks/useSearchDebounce/useSearchDebounce.d.ts +24 -0
  120. package/dist/internal/Listbox/ListboxEmpty.d.ts +3 -0
  121. package/dist/internal/Listbox/ListboxItem.d.ts +23 -0
  122. package/dist/internal/Listbox/ListboxLabel.d.ts +9 -0
  123. package/dist/internal/Listbox/ListboxSeparator.d.ts +3 -0
  124. package/dist/internal/Listbox/ListboxViewport.d.ts +9 -0
  125. package/dist/internal/Surface/Surface.d.ts +35 -0
  126. package/dist/internal/index.d.ts +13 -0
  127. package/dist/lib/cssModules.d.ts +13 -0
  128. package/dist/main.d.ts +18 -7
  129. package/dist/preflight.css +391 -0
  130. package/dist/react-design-system.css +1 -1
  131. package/dist/react-design-system.js +17244 -10361
  132. package/dist/react-design-system.umd.cjs +164 -117
  133. package/package.json +4 -2
  134. package/dist/Data/Table/TableAvatar/TableAvatar.d.ts +0 -14
  135. package/dist/Display/Tag/Tag.d.ts +0 -19
  136. package/dist/Display/Tag/index.d.ts +0 -2
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Month arithmetic the header and its two selectors all need. Mirrors
3
+ * `@sesame/orxata-core` `DatePicker/month.ts`.
4
+ *
5
+ * Shared rather than repeated because the comparison has to be the same one
6
+ * `Calendar` makes: bounds are read by month, so a `from` set mid-month does
7
+ * not hide the month it sits in.
8
+ */
9
+ /** Months since year zero, so two months compare as two numbers. */
10
+ export declare const monthIndex: (date: Date) => number;
11
+ /** The first day of the month `offsetInMonths` away from `date`. */
12
+ export declare const monthOf: (date: Date, offsetInMonths?: number) => Date;
13
+ /**
14
+ * How far the year selector reaches when nothing bounds it.
15
+ *
16
+ * A birth year is the case that makes a year selector worth having at all, so
17
+ * the window has to be deep enough to hold one; forward it only has to cover
18
+ * the scheduling a caller who set no bounds could plausibly want. Both are
19
+ * defaults a caller overrides by passing `constraints`, which is the only
20
+ * statement about reachable dates this package will believe.
21
+ */
22
+ export declare const YEARS_BACK = 100;
23
+ export declare const YEARS_FORWARD = 10;
24
+ /** The inclusive year range the year selector offers. */
25
+ export declare const yearRange: (visible: Date, from?: Date, to?: Date) => {
26
+ first: number;
27
+ last: number;
28
+ };
@@ -0,0 +1,23 @@
1
+ import { CalendarConstraints } from '../Calendar/constraints.ts';
2
+ import { CalendarNav } from '../Calendar/nav.ts';
3
+ /**
4
+ * What `DatePickerHeader` publishes to whatever is put inside it. Mirrors
5
+ * `@sesame/orxata-core` `useDatePickerHeader`.
6
+ *
7
+ * The two selectors need the visible month, a way to jump to another one, and
8
+ * the bounds that say which months exist — the same three things the header
9
+ * itself is given. Passing them down as props would be prop drilling through
10
+ * `children`, and would put `nav` on the public API of every part.
11
+ */
12
+ export interface DatePickerHeaderContextValue {
13
+ nav: CalendarNav;
14
+ constraints?: CalendarConstraints;
15
+ }
16
+ export declare const DatePickerHeaderContext: import('react').Context<DatePickerHeaderContextValue | null>;
17
+ /**
18
+ * The message is spelled identically in `@sesame/orxata-core`. A part that
19
+ * escapes its header is the same mistake in both packages, and a developer who
20
+ * meets it twice should not have to recognise two wordings of it.
21
+ */
22
+ export declare const DATE_PICKER_HEADER_MISSING = "OxDatePickerMonthSelect and OxDatePickerYearSelect must be rendered inside OxDatePickerHeader.";
23
+ export declare const useDatePickerHeader: () => DatePickerHeaderContextValue;
@@ -5,5 +5,12 @@ import { InputOtpProps } from './types.ts';
5
5
  * Radix ships no PinInput, so the behaviour lives here — focus advance,
6
6
  * backspace, arrow keys, paste spreading, per-slot labels — and reaches the
7
7
  * slots through context. One `<input>` per slot.
8
+ *
9
+ * `role="group"` is here unconditionally, not just inside a field. A bare
10
+ * `<div>` cannot take a name from the author — so without the role the slots
11
+ * announce as anonymous text fields and the `aria-labelledby` below would be
12
+ * dropped on the floor. Outside an `<OxFieldGroup>` the group has no name,
13
+ * which is correct: the design system ships no strings, so there is nothing to
14
+ * call it.
8
15
  */
9
16
  export declare const InputOtp: import('react').ForwardRefExoticComponent<InputOtpProps & import('react').RefAttributes<HTMLDivElement>>;
@@ -15,6 +15,14 @@ export interface InputPasswordProps extends Omit<React.HTMLAttributes<HTMLDivEle
15
15
  * InputPassword root — mirrors `@sesame/orxata-core` InputPassword.
16
16
  * Provides the value and clear-text state to `InputPasswordInput` and
17
17
  * `InputPasswordToggle` through context.
18
- * Both `field` and `visible` work controlled or uncontrolled.
18
+ *
19
+ * Both `field` and `visible` work controlled or uncontrolled, and which one
20
+ * you get depends on **whether the change handler is there, not whether the
21
+ * value is**. The Vue original is a pair of `defineModel`s, and a
22
+ * `defineModel` given a value but no listener keeps driving itself. Gate on
23
+ * the value alone and `visible={false}` — a perfectly ordinary way to say
24
+ * "start hidden" — turns the reveal toggle into a dead button: `toggle()`
25
+ * computes the next state, declines to store it because the prop is present,
26
+ * and calls a handler nobody passed.
19
27
  */
20
28
  export declare const InputPassword: import('react').ForwardRefExoticComponent<InputPasswordProps & import('react').RefAttributes<HTMLDivElement>>;
@@ -12,5 +12,14 @@ export interface InputTextProps extends Omit<React.InputHTMLAttributes<HTMLInput
12
12
  * `field` + `onFieldChange` are the controlled pair; native `value`/`onChange`
13
13
  * still pass through via `...props` for anyone who prefers them. `type`
14
14
  * defaults to `'text'`, and a `type` passed by the caller wins.
15
+ *
16
+ * **`field` alone does not mean "controlled" — `field` *with* `onFieldChange`
17
+ * does.** The Vue original is a `defineModel`, and a `defineModel` only hands
18
+ * control to the parent when the parent actually listens; given a value and no
19
+ * listener it seeds its own state and goes on working. Port `field` as
20
+ * unconditionally controlled and that same usage becomes an input pinned to
21
+ * its initial value with nothing able to change it — one that silently will
22
+ * not accept a keystroke. Which is exactly what `<OxInputText field="" />`
23
+ * did, in the story and in any app that wrote it.
15
24
  */
16
25
  export declare const InputText: import('react').ForwardRefExoticComponent<InputTextProps & import('react').RefAttributes<HTMLInputElement>>;
@@ -0,0 +1,35 @@
1
+ import { SearchBarVariants } from './index.ts';
2
+ export interface SearchBarProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size' | 'type' | 'value' | 'defaultValue'> {
3
+ variant?: SearchBarVariants['variant'];
4
+ size?: SearchBarVariants['size'];
5
+ /**
6
+ * Milliseconds of no typing before `onSearch` fires. `0` fires on every
7
+ * keystroke.
8
+ */
9
+ debounce?: number;
10
+ /** Controlled term. Pair with `onValueChange`; omit for uncontrolled. */
11
+ value?: string;
12
+ /** Starting term when uncontrolled. */
13
+ defaultValue?: string;
14
+ /** Called on every keystroke with the next term, without waiting. */
15
+ onValueChange?: (value: string) => void;
16
+ /** Called once typing has been quiet for `debounce` ms — and at once on Enter or clear. */
17
+ onSearch?: (term: string) => void;
18
+ dataTestid: string;
19
+ }
20
+ /**
21
+ * A search field: magnifier, term, and a clear button once there is something
22
+ * to clear. Mirrors `@sesame/orxata-core` SearchBar.
23
+ *
24
+ * Written on a native `<input type="search">` rather than on a primitive
25
+ * because there is no primitive to start from — Radix has no search component,
26
+ * and shadcn's own `Input` is a bare element too. Nothing here needs what a
27
+ * primitive would bring: no portal, no focus trap, no escape handling. The one
28
+ * browser affordance it *does* bring — WebKit's built-in cancel button — is
29
+ * turned off in the stylesheet, since we draw our own.
30
+ *
31
+ * `className` lands on the root, which is the box; everything else a native
32
+ * `<input>` takes — `placeholder`, `name`, `disabled`, `aria-label` — falls
33
+ * through to the control. The `ref` is the root for the same reason.
34
+ */
35
+ export declare const SearchBar: import('react').ForwardRefExoticComponent<SearchBarProps & import('react').RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,20 @@
1
+ import { VariantProps } from 'class-variance-authority';
2
+ export { SearchBar } from './SearchBar.tsx';
3
+ export type { SearchBarProps } from './SearchBar.tsx';
4
+ /**
5
+ * Class names, not utilities — see `Button/index.ts` for why the package
6
+ * cannot publish `.h-10` and `.rounded-lg` of its own. `SearchBar.module.css`
7
+ * gives each of these names its declarations, and `moduleClasses` does the
8
+ * lookup.
9
+ *
10
+ * Only two axes here. Figma models a third, `State`, with `Default | Focus |
11
+ * Filled`, and none of it belongs in a prop: focus is `:focus-within` and
12
+ * filled is "the input has a value". Both are things the component can see for
13
+ * itself, and a `state` prop would be asking the caller to keep telling it
14
+ * something it already knows — wrong the moment the two disagree.
15
+ */
16
+ export declare const searchBarVariants: (props?: ({
17
+ variant?: "default" | "ghost" | null | undefined;
18
+ size?: "sm" | "md" | null | undefined;
19
+ } & import('class-variance-authority/types').ClassProp) | undefined) => string;
20
+ export type SearchBarVariants = VariantProps<typeof searchBarVariants>;
@@ -0,0 +1,71 @@
1
+ import { Command } from 'cmdk';
2
+ export interface SearchPanelProps extends Omit<React.ComponentPropsWithoutRef<typeof Command>, 'value' | 'onValueChange' | 'onSelect'> {
3
+ /** A row was chosen — by click or by Enter. Carries that row's `value`. */
4
+ onSelect?: (value: string) => void;
5
+ /** Escape was pressed. What closing means is the caller's to decide. */
6
+ onClose?: () => void;
7
+ dataTestid: string;
8
+ }
9
+ /**
10
+ * A panel of search results, grouped under headings — the command-palette
11
+ * pattern. Choosing a row runs something: it navigates, opens a document, or
12
+ * fires an action.
13
+ *
14
+ * Named for what it is rather than what it shows. It was `SearchResults`, which
15
+ * described the one thing it does not do: it does not search, does not filter
16
+ * and produces no results — the caller supplies the rows. What it *is* is the
17
+ * surface searching happens on, a field above a grouped list, and `SearchPanel`
18
+ * promises nothing it cannot keep.
19
+ *
20
+ * `Menu` was the other candidate and is wrong for a reason worth writing down:
21
+ * in ARIA a `menu` is application commands with their own keyboard model, and
22
+ * this is a `listbox`. A component called `Menu` that renders `role="listbox"`
23
+ * invites the next reader to resolve the mismatch in the wrong direction.
24
+ *
25
+ * **This card is the field, and nothing else.** Collapsed it is exactly the
26
+ * search row with the same air above it as below; the results are not in it.
27
+ * `SearchPanelList` draws its own card and floats it over the page, tethered
28
+ * to this one — so a result arriving moves nothing below the panel, which is
29
+ * the whole reason a global search can live in a header. See that file for how
30
+ * the two are made to read as one surface.
31
+ *
32
+ * `Popover.Root` is pinned open and holds no state: the caller decides whether
33
+ * the list renders at all, so there is no second open state here. What it is
34
+ * for is the anchor — the card below is the box the list positions itself
35
+ * against, flips away from and takes its width from.
36
+ *
37
+ * **The list brings its own motion**, because the popper gives it a
38
+ * `data-state` and the shared surface animates on that. Do not wrap it in an
39
+ * `OxTransition*`: those animate a box growing in the flow, which is the
40
+ * behaviour this component was changed to stop, and their enter class would be
41
+ * competing with the surface's own keyframe for the `animation` property.
42
+ *
43
+ * Deliberately not a `Combobox`. A combobox's model is "pick a value, the
44
+ * field then shows it", which is wrong here twice over — the search box must
45
+ * keep the words the user typed, and a row that ran an action is not a value
46
+ * anything holds afterwards. Bending a combobox to this shape means clearing
47
+ * the value after every pick and suppressing the selected state, and the bug
48
+ * that arrives three months later is the one where a stale selection survives
49
+ * a reset. shadcn keeps `Command` apart from `Combobox` for the same reason.
50
+ *
51
+ * So this root reports `onSelect` and holds nothing. cmdk's own `value` is the
52
+ * *highlight*, not a selection, which is exactly the model wanted: no row is
53
+ * ever checked and no row draws a check.
54
+ *
55
+ * `shouldFilter` is off. The caller already has the term — `OxSearchBar` owns
56
+ * the debounce — and whether a result matches is a question about their data,
57
+ * not about the strings in the DOM.
58
+ *
59
+ * The component knows nothing about what is in it. The headings, the icons and
60
+ * the row contents are all `children`: a caller listing employees with avatars
61
+ * and files with sizes needs nothing here to change. The categories in the
62
+ * stories are one application's, not this package's.
63
+ *
64
+ * The keyboard comes from cmdk: arrows and Home/End move the highlight while
65
+ * focus stays in the search field, Enter runs the highlighted row, and
66
+ * `aria-activedescendant` keeps a screen reader in step. Focusing the field
67
+ * highlights the first row, so Enter on a fresh panel runs the top hit without
68
+ * arrowing to it — which also means the first arrow press moves to the
69
+ * *second* row. Escape is cmdk's one gap and is handled here.
70
+ */
71
+ export declare const SearchPanel: import('react').ForwardRefExoticComponent<SearchPanelProps & import('react').RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,16 @@
1
+ export type SearchPanelEmptyProps = React.ComponentPropsWithoutRef<'div'>;
2
+ /**
3
+ * Shown in place of the rows when a search found nothing.
4
+ *
5
+ * No default text. "No results found" is English, and which of the caller's
6
+ * words belong here — and in which language — is not this package's to guess;
7
+ * `OxComboboxEmpty` carries one for backwards compatibility and that is the
8
+ * exception, not the pattern. Rendering is the caller's condition too: only
9
+ * they know whether an empty list means "nothing matched" or "nothing typed
10
+ * yet".
11
+ *
12
+ * Deliberately not cmdk's `CommandEmpty`, which decides for itself when to
13
+ * appear by counting the items its own filter left — and this panel's filter
14
+ * is the caller's.
15
+ */
16
+ export declare const SearchPanelEmpty: import('react').ForwardRefExoticComponent<Omit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & import('react').RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,14 @@
1
+ import { CommandGroup } from 'cmdk';
2
+ export interface SearchPanelGroupProps extends React.ComponentPropsWithoutRef<typeof CommandGroup> {
3
+ /** The heading above the rows. Anything renderable, and always the caller's. */
4
+ label?: React.ReactNode;
5
+ }
6
+ /**
7
+ * A heading and the rows under it.
8
+ *
9
+ * Nothing here knows what the heading might say. "Documents", "Recent
10
+ * conversations", "People" are one application's categories on one day; a
11
+ * design system that shipped an enum of them would be wrong by the following
12
+ * release, and wrong for every other application immediately.
13
+ */
14
+ export declare const SearchPanelGroup: import('react').ForwardRefExoticComponent<SearchPanelGroupProps & import('react').RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,31 @@
1
+ import { CommandInput } from 'cmdk';
2
+ export type SearchPanelInputProps = Omit<React.ComponentPropsWithoutRef<typeof CommandInput>, 'asChild'>;
3
+ /**
4
+ * Joins the caller's search field to the list's keyboard.
5
+ *
6
+ * Put exactly one control inside — `OxSearchBar` is the intended one, since it
7
+ * already owns the debounce. `asChild` hands it the arrow/Home/End/Enter
8
+ * handlers and `aria-activedescendant`, so the highlight moves through the
9
+ * rows while focus never leaves the field. Radix's `Slot`, which cmdk uses,
10
+ * throws on a second child rather than quietly merging onto the first.
11
+ *
12
+ * This renders no field of its own on purpose. A results panel is a way of
13
+ * showing what a search found, not a second opinion about what a search box
14
+ * looks like.
15
+ *
16
+ * It does render the row the field sits in, which is a different thing: the
17
+ * design draws a padded title row across the top of the panel, and `asChild`
18
+ * alone would have put that padding on the caller's search bar — where it would
19
+ * have moved the field's own border in from the panel edge instead of insetting
20
+ * the row.
21
+ *
22
+ * Two things cmdk decides that the field cannot override, because it writes
23
+ * them *after* the spread: the control becomes `type="text"` rather than
24
+ * `type="search"`, and it is given `role="combobox"` with `aria-controls` and
25
+ * `aria-activedescendant`. Neither is a problem — the only thing `type=search`
26
+ * adds is the browser's own clear button, which `OxSearchBar` hides and
27
+ * redraws anyway, and a text field that owns a list of options is what the
28
+ * combobox role is for, whatever the panel above it is called. It is a real
29
+ * difference from the Vue port, where the field keeps `type="search"`.
30
+ */
31
+ export declare const SearchPanelInput: import('react').ForwardRefExoticComponent<SearchPanelInputProps & import('react').RefAttributes<HTMLInputElement>>;
@@ -0,0 +1,20 @@
1
+ import { CommandItem } from 'cmdk';
2
+ export interface SearchPanelItemProps extends Omit<React.ComponentPropsWithoutRef<typeof CommandItem>, 'value' | 'onSelect'> {
3
+ /** Handed back through the panel's `onSelect`. Unique within the panel. */
4
+ value: string;
5
+ disabled?: boolean;
6
+ }
7
+ /**
8
+ * One result. Choosing it makes the panel call `onSelect` with this `value`.
9
+ *
10
+ * No check indicator, and that is the point: nothing here is selected in the
11
+ * sense a `Select` option is. The row is a thing you run, so it never becomes
12
+ * the panel's current answer and never grows a tick beside it. The shared row
13
+ * only leaves room on the right when an indicator is passed, so these sit
14
+ * flush.
15
+ *
16
+ * Whatever goes inside is the caller's — an icon and a label, an avatar and
17
+ * two lines, a filename and a size. `value` is the only thing this package
18
+ * wants, and only so it has something to hand back.
19
+ */
20
+ export declare const SearchPanelItem: import('react').ForwardRefExoticComponent<SearchPanelItemProps & import('react').RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,11 @@
1
+ import { CommandList } from 'cmdk';
2
+ export type SearchPanelListProps = React.ComponentPropsWithoutRef<typeof CommandList>;
3
+ export declare const SearchPanelList: import('react').ForwardRefExoticComponent<Omit<{
4
+ children?: React.ReactNode;
5
+ } & Pick<Pick<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof import('react').HTMLAttributes<HTMLDivElement>> & {
6
+ ref?: React.Ref<HTMLDivElement>;
7
+ } & {
8
+ asChild?: boolean;
9
+ }, "asChild" | "key" | keyof import('react').HTMLAttributes<HTMLDivElement>> & {
10
+ label?: string;
11
+ } & import('react').RefAttributes<HTMLDivElement>, "ref"> & import('react').RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,11 @@
1
+ export interface SearchPanelContextValue {
2
+ /** Called with a row's `value` when that row is chosen. */
3
+ select: (value: string) => void;
4
+ }
5
+ export declare const SearchPanelContext: import('react').Context<SearchPanelContextValue | null>;
6
+ /**
7
+ * The Vue port reaches the root through reka's own listbox context; React has
8
+ * no equivalent to inject, so the root publishes one. The error message
9
+ * matches the Vue side's on purpose.
10
+ */
11
+ export declare const useSearchPanelContext: () => SearchPanelContextValue;
@@ -0,0 +1,6 @@
1
+ export { SearchPanel, type SearchPanelProps } from './SearchPanel.tsx';
2
+ export { SearchPanelEmpty, type SearchPanelEmptyProps, } from './SearchPanelEmpty.tsx';
3
+ export { SearchPanelGroup, type SearchPanelGroupProps, } from './SearchPanelGroup.tsx';
4
+ export { SearchPanelInput, type SearchPanelInputProps, } from './SearchPanelInput.tsx';
5
+ export { SearchPanelItem, type SearchPanelItemProps, } from './SearchPanelItem.tsx';
6
+ export { SearchPanelList, type SearchPanelListProps, } from './SearchPanelList.tsx';
@@ -4,8 +4,4 @@ export interface SelectContentProps extends Omit<React.ComponentPropsWithoutRef<
4
4
  sideOffset?: number;
5
5
  align?: 'start' | 'center' | 'end';
6
6
  }
7
- /**
8
- * The floating list. Always positioned against the trigger rather than over it,
9
- * so the popup matches the trigger's width and never covers it.
10
- */
11
7
  export declare const SelectContent: import('react').ForwardRefExoticComponent<SelectContentProps & import('react').RefAttributes<HTMLDivElement>>;
@@ -1,7 +1,11 @@
1
1
  import * as SelectPrimitive from '@radix-ui/react-select';
2
2
  export interface SelectGroupProps extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Group> {
3
- /** Optional group heading. */
4
- label?: string;
3
+ /**
4
+ * The group heading. A node rather than a string: it is the caller's word
5
+ * for their own category, and taking it as text would decide for them that
6
+ * it can only ever be text.
7
+ */
8
+ label?: React.ReactNode;
5
9
  }
6
10
  /** Groups related options under a heading, announced as a group label. */
7
11
  export declare const SelectGroup: import('react').ForwardRefExoticComponent<SelectGroupProps & import('react').RefAttributes<HTMLDivElement>>;
@@ -6,6 +6,12 @@ export interface SelectItemProps extends React.ComponentPropsWithoutRef<typeof S
6
6
  /**
7
7
  * A single option.
8
8
  *
9
+ * `asChild` hands Radix's item behaviour — `role="option"`, `data-highlighted`,
10
+ * `data-state`, typeahead, selection — to the shared row, which is the one
11
+ * thing `Select`, `Combobox` and `SearchPanel` may share. The primitive
12
+ * itself is not shared: this one and `Combobox`'s wrap different roots and
13
+ * swapping them breaks the keyboard in both.
14
+ *
9
15
  * The rendered text is published to the root on mount so the trigger's render
10
16
  * prop can name the selection. Reading it off the DOM keeps arbitrary markup
11
17
  * working, and it runs while the list is closed too: the primitive keeps items
@@ -0,0 +1,69 @@
1
+ import { ReactNode } from 'react';
2
+ import { TextareaCounterState } from './index.ts';
3
+ export interface TextareaProps extends Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'rows' | 'children'> {
4
+ /**
5
+ * How tall the surface may grow before it starts to scroll, counted in lines
6
+ * of text.
7
+ *
8
+ * In rows rather than pixels so the cap moves with the line height instead
9
+ * of cutting a row in half the first time anyone changes the type scale. The
10
+ * default is the design's 100px box, which is four 20px lines inside its own
11
+ * padding.
12
+ */
13
+ maxRows?: number;
14
+ /** Controlled value. Pair with `onFieldChange`; omit for uncontrolled. */
15
+ field?: string;
16
+ /** Called on every input with the next value. */
17
+ onFieldChange?: (value: string) => void;
18
+ /**
19
+ * Bottom-right inside the box. A node, or a render prop called with
20
+ * `{ value, length }` — the limit is the caller's business and the count is
21
+ * the value's, so neither is a prop.
22
+ */
23
+ counter?: ReactNode | ((state: TextareaCounterState) => ReactNode);
24
+ dataTestid: string;
25
+ }
26
+ /**
27
+ * The multi-line field: a `<textarea>` in the same box the single-line
28
+ * controls draw, that grows with its content and then scrolls.
29
+ * Mirrors `@sesame/orxata-core` Textarea.
30
+ *
31
+ * **Not `OxChatInput`.** That one is a chat composer — it owns a send
32
+ * contract, Enter submits, and it draws two corners of action buttons around
33
+ * the text. This one is a form field: it has no idea what happens to the
34
+ * value, Enter inserts a newline, and it sits inside an `<OxFieldGroup>` with
35
+ * a label above it and a message below. Reach for `OxChatInput` when the value
36
+ * is a message being sent somewhere; reach for this when the value is an
37
+ * answer on a form. They share `useAutoGrow` and nothing else, which is the
38
+ * only part of the two that is genuinely the same problem.
39
+ *
40
+ * **The label and the message are not here, and that is the point.**
41
+ * `<OxFieldLabel>` and `<OxFieldMessage>` already exist, already order
42
+ * themselves around a control, and — through `useFieldControl` below — already
43
+ * carry the `id`, `aria-invalid` and `aria-describedby` that tie the three
44
+ * together. A `label` prop would be a second, worse spelling of a component
45
+ * that is already in the package, and the design system ships no strings
46
+ * anyway.
47
+ *
48
+ * ```tsx
49
+ * <OxFieldGroup variant="error">
50
+ * <OxFieldLabel>Notes</OxFieldLabel>
51
+ * <OxTextarea field={notes} onFieldChange={setNotes} dataTestid="notes" />
52
+ * <OxFieldMessage>Keep it under 100 characters.</OxFieldMessage>
53
+ * </OxFieldGroup>
54
+ * ```
55
+ *
56
+ * **`field` alone does not mean "controlled" — `field` *with* `onFieldChange`
57
+ * does.** The Vue original is a `defineModel`, and a `defineModel` only hands
58
+ * control to the parent when the parent actually listens; given a value and no
59
+ * listener it seeds its own state and goes on working. Port `field` as
60
+ * unconditionally controlled and the same usage becomes a field pinned to its
61
+ * initial value that silently will not accept a keystroke.
62
+ *
63
+ * The `ref` is the **textarea**, not the box — which is where it differs from
64
+ * `OxChatInput`, whose ref is its root. This is a form control: what a caller
65
+ * reaches for a ref to do is focus it, select in it, or hand it to a form
66
+ * library. `className` still lands on the box, since the box is what reads as
67
+ * the control.
68
+ */
69
+ export declare const Textarea: import('react').ForwardRefExoticComponent<TextareaProps & import('react').RefAttributes<HTMLTextAreaElement>>;
@@ -0,0 +1,21 @@
1
+ export { Textarea, type TextareaProps } from './Textarea.tsx';
2
+ /**
3
+ * What the `counter` slot is handed.
4
+ *
5
+ * Both numbers come from the field rather than from the caller, so a counter
6
+ * works the same whether the value is controlled or left to the textarea — an
7
+ * uncontrolled field posting itself in a plain `<form>` has no value in the
8
+ * caller's scope to count.
9
+ *
10
+ * There is no `cva` here on purpose. `Textarea` has no variants: the design
11
+ * draws one box, and its states come from `OxFieldGroup` through the
12
+ * `--controller-*` properties rather than from a class this component picks.
13
+ * An empty variant map would be one more thing to keep in step across two
14
+ * packages in exchange for nothing.
15
+ */
16
+ export interface TextareaCounterState {
17
+ /** The text the field holds now. */
18
+ value: string;
19
+ /** How many characters that is — what `<OxCounter>` wants for its `value`. */
20
+ length: number;
21
+ }
@@ -5,5 +5,10 @@ export interface RadioGroupProps extends React.ComponentPropsWithoutRef<typeof R
5
5
  /**
6
6
  * RadioGroup — built on `@radix-ui/react-radio-group`.
7
7
  * `v-model` maps to Radix `value` / `onValueChange` (+ `defaultValue`).
8
+ *
9
+ * The group is what a field names, not the radios inside it: one id cannot sit
10
+ * on several `<button role="radio">`s at once, so `RadioButton` stays out of
11
+ * the field context and this root carries `aria-labelledby` instead. Radix
12
+ * gives it `role="radiogroup"`, which is what makes that name land.
8
13
  */
9
14
  export declare const RadioGroup: import('react').ForwardRefExoticComponent<RadioGroupProps & import('react').RefAttributes<HTMLDivElement>>;
@@ -1,5 +1,14 @@
1
1
  export interface ToggleLabelProps extends React.LabelHTMLAttributes<HTMLLabelElement> {
2
2
  htmlFor?: string;
3
3
  }
4
- /** ToggleLabel — mirrors `@sesame/orxata-core` ToggleLabel. */
4
+ /**
5
+ * ToggleLabel — mirrors `@sesame/orxata-core` ToggleLabel.
6
+ *
7
+ * `htmlFor` falls back to whichever control claimed the surrounding
8
+ * `<OxFieldGroup>`'s id, because the commonest checkbox layout in the system —
9
+ * a field wrapping an `<OxToggleGroup>` wrapping a toggle and this — would
10
+ * otherwise leave the toggle's own label naming nothing. It does not take the
11
+ * group's `labelId`: `OxFieldLabel` already carries that, and two elements
12
+ * cannot share an id.
13
+ */
5
14
  export declare const ToggleLabel: import('react').ForwardRefExoticComponent<ToggleLabelProps & import('react').RefAttributes<HTMLLabelElement>>;
@@ -3,6 +3,12 @@ export { InputText, type InputTextProps } from './InputText/InputText.tsx';
3
3
  export * from './InputNumber/index.ts';
4
4
  export * from './InputPassword/index.ts';
5
5
  export * from './InputOtp/index.ts';
6
+ export * from './Calendar/index.ts';
6
7
  export * from './Combobox/index.ts';
8
+ export * from './ChatInput/index.ts';
9
+ export * from './DatePicker/index.ts';
10
+ export * from './SearchBar/index.ts';
11
+ export * from './SearchPanel/index.ts';
7
12
  export * from './Select/index.ts';
13
+ export * from './Textarea/index.ts';
8
14
  export * from './Toggle/index.ts';
@@ -2,7 +2,10 @@ import { CardVariants } from './index.ts';
2
2
  export interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
3
3
  /** Render as the child element instead of a `<div>` (Radix Slot). */
4
4
  asChild?: boolean;
5
- /** Which surface it is: `default` is white, `muted` is tinted. */
5
+ /**
6
+ * Which surface it is: `default` is white, `muted` is tinted, `highlighted`
7
+ * is filled with the brand colour and carries its own light text.
8
+ */
6
9
  tone?: CardVariants['tone'];
7
10
  /** Drops the border, the shadow and the glass — just the surface and its radius. */
8
11
  flat?: boolean;
@@ -3,9 +3,15 @@ export { Card, type CardProps } from './Card.tsx';
3
3
  /**
4
4
  * Two things vary, and they are not the same thing.
5
5
  *
6
- * `tone` is which surface it is: white, or tinted for the case the white one
7
- * cannot serve. White on white needs a border around every row to read as
8
- * separate things; a tinted surface lets the white ones separate on their own.
6
+ * `tone` is which surface it is: white, tinted for the case the white one
7
+ * cannot serve, or filled with the brand colour when the card is the one thing
8
+ * on the page meant to be looked at first. White on white needs a border around
9
+ * every row to read as separate things; a tinted surface lets the white ones
10
+ * separate on their own.
11
+ *
12
+ * `highlighted` is the only tone that also sets a text colour, because it is
13
+ * the only one whose surface is dark enough to need it. Everything inside
14
+ * inherits it, so the content composes exactly as it would on a white card.
9
15
  *
10
16
  * `flat` is what it carries on top of that surface. They are kept apart
11
17
  * because the combinations are all real: a white card over a tinted one, a
@@ -16,6 +22,6 @@ export { Card, type CardProps } from './Card.tsx';
16
22
  * styles keyed off `data-flat` rather than being bent into one.
17
23
  */
18
24
  export declare const cardVariants: (props?: ({
19
- tone?: "default" | "muted" | null | undefined;
25
+ tone?: "default" | "muted" | "highlighted" | null | undefined;
20
26
  } & import('class-variance-authority/types').ClassProp) | undefined) => string;
21
27
  export type CardVariants = VariantProps<typeof cardVariants>;
@@ -0,0 +1,46 @@
1
+ import { ScrollbarPort } from './useScrollbar.ts';
2
+ export interface ScrollbarProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {
3
+ /**
4
+ * The element that scrolls. Everything is measured from it, and its native
5
+ * scrollbar is hidden for as long as this one is drawn over it.
6
+ */
7
+ port?: ScrollbarPort;
8
+ dataTestid: string;
9
+ }
10
+ /**
11
+ * An overlay scrollbar for a container that scrolls vertically, drawn instead
12
+ * of the browser's own. Mirrors `@sesame/orxata-core` Scrollbar.
13
+ *
14
+ * Reach for it where the native bar cannot say what it needs to say. A
15
+ * virtualised table is the case it was built for: the bar has to start below
16
+ * the column names, and the native one runs the full height of the scrollport
17
+ * because the scrollport contains the header. A chat composer that grows to a
18
+ * few lines and then scrolls is the other: a native bar there is a strip of
19
+ * system chrome inside a rounded box, and in the browsers that reserve a gutter
20
+ * it shifts the text sideways the moment the field overflows.
21
+ *
22
+ * It behaves the way an overlay bar does: out of the way until you scroll or
23
+ * reach for the edge, and gone again shortly after. The track takes no clicks —
24
+ * only the thumb does — so the strip down the right of the content stays live.
25
+ *
26
+ * **Placement is the parent's.** This positions itself absolutely inside the
27
+ * nearest positioned ancestor and reads four custom properties for where that
28
+ * is, all with fallbacks that spell "fill the containing block down its right
29
+ * edge": `--scrollbar-top` (`0px`), `--scrollbar-right` (`0px`),
30
+ * `--scrollbar-left` (`auto`) and `--scrollbar-height` (`100%`).
31
+ *
32
+ * A parent whose scrollport *is* the containing block sets none of them. One
33
+ * that has to compensate for something — a header inside the scrollport, an
34
+ * `offsetParent` that is not the scrollport — works the numbers out itself and
35
+ * writes them here, which is why none of that arithmetic is a prop.
36
+ *
37
+ * Vertical only, deliberately. Horizontal overflow is read from the content
38
+ * running out of room and from the shadows at the edges; nothing in the system
39
+ * wants a second bar, and adding one later takes nothing away.
40
+ *
41
+ * The bar is `aria-hidden`: it is a picture of a scroll position, and the
42
+ * scrollport it belongs to is already reachable and scrollable from the
43
+ * keyboard. `mousedown`/`mousemove` are what drive the thumb, so a coarse
44
+ * pointer gets nothing from it and keeps the native scrolling it already had.
45
+ */
46
+ export declare const Scrollbar: import('react').ForwardRefExoticComponent<ScrollbarProps & import('react').RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,2 @@
1
+ export { Scrollbar, type ScrollbarProps } from './Scrollbar.tsx';
2
+ export { useScrollbar, SCROLLBAR_THICKNESS, type ScrollbarPort, type UseScrollbarReturn, } from './useScrollbar.ts';