ics-ui-kit 0.1.13 → 0.1.14
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/{AlertIcon-5B6AgZpe.js → AlertIcon-BphnEYvV.js} +3 -3
- package/dist/AlertIcon-BphnEYvV.js.map +1 -0
- package/dist/Field-CP_-li9L.js +90 -0
- package/dist/Field-CP_-li9L.js.map +1 -0
- package/dist/{FormFooterTemplate-ClTxqrIB.js → FormFooterTemplate-Cfn5Nmge.js} +2 -2
- package/dist/{FormFooterTemplate-ClTxqrIB.js.map → FormFooterTemplate-Cfn5Nmge.js.map} +1 -1
- package/dist/{FormStack-B3UBh9oF.js → FormStack-Cc_ELdWL.js} +2 -2
- package/dist/{FormStack-B3UBh9oF.js.map → FormStack-Cc_ELdWL.js.map} +1 -1
- package/dist/{SearchSelectTag-DFCX9zT1.js → SearchSelectTag-CA7Ie3Nx.js} +2 -2
- package/dist/{SearchSelectTag-DFCX9zT1.js.map → SearchSelectTag-CA7Ie3Nx.js.map} +1 -1
- package/dist/TableFillHandle-C_yvCTSl.js +65 -0
- package/dist/TableFillHandle-C_yvCTSl.js.map +1 -0
- package/dist/TextOverflowTooltip-B1I5qwAT.js.map +1 -1
- package/dist/blocks/auth/otp-form.js +1 -1
- package/dist/components/alert/Alert.d.ts +4 -0
- package/dist/components/alert/Alert.stories.d.ts +1 -0
- package/dist/components/alert-dialog.js +1 -1
- package/dist/components/alert.js +18 -18
- package/dist/components/alert.js.map +1 -1
- package/dist/components/card.js +1 -1
- package/dist/components/dialog.js +1 -1
- package/dist/components/field/Field.d.ts +4 -0
- package/dist/components/field/Field.stories.d.ts +1 -0
- package/dist/components/field.js +1 -1
- package/dist/components/file-upload.js +1 -1
- package/dist/components/form.js +3 -3
- package/dist/components/search-select.js +1 -1
- package/dist/components/sidebar.js +204 -210
- package/dist/components/sidebar.js.map +1 -1
- package/dist/components/system-state.js +1 -1
- package/dist/components/table/Table.d.ts +109 -5
- package/dist/components/table/Table.stories.d.ts +285 -9
- package/dist/components/table/column-reorder/index.d.ts +1 -0
- package/dist/components/table/column-reorder/useColumnReorder.d.ts +82 -0
- package/dist/components/table/column-reorder.d.ts +2 -0
- package/dist/components/table/column-reorder.js +6 -0
- package/dist/components/table/column-reorder.js.map +1 -0
- package/dist/components/table/column-resize/columnAutoFit.d.ts +21 -0
- package/dist/components/table/column-resize/columnResizeSession.d.ts +9 -0
- package/dist/components/table/column-resize/index.d.ts +3 -0
- package/dist/components/table/column-resize/useColumnResize.d.ts +52 -0
- package/dist/components/table/column-resize.d.ts +2 -0
- package/dist/components/table/column-resize.js +7 -0
- package/dist/components/table/column-resize.js.map +1 -0
- package/dist/components/table/editable/TableFillHandle.d.ts +23 -0
- package/dist/components/table/editable/cellRange.d.ts +83 -0
- package/dist/components/table/editable/editableCell.d.ts +90 -0
- package/dist/components/table/editable/index.d.ts +3 -0
- package/dist/components/table/editable.d.ts +2 -0
- package/dist/components/table/editable.js +12 -0
- package/dist/components/table/editable.js.map +1 -0
- package/dist/components/table/index.d.ts +8 -1
- package/dist/components/table/opaqueCell.d.ts +47 -0
- package/dist/components/table/rowTint.d.ts +60 -0
- package/dist/components/table/sticky/index.d.ts +1 -0
- package/dist/components/table/sticky/stickyCell.d.ts +105 -0
- package/dist/components/table/sticky.d.ts +2 -0
- package/dist/components/table/sticky.js +22 -0
- package/dist/components/table/sticky.js.map +1 -0
- package/dist/components/table/tableStoryData.d.ts +84 -0
- package/dist/components/table/tableStoryParts.d.ts +72 -0
- package/dist/components/table/tree/TableTree.d.ts +106 -0
- package/dist/components/table/tree/index.d.ts +3 -0
- package/dist/components/table/tree/treeGeometry.d.ts +86 -0
- package/dist/components/table/tree/treeModel.d.ts +87 -0
- package/dist/components/table/tree.d.ts +2 -0
- package/dist/components/table/tree.js +19 -0
- package/dist/components/table/tree.js.map +1 -0
- package/dist/components/table.js +52 -79
- package/dist/components/table.js.map +1 -1
- package/dist/components/tag-input.js +1 -1
- package/dist/components/toolbar.js +1 -2
- package/dist/components/toolbar.js.map +1 -1
- package/dist/hooks.js +1 -1
- package/dist/lib/utils/dom.d.ts +72 -0
- package/dist/opaqueCell-SGaiyL54.js +31 -0
- package/dist/opaqueCell-SGaiyL54.js.map +1 -0
- package/dist/plus-BpxYPnAG.js +15 -0
- package/dist/plus-BpxYPnAG.js.map +1 -0
- package/dist/styles-scoped.css +315 -72
- package/dist/styles.css +315 -72
- package/dist/theme.css +2 -0
- package/dist/treeModel-BlPWVj4W.js +319 -0
- package/dist/treeModel-BlPWVj4W.js.map +1 -0
- package/dist/useBreakpoints-DHvp74UL.js +31 -0
- package/dist/useBreakpoints-DHvp74UL.js.map +1 -0
- package/dist/useColumnReorder-BxVZQ_Y5.js +119 -0
- package/dist/useColumnReorder-BxVZQ_Y5.js.map +1 -0
- package/dist/useColumnResize-wjfEyBBg.js +130 -0
- package/dist/useColumnResize-wjfEyBBg.js.map +1 -0
- package/dist/vendors/date-fns/index.d.ts +7 -14
- package/dist/vendors/date-fns/locale/en-US/index.d.ts +4 -0
- package/dist/vendors/date-fns/locale/ru/index.d.ts +4 -0
- package/dist/vendors/react-day-picker/index.d.ts +8 -17
- package/dist/vendors/react-hook-form/index.d.ts +8 -15
- package/dist/vendors/tanstack/react-table/index.d.ts +12 -0
- package/dist/vendors/zod/index.d.ts +8 -9
- package/package.json +3 -2
- package/tailwind.preset.js +6 -2
- package/dist/AlertIcon-5B6AgZpe.js.map +0 -1
- package/dist/Field-COD9VbUX.js +0 -86
- package/dist/Field-COD9VbUX.js.map +0 -1
- package/dist/components/data-table/DataTable.stories.d.ts +0 -8
- package/dist/useBreakpoints-D8wKOvil.js +0 -103
- package/dist/useBreakpoints-D8wKOvil.js.map +0 -1
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { VariantProps, TVReturnType } from 'tailwind-variants';
|
|
2
|
+
/**
|
|
3
|
+
* Ячейка редактируемой таблицы: скелет сетки и заливка по состоянию.
|
|
4
|
+
*
|
|
5
|
+
* Скелет один на все состояния. `relative` — контекст позиционирования для ручки
|
|
6
|
+
* автозаполнения (`TableFillHandle`), `cursor-cell` — курсор сетки вместо стрелки,
|
|
7
|
+
* `select-none` — чтобы протягивание выделения мышью не выделяло текст.
|
|
8
|
+
*
|
|
9
|
+
* **Состояние — одна ось, а не набор флагов.** Все состояния красят одно и то же —
|
|
10
|
+
* `background-color`, поэтому одновременно видно ровно одно. Будь это булевы пропы,
|
|
11
|
+
* у ячейки «изменена и нередактируема» победил бы не тот класс, который передали последним,
|
|
12
|
+
* а тот, что стоит ниже в стилях: порядок в атрибуте `class` браузер не учитывает.
|
|
13
|
+
* С одним `state` выбор делается явно — и делает его прикладной код, потому что приоритет
|
|
14
|
+
* состояний зависит от задачи: где-то важнее показать правку, где-то — запрет на неё.
|
|
15
|
+
*
|
|
16
|
+
* Что означают состояния и когда их включать, кит не знает: «изменена» — это правка,
|
|
17
|
+
* не отправленная на сервер, или отличие от прошлой версии? Ячейка только красится.
|
|
18
|
+
*
|
|
19
|
+
* | Состояние | Смысл |
|
|
20
|
+
* | ------------ | ------------------------------------------------------------ |
|
|
21
|
+
* | `readonly` | правка запрещена — приглушённый текст на серой заливке |
|
|
22
|
+
* | `modified` | значение изменено |
|
|
23
|
+
* | `editing` | открыт редактор — та же заливка плюс кольцо фокуса |
|
|
24
|
+
* | `fillSource` | ячейка, из которой тянут значения |
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* <TableCell
|
|
28
|
+
* className={cellStateStyles({
|
|
29
|
+
* state: isEditing ? "editing" : isModified ? "modified" : readonly ? "readonly" : undefined,
|
|
30
|
+
* className: column.numeric ? "text-right tabular-nums" : undefined
|
|
31
|
+
* })}
|
|
32
|
+
* >
|
|
33
|
+
*/
|
|
34
|
+
export declare const cellStateStyles: TVReturnType<{
|
|
35
|
+
state: {
|
|
36
|
+
readonly: string;
|
|
37
|
+
fillSource: string;
|
|
38
|
+
modified: string;
|
|
39
|
+
editing: string;
|
|
40
|
+
};
|
|
41
|
+
}, undefined, "relative cursor-cell select-none", {
|
|
42
|
+
state: {
|
|
43
|
+
readonly: string;
|
|
44
|
+
fillSource: string;
|
|
45
|
+
modified: string;
|
|
46
|
+
editing: string;
|
|
47
|
+
};
|
|
48
|
+
}, undefined, TVReturnType<{
|
|
49
|
+
state: {
|
|
50
|
+
readonly: string;
|
|
51
|
+
fillSource: string;
|
|
52
|
+
modified: string;
|
|
53
|
+
editing: string;
|
|
54
|
+
};
|
|
55
|
+
}, undefined, "relative cursor-cell select-none", unknown, unknown, undefined>>;
|
|
56
|
+
/**
|
|
57
|
+
* Поле правки внутри ячейки — `input`, `textarea` или редактируемый `div`.
|
|
58
|
+
*
|
|
59
|
+
* Прозрачный фон обязателен: заливку ячейка уже нарисовала своим состоянием, и собственный
|
|
60
|
+
* фон поля закрыл бы её. Снятый `outline` — по той же причине: рамку правки рисует ячейка
|
|
61
|
+
* (`state: "editing"`), а вторая обводка внутри первой выглядит браком.
|
|
62
|
+
*
|
|
63
|
+
* `multiline` возвращает выделение текста, снятое у ячейки ради протягивания мышью, и учит
|
|
64
|
+
* поле переносам: без `whitespace-pre-wrap` переносы в значении схлопнутся в пробелы,
|
|
65
|
+
* без `break-words` длинное слово растянет колонку.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* <input className={cellEditorStyles({ className: column.numeric ? "text-right" : undefined })} />
|
|
69
|
+
* <div contentEditable className={cellEditorStyles({ multiline: true })} />
|
|
70
|
+
*/
|
|
71
|
+
export declare const cellEditorStyles: TVReturnType<{
|
|
72
|
+
multiline: {
|
|
73
|
+
true: string;
|
|
74
|
+
};
|
|
75
|
+
}, undefined, "w-full bg-transparent outline-none", {
|
|
76
|
+
multiline: {
|
|
77
|
+
true: string;
|
|
78
|
+
};
|
|
79
|
+
}, undefined, TVReturnType<{
|
|
80
|
+
multiline: {
|
|
81
|
+
true: string;
|
|
82
|
+
};
|
|
83
|
+
}, undefined, "w-full bg-transparent outline-none", unknown, unknown, undefined>>;
|
|
84
|
+
/**
|
|
85
|
+
* Состояние ячейки — то, что она означает прямо сейчас.
|
|
86
|
+
*
|
|
87
|
+
* Выведено из самого `cellStateStyles`, поэтому список состояний в типе и в стилях
|
|
88
|
+
* не разъезжается.
|
|
89
|
+
*/
|
|
90
|
+
export type CellState = NonNullable<VariantProps<typeof cellStateStyles>["state"]>;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { cellStateStyles, cellEditorStyles, type CellState } from './editableCell';
|
|
2
|
+
export { cellRange, inCellRange, cellRangeEdges, cellRangeStyle, CELL_RANGE_EDGE, type CellRef, type CellRange, type CellRangeEdge } from './cellRange';
|
|
3
|
+
export { TableFillHandle, type TableFillHandleProps } from './TableFillHandle';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { C as a, T as s, a as t, b as c, d as n, e as E, c as g, i as R } from "../../TableFillHandle-C_yvCTSl.js";
|
|
2
|
+
export {
|
|
3
|
+
a as CELL_RANGE_EDGE,
|
|
4
|
+
s as TableFillHandle,
|
|
5
|
+
t as cellEditorStyles,
|
|
6
|
+
c as cellRange,
|
|
7
|
+
n as cellRangeEdges,
|
|
8
|
+
E as cellRangeStyle,
|
|
9
|
+
g as cellStateStyles,
|
|
10
|
+
R as inCellRange
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=editable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editable.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
|
|
@@ -1 +1,8 @@
|
|
|
1
|
-
export { Table, TableHeader, TableBody, TableBodyContainer, TableFooter, TableHead, TableRow, TableCell, TableCaption } from './Table';
|
|
1
|
+
export { Table, TableHeader, TableBody, TableBodyContainer, TableFooter, TableHead, TableRow, TableCell, TableCaption, TableResizeHandle, type TableProps, type TableHeaderProps, type TableFooterProps, type TableHeadProps, type TableRowProps, type TableResizeHandleProps } from './Table';
|
|
2
|
+
export { useColumnResize, getColumnAutoFitWidth, ColumnResizeSession, type ResizableColumn, type UseColumnResizeOptions, type UseColumnResizeResult, type ColumnAutoFitOptions } from './column-resize';
|
|
3
|
+
export { useColumnReorder, COLUMN_KEY_ATTRIBUTE, type UseColumnReorderOptions, type UseColumnReorderResult } from './column-reorder';
|
|
4
|
+
export { opaqueCellStyles } from './opaqueCell';
|
|
5
|
+
export { tableRowTints, TABLE_ROW_TINT, TABLE_ROW_TINT_LAYERS, TABLE_ROW_TINT_LAYERS_AFTER } from './rowTint';
|
|
6
|
+
export * from './tree';
|
|
7
|
+
export * from './editable';
|
|
8
|
+
export * from './sticky';
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { TVReturnType } from 'tailwind-variants';
|
|
2
|
+
/**
|
|
3
|
+
* Ячейка с непрозрачным фоном, сохраняющая подсветку строки.
|
|
4
|
+
*
|
|
5
|
+
* Нужна везде, где ячейка выезжает из потока и под ней оказывается чужое содержимое:
|
|
6
|
+
* закреплённая колонка (`stickyCellStyles`) и колонка, которую перетаскивают
|
|
7
|
+
* (`useColumnReorder`). Обе задачи одинаковые, поэтому рецепт один.
|
|
8
|
+
*
|
|
9
|
+
* **Почему фон нельзя просто задать.** Строка прозрачна — красит подложка секции
|
|
10
|
+
* (`TableBody`, `TableHeader`), и такой ячейке нужен свой непрозрачный фон. Но подменять
|
|
11
|
+
* им подсветку строки нельзя: `hover:bg-*` положил бы поверх полупрозрачный цвет, и чужое
|
|
12
|
+
* содержимое снова стало бы просвечивать. Поэтому подсветку рисует слой `::after` теми же
|
|
13
|
+
* переменными, что и сама строка, — заливкой (`--table-row-bg`, `--table-row-bg-hover`)
|
|
14
|
+
* и списком слоёв (`--table-row-tints`). Переменные наследуются от `tr` к ячейке сами,
|
|
15
|
+
* связывать их не нужно.
|
|
16
|
+
*
|
|
17
|
+
* Повторяются обе части: если рисовать только заливку, у закреплённой колонки пропадёт любая
|
|
18
|
+
* подкраска — и выделение, и деактивация, и что там ещё собрал потребитель.
|
|
19
|
+
*
|
|
20
|
+
* `transition-colors` совпадает с переходом у `TableRow`, поэтому строка подсвечивается
|
|
21
|
+
* целиком, а не двумя рывками. Разделители слой не задевает: `inset-0` у абсолютного
|
|
22
|
+
* потомка отсчитывается от padding-box, а границы лежат снаружи него.
|
|
23
|
+
*
|
|
24
|
+
* **Требует контекста позиционирования** — `sticky` у закреплённой ячейки, `relative`
|
|
25
|
+
* у перетаскиваемой: иначе `::after` растянется не по ячейке, а по ближайшему
|
|
26
|
+
* позиционированному предку.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* <TableCell className={opaqueCellStyles({ className: "relative" })}>…</TableCell>
|
|
30
|
+
* <TableHead className={opaqueCellStyles({ part: "head", className: "relative" })}>…</TableHead>
|
|
31
|
+
*/
|
|
32
|
+
export declare const opaqueCellStyles: TVReturnType<{
|
|
33
|
+
part: {
|
|
34
|
+
cell: string;
|
|
35
|
+
head: string;
|
|
36
|
+
};
|
|
37
|
+
}, undefined, string[], {
|
|
38
|
+
part: {
|
|
39
|
+
cell: string;
|
|
40
|
+
head: string;
|
|
41
|
+
};
|
|
42
|
+
}, undefined, TVReturnType<{
|
|
43
|
+
part: {
|
|
44
|
+
cell: string;
|
|
45
|
+
head: string;
|
|
46
|
+
};
|
|
47
|
+
}, undefined, string[], unknown, unknown, undefined>>;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Подкраска строки таблицы — стопка полупрозрачных слоёв поверх её заливки.
|
|
4
|
+
*
|
|
5
|
+
* **Когда нужно.** Когда состояний у строки больше одного. Заливка у строки одна
|
|
6
|
+
* (`background-color`), и второе состояние вытеснило бы первое: выделенная деактивированная
|
|
7
|
+
* строка выглядела бы просто выделенной. Слои же складываются альфами — и между собой,
|
|
8
|
+
* и с заливкой, какой бы она ни была, включая заданную вами `className="bg-…"`.
|
|
9
|
+
*
|
|
10
|
+
* **Почему это не пропсы строки.** `TableRow` не знает ни про «выделено», ни про «отключено»:
|
|
11
|
+
* что означает подсветка и когда её включать — знание прикладного кода. Кит даёт механизм
|
|
12
|
+
* (слои), готовые цвета (`TABLE_ROW_TINT`) и рисующие их классы; собирает их потребитель.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* <TableRow style={tableRowTints(isSelected && TABLE_ROW_TINT.selected, isInactive && TABLE_ROW_TINT.inactive)}>
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Готовые цвета подкрасок: `selected` — выделенная строка, `inactive` — деактивированная.
|
|
19
|
+
*
|
|
20
|
+
* Оба полупрозрачные, поэтому сочетаются и друг с другом, и с наведением: наведение красит
|
|
21
|
+
* заливку под слоями, и выделенная строка под курсором темнеет.
|
|
22
|
+
*
|
|
23
|
+
* Список открытый: свои состояния задавайте своими значениями, слоем годится любой
|
|
24
|
+
* полупрозрачный CSS-цвет.
|
|
25
|
+
*/
|
|
26
|
+
export declare const TABLE_ROW_TINT: {
|
|
27
|
+
readonly selected: "hsl(var(--alpha-high-05))";
|
|
28
|
+
readonly inactive: "hsl(var(--status-error) / 5%)";
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Слои подкраски для `style` строки. Первый аргумент — верхний слой, каждый следующий
|
|
32
|
+
* ложится под ним, под всеми — заливка строки.
|
|
33
|
+
*
|
|
34
|
+
* **Цвета должны быть полупрозрачными**, и следит за этим вызывающий код: значения уходят
|
|
35
|
+
* в `background-image` как есть. Непрозрачный цвет закроет всё, что под ним, — остальные
|
|
36
|
+
* слои и заливку вместе с наведением.
|
|
37
|
+
*
|
|
38
|
+
* Ложные значения отбрасываются, поэтому условия пишутся прямо в аргументах:
|
|
39
|
+
* `tableRowTints(isSelected && TABLE_ROW_TINT.selected)`. Без единого слоя строка красится
|
|
40
|
+
* одной заливкой.
|
|
41
|
+
*
|
|
42
|
+
* Результат — инлайновый стиль с CSS-переменной; она наследуется от `tr` к ячейкам, поэтому
|
|
43
|
+
* закреплённые и перетаскиваемые колонки подхватывают подкраску сами.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* <TableRow
|
|
47
|
+
* style={tableRowTints(
|
|
48
|
+
* isSelected && TABLE_ROW_TINT.selected,
|
|
49
|
+
* isOverdue && "hsl(var(--status-warning) / 12%)"
|
|
50
|
+
* )}
|
|
51
|
+
* >
|
|
52
|
+
*/
|
|
53
|
+
export declare const tableRowTints: (...tints: (string | false | null | undefined)[]) => CSSProperties;
|
|
54
|
+
/**
|
|
55
|
+
* Класс, рисующий слои подкраски на строке. Уже применён к `TableRow` — нужен, только если
|
|
56
|
+
* вы рисуете строку своим элементом.
|
|
57
|
+
*/
|
|
58
|
+
export declare const TABLE_ROW_TINT_LAYERS = "bg-[image:var(--table-row-tints,none)]";
|
|
59
|
+
/** То же самое для слоя `::after` непрозрачной ячейки — см. `opaqueCellStyles`. */
|
|
60
|
+
export declare const TABLE_ROW_TINT_LAYERS_AFTER = "after:bg-[image:var(--table-row-tints,none)]";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { stickyCellStyles, stickyOffset, STICKY_HEADER, STICKY_FOOTER } from './stickyCell';
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { TVReturnType } from 'tailwind-variants';
|
|
2
|
+
/**
|
|
3
|
+
* Классы прилипающей шапки — то, что подставляет проп `sticky` у `TableHeader`.
|
|
4
|
+
*
|
|
5
|
+
* Лежит здесь, рядом со `stickyCellStyles`, чтобы все `z-*` таблицы читались вместе.
|
|
6
|
+
* Порядок слоёв снизу вверх: обычная ячейка тела (без `z-index`), закреплённая ячейка
|
|
7
|
+
* тела (`z-10`), шапка и итоги (`z-20`), закреплённая ячейка шапки (`z-30` — она внутри
|
|
8
|
+
* стекинг-контекста шапки, поэтому спорит только с соседями по ней).
|
|
9
|
+
*
|
|
10
|
+
* Именно `z-20`, а не `z-10`: при равном `z-index` выигрывает то, что ниже по документу,
|
|
11
|
+
* и закреплённые ячейки тела заезжали бы поверх шапки. Без закреплённых колонок
|
|
12
|
+
* конкурентов нет, так что значение годится в обоих случаях и выбирать его
|
|
13
|
+
* потребителю не приходится.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* <TableHeader sticky> // штатный путь
|
|
17
|
+
* <thead className={STICKY_HEADER}> // своя шапка вместо TableHeader
|
|
18
|
+
*/
|
|
19
|
+
export declare const STICKY_HEADER = "sticky top-0 z-20";
|
|
20
|
+
/**
|
|
21
|
+
* Классы прилипающих итогов — то, что подставляет проп `sticky` у `TableFooter`.
|
|
22
|
+
*
|
|
23
|
+
* Слой тот же, что у шапки (`z-20`): спорить им не о чем, они по разные стороны тела, — а вот
|
|
24
|
+
* проезжающие под ними закреплённые ячейки (`z-10`) перекрывать обязаны обе.
|
|
25
|
+
*
|
|
26
|
+
* Непрозрачный фон итогам нужен даже без закреплённых колонок: под ними проходит тело.
|
|
27
|
+
* Он уже есть в `tableFooterStyles` (`bg-primary-bg`), отдельно задавать нечего.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* <TableFooter sticky> // штатный путь
|
|
31
|
+
* <tfoot className={STICKY_FOOTER}> // свои итоги вместо TableFooter
|
|
32
|
+
*/
|
|
33
|
+
export declare const STICKY_FOOTER = "sticky bottom-0 z-20";
|
|
34
|
+
/**
|
|
35
|
+
* Классы для закреплённой (примороженной по горизонтали) ячейки таблицы.
|
|
36
|
+
*
|
|
37
|
+
* Не компонент и не проп примитива, а именно набор классов: `left` всё равно задаёт
|
|
38
|
+
* потребитель, так что от компонента осталась бы одна обёртка. Применяется к `TableHead`
|
|
39
|
+
* или `TableCell` вместе с `left`.
|
|
40
|
+
*
|
|
41
|
+
* **`left` обязателен.** `position: sticky` без единого значения `left`/`right`/`top`/`bottom`
|
|
42
|
+
* не задаёт границы прилипания и ведёт себя как `position: relative`. У первой закреплённой
|
|
43
|
+
* колонки это константа (`left-0`), у следующих — сумма ширин предыдущих закреплённых,
|
|
44
|
+
* её считает `stickyOffset`.
|
|
45
|
+
*
|
|
46
|
+
* С границами делать ничего не нужно: таблица кита живёт в раздельной модели
|
|
47
|
+
* (`border-separate` у `Table`), где граница входит в бокс ячейки и уезжает вместе с ней —
|
|
48
|
+
* и правая у ячейки тела, и нижняя у ячейки шапки. В схлопнутой модели пришлось бы гасить
|
|
49
|
+
* `border-r` и рисовать линию inset-тенью: там граница принадлежит сетке таблицы и при
|
|
50
|
+
* прокрутке остаётся стоять на месте.
|
|
51
|
+
*
|
|
52
|
+
* Остаётся непрозрачный фон — без него под закреплённой ячейкой просвечивают уплывающие
|
|
53
|
+
* колонки, — и он берётся готовым из `opaqueCellStyles`: та же задача стоит перед колонкой,
|
|
54
|
+
* которую перетаскивают, поэтому фон и слой подсветки строки описаны один раз там.
|
|
55
|
+
* Здесь к ним добавляются только `sticky` и `z-index`.
|
|
56
|
+
*
|
|
57
|
+
* `table-layout: fixed` сам по себе не нужен: одна закреплённая колонка с `left-0` работает
|
|
58
|
+
* и при обычном автоматическом раскладе. Он требуется, только когда `left` вычисляется
|
|
59
|
+
* из объявленных ширин, — при `table-layout: auto` браузер считает ширины по содержимому,
|
|
60
|
+
* заданные значения игнорирует, и вычисленный `left` промахивается.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* <TableHead className={stickyCellStyles({ part: "head", className: "left-0" })}>Счёт</TableHead>
|
|
64
|
+
* <TableCell className={stickyCellStyles({ className: "left-0" })}>INV001</TableCell>
|
|
65
|
+
*
|
|
66
|
+
* // вторая и последующие закреплённые колонки
|
|
67
|
+
* <TableCell className={stickyCellStyles()} style={{ left: stickyOffset(pinnedWidths, index) }}>…</TableCell>
|
|
68
|
+
*/
|
|
69
|
+
export declare const stickyCellStyles: TVReturnType<{
|
|
70
|
+
part: {
|
|
71
|
+
cell: string;
|
|
72
|
+
head: string;
|
|
73
|
+
};
|
|
74
|
+
}, undefined, "sticky", {
|
|
75
|
+
part: {
|
|
76
|
+
cell: string;
|
|
77
|
+
head: string;
|
|
78
|
+
};
|
|
79
|
+
}, undefined, TVReturnType<{
|
|
80
|
+
part: {
|
|
81
|
+
cell: string;
|
|
82
|
+
head: string;
|
|
83
|
+
};
|
|
84
|
+
}, undefined, string[], {
|
|
85
|
+
part: {
|
|
86
|
+
cell: string;
|
|
87
|
+
head: string;
|
|
88
|
+
};
|
|
89
|
+
}, undefined, TVReturnType<{
|
|
90
|
+
part: {
|
|
91
|
+
cell: string;
|
|
92
|
+
head: string;
|
|
93
|
+
};
|
|
94
|
+
}, undefined, string[], unknown, unknown, undefined>>>;
|
|
95
|
+
/**
|
|
96
|
+
* Смещение слева для i-й закреплённой колонки — сумма ширин всех предыдущих.
|
|
97
|
+
*
|
|
98
|
+
* Ширины обязаны быть фиксированными: при `table-layout: auto` браузер их не соблюдает,
|
|
99
|
+
* и колонки наезжают друг на друга.
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* stickyOffset([120, 200, 90], 0); // 0
|
|
103
|
+
* stickyOffset([120, 200, 90], 2); // 320
|
|
104
|
+
*/
|
|
105
|
+
export declare const stickyOffset: (widths: number[], index: number) => number;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { T as c } from "../../index-BVqs-uqP.js";
|
|
2
|
+
import { o as l } from "../../opaqueCell-SGaiyL54.js";
|
|
3
|
+
const r = "sticky top-0 z-20", n = "sticky bottom-0 z-20", p = c({
|
|
4
|
+
extend: l,
|
|
5
|
+
base: "sticky",
|
|
6
|
+
variants: {
|
|
7
|
+
part: {
|
|
8
|
+
cell: "z-10",
|
|
9
|
+
head: "z-30"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
defaultVariants: {
|
|
13
|
+
part: "cell"
|
|
14
|
+
}
|
|
15
|
+
}), y = (t, e) => t.slice(0, e).reduce((s, o) => s + o, 0);
|
|
16
|
+
export {
|
|
17
|
+
n as STICKY_FOOTER,
|
|
18
|
+
r as STICKY_HEADER,
|
|
19
|
+
p as stickyCellStyles,
|
|
20
|
+
y as stickyOffset
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=sticky.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sticky.js","sources":["../../../src/components/table/sticky/stickyCell.ts"],"sourcesContent":["import { tv } from \"tailwind-variants\";\nimport { opaqueCellStyles } from \"../opaqueCell\";\n\n/**\n * Классы прилипающей шапки — то, что подставляет проп `sticky` у `TableHeader`.\n *\n * Лежит здесь, рядом со `stickyCellStyles`, чтобы все `z-*` таблицы читались вместе.\n * Порядок слоёв снизу вверх: обычная ячейка тела (без `z-index`), закреплённая ячейка\n * тела (`z-10`), шапка и итоги (`z-20`), закреплённая ячейка шапки (`z-30` — она внутри\n * стекинг-контекста шапки, поэтому спорит только с соседями по ней).\n *\n * Именно `z-20`, а не `z-10`: при равном `z-index` выигрывает то, что ниже по документу,\n * и закреплённые ячейки тела заезжали бы поверх шапки. Без закреплённых колонок\n * конкурентов нет, так что значение годится в обоих случаях и выбирать его\n * потребителю не приходится.\n *\n * @example\n * <TableHeader sticky> // штатный путь\n * <thead className={STICKY_HEADER}> // своя шапка вместо TableHeader\n */\nexport const STICKY_HEADER = \"sticky top-0 z-20\";\n\n/**\n * Классы прилипающих итогов — то, что подставляет проп `sticky` у `TableFooter`.\n *\n * Слой тот же, что у шапки (`z-20`): спорить им не о чем, они по разные стороны тела, — а вот\n * проезжающие под ними закреплённые ячейки (`z-10`) перекрывать обязаны обе.\n *\n * Непрозрачный фон итогам нужен даже без закреплённых колонок: под ними проходит тело.\n * Он уже есть в `tableFooterStyles` (`bg-primary-bg`), отдельно задавать нечего.\n *\n * @example\n * <TableFooter sticky> // штатный путь\n * <tfoot className={STICKY_FOOTER}> // свои итоги вместо TableFooter\n */\nexport const STICKY_FOOTER = \"sticky bottom-0 z-20\";\n\n/**\n * Классы для закреплённой (примороженной по горизонтали) ячейки таблицы.\n *\n * Не компонент и не проп примитива, а именно набор классов: `left` всё равно задаёт\n * потребитель, так что от компонента осталась бы одна обёртка. Применяется к `TableHead`\n * или `TableCell` вместе с `left`.\n *\n * **`left` обязателен.** `position: sticky` без единого значения `left`/`right`/`top`/`bottom`\n * не задаёт границы прилипания и ведёт себя как `position: relative`. У первой закреплённой\n * колонки это константа (`left-0`), у следующих — сумма ширин предыдущих закреплённых,\n * её считает `stickyOffset`.\n *\n * С границами делать ничего не нужно: таблица кита живёт в раздельной модели\n * (`border-separate` у `Table`), где граница входит в бокс ячейки и уезжает вместе с ней —\n * и правая у ячейки тела, и нижняя у ячейки шапки. В схлопнутой модели пришлось бы гасить\n * `border-r` и рисовать линию inset-тенью: там граница принадлежит сетке таблицы и при\n * прокрутке остаётся стоять на месте.\n *\n * Остаётся непрозрачный фон — без него под закреплённой ячейкой просвечивают уплывающие\n * колонки, — и он берётся готовым из `opaqueCellStyles`: та же задача стоит перед колонкой,\n * которую перетаскивают, поэтому фон и слой подсветки строки описаны один раз там.\n * Здесь к ним добавляются только `sticky` и `z-index`.\n *\n * `table-layout: fixed` сам по себе не нужен: одна закреплённая колонка с `left-0` работает\n * и при обычном автоматическом раскладе. Он требуется, только когда `left` вычисляется\n * из объявленных ширин, — при `table-layout: auto` браузер считает ширины по содержимому,\n * заданные значения игнорирует, и вычисленный `left` промахивается.\n *\n * @example\n * <TableHead className={stickyCellStyles({ part: \"head\", className: \"left-0\" })}>Счёт</TableHead>\n * <TableCell className={stickyCellStyles({ className: \"left-0\" })}>INV001</TableCell>\n *\n * // вторая и последующие закреплённые колонки\n * <TableCell className={stickyCellStyles()} style={{ left: stickyOffset(pinnedWidths, index) }}>…</TableCell>\n */\nexport const stickyCellStyles = tv({\n\textend: opaqueCellStyles,\n\tbase: \"sticky\",\n\tvariants: {\n\t\tpart: {\n\t\t\tcell: \"z-10\",\n\t\t\thead: \"z-30\"\n\t\t}\n\t},\n\tdefaultVariants: {\n\t\tpart: \"cell\"\n\t}\n});\n\n/**\n * Смещение слева для i-й закреплённой колонки — сумма ширин всех предыдущих.\n *\n * Ширины обязаны быть фиксированными: при `table-layout: auto` браузер их не соблюдает,\n * и колонки наезжают друг на друга.\n *\n * @example\n * stickyOffset([120, 200, 90], 0); // 0\n * stickyOffset([120, 200, 90], 2); // 320\n */\nexport const stickyOffset = (widths: number[], index: number) =>\n\twidths.slice(0, index).reduce((sum, width) => sum + width, 0);\n"],"names":["STICKY_HEADER","STICKY_FOOTER","stickyCellStyles","tv","opaqueCellStyles","stickyOffset","widths","index","sum","width"],"mappings":";;AAoBO,MAAMA,IAAgB,qBAehBC,IAAgB,wBAqChBC,IAAmBC,EAAG;AAAA,EAClC,QAAQC;AAAA,EACR,MAAM;AAAA,EACN,UAAU;AAAA,IACT,MAAM;AAAA,MACL,MAAM;AAAA,MACN,MAAM;AAAA,IAAA;AAAA,EAER;AAAA,EACA,iBAAiB;AAAA,IAChB,MAAM;AAAA,EAAA;AAER,CAAC,GAYYC,IAAe,CAACC,GAAkBC,MAC9CD,EAAO,MAAM,GAAGC,CAAK,EAAE,OAAO,CAACC,GAAKC,MAAUD,IAAMC,GAAO,CAAC;"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Данные для стори таблицы. Вынесены из `Table.stories.tsx`, чтобы в самих стори
|
|
3
|
+
* оставалась только разметка и было видно, что именно демонстрирует пример.
|
|
4
|
+
*
|
|
5
|
+
* Не совпадает с glob'ом Storybook (`*.stories.@(ts|tsx)`), поэтому как стори не подхватывается.
|
|
6
|
+
*/
|
|
7
|
+
export type ProductRow = {
|
|
8
|
+
id: number;
|
|
9
|
+
name: string;
|
|
10
|
+
category: string;
|
|
11
|
+
price: string;
|
|
12
|
+
stock: number;
|
|
13
|
+
zone: string;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Достаточно строк, чтобы контейнер реально прокручивался по вертикали.
|
|
17
|
+
* `zone` — под заголовок «Warehouse Zone»: два слова без принудительного `nowrap`,
|
|
18
|
+
* поэтому при сужении контейнера они переносятся и шапка растёт по высоте.
|
|
19
|
+
*/
|
|
20
|
+
export declare const PRODUCT_ROWS: ProductRow[];
|
|
21
|
+
export type AccessRow = {
|
|
22
|
+
login: string;
|
|
23
|
+
name: string;
|
|
24
|
+
email: string;
|
|
25
|
+
type: string;
|
|
26
|
+
module: string;
|
|
27
|
+
activity: string;
|
|
28
|
+
};
|
|
29
|
+
/** Реконструкция макета «Пользователи» из Figma (UIK Data Table). */
|
|
30
|
+
export declare const ACCESS_ROWS: AccessRow[];
|
|
31
|
+
export type DistributorRow = {
|
|
32
|
+
id: string;
|
|
33
|
+
distributor: string;
|
|
34
|
+
region: string;
|
|
35
|
+
/** Длинный текст — нужен, чтобы в примере с ресайзом был многострочный контент. */
|
|
36
|
+
terms: string;
|
|
37
|
+
manager: string;
|
|
38
|
+
units: number;
|
|
39
|
+
revenue: number;
|
|
40
|
+
growth: number;
|
|
41
|
+
};
|
|
42
|
+
export declare const DISTRIBUTOR_ROWS: DistributorRow[];
|
|
43
|
+
export type EditableRow = {
|
|
44
|
+
id: string;
|
|
45
|
+
distributor: string;
|
|
46
|
+
region: string;
|
|
47
|
+
manager: string;
|
|
48
|
+
plan: number;
|
|
49
|
+
fact: number;
|
|
50
|
+
/** Многострочный текст: переносы значимы и должны переживать правку. */
|
|
51
|
+
comment: string;
|
|
52
|
+
};
|
|
53
|
+
/** Данные для стори инлайн-редактирования. */
|
|
54
|
+
export declare const EDITABLE_ROWS: EditableRow[];
|
|
55
|
+
export type TreeNode = {
|
|
56
|
+
id: string;
|
|
57
|
+
name: string;
|
|
58
|
+
/** Что демонстрирует строка — выводится отдельной колонкой. */
|
|
59
|
+
note?: string;
|
|
60
|
+
children?: TreeNode[];
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Дерево для стори иерархии.
|
|
64
|
+
*
|
|
65
|
+
* Названия намеренно безликие: «Раздел 1.1.2» читается как позиция в дереве, поэтому
|
|
66
|
+
* достаточно взглянуть на строку, чтобы понять, правильные ли линии слева от неё.
|
|
67
|
+
*
|
|
68
|
+
* Набор узлов подобран под разбор случаев, а не под правдоподобие: тут есть последние
|
|
69
|
+
* потомки на каждом уровне, ветка глубиной пять, свёрнутый узел, лист на верхнем уровне,
|
|
70
|
+
* единственный потомок, перенос длинного текста и — главное — глубокая ветка, за которой
|
|
71
|
+
* идёт соседний узел мелкого уровня. Именно на последнем случае ломались прежние версии:
|
|
72
|
+
* сквозная вертикаль либо не доходила до соседа, либо протекала мимо уголка.
|
|
73
|
+
*/
|
|
74
|
+
export declare const NAV_TREE: TreeNode[];
|
|
75
|
+
export type MetricRow = {
|
|
76
|
+
id: string;
|
|
77
|
+
account: string;
|
|
78
|
+
manager: string;
|
|
79
|
+
values: number[];
|
|
80
|
+
};
|
|
81
|
+
/** Заголовки для стори со sticky-колонками: месяцы, при необходимости с номером года. */
|
|
82
|
+
export declare function buildMetricColumns(count: number): string[];
|
|
83
|
+
/** Детерминированные значения — чтобы снапшоты стори не плыли между рендерами. */
|
|
84
|
+
export declare const METRIC_ROWS: MetricRow[];
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { CellRef } from './editable';
|
|
2
|
+
export type SortDirection = "asc" | "desc";
|
|
3
|
+
/** Состояние фильтра одной колонки. */
|
|
4
|
+
export type ColumnFilter = {
|
|
5
|
+
/** Подстрока быстрого поиска. */
|
|
6
|
+
query: string;
|
|
7
|
+
/** Значения, с которых снята галочка. Пустое множество — выбрано всё. */
|
|
8
|
+
excluded: Set<string>;
|
|
9
|
+
};
|
|
10
|
+
export declare const EMPTY_FILTER: ColumnFilter;
|
|
11
|
+
/** Уникальные значения колонки в алфавитном порядке — из них строится список галочек. */
|
|
12
|
+
export declare const uniqueValues: (values: string[]) => string[];
|
|
13
|
+
/** Проходит ли значение фильтр колонки: и подстроку быстрого поиска, и снятые галочки. */
|
|
14
|
+
export declare const matchesColumnFilter: (value: string, filter: ColumnFilter | undefined) => boolean;
|
|
15
|
+
/** Применены ли к колонке хоть какие-то условия — от этого зависит значок воронки. */
|
|
16
|
+
export declare const isFilterActive: (filter: ColumnFilter) => boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Заголовок-триггер колоночного меню: подпись, значки применённых условий и само меню.
|
|
19
|
+
*
|
|
20
|
+
* Кликабельная зона — не сам `th`, а растянутая по нему кнопка, и это не формальность:
|
|
21
|
+
*
|
|
22
|
+
* - `th` не держит фокус, а вешать на него `tabIndex` — самодеятельность; кнопка внутри
|
|
23
|
+
* заголовка это и есть предписанный WAI-ARIA APG способ сделать колонку интерактивной;
|
|
24
|
+
* - другие интерактивные элементы шапки (`TableResizeHandle`, грип перетаскивания, чекбокс
|
|
25
|
+
* «выбрать всё») кладутся в `th` **соседями** кнопки, а не внутрь неё. Будь триггером сам
|
|
26
|
+
* `th`, любой клик по ним всплывал бы в меню; здесь всплывать некуда — кнопка им не предок.
|
|
27
|
+
*
|
|
28
|
+
* Ячейку под неё нужно перевести в `TableHead interactive`: этот вариант отдаёт кнопке свой
|
|
29
|
+
* паддинг, иначе кликабельной будет не вся ячейка, а только её середина.
|
|
30
|
+
*
|
|
31
|
+
* Значки сортировки и фильтра в макете не нарисованы — там показано состояние без наложенных
|
|
32
|
+
* условий. Добавлены по индустриальному стандарту (MUI X, Ignite UI, DevExpress): без них
|
|
33
|
+
* применённые к колонке сортировка и фильтр никак не видны, когда меню закрыто.
|
|
34
|
+
*/
|
|
35
|
+
export declare function ColumnHeaderMenu({ header, values, filter, sortDirection, onSortChange, onFilterChange, onReset, className }: {
|
|
36
|
+
header: string;
|
|
37
|
+
values: string[];
|
|
38
|
+
filter: ColumnFilter;
|
|
39
|
+
sortDirection: SortDirection | null;
|
|
40
|
+
onSortChange: (direction: SortDirection) => void;
|
|
41
|
+
onFilterChange: (next: ColumnFilter) => void;
|
|
42
|
+
onReset: () => void;
|
|
43
|
+
/** Правка паддинга, когда в ячейке рядом с кнопкой стоит ещё и грип перетаскивания. */
|
|
44
|
+
className?: string;
|
|
45
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
46
|
+
/**
|
|
47
|
+
* Состояние открытого редактора.
|
|
48
|
+
*
|
|
49
|
+
* `full` — различие Excel между «полным» редактированием (F2, двойной клик) и «быстрым»
|
|
50
|
+
* (пользователь начал печатать поверх ячейки). В полном стрелки двигают каретку внутри поля,
|
|
51
|
+
* в быстром — сохраняют значение и переводят активную ячейку. Без этого флага одна и та же
|
|
52
|
+
* клавиша не может означать разное, и приходится выбирать между удобной навигацией
|
|
53
|
+
* и правкой текста. Так же устроен инлайн в MDT (`fullEdit` в `inline/scripts/ui-bindings.ts`).
|
|
54
|
+
*/
|
|
55
|
+
export type EditState = CellRef & {
|
|
56
|
+
full: boolean;
|
|
57
|
+
/** Начальное значение. У быстрого редактирования — набранный символ, он же затирает старое. */
|
|
58
|
+
seed?: string;
|
|
59
|
+
/** `clientX` двойного клика: куда поставить каретку при открытии. */
|
|
60
|
+
caretX?: number;
|
|
61
|
+
/** `clientY` двойного клика. Нужен только многострочной ячейке — в одну строку хватает `caretX`. */
|
|
62
|
+
caretY?: number;
|
|
63
|
+
};
|
|
64
|
+
/** Смещения активной ячейки для стрелок. */
|
|
65
|
+
export declare const ARROW_DELTA: Record<string, [row: number, col: number]>;
|
|
66
|
+
export declare const clampIndex: (value: number, max: number) => number;
|
|
67
|
+
/**
|
|
68
|
+
* Ключ ячейки. Части соединяются двоеточием и годятся любые: пара индексов для таблицы
|
|
69
|
+
* с неизменным порядком строк, пара «id строки + ключ колонки» — для таблицы с сортировкой
|
|
70
|
+
* и фильтрами, где индекс перестаёт указывать на ту же ячейку после каждого действия.
|
|
71
|
+
*/
|
|
72
|
+
export declare const cellId: (row: string | number, col: string | number) => string;
|