@sesamehr/react-design-system 2.0.0-beta.9 → 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.
- package/dist/Display/Avatar/AvatarSkeleton/AvatarSkeleton.d.ts +1 -1
- package/dist/Display/AvatarDetails/AvatarDetails.d.ts +46 -9
- package/dist/Display/AvatarDetails/index.d.ts +1 -1
- package/dist/Display/AvatarGroup/AvatarGroup.d.ts +3 -0
- package/dist/Feedback/Skeleton/Skeleton.d.ts +2 -1
- package/dist/Forms/Inputs/Combobox/Combobox.d.ts +19 -0
- package/dist/Forms/Inputs/Combobox/ComboboxChipsInput.d.ts +7 -0
- package/dist/Forms/Inputs/Combobox/ComboboxItemEdit.d.ts +134 -0
- package/dist/Forms/Inputs/Combobox/context.d.ts +14 -1
- package/dist/Forms/Inputs/Combobox/index.d.ts +1 -0
- package/dist/Forms/Inputs/Combobox/useComboboxEditing.d.ts +40 -0
- package/dist/Forms/Inputs/Combobox/useComboboxSearch.d.ts +20 -0
- package/dist/Forms/Inputs/SearchBar/SearchBar.d.ts +2 -2
- package/dist/Forms/Inputs/SearchBar/index.d.ts +0 -2
- package/dist/Layout/Card/Card.d.ts +4 -1
- package/dist/Layout/Card/index.d.ts +10 -4
- package/dist/Navigation/ToggleTabs/useToggleTabsPill.d.ts +27 -0
- package/dist/hooks/index.d.ts +4 -2
- package/dist/{Forms/Inputs/SearchBar/useSearchDelay.d.ts → hooks/useSearchDebounce/useSearchDebounce.d.ts} +3 -3
- package/dist/main.d.ts +2 -2
- package/dist/react-design-system.css +1 -1
- package/dist/react-design-system.js +6899 -6605
- package/dist/react-design-system.umd.cjs +46 -46
- package/package.json +1 -1
- package/src/assets/styles/theme-v3.css +19 -1
- /package/dist/hooks/{useAutoGrow.d.ts → useAutoGrow/useAutoGrow.d.ts} +0 -0
|
@@ -24,7 +24,7 @@ export interface AvatarSkeletonProps extends React.HTMLAttributes<HTMLDivElement
|
|
|
24
24
|
* wrapper-with-no-behaviour that `.claude/rules/component-architecture.md` §11
|
|
25
25
|
* rejects.
|
|
26
26
|
*
|
|
27
|
-
* The
|
|
27
|
+
* The sweep and the reduced-motion behaviour are not reimplemented here: they
|
|
28
28
|
* come from `Skeleton`, which is the only place they are declared.
|
|
29
29
|
*/
|
|
30
30
|
export declare const AvatarSkeleton: import('react').ForwardRefExoticComponent<AvatarSkeletonProps & import('react').RefAttributes<HTMLDivElement>>;
|
|
@@ -1,3 +1,28 @@
|
|
|
1
|
+
import { AvatarSize } from '../Avatar/index.ts';
|
|
2
|
+
/**
|
|
3
|
+
* What the avatar itself is: the picture, the fallback for when there is no
|
|
4
|
+
* picture, and how big the whole thing is drawn.
|
|
5
|
+
*
|
|
6
|
+
* One object rather than three props, the way `ChatInput` takes `actionLabels`
|
|
7
|
+
* and `ChatBubble` takes `delivery`. The prop budget is five and the text beside
|
|
8
|
+
* the avatar already spends three of them; folding the avatar's own settings
|
|
9
|
+
* into the one value they all describe buys back the room `size` needed, and
|
|
10
|
+
* leaves room for the next thing the avatar grows.
|
|
11
|
+
*
|
|
12
|
+
* `initials` is a field and not something derived from `name` on purpose. Real
|
|
13
|
+
* records carry initials separately precisely *because* the name arrives badly
|
|
14
|
+
* formatted — "GARCÍA LÓPEZ, M.ª José", a single word, an email address — so a
|
|
15
|
+
* derivation is a rule that works on every example anyone writes by hand and
|
|
16
|
+
* fails on the data.
|
|
17
|
+
*/
|
|
18
|
+
export interface AvatarDetailsAvatar {
|
|
19
|
+
/** Image source URL */
|
|
20
|
+
src?: string;
|
|
21
|
+
/** Fallback initials (max 2 characters), shown when there is no image */
|
|
22
|
+
initials?: string;
|
|
23
|
+
/** 24, 32, 48, 64 or 80px. Also sets the text scale beside it. */
|
|
24
|
+
size?: AvatarSize;
|
|
25
|
+
}
|
|
1
26
|
/**
|
|
2
27
|
* An avatar with a name and an optional second line beside it.
|
|
3
28
|
*
|
|
@@ -11,21 +36,33 @@
|
|
|
11
36
|
* anything. Callers who genuinely need arbitrary content next to an avatar
|
|
12
37
|
* should compose `AvatarSquare` themselves rather than widen this.
|
|
13
38
|
*
|
|
14
|
-
* The
|
|
15
|
-
*
|
|
16
|
-
*
|
|
39
|
+
* ### The text scales with the avatar, and the caller still cannot choose it
|
|
40
|
+
*
|
|
41
|
+
* The size spans 24px to 80px, and a name at one fixed size across that range is
|
|
42
|
+
* wrong at both ends. So the two lines step with the box — the pairs are in the
|
|
43
|
+
* stylesheet, keyed off `data-size`, and they are **derived**, never passed.
|
|
44
|
+
* There is no text-size prop and no CSS variable a caller pokes: every
|
|
45
|
+
* `AvatarDetails` at a given size still renders identically to every other one,
|
|
46
|
+
* which is the guarantee the paragraph above is about. What the fixed-size
|
|
47
|
+
* version guaranteed was narrower than it looked — it guaranteed sameness
|
|
48
|
+
* between a 32px row and a 32px row, and there were no other sizes.
|
|
49
|
+
*
|
|
50
|
+
* `xs` and `sm` deliberately share a pair: 14/12 is already the smallest
|
|
51
|
+
* readable step we have, so below 32px only the picture shrinks.
|
|
52
|
+
*
|
|
53
|
+
* The prop list is four plus `dataTestid`, against a cap of five. The one spare
|
|
54
|
+
* is not an invitation — anything that belongs to the avatar goes into
|
|
55
|
+
* `AvatarDetailsAvatar`, and anything that does not has to argue for itself.
|
|
17
56
|
*/
|
|
18
57
|
export interface AvatarDetailsProps extends React.ComponentPropsWithoutRef<'div'> {
|
|
19
|
-
/**
|
|
20
|
-
|
|
21
|
-
/** Fallback initials (max 2 characters) */
|
|
22
|
-
initials?: string;
|
|
23
|
-
/** Disabled state */
|
|
24
|
-
disabled?: boolean;
|
|
58
|
+
/** The avatar itself: image, fallback initials and size */
|
|
59
|
+
avatar?: AvatarDetailsAvatar;
|
|
25
60
|
/** Full name to display */
|
|
26
61
|
name: string;
|
|
27
62
|
/** Subtitle (department, role, etc.) */
|
|
28
63
|
subtitle?: string;
|
|
64
|
+
/** Disabled state */
|
|
65
|
+
disabled?: boolean;
|
|
29
66
|
dataTestid: string;
|
|
30
67
|
}
|
|
31
68
|
export declare const AvatarDetails: import('react').ForwardRefExoticComponent<AvatarDetailsProps & import('react').RefAttributes<HTMLDivElement>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { AvatarDetails, type AvatarDetailsProps } from './AvatarDetails.tsx';
|
|
1
|
+
export { AvatarDetails, type AvatarDetailsAvatar, type AvatarDetailsProps, } from './AvatarDetails.tsx';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AvatarSize } from '../Avatar/index.ts';
|
|
1
2
|
export interface AvatarItem {
|
|
2
3
|
src?: string;
|
|
3
4
|
initials?: string;
|
|
@@ -10,6 +11,8 @@ export interface AvatarGroupProps extends Omit<React.ButtonHTMLAttributes<HTMLBu
|
|
|
10
11
|
max?: number;
|
|
11
12
|
/** Whether the group is interactive (clickable) */
|
|
12
13
|
interactive?: boolean;
|
|
14
|
+
/** The size every avatar in the stack is drawn at. */
|
|
15
|
+
size?: AvatarSize;
|
|
13
16
|
/** Click handler (only fired when interactive) */
|
|
14
17
|
onClick?: React.MouseEventHandler<HTMLButtonElement>;
|
|
15
18
|
dataTestid: string;
|
|
@@ -2,7 +2,8 @@ export interface SkeletonProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
2
2
|
dataTestid: string;
|
|
3
3
|
}
|
|
4
4
|
/**
|
|
5
|
-
* A block
|
|
5
|
+
* A block a sheen sweeps across while the content it stands in for is still
|
|
6
|
+
* loading.
|
|
6
7
|
*
|
|
7
8
|
* It configures nothing. One surface, and the caller gives it its shape with
|
|
8
9
|
* ordinary classes — `h-4 w-48` is a line of text, `size-10 rounded-full` is an
|
|
@@ -16,6 +16,25 @@ export interface ComboboxProps extends Omit<React.HTMLAttributes<HTMLDivElement>
|
|
|
16
16
|
/** Emitted when the open state changes. */
|
|
17
17
|
onOpenChange?: (open: boolean) => void;
|
|
18
18
|
children?: React.ReactNode;
|
|
19
|
+
/**
|
|
20
|
+
* The term to search for, once typing has stopped. Binding it is what tells
|
|
21
|
+
* the combobox its options are an answer it asked for — see `ignoreFilter`.
|
|
22
|
+
*/
|
|
23
|
+
onSearch?: (term: string) => void;
|
|
24
|
+
/**
|
|
25
|
+
* Quiet period, in milliseconds, between the last keystroke and `onSearch`.
|
|
26
|
+
* `0` emits in the same tick.
|
|
27
|
+
*/
|
|
28
|
+
debounce?: number;
|
|
29
|
+
/**
|
|
30
|
+
* Whether to skip filtering the rendered options in the browser. Left unset
|
|
31
|
+
* it follows `onSearch`: options the caller went and fetched have already
|
|
32
|
+
* been filtered, by something that knows more than a literal text match does
|
|
33
|
+
* — search "peres", get "Ana Pérez" back from a server that folds accents,
|
|
34
|
+
* and a second pass here hides a correct answer with nothing logged. Pass it
|
|
35
|
+
* explicitly to override, `false` included.
|
|
36
|
+
*/
|
|
37
|
+
ignoreFilter?: boolean;
|
|
19
38
|
dataTestid: string;
|
|
20
39
|
}
|
|
21
40
|
/**
|
|
@@ -3,6 +3,13 @@ export interface ComboboxChipsInputProps extends Omit<React.InputHTMLAttributes<
|
|
|
3
3
|
placeholder?: string;
|
|
4
4
|
disabled?: boolean;
|
|
5
5
|
size?: InputSize;
|
|
6
|
+
/**
|
|
7
|
+
* Names a chip the options cannot: a selection that arrived with the record,
|
|
8
|
+
* from a server, before any item existed to report a label. Return
|
|
9
|
+
* `undefined` for anything it does not know and the option's own label is
|
|
10
|
+
* used, so it never has to answer for values the list can speak for itself.
|
|
11
|
+
*/
|
|
12
|
+
chipLabel?: (value: string) => string | undefined;
|
|
6
13
|
/** Custom trigger content (defaults to a chevron icon). */
|
|
7
14
|
trigger?: React.ReactNode;
|
|
8
15
|
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
export interface ComboboxItemEditPreview {
|
|
2
|
+
/**
|
|
3
|
+
* Enter the editing state. Pass it straight to the control that starts the
|
|
4
|
+
* edit — `onClick={edit}` — so it receives the event and can stop it.
|
|
5
|
+
*/
|
|
6
|
+
edit: (event?: {
|
|
7
|
+
stopPropagation: () => void;
|
|
8
|
+
}) => void;
|
|
9
|
+
}
|
|
10
|
+
export interface ComboboxItemEditField {
|
|
11
|
+
/** The text as it currently stands. */
|
|
12
|
+
value: string | undefined;
|
|
13
|
+
/** Report a keystroke from the field. */
|
|
14
|
+
setValue: (value: string | undefined) => void;
|
|
15
|
+
/** Save, and leave the editing state. */
|
|
16
|
+
commit: () => void;
|
|
17
|
+
/** Put the text back as it was, and leave the editing state. */
|
|
18
|
+
cancel: () => void;
|
|
19
|
+
}
|
|
20
|
+
export interface ComboboxItemEditProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children' | 'onChange'> {
|
|
21
|
+
/**
|
|
22
|
+
* The text being edited. Pass it one way — `value={label}` — and let
|
|
23
|
+
* `onCommit` write the new one back: it seeds the draft and re-seeds it
|
|
24
|
+
* whenever it changes, so the caller never holds the draft and the field
|
|
25
|
+
* inside `field` never has a second copy of it to disagree with. Add
|
|
26
|
+
* `onValueChange` for a caller who wants every keystroke.
|
|
27
|
+
*/
|
|
28
|
+
value?: string;
|
|
29
|
+
/** The starting text when nothing is passed for `value`. */
|
|
30
|
+
defaultValue?: string;
|
|
31
|
+
/** Every keystroke, for a caller controlling the draft. */
|
|
32
|
+
onValueChange?: (value: string | undefined) => void;
|
|
33
|
+
/** The edit was saved. Carries the text as it now stands. */
|
|
34
|
+
onCommit?: (value: string | undefined) => void;
|
|
35
|
+
/** The edit was abandoned; the draft has already been put back. */
|
|
36
|
+
onCancel?: () => void;
|
|
37
|
+
/** The row while it is being edited. */
|
|
38
|
+
field?: (context: ComboboxItemEditField) => React.ReactNode;
|
|
39
|
+
/** The row the rest of the time. */
|
|
40
|
+
children?: (context: ComboboxItemEditPreview) => React.ReactNode;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* An option that can be renamed without leaving the list: the row shows its
|
|
44
|
+
* normal content until the caller's own control asks to edit it, then hands the
|
|
45
|
+
* row over to the caller's own field. Port of
|
|
46
|
+
* `core/src/Forms/Inputs/Combobox/ComboboxItemEdit`.
|
|
47
|
+
*
|
|
48
|
+
* It holds no strings and draws no buttons — the design system ships neither.
|
|
49
|
+
* What it owns is the part a caller cannot get right from outside: a list whose
|
|
50
|
+
* every reflex is to select the row and close, aimed at a field that needs the
|
|
51
|
+
* click, the keystroke and the `Escape` for itself.
|
|
52
|
+
*
|
|
53
|
+
* ```tsx
|
|
54
|
+
* <OxComboboxItem value="other">
|
|
55
|
+
* <OxComboboxItemEdit
|
|
56
|
+
* value={label}
|
|
57
|
+
* onCommit={next => setLabel(next ?? '')}
|
|
58
|
+
* field={({ value, setValue, commit }) => (
|
|
59
|
+
* <>
|
|
60
|
+
* <OxInputText size="sm" field={value} onFieldChange={setValue} />
|
|
61
|
+
* <OxButton variant="ghost" onClick={commit}>…</OxButton>
|
|
62
|
+
* </>
|
|
63
|
+
* )}
|
|
64
|
+
* >
|
|
65
|
+
* {({ edit }) => (
|
|
66
|
+
* <>
|
|
67
|
+
* {label}
|
|
68
|
+
* <OxButton variant="ghost" onClick={edit}>…</OxButton>
|
|
69
|
+
* </>
|
|
70
|
+
* )}
|
|
71
|
+
* </OxComboboxItemEdit>
|
|
72
|
+
* </OxComboboxItem>
|
|
73
|
+
* ```
|
|
74
|
+
*
|
|
75
|
+
* Both states live here rather than behind the caller's own conditional for one
|
|
76
|
+
* reason worth the extra render prop: the control that *starts* the edit is
|
|
77
|
+
* itself inside the row, so its click selects the option and shuts the popover
|
|
78
|
+
* unless it is stopped. `edit` stops it. A caller assembling the two states
|
|
79
|
+
* themselves has to know that, and the version that does not know it looks
|
|
80
|
+
* exactly right until it is clicked.
|
|
81
|
+
*
|
|
82
|
+
* ### What is taken away from the list while editing, and by whom
|
|
83
|
+
*
|
|
84
|
+
* The Vue half is fighting reka; this one is fighting cmdk, and the two land on
|
|
85
|
+
* very nearly the same list:
|
|
86
|
+
*
|
|
87
|
+
* - **The click.** cmdk's `CommandItem` calls `onSelect` on `click`, and a
|
|
88
|
+
* single-select combobox turns a selection into `setOpen(false)`. Clicking
|
|
89
|
+
* into the field is a click on the row, so the popover closed under the
|
|
90
|
+
* cursor that opened it.
|
|
91
|
+
* - **`Enter`.** cmdk's `Command` dispatches a select on the highlighted row,
|
|
92
|
+
* which is the same close by another route. Here it is what saves the edit.
|
|
93
|
+
* - **`ArrowUp` / `ArrowDown` / `Home` / `End`.** All four are
|
|
94
|
+
* `preventDefault()`ed by `Command`, so the caret could not be moved.
|
|
95
|
+
* - **`pointermove`.** `CommandItem` moves the highlight onto the row under the
|
|
96
|
+
* cursor.
|
|
97
|
+
* - **`Space`** is in the list for the Vue half's sake — reka's `ListboxItem`
|
|
98
|
+
* selects on it *with `prevent`*, so a name with two words in it could not be
|
|
99
|
+
* typed. cmdk leaves the space bar alone; stopping it here costs nothing and
|
|
100
|
+
* keeps one list of claimed keys instead of two that drift.
|
|
101
|
+
*
|
|
102
|
+
* `Escape` is deliberately absent and is answered in `ComboboxContent`. See
|
|
103
|
+
* `useComboboxEditing` for why it cannot be answered here.
|
|
104
|
+
*
|
|
105
|
+
* ### Focus
|
|
106
|
+
*
|
|
107
|
+
* Nothing in this half steals focus the way reka's listbox can, so there is no
|
|
108
|
+
* equivalent of the `focusable` flag the Vue port suspends and restores:
|
|
109
|
+
* Radix's popover is non-modal and `onOpenAutoFocus` is already prevented,
|
|
110
|
+
* cmdk's highlight is an `aria-activedescendant` rather than a real focus move,
|
|
111
|
+
* and its one refocusing path fires only when the active element is cmdk's own
|
|
112
|
+
* input or root — never a field inside a row. What is left is the same on both
|
|
113
|
+
* sides: take focus on entering the edit, hand it back to the combobox's own
|
|
114
|
+
* field on leaving.
|
|
115
|
+
*
|
|
116
|
+
* **A dialog around the combobox is free here and was not in Vue.** A dialog
|
|
117
|
+
* traps focus, the popover is portalled to `body` and is therefore outside what
|
|
118
|
+
* the trap considers the dialog, so the `.focus()` below reads as focus
|
|
119
|
+
* escaping — unless a nearer focus layer has suspended the trap.
|
|
120
|
+
* `Popover.Content` registers one in every Radix build, untrapped when the
|
|
121
|
+
* popover is non-modal, which ours is. reka gives `SelectContentImpl`,
|
|
122
|
+
* `PopoverContentImpl` and `MenuContentImpl` a `FocusScope` and
|
|
123
|
+
* `ComboboxContentImpl` none, so the Vue `ComboboxContent` has to add the layer
|
|
124
|
+
* by hand to reach the behaviour this side gets for nothing.
|
|
125
|
+
*
|
|
126
|
+
* **One thing here has no Vue counterpart.** cmdk re-sorts the option elements
|
|
127
|
+
* by moving the DOM nodes themselves whenever the search term changes, and a
|
|
128
|
+
* focused field inside a row that gets reparented loses focus. Typing in the
|
|
129
|
+
* combobox's own search box while a row edit is open is therefore not the same
|
|
130
|
+
* experience in the two packages. Editing is reached by clicking a control in
|
|
131
|
+
* the row, which leaves the search box unfocused, so it takes a deliberate
|
|
132
|
+
* detour to hit.
|
|
133
|
+
*/
|
|
134
|
+
export declare const ComboboxItemEdit: import('react').ForwardRefExoticComponent<ComboboxItemEditProps & import('react').RefAttributes<HTMLDivElement>>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ComboboxEditing } from './useComboboxEditing.ts';
|
|
1
2
|
/**
|
|
2
3
|
* Shared Combobox state.
|
|
3
4
|
*
|
|
@@ -6,7 +7,7 @@
|
|
|
6
7
|
* every part needs — the value, `multiple`, `disabled` and the search term — so
|
|
7
8
|
* a part can be used on its own without threading props through the tree.
|
|
8
9
|
*/
|
|
9
|
-
export interface ComboboxContextValue {
|
|
10
|
+
export interface ComboboxContextValue extends ComboboxEditing {
|
|
10
11
|
/** Current selection. `string` for single-select, `string[]` for multiple. */
|
|
11
12
|
value: string | string[] | undefined;
|
|
12
13
|
/** Commit a selection (toggles for `multiple`). */
|
|
@@ -21,6 +22,12 @@ export interface ComboboxContextValue {
|
|
|
21
22
|
/** Search string driving cmdk filtering. */
|
|
22
23
|
search: string;
|
|
23
24
|
setSearch: (search: string) => void;
|
|
25
|
+
/** Typing: restart the quiet period before the root's `onSearch`. */
|
|
26
|
+
scheduleSearch: (term: string) => void;
|
|
27
|
+
/** A gesture that settles the term — clearing it. Report now. */
|
|
28
|
+
searchImmediately: (term: string) => void;
|
|
29
|
+
/** Whether cmdk should leave the rendered options alone. */
|
|
30
|
+
skipFilter: boolean;
|
|
24
31
|
/**
|
|
25
32
|
* The text each option renders, keyed by the value it selects, so the field
|
|
26
33
|
* can show `Barcelona` rather than `barcelona`. See `useComboboxLabels` for
|
|
@@ -28,6 +35,12 @@ export interface ComboboxContextValue {
|
|
|
28
35
|
*/
|
|
29
36
|
registerLabel: (value: string, label: string) => void;
|
|
30
37
|
labelFor: (value: string) => string | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* The field itself, so a row that took focus for an in-place edit can hand it
|
|
40
|
+
* back when the edit ends. reka carries the same element on its own combobox
|
|
41
|
+
* context, which is where the Vue half gets it.
|
|
42
|
+
*/
|
|
43
|
+
inputRef: React.RefObject<HTMLInputElement | null>;
|
|
31
44
|
}
|
|
32
45
|
export declare const ComboboxContext: import('react').Context<ComboboxContextValue | null>;
|
|
33
46
|
export declare function useComboboxContext(): ComboboxContextValue;
|
|
@@ -4,6 +4,7 @@ export { ComboboxInput, type ComboboxInputProps } from './ComboboxInput.tsx';
|
|
|
4
4
|
export { ComboboxChipsInput, type ComboboxChipsInputProps, } from './ComboboxChipsInput.tsx';
|
|
5
5
|
export { ComboboxContent, type ComboboxContentProps, } from './ComboboxContent.tsx';
|
|
6
6
|
export { ComboboxItem, type ComboboxItemProps } from './ComboboxItem.tsx';
|
|
7
|
+
export { ComboboxItemEdit, type ComboboxItemEditProps, } from './ComboboxItemEdit.tsx';
|
|
7
8
|
export { ComboboxEmpty, type ComboboxEmptyProps } from './ComboboxEmpty.tsx';
|
|
8
9
|
export { ComboboxGroup, type ComboboxGroupProps } from './ComboboxGroup.tsx';
|
|
9
10
|
export { ComboboxSeparator, type ComboboxSeparatorProps, } from './ComboboxSeparator.tsx';
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export interface ComboboxEditing {
|
|
2
|
+
/** The row entering its editing state announces how to back out of it. */
|
|
3
|
+
openEdit: (cancel: () => void) => void;
|
|
4
|
+
/** The row leaving its editing state withdraws that offer. */
|
|
5
|
+
closeEdit: (cancel: () => void) => void;
|
|
6
|
+
/**
|
|
7
|
+
* Back out of the open edit, if there is one. Returns whether there was —
|
|
8
|
+
* the caller uses that to decide whether the keystroke has been spent.
|
|
9
|
+
*/
|
|
10
|
+
cancelOpenEdit: () => boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Which row, if any, is currently being edited in place. Port of
|
|
14
|
+
* `core/src/Forms/Inputs/Combobox/useComboboxEditing`, where Vue's
|
|
15
|
+
* `provide`/`inject` does what this hook plus `ComboboxContext` do here.
|
|
16
|
+
*
|
|
17
|
+
* It exists for one keystroke. `Escape` inside the edit has to cancel the edit
|
|
18
|
+
* and leave the list open, and the only thing that can stop the list closing is
|
|
19
|
+
* the content's `onEscapeKeyDown`: Radix's dismissable layer listens on
|
|
20
|
+
* `document` with `capture: true`, so the editing field never sees the key
|
|
21
|
+
* first and cannot swallow it however hard it tries. The layer offers exactly
|
|
22
|
+
* one way out — `preventDefault()` on the event it hands up. So the content is
|
|
23
|
+
* where `Escape` has to be answered, the state is in the row, and this is the
|
|
24
|
+
* wire between them.
|
|
25
|
+
*
|
|
26
|
+
* The Vue half reaches the same arrangement from the opposite constraint: reka
|
|
27
|
+
* listens on `window` in the bubble phase, so there the field *would* see the
|
|
28
|
+
* key first, and handling it in both places would close the edit before the
|
|
29
|
+
* content was asked whether to prevent the dismissal — closing the list, which
|
|
30
|
+
* is the one thing this must not do. One mechanism, in the content, on both
|
|
31
|
+
* sides.
|
|
32
|
+
*
|
|
33
|
+
* A ref rather than state: nothing renders differently for knowing which row is
|
|
34
|
+
* open, and the only reader is an event handler, which wants the current value
|
|
35
|
+
* and not the one captured when it was last rendered.
|
|
36
|
+
*
|
|
37
|
+
* One edit at a time, and opening a second cancels the first: two rows in edit
|
|
38
|
+
* mode have two answers to `Escape` and no way to say which one the user meant.
|
|
39
|
+
*/
|
|
40
|
+
export declare function useComboboxEditing(): ComboboxEditing;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface ComboboxSearch {
|
|
2
|
+
/** Typing: restart the quiet period, emit when it elapses. */
|
|
3
|
+
schedule: (term: string) => void;
|
|
4
|
+
/** A gesture that settles the term — clearing it. Emit now. */
|
|
5
|
+
immediately: (term: string) => void;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* The wire between whichever field is typed into and the root's `onSearch`.
|
|
9
|
+
*
|
|
10
|
+
* The root is where `debounce` and `onSearch` belong — there are three fields
|
|
11
|
+
* (`ComboboxInput`, `ComboboxChipsInput`, and `ComboboxCancel` clearing one of
|
|
12
|
+
* them) and a prop on each would be the same number asked three times. The
|
|
13
|
+
* fields reach it through the shared context, beside `setSearch`.
|
|
14
|
+
*
|
|
15
|
+
* The fields report from their `onChange` rather than from the term itself,
|
|
16
|
+
* because the term is also written when a value is selected — the field is
|
|
17
|
+
* reset and the resolved label put in its place — and a search fired for the
|
|
18
|
+
* text of the option the user just picked is a request nobody asked for.
|
|
19
|
+
*/
|
|
20
|
+
export declare function useComboboxSearch(debounce: number, onSearch: ((term: string) => void) | undefined): ComboboxSearch;
|
|
@@ -6,14 +6,14 @@ export interface SearchBarProps extends Omit<React.InputHTMLAttributes<HTMLInput
|
|
|
6
6
|
* Milliseconds of no typing before `onSearch` fires. `0` fires on every
|
|
7
7
|
* keystroke.
|
|
8
8
|
*/
|
|
9
|
-
|
|
9
|
+
debounce?: number;
|
|
10
10
|
/** Controlled term. Pair with `onValueChange`; omit for uncontrolled. */
|
|
11
11
|
value?: string;
|
|
12
12
|
/** Starting term when uncontrolled. */
|
|
13
13
|
defaultValue?: string;
|
|
14
14
|
/** Called on every keystroke with the next term, without waiting. */
|
|
15
15
|
onValueChange?: (value: string) => void;
|
|
16
|
-
/** Called once typing has been quiet for `
|
|
16
|
+
/** Called once typing has been quiet for `debounce` ms — and at once on Enter or clear. */
|
|
17
17
|
onSearch?: (term: string) => void;
|
|
18
18
|
dataTestid: string;
|
|
19
19
|
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { VariantProps } from 'class-variance-authority';
|
|
2
2
|
export { SearchBar } from './SearchBar.tsx';
|
|
3
3
|
export type { SearchBarProps } from './SearchBar.tsx';
|
|
4
|
-
export { useSearchDelay } from './useSearchDelay.ts';
|
|
5
|
-
export type { UseSearchDelayReturn } from './useSearchDelay.ts';
|
|
6
4
|
/**
|
|
7
5
|
* Class names, not utilities — see `Button/index.ts` for why the package
|
|
8
6
|
* cannot publish `.h-10` and `.rounded-lg` of its own. `SearchBar.module.css`
|
|
@@ -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
|
-
/**
|
|
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,
|
|
7
|
-
* cannot serve
|
|
8
|
-
*
|
|
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,27 @@
|
|
|
1
|
+
import { RefObject } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Moves the selected pill over whichever tab is active.
|
|
4
|
+
*
|
|
5
|
+
* The selected state used to be a background on the trigger itself, which is
|
|
6
|
+
* why it could not travel: two elements cannot transition into one another. So
|
|
7
|
+
* the pill is a single element in the track, taken out of flow, and what moves
|
|
8
|
+
* is its geometry — published as custom properties on the track
|
|
9
|
+
* (`--toggle-tabs-pill-x/y/width/height`) for the stylesheet to spend.
|
|
10
|
+
*
|
|
11
|
+
* The handoff is the point. Nothing here decides how the pill is drawn: no
|
|
12
|
+
* `transform` string, no radius, no colour, no orientation branch. This writes
|
|
13
|
+
* four numbers and the component's own rule composes them, which keeps a
|
|
14
|
+
* measurement out of the stylesheet's job and the stylesheet's job out of here
|
|
15
|
+
* — and means the vertical orientation needs no code, only the `y` that is
|
|
16
|
+
* already being written.
|
|
17
|
+
*
|
|
18
|
+
* Both axes always, for that reason: `data-orientation="vertical"` turns the
|
|
19
|
+
* track into a column and the pill then travels down it, measured by exactly
|
|
20
|
+
* the same two rectangles.
|
|
21
|
+
*
|
|
22
|
+
* The whole of it runs off observers rather than off the render, which is what
|
|
23
|
+
* lets it be a single effect with no dependency on the active value: a tab
|
|
24
|
+
* changing, a tab arriving and a tab being resized are all DOM events by the
|
|
25
|
+
* time they matter here.
|
|
26
|
+
*/
|
|
27
|
+
export declare function useToggleTabsPill(track: RefObject<HTMLElement | null>): void;
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -8,5 +8,7 @@
|
|
|
8
8
|
* sibling's folder and a reader having to know that `Textarea`'s sizing is
|
|
9
9
|
* really `ChatInput`'s. See `.claude/rules/component-architecture.md` §13.
|
|
10
10
|
*/
|
|
11
|
-
export { useAutoGrow } from './useAutoGrow.ts';
|
|
12
|
-
export type { UseAutoGrowReturn } from './useAutoGrow.ts';
|
|
11
|
+
export { useAutoGrow } from './useAutoGrow/useAutoGrow.ts';
|
|
12
|
+
export type { UseAutoGrowReturn } from './useAutoGrow/useAutoGrow.ts';
|
|
13
|
+
export { useSearchDebounce } from './useSearchDebounce/useSearchDebounce.ts';
|
|
14
|
+
export type { UseSearchDebounceReturn } from './useSearchDebounce/useSearchDebounce.ts';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The quiet period between typing and searching — mirrors
|
|
3
|
-
* `@sesame/orxata-core` `
|
|
3
|
+
* `@sesame/orxata-core` `useSearchDebounce`.
|
|
4
4
|
*
|
|
5
5
|
* A search field that emits on every keystroke turns "Marie" into five
|
|
6
6
|
* requests, four of which are already stale by the time they land. Waiting for
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* drops whatever `schedule` had pending, which would otherwise fire a moment
|
|
14
14
|
* later with a term the user has already moved on from.
|
|
15
15
|
*/
|
|
16
|
-
export interface
|
|
16
|
+
export interface UseSearchDebounceReturn {
|
|
17
17
|
/** Restart the quiet period; emit when it elapses. */
|
|
18
18
|
schedule: (term: string) => void;
|
|
19
19
|
/** Emit now, dropping anything pending. */
|
|
@@ -21,4 +21,4 @@ export interface UseSearchDelayReturn {
|
|
|
21
21
|
/** Drop anything pending without emitting. */
|
|
22
22
|
cancel: () => void;
|
|
23
23
|
}
|
|
24
|
-
export declare const
|
|
24
|
+
export declare const useSearchDebounce: (debounce: number, emit: (term: string) => void) => UseSearchDebounceReturn;
|
package/dist/main.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ export { Scrollbar as OxScrollbar, useScrollbar, SCROLLBAR_THICKNESS, type Scrol
|
|
|
17
17
|
export { LocaleProvider as OxLocaleProvider } from './Locale/index.ts';
|
|
18
18
|
export { normalizeLocale, useLocale } from './Locale/index.ts';
|
|
19
19
|
export { AvatarRounded as OxAvatarRounded, AvatarSkeleton as OxAvatarSkeleton, AvatarSquare as OxAvatarSquare, avatarRoundedVariants, avatarSquareVariants, type AvatarRoundedVariants, type AvatarSize, type AvatarSquareVariants, type AvatarTone, } from './Display/Avatar/index.ts';
|
|
20
|
-
export { AvatarDetails as OxAvatarDetails } from './Display/AvatarDetails/index.ts';
|
|
20
|
+
export { AvatarDetails as OxAvatarDetails, type AvatarDetailsAvatar, } from './Display/AvatarDetails/index.ts';
|
|
21
21
|
export { AvatarGroup as OxAvatarGroup, type AvatarItem, } from './Display/AvatarGroup/index.ts';
|
|
22
22
|
export { Badge as OxBadge, badgeVariants, type BadgeVariants, } from './Display/Badge/index.ts';
|
|
23
23
|
export { CalendarDate as OxCalendarDate, calendarDateVariants, type CalendarDateVariants, } from './Display/CalendarDate/index.ts';
|
|
@@ -44,6 +44,6 @@ export { PageControl as OxPageControl, pageControlDots, PAGE_CONTROL_WINDOW, typ
|
|
|
44
44
|
export { Breadcrumb as OxBreadcrumb, BreadcrumbList as OxBreadcrumbList, BreadcrumbItem as OxBreadcrumbItem, BreadcrumbLink as OxBreadcrumbLink, BreadcrumbPage as OxBreadcrumbPage, BreadcrumbSeparator as OxBreadcrumbSeparator, BreadcrumbEllipsis as OxBreadcrumbEllipsis, } from './Navigation/Breadcrumb/index.ts';
|
|
45
45
|
export { Counter as OxCounter, counterVariants, type CounterVariants, } from './Forms/Field/Counter/index.ts';
|
|
46
46
|
export { FieldGroup as OxFieldGroup, FieldLabel as OxFieldLabel, FieldMessage as OxFieldMessage, useFieldControl, useFieldControlGroup, type FieldControlAttrs, type FieldControlGroupAttrs, type FieldGroupProps, type FieldVariant, } from './Forms/Field/index.ts';
|
|
47
|
-
export { InputGroup as OxInputGroup, InputText as OxInputText, InputNumber as OxInputNumber, InputNumberContent as OxInputNumberContent, InputNumberDecrement as OxInputNumberDecrement, InputNumberIncrement as OxInputNumberIncrement, InputNumberInput as OxInputNumberInput, InputPassword as OxInputPassword, InputPasswordInput as OxInputPasswordInput, InputPasswordToggle as OxInputPasswordToggle, useInputPassword, InputOtp as OxInputOtp, InputOtpGroup as OxInputOtpGroup, InputOtpSlot as OxInputOtpSlot, InputOtpSeparator as OxInputOtpSeparator, useInputOtp, Calendar as OxCalendar, CalendarRange as OxCalendarRange, CalendarDay as OxCalendarDay, calendarDayVariants, Combobox as OxCombobox, ComboboxCancel as OxComboboxCancel, ComboboxInput as OxComboboxInput, ComboboxChipsInput as OxComboboxChipsInput, ComboboxContent as OxComboboxContent, ComboboxItem as OxComboboxItem, ComboboxEmpty as OxComboboxEmpty, ComboboxGroup as OxComboboxGroup, ComboboxSeparator as OxComboboxSeparator, ChatInput as OxChatInput, DatePicker as OxDatePicker, DateRangePicker as OxDateRangePicker, DatePickerTrigger as OxDatePickerTrigger, DatePickerHeader as OxDatePickerHeader, DatePickerMonthSelect as OxDatePickerMonthSelect, DatePickerYearSelect as OxDatePickerYearSelect, SearchBar as OxSearchBar, searchBarVariants,
|
|
47
|
+
export { InputGroup as OxInputGroup, InputText as OxInputText, InputNumber as OxInputNumber, InputNumberContent as OxInputNumberContent, InputNumberDecrement as OxInputNumberDecrement, InputNumberIncrement as OxInputNumberIncrement, InputNumberInput as OxInputNumberInput, InputPassword as OxInputPassword, InputPasswordInput as OxInputPasswordInput, InputPasswordToggle as OxInputPasswordToggle, useInputPassword, InputOtp as OxInputOtp, InputOtpGroup as OxInputOtpGroup, InputOtpSlot as OxInputOtpSlot, InputOtpSeparator as OxInputOtpSeparator, useInputOtp, Calendar as OxCalendar, CalendarRange as OxCalendarRange, CalendarDay as OxCalendarDay, calendarDayVariants, Combobox as OxCombobox, ComboboxCancel as OxComboboxCancel, ComboboxInput as OxComboboxInput, ComboboxChipsInput as OxComboboxChipsInput, ComboboxContent as OxComboboxContent, ComboboxItem as OxComboboxItem, ComboboxItemEdit as OxComboboxItemEdit, ComboboxEmpty as OxComboboxEmpty, ComboboxGroup as OxComboboxGroup, ComboboxSeparator as OxComboboxSeparator, ChatInput as OxChatInput, DatePicker as OxDatePicker, DateRangePicker as OxDateRangePicker, DatePickerTrigger as OxDatePickerTrigger, DatePickerHeader as OxDatePickerHeader, DatePickerMonthSelect as OxDatePickerMonthSelect, DatePickerYearSelect as OxDatePickerYearSelect, SearchBar as OxSearchBar, searchBarVariants, SearchPanel as OxSearchPanel, SearchPanelInput as OxSearchPanelInput, SearchPanelList as OxSearchPanelList, SearchPanelGroup as OxSearchPanelGroup, SearchPanelItem as OxSearchPanelItem, SearchPanelEmpty as OxSearchPanelEmpty, Select as OxSelect, SelectTrigger as OxSelectTrigger, SelectContent as OxSelectContent, SelectItem as OxSelectItem, SelectGroup as OxSelectGroup, SelectSeparator as OxSelectSeparator, Textarea as OxTextarea, Switch as OxSwitch, Checkbox as OxCheckbox, RadioButton as OxRadioButton, RadioGroup as OxRadioGroup, ToggleGroup as OxToggleGroup, ToggleLabel as OxToggleLabel, ToggleDescription as OxToggleDescription, SWITCH_SIZES, type InputNumberProps, type InputPasswordProps, type InputPasswordContext, type InputOtpProps, type InputOtpSlotProps, type InputOtpContext, type CalendarProps, type CalendarRangeProps, type CalendarDateRange, type CalendarDayProps, type CalendarDayState, type CalendarDayVariants, type CalendarConstraints, type CalendarNav, type ComboboxProps, type ChatInputActionLabels, type ChatInputState, type DatePickerProps, type DateRangePickerProps, type DatePickerTriggerProps, type DatePickerHeaderProps, type DatePickerMonthSelectProps, type DatePickerYearSelectProps, type SearchBarVariants, type SelectProps, type TextareaCounterState, type RadioGroupProps, type ToggleGroupProps, type ToggleLabelProps, type ToggleDescriptionProps, } from './Forms/Inputs/index.ts';
|
|
48
48
|
export { Table as OxTable, TableVirtualized as OxTableVirtualized, TableHead as OxTableHead, TableBody as OxTableBody, TableRow as OxTableRow, TableCell as OxTableCell, TableHeaderCell as OxTableHeaderCell, TableSelectCell as OxTableSelectCell, TableDragCell as OxTableDragCell, TableBulkHeader as OxTableBulkHeader, TablePagination as OxTablePagination, TableEmpty as OxTableEmpty, TableRowExpanded as OxTableRowExpanded, TableExpandCell as OxTableExpandCell, TableColumnVisibility as OxTableColumnVisibility, useTable, useTableSelection, useTableSorting, useTablePagination, useTableDetailRow, useTablePinning, useTableColumns, useScrollShadow, useDragToScroll, useFixedColumns, useTableVirtual, } from './Data/Table/index.ts';
|
|
49
49
|
export type { UseTableOptions, UseTableReturn, UseTableSelectionReturn, UseTableSortingReturn, UseTablePaginationOptions, UseTablePaginationReturn, DetailRowInstance, DetailRowOptions, DetailRowPluginDef, UseTablePinningOptions, UseTablePinningReturn, CellInfo, HeaderInfo, UseTableVirtualOptions, UseTableVirtualReturn, UseTableColumnsOptions, UseTableColumnsReturn, UseScrollShadowOptions, UseScrollShadowReturn, UseDragToScrollOptions, UseDragToScrollReturn, UseFixedColumnsOptions, TableProps, TableMode, ColumnDef, ColumnAlign, CellContext, SortingState, PaginationState, PaginationChangePayload, SortingChangePayload, SelectionChangePayload, FilterChangePayload, ColumnResizeMode, ColumnVisibilityState, ColumnOrderState, ExpandedState, ColumnVisibilityChangePayload, ColumnOrderChangePayload, RowExpandChangePayload, ColumnResizePayload, ColumnPinningState, } from './Data/Table/index.ts';
|