@sesamehr/react-design-system 2.0.0-beta.4 → 2.0.0-beta.6
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/Button/IconButton/IconButton.d.ts +32 -0
- package/dist/Button/IconButton/index.d.ts +27 -0
- package/dist/Data/Table/Table.d.ts +1 -1
- package/dist/Data/Table/TableSelectCell/TableSelectCell.d.ts +8 -0
- package/dist/Data/Table/hooks/useTableVirtual/useTableVirtual.d.ts +1 -1
- package/dist/Data/Table/hooks/useTableVirtual/useTableVirtual.types.d.ts +15 -3
- package/dist/Data/Table/index.d.ts +0 -1
- package/dist/Display/AvatarDetails/AvatarDetails.d.ts +31 -0
- package/dist/Display/AvatarDetails/index.d.ts +1 -0
- package/dist/Display/Chip/Chip.d.ts +7 -1
- package/dist/Display/Chip/index.d.ts +9 -4
- package/dist/Feedback/Loader/Loader.d.ts +16 -0
- package/dist/Feedback/Loader/index.d.ts +2 -0
- package/dist/Feedback/Progress/Progress.d.ts +3 -0
- package/dist/Feedback/Progress/index.d.ts +17 -0
- package/dist/Forms/Inputs/Calendar/Calendar.d.ts +60 -0
- package/dist/Forms/Inputs/Calendar/CalendarDay.d.ts +37 -0
- package/dist/Forms/Inputs/Calendar/CalendarRange.d.ts +61 -0
- package/dist/Forms/Inputs/Calendar/constraints.d.ts +19 -0
- package/dist/Forms/Inputs/Calendar/index.d.ts +20 -0
- package/dist/Forms/Inputs/Calendar/testids.d.ts +25 -0
- package/dist/Forms/Inputs/Calendar/useCalendarLocale.d.ts +22 -0
- package/dist/Forms/Inputs/Combobox/ComboboxCancel.d.ts +14 -0
- package/dist/Forms/Inputs/Combobox/ComboboxChipsInput.d.ts +4 -0
- package/dist/Forms/Inputs/Combobox/index.d.ts +1 -0
- package/dist/Forms/Inputs/Combobox/useChipOverflow.d.ts +30 -0
- package/dist/Forms/Inputs/SearchBar/SearchBar.d.ts +35 -0
- package/dist/Forms/Inputs/SearchBar/index.d.ts +22 -0
- package/dist/Forms/Inputs/SearchBar/useSearchDelay.d.ts +24 -0
- package/dist/Forms/Inputs/index.d.ts +2 -0
- package/dist/main.d.ts +5 -2
- package/dist/react-design-system.css +1 -1
- package/dist/react-design-system.js +13560 -9624
- package/dist/react-design-system.umd.cjs +58 -48
- package/package.json +3 -1
- package/dist/Data/Table/TableAvatar/TableAvatar.d.ts +0 -14
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ButtonVariants } from '../index.ts';
|
|
2
|
+
import { IconButtonVariants } from './index.ts';
|
|
3
|
+
export interface IconButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
4
|
+
/**
|
|
5
|
+
* `Button`'s colours, by its own words — the design file calls the filled
|
|
6
|
+
* one `primary`, but `Button` has called it `default` since it shipped and a
|
|
7
|
+
* caller swapping one for the other should not relearn the one word that
|
|
8
|
+
* differs. No `link`: the design has no such icon button, and a link with no
|
|
9
|
+
* text has no accessible name by construction.
|
|
10
|
+
*/
|
|
11
|
+
variant?: Exclude<ButtonVariants['variant'], 'link'>;
|
|
12
|
+
size?: IconButtonVariants['size'];
|
|
13
|
+
/**
|
|
14
|
+
* What a screen reader announces. Required — it narrows the optional
|
|
15
|
+
* `aria-label` this inherits from `ButtonHTMLAttributes` — because the glyph
|
|
16
|
+
* is the whole control, so there is no text for the browser to fall back to
|
|
17
|
+
* and an unlabelled one announces as "button" and nothing else. No default
|
|
18
|
+
* can describe what an icon a caller chose is for, so there is not one.
|
|
19
|
+
*/
|
|
20
|
+
'aria-label': string;
|
|
21
|
+
/** Render as the child element instead of a `<button>` (Radix Slot). */
|
|
22
|
+
asChild?: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* IconButton — mirrors `@sesame/orxata-core` IconButton.
|
|
26
|
+
*
|
|
27
|
+
* A button whose entire content is an icon, circular at every size. The icon
|
|
28
|
+
* comes from the caller as `children`; this sizes it and never picks it.
|
|
29
|
+
* `asChild` renders the child element instead of a `<button>`, via
|
|
30
|
+
* `@radix-ui/react-slot`.
|
|
31
|
+
*/
|
|
32
|
+
export declare const IconButton: import('react').ForwardRefExoticComponent<IconButtonProps & import('react').RefAttributes<HTMLButtonElement>>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { VariantProps } from 'class-variance-authority';
|
|
2
|
+
export { IconButton, type IconButtonProps } from './IconButton.tsx';
|
|
3
|
+
/**
|
|
4
|
+
* The shape half only — the radius and the four square boxes. That is all this
|
|
5
|
+
* component adds.
|
|
6
|
+
*
|
|
7
|
+
* The colours are `Button`'s, and not a copy of them: `IconButton.tsx` calls
|
|
8
|
+
* `buttonVariants` for the variant and this for the size, so the six colour
|
|
9
|
+
* rules live in one file and a token changes in one place. Use both together if
|
|
10
|
+
* you are putting the classes on your own element:
|
|
11
|
+
*
|
|
12
|
+
* ```ts
|
|
13
|
+
* cn(buttonVariants({ variant, size: null }), iconButtonVariants({ size }))
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* `size: null` is cva's opt-out, and it is load-bearing: `buttonVariants`
|
|
17
|
+
* defaults to `md`, which would bring `px-5`, `h-12` and `rounded-2xl` along
|
|
18
|
+
* and stop the box being a square circle.
|
|
19
|
+
*
|
|
20
|
+
* Class names, not utilities — see the long note in `../index.ts` for why a
|
|
21
|
+
* utility in a variant forces the package to publish `.size-12` into the
|
|
22
|
+
* consumer's cascade.
|
|
23
|
+
*/
|
|
24
|
+
export declare const iconButtonVariants: (props?: ({
|
|
25
|
+
size?: "xs" | "sm" | "md" | "lg" | null | undefined;
|
|
26
|
+
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
27
|
+
export type IconButtonVariants = VariantProps<typeof iconButtonVariants>;
|
|
@@ -37,7 +37,7 @@ export interface TableComponentProps<TData = unknown> {
|
|
|
37
37
|
/** Center table content (default slot) — custom mode only. */
|
|
38
38
|
children?: ReactNode;
|
|
39
39
|
}
|
|
40
|
-
export declare function Table<TData = unknown>({ enableDragToScroll, table, renderCell, renderHeader, detailRow: detailRowSlot, bulkHeader, bulkActions, pagination, empty, fixedLeft, fixedRight, children, }: TableComponentProps<TData>): import("react/jsx-runtime").JSX.Element;
|
|
40
|
+
export declare function Table<TData = unknown>({ loading, enableDragToScroll, table, renderCell, renderHeader, detailRow: detailRowSlot, bulkHeader, bulkActions, pagination, empty, fixedLeft, fixedRight, children, }: TableComponentProps<TData>): import("react/jsx-runtime").JSX.Element;
|
|
41
41
|
export declare namespace Table {
|
|
42
42
|
var displayName: string;
|
|
43
43
|
}
|
|
@@ -4,6 +4,14 @@ export interface TableSelectCellProps extends Omit<React.ComponentPropsWithoutRe
|
|
|
4
4
|
/** Usually fixed to left */
|
|
5
5
|
fixed?: boolean;
|
|
6
6
|
fixedOffset?: string;
|
|
7
|
+
/**
|
|
8
|
+
* Whether this row can be selected at all.
|
|
9
|
+
*
|
|
10
|
+
* On the header cell it disables select-all, which is the right thing when
|
|
11
|
+
* nothing in the table can be selected — a checkbox that ticks and then
|
|
12
|
+
* selects nothing is worse than one that says so.
|
|
13
|
+
*/
|
|
14
|
+
disabled?: boolean;
|
|
7
15
|
onChange?: (checked: boolean) => void;
|
|
8
16
|
}
|
|
9
17
|
export declare const TableSelectCell: import('react').ForwardRefExoticComponent<TableSelectCellProps & import('react').RefAttributes<HTMLTableCellElement>>;
|
|
@@ -7,7 +7,7 @@ import { UseTableVirtualOptions, UseTableVirtualReturn } from './useTableVirtual
|
|
|
7
7
|
* the other nine thousand nine hundred and eighty.
|
|
8
8
|
*
|
|
9
9
|
* ```tsx
|
|
10
|
-
* const virtual = useTableVirtual(employees, {
|
|
10
|
+
* const virtual = useTableVirtual(employees, { maxHeight: '480px' });
|
|
11
11
|
*
|
|
12
12
|
* <TableVirtualized virtualizer={virtual}>
|
|
13
13
|
* <TableBody>
|
|
@@ -1,13 +1,25 @@
|
|
|
1
1
|
import { RefObject } from 'react';
|
|
2
2
|
export interface UseTableVirtualOptions {
|
|
3
3
|
/**
|
|
4
|
-
* How tall the table's scrollport is, as a CSS length.
|
|
4
|
+
* How tall the table's scrollport is allowed to get, as a CSS length.
|
|
5
|
+
*
|
|
6
|
+
* A ceiling rather than a measurement: given fewer rows than it has room
|
|
7
|
+
* for, the table shrinks to them instead of leaving empty space under the
|
|
8
|
+
* last one.
|
|
9
|
+
*
|
|
10
|
+
* Any length the browser understands: `'480px'`, `'30vh'`,
|
|
11
|
+
* `'calc(100vh - 12rem)'`. It is written straight onto the element and the
|
|
12
|
+
* window is worked out from what that element ends up measuring, so nothing
|
|
13
|
+
* here cares which unit you used. `'100%'` works too, as long as whatever
|
|
14
|
+
* contains the table has a height of its own — a percentage of `auto` is
|
|
15
|
+
* `auto`, and a table that grows to fit its rows is the one case this cannot
|
|
16
|
+
* work with.
|
|
5
17
|
*
|
|
6
18
|
* Virtualising needs one. A table that grows to fit its rows has no scrollbar
|
|
7
19
|
* of its own — the page scrolls instead — and with nothing scrolling there is
|
|
8
20
|
* no position to work a window out from.
|
|
9
21
|
*/
|
|
10
|
-
|
|
22
|
+
maxHeight?: string;
|
|
11
23
|
/**
|
|
12
24
|
* How tall one row is, in pixels.
|
|
13
25
|
*
|
|
@@ -48,7 +60,7 @@ export interface UseTableVirtualReturn<TData> {
|
|
|
48
60
|
* stopped from taking it over.
|
|
49
61
|
*/
|
|
50
62
|
claim: (element: HTMLElement | null) => void;
|
|
51
|
-
|
|
63
|
+
maxHeight: string | undefined;
|
|
52
64
|
/** The height of everything above the window, and of everything below it. */
|
|
53
65
|
padStart: number;
|
|
54
66
|
padEnd: number;
|
|
@@ -10,7 +10,6 @@ export { TableDragCell, type TableDragCellProps, } from './TableDragCell/TableDr
|
|
|
10
10
|
export { TableBulkHeader, type TableBulkHeaderProps, } from './TableBulkHeader/TableBulkHeader.tsx';
|
|
11
11
|
export { TablePagination, type TablePaginationProps, } from './TablePagination/TablePagination.tsx';
|
|
12
12
|
export { TableEmpty, type TableEmptyProps } from './TableEmpty/TableEmpty.tsx';
|
|
13
|
-
export { TableAvatar, type TableAvatarProps, } from './TableAvatar/TableAvatar.tsx';
|
|
14
13
|
export { TableRowExpanded, type TableRowExpandedProps, } from './TableRowExpanded/TableRowExpanded.tsx';
|
|
15
14
|
export { TableExpandCell, type TableExpandCellProps, } from './TableExpandCell/TableExpandCell.tsx';
|
|
16
15
|
export { TableColumnVisibility, type TableColumnVisibilityProps, } from './TableColumnVisibility/TableColumnVisibility.tsx';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An avatar with a name and an optional second line beside it.
|
|
3
|
+
*
|
|
4
|
+
* `name` and `subtitle` are props and not `children`, which reads as a
|
|
5
|
+
* violation of composition-over-configuration and is a deliberate exception.
|
|
6
|
+
* Sameness is the whole product here: this pattern appears on every list, table
|
|
7
|
+
* and picker we ship, and the point of having a component for it is that all of
|
|
8
|
+
* them render the same two lines at the same sizes and weights. Taking a node
|
|
9
|
+
* hands that decision back to the caller, and the first one to put a badge, a
|
|
10
|
+
* link or a third line in it is the moment the component stops guaranteeing
|
|
11
|
+
* anything. Callers who genuinely need arbitrary content next to an avatar
|
|
12
|
+
* should compose `AvatarSquare` themselves rather than widen this.
|
|
13
|
+
*
|
|
14
|
+
* The prop list is full at five plus `dataTestid`, which is the cap. Anything
|
|
15
|
+
* further has to replace one of these or be argued as a separate component —
|
|
16
|
+
* there is no room left to slip one in.
|
|
17
|
+
*/
|
|
18
|
+
export interface AvatarDetailsProps extends React.ComponentPropsWithoutRef<'div'> {
|
|
19
|
+
/** Image source URL */
|
|
20
|
+
src?: string;
|
|
21
|
+
/** Fallback initials (max 2 characters) */
|
|
22
|
+
initials?: string;
|
|
23
|
+
/** Disabled state */
|
|
24
|
+
disabled?: boolean;
|
|
25
|
+
/** Full name to display */
|
|
26
|
+
name: string;
|
|
27
|
+
/** Subtitle (department, role, etc.) */
|
|
28
|
+
subtitle?: string;
|
|
29
|
+
dataTestid: string;
|
|
30
|
+
}
|
|
31
|
+
export declare const AvatarDetails: import('react').ForwardRefExoticComponent<AvatarDetailsProps & import('react').RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { AvatarDetails, type AvatarDetailsProps } from './AvatarDetails.tsx';
|
|
@@ -12,7 +12,13 @@ export interface ChipProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonEle
|
|
|
12
12
|
* `:focus-visible`, and there is no `:dragging`.
|
|
13
13
|
*/
|
|
14
14
|
dragged?: boolean;
|
|
15
|
+
/** Render as the child element instead of a `<button>` (Radix Slot). */
|
|
16
|
+
asChild?: boolean;
|
|
15
17
|
dataTestid: string;
|
|
16
18
|
}
|
|
17
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* Chip — mirrors `@sesame/orxata-core` Chip.
|
|
21
|
+
* `asChild` renders the child element instead of a `<button>`, via
|
|
22
|
+
* `@radix-ui/react-slot`. It is what the Vue side spells `as` / `as-child`.
|
|
23
|
+
*/
|
|
18
24
|
export declare const Chip: import('react').ForwardRefExoticComponent<ChipProps & import('react').RefAttributes<HTMLButtonElement>>;
|
|
@@ -2,10 +2,15 @@ import { VariantProps } from 'class-variance-authority';
|
|
|
2
2
|
export { Chip } from './Chip.tsx';
|
|
3
3
|
export type { ChipProps } from './Chip.tsx';
|
|
4
4
|
/**
|
|
5
|
-
* A chip is a
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* A chip is a value the user picked — one they can drop, a filter they can
|
|
6
|
+
* press. `Badge` is the system talking back: a status it assigned, a count it
|
|
7
|
+
* worked out. That is the line between them, and it is why this one is outlined
|
|
8
|
+
* and that one a solid fill.
|
|
9
|
+
*
|
|
10
|
+
* It renders a `<button>` by default because pressing one is the common case,
|
|
11
|
+
* but that is a default and not the component: `asChild` renders it as anything,
|
|
12
|
+
* and a chip that only shows a value should be a `<span>` rather than a control
|
|
13
|
+
* with nothing behind it.
|
|
9
14
|
*
|
|
10
15
|
* Class names, not utilities: the declarations live in `Chip.module.css` behind
|
|
11
16
|
* `@apply`. See `Button/index.ts` for the full reasoning.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface LoaderProps extends React.HTMLAttributes<HTMLSpanElement> {
|
|
2
|
+
dataTestid: string;
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* The Sesame mark drawing itself, ported from the `HR-loading` After Effects
|
|
6
|
+
* composition the product ships as a Lottie.
|
|
7
|
+
*
|
|
8
|
+
* Nothing in that composition moves: all twelve layers have a static transform
|
|
9
|
+
* and the whole animation lives in trim paths, which is `stroke-dasharray` plus
|
|
10
|
+
* `stroke-dashoffset` under another name. So the port needs no player — the
|
|
11
|
+
* twelve layers collapse to two shapes drawn twice, and the trims become the
|
|
12
|
+
* `@keyframes` in the stylesheet. That is the reason there is no `lottie-web`
|
|
13
|
+
* here: 250 KB on every consumer to replay an animation the stylesheet can
|
|
14
|
+
* express itself.
|
|
15
|
+
*/
|
|
16
|
+
export declare const Loader: import('react').ForwardRefExoticComponent<LoaderProps & import('react').RefAttributes<HTMLSpanElement>>;
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import { ProgressVariants } from './index.ts';
|
|
1
2
|
import * as ProgressPrimitive from '@radix-ui/react-progress';
|
|
2
3
|
export interface ProgressProps extends Omit<React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>, 'value'> {
|
|
3
4
|
/** How far along, 0 to 100 */
|
|
4
5
|
value?: number;
|
|
6
|
+
/** What the bar is saying: still going, done, done with a caveat, or failed */
|
|
7
|
+
variant?: ProgressVariants['variant'];
|
|
5
8
|
dataTestid: string;
|
|
6
9
|
}
|
|
7
10
|
/** Progress — mirrors `@sesame/orxata-core` Progress. */
|
|
@@ -1,2 +1,19 @@
|
|
|
1
|
+
import { VariantProps } from 'class-variance-authority';
|
|
1
2
|
export { Progress } from './Progress.tsx';
|
|
2
3
|
export type { ProgressProps } from './Progress.tsx';
|
|
4
|
+
/**
|
|
5
|
+
* What the bar is saying, not how far along it is.
|
|
6
|
+
*
|
|
7
|
+
* `brand` is a bar still filling. The other three are a bar that has stopped
|
|
8
|
+
* and has something to report: a job that finished, one that finished with
|
|
9
|
+
* something to look at, one that failed. They are the same three the rest of
|
|
10
|
+
* the system uses for that, and they read the same here.
|
|
11
|
+
*
|
|
12
|
+
* A determinate bar at 100% is not automatically `success` — an upload that
|
|
13
|
+
* reached the end and then failed to process is at 100% and is not good news.
|
|
14
|
+
* The variant is the caller's to say.
|
|
15
|
+
*/
|
|
16
|
+
export declare const progressVariants: (props?: ({
|
|
17
|
+
variant?: "success" | "warning" | "brand" | "error" | null | undefined;
|
|
18
|
+
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
19
|
+
export type ProgressVariants = VariantProps<typeof progressVariants>;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { CalendarDayState } from './CalendarDay.tsx';
|
|
2
|
+
import { CalendarConstraints } from './constraints.ts';
|
|
3
|
+
/** One day. Falls back to `OxCalendarDay`. */
|
|
4
|
+
type DayRenderer = (props: {
|
|
5
|
+
date: Date;
|
|
6
|
+
state: CalendarDayState;
|
|
7
|
+
}) => React.ReactNode;
|
|
8
|
+
/**
|
|
9
|
+
* A month of days, and nothing around it. Mirrors `@sesame/orxata-core`
|
|
10
|
+
* Calendar.
|
|
11
|
+
*
|
|
12
|
+
* `Calendar` speaks `Date`. A `Date` at the boundary means the calendar day
|
|
13
|
+
* formed by its local year, month and day: the time is ignored on the way in,
|
|
14
|
+
* and is local midnight on the way out.
|
|
15
|
+
*
|
|
16
|
+
* There is no month title and no navigation — `header` is not called until you
|
|
17
|
+
* pass one, and is handed everything a header needs. The shared, opinionated
|
|
18
|
+
* one belongs a layer up, in `DatePicker`.
|
|
19
|
+
*
|
|
20
|
+
* Not `OxCalendarDate`, which also ships: that is a `<time>` chip showing a day
|
|
21
|
+
* and an abbreviated month, not a grid.
|
|
22
|
+
*/
|
|
23
|
+
export interface CalendarProps extends Pick<React.HTMLAttributes<HTMLDivElement>, 'className'> {
|
|
24
|
+
/** The selected day, or `undefined` for none. Controlled. */
|
|
25
|
+
value?: Date;
|
|
26
|
+
/** The initially selected day, for the uncontrolled case. */
|
|
27
|
+
defaultValue?: Date;
|
|
28
|
+
onValueChange?: (value: Date | undefined) => void;
|
|
29
|
+
/** How many month grids to render. */
|
|
30
|
+
months?: number;
|
|
31
|
+
/** What can be picked, and where navigation stops. */
|
|
32
|
+
constraints?: CalendarConstraints;
|
|
33
|
+
/**
|
|
34
|
+
* Empty by default. Receives the visible month and the navigation state,
|
|
35
|
+
* because without those nobody could build a header at all.
|
|
36
|
+
*/
|
|
37
|
+
header?: (state: {
|
|
38
|
+
month: Date;
|
|
39
|
+
goToPrev: () => void;
|
|
40
|
+
goToNext: () => void;
|
|
41
|
+
canGoPrev: boolean;
|
|
42
|
+
canGoNext: boolean;
|
|
43
|
+
}) => React.ReactNode;
|
|
44
|
+
/**
|
|
45
|
+
* One month's name, above its grid. Falls back to the month and year from
|
|
46
|
+
* `Intl`, and only renders when `months` is more than one — a lone month is
|
|
47
|
+
* named by `header`, and naming it twice is worse than not at all.
|
|
48
|
+
*/
|
|
49
|
+
month?: (props: {
|
|
50
|
+
month: Date;
|
|
51
|
+
}) => React.ReactNode;
|
|
52
|
+
/** One day. Falls back to `OxCalendarDay`. */
|
|
53
|
+
day?: DayRenderer;
|
|
54
|
+
dataTestid: string;
|
|
55
|
+
}
|
|
56
|
+
export declare const Calendar: {
|
|
57
|
+
({ className, value, defaultValue, onValueChange, months, month: renderMonth, constraints, header, day, dataTestid, }: CalendarProps): import("react/jsx-runtime").JSX.Element;
|
|
58
|
+
displayName: string;
|
|
59
|
+
};
|
|
60
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The five booleans are what `Calendar` hands to the `day` render prop, and
|
|
3
|
+
* they are the `data-*` vocabulary this emits. `range` is `CalendarRange`'s
|
|
4
|
+
* alone.
|
|
5
|
+
*/
|
|
6
|
+
export interface CalendarDayState {
|
|
7
|
+
selected: boolean;
|
|
8
|
+
today: boolean;
|
|
9
|
+
disabled: boolean;
|
|
10
|
+
outside: boolean;
|
|
11
|
+
focused: boolean;
|
|
12
|
+
range?: 'start' | 'middle' | 'end';
|
|
13
|
+
}
|
|
14
|
+
export interface CalendarDayProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
15
|
+
/**
|
|
16
|
+
* Partial so a single state can be shown on its own, which is what the guide
|
|
17
|
+
* does. Inside a calendar the render prop always supplies all of it.
|
|
18
|
+
*/
|
|
19
|
+
state?: Partial<CalendarDayState>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* One day in a calendar grid: a button that shows its number and paints the
|
|
23
|
+
* state it is told about. Mirrors `@sesame/orxata-core` CalendarDay.
|
|
24
|
+
*
|
|
25
|
+
* Not `OxCalendarDate`, which also ships and which the name invites confusing
|
|
26
|
+
* this with. That one is a `<time>` chip showing a day and an abbreviated
|
|
27
|
+
* month — no button, no selection, no keyboard. This one is the cell.
|
|
28
|
+
*
|
|
29
|
+
* It is **told** its state and never reads it from context, so it renders on
|
|
30
|
+
* its own — the guide shows the states as a legend, outside any calendar — and
|
|
31
|
+
* so that it is assembled the same way as its Vue original.
|
|
32
|
+
*
|
|
33
|
+
* `disabled` is applied before the prop spread on purpose: `DayPicker` passes
|
|
34
|
+
* its own, leaving a focused-but-disabled day focusable with `aria-disabled`
|
|
35
|
+
* instead, and its answer has to win over the one derived from `state`.
|
|
36
|
+
*/
|
|
37
|
+
export declare const CalendarDay: import('react').ForwardRefExoticComponent<CalendarDayProps & import('react').RefAttributes<HTMLButtonElement>>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { CalendarDayState } from './CalendarDay.tsx';
|
|
2
|
+
import { CalendarConstraints } from './constraints.ts';
|
|
3
|
+
/** One day. Falls back to `OxCalendarDay`. */
|
|
4
|
+
type DayRenderer = (props: {
|
|
5
|
+
date: Date;
|
|
6
|
+
state: CalendarDayState;
|
|
7
|
+
}) => React.ReactNode;
|
|
8
|
+
/**
|
|
9
|
+
* `start` and `end`, not `from` and `to` — those two words are already the
|
|
10
|
+
* navigation bounds in `constraints`, and one word meaning two things inside
|
|
11
|
+
* the same component is the confusion this naming was chosen to avoid.
|
|
12
|
+
*/
|
|
13
|
+
export interface CalendarDateRange {
|
|
14
|
+
start?: Date;
|
|
15
|
+
end?: Date;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* A month of days where two clicks pick a span. Mirrors `@sesame/orxata-core`
|
|
19
|
+
* CalendarRange. A sibling of `Calendar` with its own API, not a part of it.
|
|
20
|
+
*
|
|
21
|
+
* Same date contract: a `Date` at the boundary means the calendar day formed by
|
|
22
|
+
* its local year, month and day.
|
|
23
|
+
*/
|
|
24
|
+
export interface CalendarRangeProps extends Pick<React.HTMLAttributes<HTMLDivElement>, 'className'> {
|
|
25
|
+
/** The selected span. Either end may be absent while one is being picked. */
|
|
26
|
+
value?: CalendarDateRange;
|
|
27
|
+
/** The initially selected span, for the uncontrolled case. */
|
|
28
|
+
defaultValue?: CalendarDateRange;
|
|
29
|
+
onValueChange?: (value: CalendarDateRange) => void;
|
|
30
|
+
/** How many month grids to render. */
|
|
31
|
+
months?: number;
|
|
32
|
+
/** What can be picked, and where navigation stops. */
|
|
33
|
+
constraints?: CalendarConstraints;
|
|
34
|
+
/**
|
|
35
|
+
* Empty by default. Receives the visible month and the navigation state,
|
|
36
|
+
* because without those nobody could build a header at all.
|
|
37
|
+
*/
|
|
38
|
+
header?: (state: {
|
|
39
|
+
month: Date;
|
|
40
|
+
goToPrev: () => void;
|
|
41
|
+
goToNext: () => void;
|
|
42
|
+
canGoPrev: boolean;
|
|
43
|
+
canGoNext: boolean;
|
|
44
|
+
}) => React.ReactNode;
|
|
45
|
+
/**
|
|
46
|
+
* One month's name, above its grid. Falls back to the month and year from
|
|
47
|
+
* `Intl`, and only renders at all when there is more than one grid — a lone
|
|
48
|
+
* month is named by `header`, and naming it twice is worse than not at all.
|
|
49
|
+
*/
|
|
50
|
+
month?: (props: {
|
|
51
|
+
month: Date;
|
|
52
|
+
}) => React.ReactNode;
|
|
53
|
+
/** One day. Falls back to `OxCalendarDay`. */
|
|
54
|
+
day?: DayRenderer;
|
|
55
|
+
dataTestid: string;
|
|
56
|
+
}
|
|
57
|
+
export declare const CalendarRange: {
|
|
58
|
+
({ className, value, defaultValue, onValueChange, months, month: renderMonth, constraints, header, day, dataTestid, }: CalendarRangeProps): import("react/jsx-runtime").JSX.Element;
|
|
59
|
+
displayName: string;
|
|
60
|
+
};
|
|
61
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What can be picked, and where navigation stops.
|
|
3
|
+
*
|
|
4
|
+
* Grouped on purpose: the three fields are one concept, and the range-length
|
|
5
|
+
* pair `CalendarRange` will eventually want has to fit here without a redesign.
|
|
6
|
+
*
|
|
7
|
+
* The bounds are `from` / `to`, not `min` / `max`. In `react-day-picker` those
|
|
8
|
+
* two words already mean the minimum and maximum *number of days* a range may
|
|
9
|
+
* span, which is the length limit this will grow. Keeping them free avoids the
|
|
10
|
+
* collision instead of explaining it forever.
|
|
11
|
+
*/
|
|
12
|
+
export interface CalendarConstraints {
|
|
13
|
+
/** The earliest month the calendar will navigate to. */
|
|
14
|
+
from?: Date;
|
|
15
|
+
/** The latest month the calendar will navigate to. */
|
|
16
|
+
to?: Date;
|
|
17
|
+
/** Called per day. Return `true` to make it unpickable. */
|
|
18
|
+
isDisabled?: (date: Date) => boolean;
|
|
19
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { VariantProps } from 'class-variance-authority';
|
|
2
|
+
export { Calendar, type CalendarProps } from './Calendar.tsx';
|
|
3
|
+
export { CalendarRange, type CalendarRangeProps, type CalendarDateRange, } from './CalendarRange.tsx';
|
|
4
|
+
export { CalendarDay, type CalendarDayProps, type CalendarDayState, } from './CalendarDay.tsx';
|
|
5
|
+
export type { CalendarConstraints } from './constraints.ts';
|
|
6
|
+
/**
|
|
7
|
+
* Only the range position varies here. The other five states — selected,
|
|
8
|
+
* today, disabled, focused, outside — are `data-*` attributes rather than
|
|
9
|
+
* classes, because those five are the vocabulary a caller writes their own CSS
|
|
10
|
+
* against and a parallel set of class names would be a second spelling of the
|
|
11
|
+
* same thing.
|
|
12
|
+
*
|
|
13
|
+
* The range position is not in that vocabulary: it is `CalendarRange`'s alone,
|
|
14
|
+
* and `react-day-picker` and reka disagree about what to call it, so it stays
|
|
15
|
+
* ours and stays a class.
|
|
16
|
+
*/
|
|
17
|
+
export declare const calendarDayVariants: (props?: ({
|
|
18
|
+
range?: "end" | "start" | "middle" | null | undefined;
|
|
19
|
+
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
20
|
+
export type CalendarDayVariants = VariantProps<typeof calendarDayVariants>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test ids are derived from the root's, so `months: 12` still produces twelve
|
|
3
|
+
* distinct `day-12`s — the month precedes them.
|
|
4
|
+
*
|
|
5
|
+
* The month is numeric, not a name: a name derived from `Intl` becomes
|
|
6
|
+
* `month-marzo` the moment the locale changes, and takes every test with it.
|
|
7
|
+
*
|
|
8
|
+
* calendar-for-vacations ← root, supplied by the caller
|
|
9
|
+
* calendar-for-vacations-month-2026-03 ← each month grid
|
|
10
|
+
* calendar-for-vacations-month-2026-03-day-12 ← each cell
|
|
11
|
+
*/
|
|
12
|
+
/** Built from the local parts, for the same reason `date.ts` is. */
|
|
13
|
+
export declare const monthTestid: (root: string, month: Date) => string;
|
|
14
|
+
/**
|
|
15
|
+
* `undefined` for a day borrowed from the neighbouring month, which is why the
|
|
16
|
+
* `outside` argument is not optional — the caller has to have answered it.
|
|
17
|
+
*
|
|
18
|
+
* Such a day is drawn in a grid it does not belong to, and with `months: 2` it
|
|
19
|
+
* is drawn twice: the 1st of April sits in April's grid and again in the tail
|
|
20
|
+
* of March's. Giving both the same id would hand `getByTestId` two elements and
|
|
21
|
+
* fail the query; giving them different ids would mean an id that does not say
|
|
22
|
+
* which grid it came from. Neither is worth it for a day that is decoration —
|
|
23
|
+
* a test that wants the 1st of April pins April.
|
|
24
|
+
*/
|
|
25
|
+
export declare const dayTestid: (monthId: string, day: Date, outside: boolean) => string | undefined;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** Sunday through Saturday, the numbering both primitives take. */
|
|
2
|
+
export type WeekStart = 0 | 1 | 2 | 3 | 4 | 5 | 6;
|
|
3
|
+
/**
|
|
4
|
+
* Derived from the locale rather than taken as a prop. A prop would let an
|
|
5
|
+
* application put Monday first while every date it formats says otherwise, and
|
|
6
|
+
* the locale already carries the answer for every region ICU knows.
|
|
7
|
+
*/
|
|
8
|
+
export declare const weekStartsOnFor: (locale: string) => WeekStart;
|
|
9
|
+
/**
|
|
10
|
+
* The locale the calendar formats in, and the week start that follows from it.
|
|
11
|
+
*
|
|
12
|
+
* `useLocale()` yields `undefined` when nothing provided one, which every other
|
|
13
|
+
* component hands straight to `Intl` to mean "follow the runtime".
|
|
14
|
+
* `react-day-picker` instead needs a `date-fns` locale *object*, and the one it
|
|
15
|
+
* falls back to is `en-US` — so the month names would disagree with the rest of
|
|
16
|
+
* the page. Resolving the runtime's own locale here, and formatting through
|
|
17
|
+
* `Intl`, keeps them in step without shipping a locale table.
|
|
18
|
+
*/
|
|
19
|
+
export declare const useCalendarLocale: () => {
|
|
20
|
+
locale: string;
|
|
21
|
+
weekStartsOn: WeekStart;
|
|
22
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface ComboboxCancelProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
2
|
+
dataTestid: string;
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* ComboboxCancel — clears the search term without closing the popup.
|
|
6
|
+
*
|
|
7
|
+
* Radix ships no combobox at all, so there is no `Cancel` part to wrap: this
|
|
8
|
+
* reproduces reka's, which renders a `<button type="button" tabindex="-1">` and
|
|
9
|
+
* empties the filter on click. `tabindex="-1"` is reka's and is kept — the
|
|
10
|
+
* field's own clear affordances are the keyboard path, and a tab stop between
|
|
11
|
+
* the input and the trigger would be one more thing to pass through on the way
|
|
12
|
+
* to the list.
|
|
13
|
+
*/
|
|
14
|
+
export declare const ComboboxCancel: import('react').ForwardRefExoticComponent<ComboboxCancelProps & import('react').RefAttributes<HTMLButtonElement>>;
|
|
@@ -10,5 +10,9 @@ export interface ComboboxChipsInputProps extends Omit<React.InputHTMLAttributes<
|
|
|
10
10
|
* ComboboxChipsInput — the search field with the current selection as chips.
|
|
11
11
|
* Multi-select field: renders the selected values as removable chips (read from
|
|
12
12
|
* the shared `multiple` model) alongside the search field.
|
|
13
|
+
*
|
|
14
|
+
* The chips stay on one line. Those that do not fit are taken out of flow and
|
|
15
|
+
* stood in for by a `+N` counter; see `useChipOverflow` for how the line is
|
|
16
|
+
* measured.
|
|
13
17
|
*/
|
|
14
18
|
export declare const ComboboxChipsInput: import('react').ForwardRefExoticComponent<ComboboxChipsInputProps & import('react').RefAttributes<HTMLInputElement>>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { Combobox, type ComboboxProps } from './Combobox.tsx';
|
|
2
|
+
export { ComboboxCancel, type ComboboxCancelProps } from './ComboboxCancel.tsx';
|
|
2
3
|
export { ComboboxInput, type ComboboxInputProps } from './ComboboxInput.tsx';
|
|
3
4
|
export { ComboboxChipsInput, type ComboboxChipsInputProps, } from './ComboboxChipsInput.tsx';
|
|
4
5
|
export { ComboboxContent, type ComboboxContentProps, } from './ComboboxContent.tsx';
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { RefObject } from 'react';
|
|
2
|
+
export interface ChipOverflowTargets {
|
|
3
|
+
/**
|
|
4
|
+
* The single-line row holding the chips, the `+N` counter and the query
|
|
5
|
+
* field. Its width is the whole budget, which only holds because the row is
|
|
6
|
+
* laid out `flex: 1 1 0` with `min-width: 0` — its width is then whatever its
|
|
7
|
+
* siblings leave behind and owes nothing to its own content. Measuring an
|
|
8
|
+
* element whose size depends on how many chips we decided to show is exactly
|
|
9
|
+
* what turns this into an infinite loop.
|
|
10
|
+
*/
|
|
11
|
+
row: RefObject<HTMLElement | null>;
|
|
12
|
+
/** Offscreen stand-in for the `+N` counter, rendered at its widest. */
|
|
13
|
+
sizer: RefObject<HTMLElement | null>;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Decides how many chips of a multi-select field fit on one line.
|
|
17
|
+
*
|
|
18
|
+
* The chips past the edge are not removed from the DOM — the component keeps
|
|
19
|
+
* them rendered and takes them out of flow — so every chip reports its natural
|
|
20
|
+
* width on every pass, whether or not it is currently shown. That is the whole
|
|
21
|
+
* trick: nothing measured here changes as a result of what is decided here, so
|
|
22
|
+
* a measurement can never provoke the measurement that follows it.
|
|
23
|
+
*
|
|
24
|
+
* With no layout at all — a test environment, the tick before styles land —
|
|
25
|
+
* every width reads zero, `0 <= 0` holds, and the answer is "all of them".
|
|
26
|
+
* Showing the full selection is the right way to be wrong: it is what the field
|
|
27
|
+
* did before, and it fails towards markup that shows too much rather than a
|
|
28
|
+
* field that hides its own contents.
|
|
29
|
+
*/
|
|
30
|
+
export declare function useChipOverflow({ row, sizer }: ChipOverflowTargets, total: number): number;
|
|
@@ -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
|
+
delay?: 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 `delay` 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>>;
|