@ssa-ui-kit/core 3.23.0 → 3.24.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/ai/source-map.md +156 -53
- package/dist/components/Calendar/Calendar.d.ts +130 -0
- package/dist/components/Calendar/CalendarContext.d.ts +25 -0
- package/dist/components/Calendar/CalendarEventDetails.d.ts +80 -0
- package/dist/components/Calendar/components/CalendarToolbar.d.ts +20 -0
- package/dist/components/Calendar/components/DayView.d.ts +14 -0
- package/dist/components/Calendar/components/EventDetailsLayer.d.ts +17 -0
- package/dist/components/Calendar/components/EventSlot.d.ts +17 -0
- package/dist/components/Calendar/components/HighlightBadge.d.ts +5 -0
- package/dist/components/Calendar/components/MonthView.d.ts +19 -0
- package/dist/components/Calendar/components/MoreEventsPopover.d.ts +16 -0
- package/dist/components/Calendar/components/TaskCheckbox.d.ts +8 -0
- package/dist/components/Calendar/components/useEventClick.d.ts +10 -0
- package/dist/components/Calendar/consts.d.ts +47 -0
- package/dist/components/Calendar/index.d.ts +2 -0
- package/dist/components/Calendar/styles.d.ts +137 -0
- package/dist/components/Calendar/types.d.ts +383 -0
- package/dist/components/Calendar/utils.d.ts +116 -0
- package/dist/components/Carousel/types.d.ts +2 -1
- package/dist/components/NestedTable/NestedTableContext.d.ts +3 -3
- package/dist/components/NestedTable/components/NestedTable.d.ts +37 -4
- package/dist/components/NestedTable/components/NestedTableCell.d.ts +2 -3
- package/dist/components/NestedTable/components/NestedTableCellBase.d.ts +16 -0
- package/dist/components/NestedTable/components/NestedTableCellHeader.d.ts +36 -0
- package/dist/components/NestedTable/components/index.d.ts +1 -0
- package/dist/components/NestedTable/consts.d.ts +5 -0
- package/dist/components/NestedTable/hooks/useNestedTableContext.d.ts +1 -1
- package/dist/components/NestedTable/types.d.ts +31 -0
- package/dist/components/Table/ColumnFreezeContext.d.ts +27 -0
- package/dist/components/Table/ColumnFreezeMenu.d.ts +33 -0
- package/dist/components/Table/TableBase.d.ts +8 -1
- package/dist/components/Table/hooks/useColumnFreeze.d.ts +44 -0
- package/dist/components/Table/index.d.ts +2 -0
- package/dist/components/Table/types.d.ts +97 -2
- package/dist/components/Table/utils.d.ts +21 -0
- package/dist/components/TableCellHeader/TableCellHeader.d.ts +2 -1
- package/dist/components/TableCellHeader/types.d.ts +17 -0
- package/dist/components/TableContainer/TableContainer.d.ts +50 -0
- package/dist/components/TableContainer/index.d.ts +2 -0
- package/dist/components/TableContainer/types.d.ts +21 -0
- package/dist/components/index.d.ts +6 -2
- package/dist/index.js +3964 -365
- package/dist/index.mjs +3718 -125
- package/dist/tsbuildcache +1 -1
- package/dist/types/emotion.d.ts +2 -0
- package/package.json +3 -3
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { DateTime } from 'luxon';
|
|
3
|
+
import { CalendarDateInput, CalendarEvent } from './types';
|
|
4
|
+
/** Length given to a timed event that has no `end`. */
|
|
5
|
+
export declare const DEFAULT_EVENT_MINUTES = 30;
|
|
6
|
+
/**
|
|
7
|
+
* Most days an entry is repeated on. A mistyped `end` years away would
|
|
8
|
+
* otherwise fill every cell up to it.
|
|
9
|
+
*/
|
|
10
|
+
export declare const MAX_SPAN_DAYS = 366;
|
|
11
|
+
/** `Date` or ISO string → luxon, in local time. */
|
|
12
|
+
export declare const toDateTime: (value: CalendarDateInput) => DateTime;
|
|
13
|
+
/** `yyyy-MM-dd` of a date — the key events are grouped by. */
|
|
14
|
+
export declare const toDayKey: (value: DateTime) => string;
|
|
15
|
+
/**
|
|
16
|
+
* An event with its dates parsed once, so rendering never re-parses them.
|
|
17
|
+
*/
|
|
18
|
+
export type NormalizedEvent<TData = unknown> = {
|
|
19
|
+
event: CalendarEvent<TData>;
|
|
20
|
+
start: DateTime;
|
|
21
|
+
/** For untimed events, the start of the last day (inclusive). */
|
|
22
|
+
end: DateTime;
|
|
23
|
+
allDay: boolean;
|
|
24
|
+
/** Days the entry is repeated on: 1 unless it spans several. */
|
|
25
|
+
spanDays: number;
|
|
26
|
+
/** Which of those days this copy is on, from 1. */
|
|
27
|
+
dayOfSpan: number;
|
|
28
|
+
};
|
|
29
|
+
export declare const normalizeEvent: <TData>(event: CalendarEvent<TData>) => NormalizedEvent<TData> | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* Whether an entry fills a day: untimed, or timed and running from before
|
|
32
|
+
* the day starts to after it ends. Such entries are listed above the day
|
|
33
|
+
* view's timeline rather than placed on it.
|
|
34
|
+
*/
|
|
35
|
+
export declare const isWholeDay: (item: NormalizedEvent, day: DateTime) => boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Groups events by day (`yyyy-MM-dd`), each day sorted for display. An event
|
|
38
|
+
* spanning several days (see `NormalizedEvent.spanDays`) is repeated on
|
|
39
|
+
* each, with its `dayOfSpan`. Events with an unparsable `start` are dropped.
|
|
40
|
+
*/
|
|
41
|
+
export declare const groupEventsByDay: <TData>(events: CalendarEvent<TData>[]) => Map<string, NormalizedEvent<TData>[]>;
|
|
42
|
+
/** A cell of the month grid. */
|
|
43
|
+
export type MonthDay = {
|
|
44
|
+
date: DateTime;
|
|
45
|
+
key: string;
|
|
46
|
+
isCurrentMonth: boolean;
|
|
47
|
+
isToday: boolean;
|
|
48
|
+
isWeekend: boolean;
|
|
49
|
+
};
|
|
50
|
+
/** A row of the month grid. */
|
|
51
|
+
export type MonthWeek = {
|
|
52
|
+
key: string;
|
|
53
|
+
days: MonthDay[];
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* The Monday-first week rows covering `month`, padded out with the
|
|
57
|
+
* neighbouring months' days. With five weekdays a row that holds only the
|
|
58
|
+
* neighbours' days is dropped — a month that ends on a Saturday would
|
|
59
|
+
* otherwise get a row of nothing but padding.
|
|
60
|
+
*/
|
|
61
|
+
export declare const buildMonthWeeks: (month: DateTime, weekdays: 5 | 7, today?: DateTime) => MonthWeek[];
|
|
62
|
+
/** Monday-first weekday names, `long` (`Monday`) or `short` (`Mon`). */
|
|
63
|
+
export declare const getWeekdayNames: (format: "long" | "short", locale?: string) => string[];
|
|
64
|
+
/** `09:30` or `09:30 AM`. */
|
|
65
|
+
export declare const formatTime: (value: DateTime, timeFormat: "24h" | "12h") => string;
|
|
66
|
+
/**
|
|
67
|
+
* Hour label of the day view: `09:00` or `9 AM`. Formatted on a fixed date
|
|
68
|
+
* with no DST change, so every hour exists — on today's date an hour skipped
|
|
69
|
+
* by DST would be moved on, and labelled like the next one.
|
|
70
|
+
*/
|
|
71
|
+
export declare const formatHourLabel: (hour: number, timeFormat: "24h" | "12h") => string;
|
|
72
|
+
/**
|
|
73
|
+
* Minutes from midnight as the clock shows them. The timeline draws 24
|
|
74
|
+
* labelled hours on every day, so positions follow the clock rather than
|
|
75
|
+
* elapsed time — on a DST day, elapsed time would put entries after the
|
|
76
|
+
* change an hour off their labels.
|
|
77
|
+
*/
|
|
78
|
+
export declare const clockMinutes: (value: DateTime) => number;
|
|
79
|
+
/** A timed event placed on the day view's timeline. */
|
|
80
|
+
export type PositionedEvent<TData = unknown> = {
|
|
81
|
+
item: NormalizedEvent<TData>;
|
|
82
|
+
/** Minutes from midnight to the start. */
|
|
83
|
+
startMinutes: number;
|
|
84
|
+
/** Minutes the event lasts, clipped to the day. */
|
|
85
|
+
durationMinutes: number;
|
|
86
|
+
/** Column within its overlap group, from 0. */
|
|
87
|
+
column: number;
|
|
88
|
+
/** Columns in its overlap group. */
|
|
89
|
+
columns: number;
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* Places a day's timed events on the timeline. Events that overlap share the
|
|
93
|
+
* width side by side; each overlap group gets just as many columns as it
|
|
94
|
+
* needs at its busiest moment.
|
|
95
|
+
*
|
|
96
|
+
* Expects events sorted by start: the day's own (as `groupEventsByDay`
|
|
97
|
+
* returns them), after any carried over from earlier days. Events running
|
|
98
|
+
* past either midnight are clipped to the day; events not on it are skipped.
|
|
99
|
+
*/
|
|
100
|
+
export declare const layoutDayEvents: <TData>(items: NormalizedEvent<TData>[], day: DateTime) => PositionedEvent<TData>[];
|
|
101
|
+
/** Applies `locale` when given; otherwise keeps luxon's default. */
|
|
102
|
+
export declare const withLocale: (value: DateTime, locale?: string) => DateTime<boolean>;
|
|
103
|
+
/**
|
|
104
|
+
* First and last day a view shows: the whole grid of the month view,
|
|
105
|
+
* neighbouring months' days included, or the single day.
|
|
106
|
+
*/
|
|
107
|
+
export declare const getVisibleRange: (view: "month" | "day", date: DateTime, weekdays: 5 | 7) => {
|
|
108
|
+
start: DateTime;
|
|
109
|
+
end: DateTime;
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* Whether a slot has something to draw. Like React itself, keeps `0` and
|
|
113
|
+
* `''` but skips `false` — so `slot={cond && <Button />}` adds no empty
|
|
114
|
+
* wrapper when `cond` is false.
|
|
115
|
+
*/
|
|
116
|
+
export declare const hasContent: (node: ReactNode) => node is string | number | bigint | true | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | import("react").ReactPortal | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined>;
|
|
@@ -41,7 +41,8 @@ export type CarouselFit = 'contain' | 'cover';
|
|
|
41
41
|
*/
|
|
42
42
|
export type CarouselProps = {
|
|
43
43
|
/**
|
|
44
|
-
* Slides to show, in order.
|
|
44
|
+
* Slides to show, in order. When empty, a single picture placeholder is
|
|
45
|
+
* shown in place of the slide.
|
|
45
46
|
*/
|
|
46
47
|
items: CarouselItem[];
|
|
47
48
|
/**
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare const NestedTableContext: import("react").Context<
|
|
3
|
-
export declare const NestedTableProvider: ({ children, collapsedIconName, expandedIconName, defaultCollapsed, }: React.PropsWithChildren<
|
|
1
|
+
import { NestedTableContextValue } from './types';
|
|
2
|
+
export declare const NestedTableContext: import("react").Context<NestedTableContextValue>;
|
|
3
|
+
export declare const NestedTableProvider: ({ children, collapsedIconName, expandedIconName, defaultCollapsed, opaqueCells, isResizable, }: React.PropsWithChildren<NestedTableContextValue>) => import("@emotion/react/jsx-runtime").JSX.Element;
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { CommonProps } from '../../../types/emotion';
|
|
3
|
-
import { NestedTableContextType } from '../types';
|
|
1
|
+
import { TableProps } from '../../Table/types';
|
|
4
2
|
/**
|
|
5
3
|
* NestedTable - Table whose rows collapse into expandable groups.
|
|
6
4
|
*
|
|
@@ -26,6 +24,21 @@ import { NestedTableContextType } from '../types';
|
|
|
26
24
|
* is what makes the transition animate. They remain findable by queries and by
|
|
27
25
|
* `Ctrl+F`, so do not rely on collapse to hide sensitive content.
|
|
28
26
|
*
|
|
27
|
+
* ### Resizing and freezing columns
|
|
28
|
+
* Takes every `Table` option — `resizableColumns`, `frozenColumns`,
|
|
29
|
+
* `freezeControls`, `stickyHeader` — and works inside `TableContainer`. Build
|
|
30
|
+
* the header from `NestedTableCellHeader` so the columns get their drag handles
|
|
31
|
+
* and freeze menus.
|
|
32
|
+
*
|
|
33
|
+
* Column positions skip the toggle column: `0` is your first column in
|
|
34
|
+
* `frozenColumns`, and width arrays hold one entry per column of yours. The
|
|
35
|
+
* toggle column freezes by itself only when your first column is frozen to the
|
|
36
|
+
* left; otherwise it scrolls like any other column.
|
|
37
|
+
*
|
|
38
|
+
* Frozen cells and a sticky header paint the row's background, so give rows an
|
|
39
|
+
* opaque one — a translucent row would let scrolled content show through.
|
|
40
|
+
* With resizing on, the table renders its own `colgroup`; drop any you had.
|
|
41
|
+
*
|
|
29
42
|
* @category Components
|
|
30
43
|
* @subcategory Data Display
|
|
31
44
|
*
|
|
@@ -57,5 +70,25 @@ import { NestedTableContextType } from '../types';
|
|
|
57
70
|
* {groups}
|
|
58
71
|
* </NestedTable>
|
|
59
72
|
* ```
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```tsx
|
|
76
|
+
* // Resizable, with the first column frozen and a sticky header
|
|
77
|
+
* <TableContainer maxHeight={400}>
|
|
78
|
+
* <NestedTable
|
|
79
|
+
* resizableColumns
|
|
80
|
+
* freezeControls
|
|
81
|
+
* stickyHeader
|
|
82
|
+
* defaultFrozenColumns={{ start: ['team'] }}>
|
|
83
|
+
* <TableHead>
|
|
84
|
+
* <NestedTableRow isHeader>
|
|
85
|
+
* <NestedTableCellHeader columnId="team">Team</NestedTableCellHeader>
|
|
86
|
+
* <NestedTableCellHeader columnId="size">Headcount</NestedTableCellHeader>
|
|
87
|
+
* </NestedTableRow>
|
|
88
|
+
* </TableHead>
|
|
89
|
+
* <TableBody>{groups}</TableBody>
|
|
90
|
+
* </NestedTable>
|
|
91
|
+
* </TableContainer>
|
|
92
|
+
* ```
|
|
60
93
|
*/
|
|
61
|
-
export declare const NestedTable: (
|
|
94
|
+
export declare const NestedTable: import("react").ForwardRefExoticComponent<TableProps & import("../types").NestedTableContextType & import("react").RefAttributes<HTMLTableElement>>;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { CommonProps } from '../../../types/emotion';
|
|
1
|
+
import { NestedTableCellBaseProps } from './NestedTableCellBase';
|
|
3
2
|
/**
|
|
4
3
|
* NestedTableCell - Cell for a `NestedTableRow`.
|
|
5
4
|
*
|
|
@@ -33,4 +32,4 @@ import { CommonProps } from '../../../types/emotion';
|
|
|
33
32
|
* <NestedTableCell as="th">Headcount</NestedTableCell>
|
|
34
33
|
* ```
|
|
35
34
|
*/
|
|
36
|
-
export declare const NestedTableCell: (
|
|
35
|
+
export declare const NestedTableCell: (props: Omit<NestedTableCellBaseProps, "adornment" | "trailing">) => import("@emotion/react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { TableCellProps } from '../../TableCell/types';
|
|
3
|
+
export type NestedTableCellBaseProps = React.PropsWithChildren<TableCellProps> & {
|
|
4
|
+
/** Rendered inside the content wrapper, after the content. */
|
|
5
|
+
adornment?: ReactNode;
|
|
6
|
+
/**
|
|
7
|
+
* Rendered after the content wrapper, straight inside the cell — where
|
|
8
|
+
* the table's stylesheet expects a column's resize handle.
|
|
9
|
+
*/
|
|
10
|
+
trailing?: ReactNode;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* The cell shared by `NestedTableCell` and `NestedTableCellHeader`. Not
|
|
14
|
+
* exported from the package.
|
|
15
|
+
*/
|
|
16
|
+
export declare const NestedTableCellBase: ({ children, adornment, trailing, ...props }: NestedTableCellBaseProps) => import("@emotion/react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { NestedTableCellHeaderProps } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* NestedTableCellHeader - Column header cell for a `NestedTable`.
|
|
4
|
+
*
|
|
5
|
+
* The nested counterpart of `TableCellHeader`: renders a `th` styled like a
|
|
6
|
+
* `NestedTableCell`, and carries the column's drag handle when the table has
|
|
7
|
+
* `resizableColumns` and its freeze menu when the table has `freezeControls`.
|
|
8
|
+
* Outside those modes it is just a header cell, so it is safe to use in every
|
|
9
|
+
* nested table.
|
|
10
|
+
*
|
|
11
|
+
* Use it in the header `NestedTableRow` (the one with `isHeader`). The
|
|
12
|
+
* toggle column the row adds in front gets no handle or menu, and does not
|
|
13
|
+
* count as a column — `0` is the first header cell you render.
|
|
14
|
+
*
|
|
15
|
+
* @category Components
|
|
16
|
+
* @subcategory Data Display
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```tsx
|
|
20
|
+
* <TableHead>
|
|
21
|
+
* <NestedTableRow isHeader>
|
|
22
|
+
* <NestedTableCellHeader columnId="team">Team</NestedTableCellHeader>
|
|
23
|
+
* <NestedTableCellHeader columnId="size">Headcount</NestedTableCellHeader>
|
|
24
|
+
* <NestedTableCellHeader columnId="actions" resizable={false} freezable={false} />
|
|
25
|
+
* </NestedTableRow>
|
|
26
|
+
* </TableHead>
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @see {@link NestedTable} - `resizableColumns`, `frozenColumns`, `freezeControls`
|
|
30
|
+
* @see {@link TableCellHeader} - the same cell for a plain `Table`
|
|
31
|
+
*
|
|
32
|
+
* @accessibility
|
|
33
|
+
* - Renders a semantic `th`
|
|
34
|
+
* - The resize handle and freeze menu are keyboard operable
|
|
35
|
+
*/
|
|
36
|
+
export declare const NestedTableCellHeader: ({ children, resizable, freezable, columnId, ...props }: React.PropsWithChildren<NestedTableCellHeaderProps>) => import("@emotion/react/jsx-runtime").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const useNestedTableContext: () => import("..").
|
|
1
|
+
export declare const useNestedTableContext: () => import("..").NestedTableContextValue;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Dispatch, SetStateAction } from 'react';
|
|
2
2
|
import { IconProps } from '../Icon/types';
|
|
3
|
+
import { TableProps } from '../Table/types';
|
|
4
|
+
import { TableCellHeaderProps } from '../TableCellHeader/types';
|
|
3
5
|
export type NestedTableContextType = {
|
|
4
6
|
/** Toggle icon shown while a group is collapsed. @default 'carrot-up' */
|
|
5
7
|
collapsedIconName?: IconProps['name'];
|
|
@@ -14,6 +16,35 @@ export type NestedTableContextType = {
|
|
|
14
16
|
*/
|
|
15
17
|
defaultCollapsed?: boolean;
|
|
16
18
|
};
|
|
19
|
+
/** What `NestedTable` hands its rows and cells, beyond its own props. */
|
|
20
|
+
export type NestedTableContextValue = NestedTableContextType & {
|
|
21
|
+
/**
|
|
22
|
+
* Set while columns can freeze or the header sticks. Cells then paint the
|
|
23
|
+
* row's background themselves, and the row paints it opaque, so content
|
|
24
|
+
* scrolled under a stuck cell does not show through.
|
|
25
|
+
*/
|
|
26
|
+
opaqueCells?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Mirrors the table's `resizableColumns`. Cells read it here rather than
|
|
29
|
+
* from the resize context, whose value changes on every frame of a drag and
|
|
30
|
+
* would re-render every cell in the table with it.
|
|
31
|
+
*/
|
|
32
|
+
isResizable?: boolean;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Props for {@link NestedTable}: everything `Table` accepts, plus the group
|
|
36
|
+
* toggle options.
|
|
37
|
+
*
|
|
38
|
+
* Column positions in `columnWidths`, `defaultColumnWidths`,
|
|
39
|
+
* `onColumnWidthsChange` and `frozenColumns` count only your own columns — the
|
|
40
|
+
* toggle column `NestedTableRow` adds in front is left out of all of them.
|
|
41
|
+
*/
|
|
42
|
+
export type NestedTableProps = TableProps & NestedTableContextType;
|
|
43
|
+
/**
|
|
44
|
+
* Props for {@link NestedTableCellHeader}: the same column options as
|
|
45
|
+
* `TableCellHeader` — `columnId`, `resizable`, `freezable`.
|
|
46
|
+
*/
|
|
47
|
+
export type NestedTableCellHeaderProps = TableCellHeaderProps;
|
|
17
48
|
export type NestedTableRowContextType = {
|
|
18
49
|
isCollapsed: boolean;
|
|
19
50
|
isSubHeader: boolean;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ColumnFreezeApi } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Null outside a `Table` that freezes columns or offers freeze controls, so
|
|
4
|
+
* header cells in an ordinary table stay exactly as they were.
|
|
5
|
+
*/
|
|
6
|
+
export declare const ColumnFreezeContext: import("react").Context<ColumnFreezeApi | null>;
|
|
7
|
+
/**
|
|
8
|
+
* The enclosing table's column-freezing state, or `null` when it has none.
|
|
9
|
+
*
|
|
10
|
+
* Lets a custom header cell render {@link ColumnFreezeMenu} only when the
|
|
11
|
+
* table asked for freeze controls.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* const MyHeaderCell = ({ children }) => {
|
|
16
|
+
* const columnFreeze = useColumnFreezeContext();
|
|
17
|
+
*
|
|
18
|
+
* return (
|
|
19
|
+
* <TableCell as="th">
|
|
20
|
+
* {children}
|
|
21
|
+
* {columnFreeze?.freezeControls && <ColumnFreezeMenu />}
|
|
22
|
+
* </TableCell>
|
|
23
|
+
* );
|
|
24
|
+
* };
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare const useColumnFreezeContext: () => ColumnFreezeApi | null;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ColumnFreezeMenuProps } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* ColumnFreezeMenu - The freeze/unfreeze menu in a table header cell
|
|
4
|
+
*
|
|
5
|
+
* `TableCellHeader` renders it for you when its `Table` has `freezeControls`.
|
|
6
|
+
* Render it yourself only in a custom header cell, passing the column's id;
|
|
7
|
+
* without one it falls back to the `columnId` or position of the `th` it
|
|
8
|
+
* sits in.
|
|
9
|
+
*
|
|
10
|
+
* Any column can be frozen to either edge. It stays where it is until
|
|
11
|
+
* scrolling would take it out of view, then sticks to that edge while the
|
|
12
|
+
* columns between slide underneath.
|
|
13
|
+
*
|
|
14
|
+
* @category Components
|
|
15
|
+
* @subcategory Data Display
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* <TableCell as="th" data-column-id="email">
|
|
20
|
+
* Email
|
|
21
|
+
* <ColumnFreezeMenu columnId="email" />
|
|
22
|
+
* </TableCell>
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @see {@link Table} - `freezeControls` and `frozenColumns`
|
|
26
|
+
* @see {@link useColumnFreezeContext} - whether the table wants the menu
|
|
27
|
+
*
|
|
28
|
+
* @accessibility
|
|
29
|
+
* - The trigger is a labelled button, reachable by keyboard even while hidden
|
|
30
|
+
* - Clicks inside the menu do not reach the header cell, so they never sort
|
|
31
|
+
*/
|
|
32
|
+
export declare const ColumnFreezeMenu: ({ columnId }: ColumnFreezeMenuProps) => import("@emotion/react/jsx-runtime").JSX.Element;
|
|
33
|
+
export default ColumnFreezeMenu;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CommonProps } from '../../types/emotion';
|
|
2
|
-
import { ColumnResizeMode } from './types';
|
|
2
|
+
import { ColumnResizeMode, FrozenColumnIndices } from './types';
|
|
3
3
|
export interface TableBaseProps extends CommonProps {
|
|
4
4
|
/** Applies the truncation rules resizing depends on. */
|
|
5
5
|
isResizable?: boolean;
|
|
@@ -11,6 +11,13 @@ export interface TableBaseProps extends CommonProps {
|
|
|
11
11
|
hasColumnWidths?: boolean;
|
|
12
12
|
/** How a resize distributes width. See TableProps.columnResizeMode. */
|
|
13
13
|
columnResizeMode?: ColumnResizeMode;
|
|
14
|
+
/**
|
|
15
|
+
* Positions of the frozen columns on each edge, resolved by `Table` from
|
|
16
|
+
* the ids in TableProps.frozenColumns.
|
|
17
|
+
*/
|
|
18
|
+
frozenIndices?: FrozenColumnIndices;
|
|
19
|
+
/** Keeps the header row in view. See TableProps.stickyHeader. */
|
|
20
|
+
stickyHeader?: boolean;
|
|
14
21
|
}
|
|
15
22
|
/**
|
|
16
23
|
* The styled element behind `Table`.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { RefObject } from 'react';
|
|
2
|
+
import { ColumnFreezeApi, FrozenColumnIndices, FrozenColumns } from '../types';
|
|
3
|
+
/** Custom property holding the sticky offset of the column at `index`. */
|
|
4
|
+
export declare const frozenOffsetVar: (index: number) => string;
|
|
5
|
+
/** Attributes naming the frozen column that currently casts each shadow. */
|
|
6
|
+
export declare const SHADOW_START_ATTR = "data-frozen-shadow-start";
|
|
7
|
+
export declare const SHADOW_END_ATTR = "data-frozen-shadow-end";
|
|
8
|
+
interface UseColumnFreezeOptions {
|
|
9
|
+
tableRef: RefObject<HTMLTableElement | null>;
|
|
10
|
+
frozenColumns?: FrozenColumns;
|
|
11
|
+
defaultFrozenColumns?: FrozenColumns;
|
|
12
|
+
onFrozenColumnsChange?: (frozenColumns: Required<FrozenColumns>) => void;
|
|
13
|
+
freezeControls: boolean;
|
|
14
|
+
controlled: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Frozen-column state for `Table`, plus the DOM work that keeps frozen cells
|
|
18
|
+
* in place.
|
|
19
|
+
*
|
|
20
|
+
* ## Ids are resolved against the header
|
|
21
|
+
*
|
|
22
|
+
* The caller speaks in column ids; the stylesheet needs positions. After every
|
|
23
|
+
* render the header cells are read back, ids matched to positions, and the
|
|
24
|
+
* positions handed to `TableBase`. Only the set of frozen positions ever
|
|
25
|
+
* reaches emotion, so a column changing width mints no new rules.
|
|
26
|
+
*
|
|
27
|
+
* ## Offsets live in custom properties
|
|
28
|
+
*
|
|
29
|
+
* Each frozen cell is `position: sticky` with a `left`/`right` equal to the
|
|
30
|
+
* width of the frozen columns between it and its edge. Those widths change
|
|
31
|
+
* with every frame of a column resize, so they are written to custom
|
|
32
|
+
* properties on the table element directly.
|
|
33
|
+
*
|
|
34
|
+
* ## Shadows follow the scroll position
|
|
35
|
+
*
|
|
36
|
+
* `data-frozen-shadow-start` / `-end` on the table name the frozen column on
|
|
37
|
+
* each side that has content scrolled underneath it, so the divider only
|
|
38
|
+
* shows when there is something to divide.
|
|
39
|
+
*/
|
|
40
|
+
export declare const useColumnFreeze: ({ tableRef, frozenColumns, defaultFrozenColumns, onFrozenColumnsChange, freezeControls, controlled, }: UseColumnFreezeOptions) => {
|
|
41
|
+
api: ColumnFreezeApi;
|
|
42
|
+
indices: FrozenColumnIndices;
|
|
43
|
+
};
|
|
44
|
+
export {};
|
|
@@ -2,5 +2,7 @@ export { default } from './Table';
|
|
|
2
2
|
export { default as ColumnResizeHandle } from './ColumnResizeHandle';
|
|
3
3
|
export { useColumnResize } from './hooks/useColumnResize';
|
|
4
4
|
export { useColumnResizeContext } from './ColumnResizeContext';
|
|
5
|
+
export { default as ColumnFreezeMenu } from './ColumnFreezeMenu';
|
|
6
|
+
export { useColumnFreezeContext } from './ColumnFreezeContext';
|
|
5
7
|
export * from './types';
|
|
6
8
|
export * from './ColumnResizeHandle.types';
|
|
@@ -97,6 +97,12 @@ export interface UseColumnResizeOptions extends ColumnResizeOptions {
|
|
|
97
97
|
export interface ColumnResizeApi {
|
|
98
98
|
/** Current width of each column, in pixels. Empty until measured. */
|
|
99
99
|
columnWidths: number[];
|
|
100
|
+
/**
|
|
101
|
+
* Positions of the columns the table added on its own, such as the toggle
|
|
102
|
+
* column of a `NestedTable`. In `fit` mode they keep their width exactly,
|
|
103
|
+
* and only the other columns share out any space the table has to spare.
|
|
104
|
+
*/
|
|
105
|
+
fixedColumns: number[];
|
|
100
106
|
/** Attach to the `table` element so the hook can measure its columns. */
|
|
101
107
|
tableRef: RefObject<HTMLTableElement | null>;
|
|
102
108
|
/** Whether a drag is in progress. */
|
|
@@ -119,11 +125,100 @@ export interface ColumnResizeApi {
|
|
|
119
125
|
/** Builds the props for the drag handle of a given column. */
|
|
120
126
|
getResizeHandleProps: (index: number) => ResizeHandleProps;
|
|
121
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* Identifies a table column: the `columnId` of its `TableCellHeader`, or its
|
|
130
|
+
* zero-based position when the header has none. Ids are compared as strings,
|
|
131
|
+
* so `3` and `'3'` are the same column.
|
|
132
|
+
*/
|
|
133
|
+
export type ColumnId = string | number;
|
|
134
|
+
/**
|
|
135
|
+
* Which columns of a {@link Table} are frozen, and to which edge.
|
|
136
|
+
*
|
|
137
|
+
* A frozen column stays where it is until scrolling would take it out of view;
|
|
138
|
+
* from then on it sticks to its edge and the columns between it and the edge
|
|
139
|
+
* slide underneath. Several frozen columns on one edge stack up in column
|
|
140
|
+
* order.
|
|
141
|
+
*
|
|
142
|
+
* Give the header cells a `columnId` so the frozen state follows the column
|
|
143
|
+
* when the app hides or reorders columns; without one, a column is
|
|
144
|
+
* identified by its position.
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```tsx
|
|
148
|
+
* const frozen: FrozenColumns = { start: ['name', 'status'], end: ['actions'] };
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
export interface FrozenColumns {
|
|
152
|
+
/**
|
|
153
|
+
* Columns that stick to the left edge.
|
|
154
|
+
* @default []
|
|
155
|
+
*/
|
|
156
|
+
start?: ColumnId[];
|
|
157
|
+
/**
|
|
158
|
+
* Columns that stick to the right edge.
|
|
159
|
+
* @default []
|
|
160
|
+
*/
|
|
161
|
+
end?: ColumnId[];
|
|
162
|
+
}
|
|
163
|
+
/** Which columns, by position, are frozen to each edge, in column order. */
|
|
164
|
+
export interface FrozenColumnIndices {
|
|
165
|
+
start: number[];
|
|
166
|
+
end: number[];
|
|
167
|
+
}
|
|
168
|
+
/** Options for freezing columns and the header row of a `Table`. */
|
|
169
|
+
export interface ColumnFreezeOptions {
|
|
170
|
+
/**
|
|
171
|
+
* Columns frozen to each edge. Passing this prop puts freezing into
|
|
172
|
+
* controlled mode — hold the value in state and update it from
|
|
173
|
+
* `onFrozenColumnsChange`, or the header controls will have no effect.
|
|
174
|
+
*/
|
|
175
|
+
frozenColumns?: FrozenColumns;
|
|
176
|
+
/** Columns frozen to each edge to begin with, for the uncontrolled case. */
|
|
177
|
+
defaultFrozenColumns?: FrozenColumns;
|
|
178
|
+
/**
|
|
179
|
+
* Called whenever the user freezes or unfreezes columns from the header
|
|
180
|
+
* controls. Always receives both lists.
|
|
181
|
+
*/
|
|
182
|
+
onFrozenColumnsChange?: (frozenColumns: Required<FrozenColumns>) => void;
|
|
183
|
+
/**
|
|
184
|
+
* Gives every `TableCellHeader` a menu to freeze its column to either edge,
|
|
185
|
+
* or unfreeze it. Independent of `frozenColumns` — a table can have frozen
|
|
186
|
+
* columns without letting the user change them.
|
|
187
|
+
*
|
|
188
|
+
* @default false
|
|
189
|
+
*/
|
|
190
|
+
freezeControls?: boolean;
|
|
191
|
+
/**
|
|
192
|
+
* Keeps the header row in view while the table scrolls vertically. Needs a
|
|
193
|
+
* scroll container with a height limit, such as `TableContainer` with
|
|
194
|
+
* `maxHeight`.
|
|
195
|
+
*
|
|
196
|
+
* @default false
|
|
197
|
+
*/
|
|
198
|
+
stickyHeader?: boolean;
|
|
199
|
+
}
|
|
200
|
+
/** Props for {@link ColumnFreezeMenu}. */
|
|
201
|
+
export interface ColumnFreezeMenuProps {
|
|
202
|
+
/**
|
|
203
|
+
* The column the menu freezes. Defaults to the `data-column-id` of the
|
|
204
|
+
* header cell it sits in, or that cell's position.
|
|
205
|
+
*/
|
|
206
|
+
columnId?: ColumnId;
|
|
207
|
+
}
|
|
208
|
+
/** What the freezing context hands to header cells. */
|
|
209
|
+
export interface ColumnFreezeApi {
|
|
210
|
+
/** Current frozen columns, both lists always present. */
|
|
211
|
+
frozenColumns: Required<FrozenColumns>;
|
|
212
|
+
/** Replaces the frozen columns and notifies `onFrozenColumnsChange`. */
|
|
213
|
+
setFrozenColumns: (frozenColumns: Required<FrozenColumns>) => void;
|
|
214
|
+
/** Whether header cells should render the freeze menu. */
|
|
215
|
+
freezeControls: boolean;
|
|
216
|
+
}
|
|
122
217
|
/**
|
|
123
218
|
* Props for the {@link Table} component.
|
|
124
219
|
*
|
|
125
220
|
* Every attribute of a `table` element, plus the column-resizing options that
|
|
126
|
-
* `resizableColumns` turns on.
|
|
221
|
+
* `resizableColumns` turns on and the column-freezing options.
|
|
127
222
|
*
|
|
128
223
|
* @example
|
|
129
224
|
* ```tsx
|
|
@@ -132,7 +227,7 @@ export interface ColumnResizeApi {
|
|
|
132
227
|
* </Table>
|
|
133
228
|
* ```
|
|
134
229
|
*/
|
|
135
|
-
export interface TableProps extends CommonProps, ColumnResizeOptions, TableHTMLAttributes<HTMLTableElement> {
|
|
230
|
+
export interface TableProps extends CommonProps, ColumnResizeOptions, ColumnFreezeOptions, TableHTMLAttributes<HTMLTableElement> {
|
|
136
231
|
/**
|
|
137
232
|
* Lets columns be resized by dragging the right edge of each header cell.
|
|
138
233
|
*
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ColumnId } from './types';
|
|
2
|
+
/** The cells that define the column grid — the first header row, or row one. */
|
|
3
|
+
export declare const getHeaderCells: (table: HTMLTableElement | null) => HTMLTableCellElement[];
|
|
4
|
+
/**
|
|
5
|
+
* Marks a structural column the table adds on its own, such as the toggle
|
|
6
|
+
* column `NestedTableRow` puts in front of every row. It has no id of its own,
|
|
7
|
+
* is skipped when columns are numbered, and freezes to the start only when the
|
|
8
|
+
* column right after it does.
|
|
9
|
+
*/
|
|
10
|
+
export declare const EXPANDER_ATTR = "data-column-expander";
|
|
11
|
+
export declare const isExpanderCell: (cell: HTMLTableCellElement) => boolean;
|
|
12
|
+
/**
|
|
13
|
+
* The id each cell answers to: its `columnId`, else its position counting only
|
|
14
|
+
* the columns the app itself rendered. `null` for expander cells.
|
|
15
|
+
*/
|
|
16
|
+
export declare const getColumnKeys: (cells: HTMLTableCellElement[]) => (string | null)[];
|
|
17
|
+
/**
|
|
18
|
+
* The id of the column a header cell belongs to: its `columnId`, else its
|
|
19
|
+
* position as a number. `null` for an expander. See getColumnKeys.
|
|
20
|
+
*/
|
|
21
|
+
export declare const getColumnIdOf: (cell: HTMLTableCellElement) => ColumnId | null;
|
|
@@ -54,6 +54,7 @@ import { TableCellHeaderProps } from './types';
|
|
|
54
54
|
* @see {@link TableCell} - Data cell component (use in TableBody)
|
|
55
55
|
* @see {@link TableBody} - Body section component
|
|
56
56
|
* @see {@link ColumnResizeHandle} - the handle rendered inside resizable headers
|
|
57
|
+
* @see {@link ColumnFreezeMenu} - the menu rendered when the table has `freezeControls`
|
|
57
58
|
*
|
|
58
59
|
* @accessibility
|
|
59
60
|
* - Semantic HTML th element (renders as th)
|
|
@@ -61,5 +62,5 @@ import { TableCellHeaderProps } from './types';
|
|
|
61
62
|
* - Supports ARIA attributes via TableCellProps
|
|
62
63
|
* - Better accessibility than using TableCell in headers
|
|
63
64
|
*/
|
|
64
|
-
declare const TableCellHeader: ({ children, resizable, ...props }: React.PropsWithChildren<TableCellHeaderProps>) => import("@emotion/react/jsx-runtime").JSX.Element;
|
|
65
|
+
declare const TableCellHeader: ({ children, resizable, freezable, columnId, ...props }: React.PropsWithChildren<TableCellHeaderProps>) => import("@emotion/react/jsx-runtime").JSX.Element;
|
|
65
66
|
export default TableCellHeader;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { TableCellProps } from '../TableCell/types';
|
|
2
|
+
import { ColumnId } from '../Table/types';
|
|
2
3
|
/**
|
|
3
4
|
* Props for the TableCellHeader component
|
|
4
5
|
*
|
|
@@ -42,4 +43,20 @@ export interface TableCellHeaderProps extends TableCellProps {
|
|
|
42
43
|
* @default true
|
|
43
44
|
*/
|
|
44
45
|
resizable?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Whether this header cell offers the freeze menu inside a `Table` with
|
|
48
|
+
* `freezeControls`. Set it to `false` for columns the user should not
|
|
49
|
+
* freeze, such as a checkbox column. The app can still freeze it through
|
|
50
|
+
* `frozenColumns`.
|
|
51
|
+
*
|
|
52
|
+
* @default true
|
|
53
|
+
*/
|
|
54
|
+
freezable?: boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Stable id for this column, used by `frozenColumns` on the `Table`. Give
|
|
57
|
+
* every header one when the app can hide or reorder columns, so frozen
|
|
58
|
+
* state follows the column rather than its position. Without it the column
|
|
59
|
+
* is identified by its zero-based position.
|
|
60
|
+
*/
|
|
61
|
+
columnId?: ColumnId;
|
|
45
62
|
}
|