@sesamehr/react-design-system 2.0.0-beta.3 → 2.0.0-beta.5

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.
@@ -16,5 +16,8 @@ export interface TableBodyProps extends React.ComponentPropsWithoutRef<'tbody'>
16
16
  /**
17
17
  * Styled `<tbody>`. When `draggable`, wraps rows in a dnd-kit sortable
18
18
  * context. Sortable item ids are derived from the index of each `items` entry.
19
+ *
20
+ * Virtualised, it also renders the two rows that stand in for the ones not
21
+ * rendered — see `Spacer` below — and refuses to be draggable at the same time.
19
22
  */
20
23
  export declare const TableBody: import('react').ForwardRefExoticComponent<TableBodyProps & import('react').RefAttributes<HTMLTableSectionElement>>;
@@ -1,3 +1,27 @@
1
1
  export type TableHeadProps = React.ComponentPropsWithoutRef<'thead'>;
2
- /** Styled `<thead>` wrapping its children in a header row. */
2
+ /**
3
+ * Styled `<thead>`. Virtualised, it renders its row twice and keeps the copy on
4
+ * screen.
5
+ *
6
+ * A virtualised table is the one case where the table is certain to be taller
7
+ * than what you can see — that is what virtualising is for — and a header that
8
+ * scrolls away takes the column names and the select-all checkbox with it. At
9
+ * ten thousand rows, getting back to them means scrolling back through all of
10
+ * them.
11
+ *
12
+ * Neither obvious way works. `position: sticky` answers to the nearest
13
+ * scrolling ancestor and nothing above it, and with pinned columns that
14
+ * ancestor is the section that owns the horizontal scroll — a box that never
15
+ * moves vertically, so the header rides away with the rows. Moving the header
16
+ * from a scroll handler works but is always one frame behind what the
17
+ * compositor has already painted, which reads as the header dropping away and
18
+ * snapping back on every frame of a scroll.
19
+ *
20
+ * So the row is rendered twice. The one in the table stays and is hidden, still
21
+ * doing the two jobs only it can do: reserving the header's height and settling
22
+ * the column widths. The copy is positioned against an ancestor that does not
23
+ * scroll, so vertical scrolling does not move it and there is nothing to
24
+ * correct. It is the same elements rendered again rather than a cloned node, so
25
+ * sorting and select-all still work in the one you can see.
26
+ */
3
27
  export declare const TableHead: import('react').ForwardRefExoticComponent<Omit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLTableSectionElement>, HTMLTableSectionElement>, "ref"> & import('react').RefAttributes<HTMLTableSectionElement>>;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * The scrollbar a virtualised table draws for itself.
3
+ *
4
+ * Every other table in the system hides its bar: they scroll sideways, the
5
+ * shadows at the edges say there is more, and a bar would be chrome. A list of
6
+ * ten thousand rows is the opposite case — without one there is nothing to read
7
+ * your position from, and no way to cross the list in one gesture.
8
+ *
9
+ * The browser's own bar cannot be that thing here. It runs the full height of
10
+ * the scrollport, and the scrollport has to contain the header, so it always
11
+ * cuts across the column names. This one starts below them.
12
+ *
13
+ * It behaves the way an overlay bar does: out of the way until you scroll or
14
+ * reach for the edge, and gone again shortly after.
15
+ */
16
+ export declare function TableScrollbar(): import("react/jsx-runtime").JSX.Element | null;
17
+ export declare namespace TableScrollbar {
18
+ var displayName: string;
19
+ }
@@ -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>>;
@@ -0,0 +1,45 @@
1
+ import { TableComponentProps } from '../Table.tsx';
2
+ import { UseTableVirtualReturn } from '../hooks/useTableVirtual/useTableVirtual.types.ts';
3
+ export type TableVirtualizedProps<TData = unknown> = TableComponentProps<TData> & {
4
+ /**
5
+ * What `useTableVirtual()` returned.
6
+ *
7
+ * Not the rows — those you map yourself, the same as in any other table.
8
+ * This is the thing that works out which rows those are, and the table
9
+ * hands it the element they scroll inside.
10
+ */
11
+ virtualizer: UseTableVirtualReturn<never>;
12
+ };
13
+ /**
14
+ * A `Table` that renders only the rows on screen.
15
+ *
16
+ * Everything but `virtualizer` is a `Table` prop and is passed straight through.
17
+ * What goes inside is what goes inside a `Table`: this is the same component,
18
+ * told where its virtualiser is.
19
+ *
20
+ * ```tsx
21
+ * const virtual = useTableVirtual(employees, { height: '480px' });
22
+ *
23
+ * <TableVirtualized virtualizer={virtual}>
24
+ * <TableBody>
25
+ * {virtual.rows.map(row => <TableRow key={row.id}>…</TableRow>)}
26
+ * </TableBody>
27
+ * </TableVirtualized>
28
+ * ```
29
+ *
30
+ * It is the one piece the Vue side does not have, and it exists because of how
31
+ * the two frameworks differ rather than because the tables do. There
32
+ * `useTableVirtual` runs in the caller's `setup`, which is already above the
33
+ * table, so it provides itself and `<Table>` is written exactly as it always
34
+ * was. A hook has nothing to provide to until something renders — so this
35
+ * renders.
36
+ *
37
+ * The alternative was a prop on `Table`, and it would not have stopped there:
38
+ * the spacers belong inside `TableBody`'s `<tbody>` and the pinned header is
39
+ * `TableHead`'s, so it would have had to be threaded to both of those by hand
40
+ * as well. A wrapper reaches all three and leaves `Table`'s own API alone.
41
+ */
42
+ export declare function TableVirtualized<TData = unknown>({ virtualizer, ...props }: TableVirtualizedProps<TData>): import("react/jsx-runtime").JSX.Element;
43
+ export declare namespace TableVirtualized {
44
+ var displayName: string;
45
+ }
@@ -0,0 +1,2 @@
1
+ export { TableVirtualized } from './TableVirtualized.tsx';
2
+ export type { TableVirtualizedProps } from './TableVirtualized.tsx';
@@ -18,3 +18,6 @@ export { useDragToScroll } from './useDragToScroll/useDragToScroll.ts';
18
18
  export type { UseDragToScrollOptions, UseDragToScrollReturn, } from './useDragToScroll/useDragToScroll.ts';
19
19
  export { useFixedColumns } from './useFixedColumns.ts';
20
20
  export type { UseFixedColumnsOptions } from './useFixedColumns.ts';
21
+ export { useTableVirtual } from './useTableVirtual/useTableVirtual.ts';
22
+ export { TableVirtualContext, useTableVirtualContext, } from './useTableVirtual/context.ts';
23
+ export type { UseTableVirtualOptions, UseTableVirtualReturn, } from './useTableVirtual/useTableVirtual.types.ts';
@@ -0,0 +1,16 @@
1
+ import { UseTableVirtualReturn } from './useTableVirtual.types.ts';
2
+ /**
3
+ * How the virtualiser reaches the parts of the table that need it.
4
+ *
5
+ * The Vue side has no equivalent: `useTableVirtual` runs in the caller's
6
+ * `setup`, which is above the table, so it provides itself and nothing has to
7
+ * be passed anywhere. A hook cannot do that — nothing is above anything until
8
+ * something renders — which is what `TableVirtualized` is for.
9
+ *
10
+ * They do need reaching. The spacers standing in for the unrendered rows have
11
+ * to sit inside the `<tbody>`, which `TableBody` renders from the caller's own
12
+ * markup, and the floating header belongs to `TableHead`. Handing each of them
13
+ * a prop is the boilerplate this removes.
14
+ */
15
+ export declare const TableVirtualContext: import('react').Context<UseTableVirtualReturn<unknown> | null>;
16
+ export declare function useTableVirtualContext(): UseTableVirtualReturn<unknown> | null;
@@ -0,0 +1,3 @@
1
+ export { TableVirtualContext, useTableVirtualContext } from './context.ts';
2
+ export { useTableVirtual } from './useTableVirtual.ts';
3
+ export type { UseTableVirtualOptions, UseTableVirtualReturn, } from './useTableVirtual.types.ts';
@@ -0,0 +1,36 @@
1
+ import { UseTableVirtualOptions, UseTableVirtualReturn } from './useTableVirtual.types.ts';
2
+ /**
3
+ * Renders only the rows that are on screen, however many the table is given.
4
+ *
5
+ * Hand it the whole list and map `rows` instead: at ten thousand rows that is
6
+ * about twenty in the DOM, and the browser stops doing the work of laying out
7
+ * the other nine thousand nine hundred and eighty.
8
+ *
9
+ * ```tsx
10
+ * const virtual = useTableVirtual(employees, { maxHeight: '480px' });
11
+ *
12
+ * <TableVirtualized virtualizer={virtual}>
13
+ * <TableBody>
14
+ * {virtual.rows.map(row => <TableRow key={row.id}>…</TableRow>)}
15
+ * </TableBody>
16
+ * </TableVirtualized>
17
+ * ```
18
+ *
19
+ * `TableVirtualized` is the one piece the Vue side does not have. There the
20
+ * composable provides itself from the caller's `setup`; a hook has nothing to
21
+ * provide to until something renders, so the wrapper does it instead — and
22
+ * `Table` itself gains no prop on either side.
23
+ *
24
+ * **Not with row reordering.** `TableBody` throws if both are on. Where a row
25
+ * sits in the DOM is not where it sits in the list once only part of it is
26
+ * rendered, and dragging across ten thousand rows is not a gesture anyone can
27
+ * make. A reorderable table is a paged one.
28
+ *
29
+ * **Why spacers.** Rendering twenty rows would leave a table twenty rows tall,
30
+ * with no scrollbar and so nothing to scroll — the window could never move.
31
+ * Something has to stand in for the height of everything that is not rendered,
32
+ * and in a `<table>` that something is a pair of empty rows, one above the
33
+ * window and one below. They belong inside the `<tbody>`, so `TableBody` is
34
+ * what renders them. A caller never writes a spacer, and never should have to.
35
+ */
36
+ export declare function useTableVirtual<TData>(items: TData[], options?: UseTableVirtualOptions): UseTableVirtualReturn<TData>;
@@ -0,0 +1,73 @@
1
+ import { RefObject } from 'react';
2
+ export interface UseTableVirtualOptions {
3
+ /**
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.
17
+ *
18
+ * Virtualising needs one. A table that grows to fit its rows has no scrollbar
19
+ * of its own — the page scrolls instead — and with nothing scrolling there is
20
+ * no position to work a window out from.
21
+ */
22
+ maxHeight?: string;
23
+ /**
24
+ * How tall one row is, in pixels.
25
+ *
26
+ * This is what turns a scroll position into a row index, so it is worth
27
+ * getting right: the error is paid on every row crossed, which is nothing at
28
+ * one click of the wheel and hundreds of rows after a flick. The default,
29
+ * 48px, is the height `TableRow` gives itself with plain text in it. Rows
30
+ * with an avatar or two lines of text are taller, and those tables should say
31
+ * so here.
32
+ *
33
+ * It is deliberately a number you give rather than one measured from the
34
+ * page. Measuring as you scroll means the total height changes as you scroll,
35
+ * and a table whose content grows and shrinks underneath the scrollbar throws
36
+ * you somewhere else every time it does.
37
+ */
38
+ estimateSize?: number;
39
+ /** How many rows to keep either side of the window, so scrolling stays smooth. */
40
+ overscan?: number;
41
+ }
42
+ export interface UseTableVirtualReturn<TData> {
43
+ /**
44
+ * The rows that belong on screen right now, as data rather than indices — a
45
+ * caller maps these exactly the way it would map the whole list.
46
+ */
47
+ rows: TData[];
48
+ /** How many rows there are in total, window or no window. */
49
+ total: number;
50
+ /** Where a windowed row sits in the full list, for callers that need to know. */
51
+ indexOf: (windowIndex: number) => number;
52
+ /**
53
+ * Everything below is how `Table` drives this, and no caller should have to
54
+ * touch it. The scrollport is the table's, the spacers are `TableBody`'s, and
55
+ * both reach it through `TableVirtualized` rather than by hand.
56
+ */
57
+ containerRef: RefObject<HTMLElement | null>;
58
+ /**
59
+ * How `Table` registers itself as the scrollport, and how a second one is
60
+ * stopped from taking it over.
61
+ */
62
+ claim: (element: HTMLElement | null) => void;
63
+ maxHeight: string | undefined;
64
+ /** The height of everything above the window, and of everything below it. */
65
+ padStart: number;
66
+ padEnd: number;
67
+ /**
68
+ * Measures a row that turned out taller than the estimate. Without it the
69
+ * scrollbar drifts: every row that wraps makes the list a little longer than
70
+ * the virtualiser thinks it is, and by the bottom the two disagree.
71
+ */
72
+ measure: (element: Element | null) => void;
73
+ }
@@ -1,4 +1,5 @@
1
1
  export { Table, type TableComponentProps } from './Table.tsx';
2
+ export { TableVirtualized, type TableVirtualizedProps, } from './TableVirtualized/TableVirtualized.tsx';
2
3
  export { TableHead, type TableHeadProps } from './TableHead/TableHead.tsx';
3
4
  export { TableBody, type TableBodyProps } from './TableBody/TableBody.tsx';
4
5
  export { TableRow, type TableRowProps } from './TableRow/TableRow.tsx';
@@ -13,5 +14,5 @@ export { TableAvatar, type TableAvatarProps, } from './TableAvatar/TableAvatar.t
13
14
  export { TableRowExpanded, type TableRowExpandedProps, } from './TableRowExpanded/TableRowExpanded.tsx';
14
15
  export { TableExpandCell, type TableExpandCellProps, } from './TableExpandCell/TableExpandCell.tsx';
15
16
  export { TableColumnVisibility, type TableColumnVisibilityProps, } from './TableColumnVisibility/TableColumnVisibility.tsx';
16
- export { useTable, type UseTableOptions, type UseTableReturn, useTableSelection, type SelectionInstance as UseTableSelectionReturn, useTableSorting, type SortingInstance as UseTableSortingReturn, useTablePagination, type UseTablePaginationOptions, type UseTablePaginationReturn, useTableDetailRow, type DetailRowInstance, type DetailRowOptions, type DetailRowPluginDef, useTablePinning, type PinningOptions as UseTablePinningOptions, type PinningInstance as UseTablePinningReturn, type CellInfo, type HeaderInfo, useTableColumns, type ColumnsOptions as UseTableColumnsOptions, type ColumnsInstance as UseTableColumnsReturn, useScrollShadow, type UseScrollShadowOptions, type UseScrollShadowReturn, useDragToScroll, type UseDragToScrollOptions, type UseDragToScrollReturn, useFixedColumns, type UseFixedColumnsOptions, } from './hooks/index.ts';
17
+ export { useTable, type UseTableOptions, type UseTableReturn, useTableSelection, type SelectionInstance as UseTableSelectionReturn, useTableSorting, type SortingInstance as UseTableSortingReturn, useTablePagination, type UseTablePaginationOptions, type UseTablePaginationReturn, useTableDetailRow, type DetailRowInstance, type DetailRowOptions, type DetailRowPluginDef, useTablePinning, type PinningOptions as UseTablePinningOptions, type PinningInstance as UseTablePinningReturn, type CellInfo, type HeaderInfo, useTableColumns, type ColumnsOptions as UseTableColumnsOptions, type ColumnsInstance as UseTableColumnsReturn, useScrollShadow, type UseScrollShadowOptions, type UseScrollShadowReturn, useDragToScroll, type UseDragToScrollOptions, type UseDragToScrollReturn, useFixedColumns, type UseFixedColumnsOptions, useTableVirtual, type UseTableVirtualOptions, type UseTableVirtualReturn, } from './hooks/index.ts';
17
18
  export type { TableProps, TableMode, ColumnDef, ColumnAlign, CellContext, SortingState, PaginationState, PaginationChangePayload, SortingChangePayload, SelectionChangePayload, FilterChangePayload, ColumnResizeMode, ColumnVisibilityState, ColumnOrderState, ExpandedState, ColumnVisibilityChangePayload, ColumnOrderChangePayload, RowExpandChangePayload, ColumnResizePayload, ColumnPinningState, } from './types';
package/dist/main.d.ts CHANGED
@@ -36,5 +36,5 @@ export { Breadcrumb as OxBreadcrumb, BreadcrumbList as OxBreadcrumbList, Breadcr
36
36
  export { Counter as OxCounter, counterVariants, type CounterVariants, } from './Forms/Field/Counter/index.ts';
37
37
  export { FieldGroup as OxFieldGroup, FieldLabel as OxFieldLabel, FieldMessage as OxFieldMessage, type FieldGroupProps, } from './Forms/Field/index.ts';
38
38
  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, Combobox as OxCombobox, ComboboxInput as OxComboboxInput, ComboboxChipsInput as OxComboboxChipsInput, ComboboxContent as OxComboboxContent, ComboboxItem as OxComboboxItem, ComboboxEmpty as OxComboboxEmpty, ComboboxGroup as OxComboboxGroup, ComboboxSeparator as OxComboboxSeparator, Select as OxSelect, SelectTrigger as OxSelectTrigger, SelectContent as OxSelectContent, SelectItem as OxSelectItem, SelectGroup as OxSelectGroup, SelectSeparator as OxSelectSeparator, 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 ComboboxProps, type SelectProps, type RadioGroupProps, type ToggleGroupProps, type ToggleLabelProps, type ToggleDescriptionProps, } from './Forms/Inputs/index.ts';
39
- export { Table as OxTable, 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, TableAvatar as OxTableAvatar, TableRowExpanded as OxTableRowExpanded, TableExpandCell as OxTableExpandCell, TableColumnVisibility as OxTableColumnVisibility, useTable, useTableSelection, useTableSorting, useTablePagination, useTableDetailRow, useTablePinning, useTableColumns, useScrollShadow, useDragToScroll, useFixedColumns, } from './Data/Table/index.ts';
40
- export type { UseTableOptions, UseTableReturn, UseTableSelectionReturn, UseTableSortingReturn, UseTablePaginationOptions, UseTablePaginationReturn, DetailRowInstance, DetailRowOptions, DetailRowPluginDef, UseTablePinningOptions, UseTablePinningReturn, CellInfo, HeaderInfo, 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';
39
+ 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, TableAvatar as OxTableAvatar, 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';
40
+ 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';