@synopackageland/ui 0.20.3 → 0.20.4

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.
Files changed (146) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/LICENSES/ux-foundation.md +83 -0
  3. package/LICENSES/ux-grid-baserow.md +35 -0
  4. package/LICENSES/ux-grid-teable.md +48 -0
  5. package/README.md +3 -0
  6. package/dist/cli.js +0 -0
  7. package/dist/components/app/app-layout/AppLayout.vue.d.ts +31 -4
  8. package/dist/components/app/app-root/AppRoot.vue.d.ts +9 -0
  9. package/dist/components/app/aside-panel/AsidePanel.vue.d.ts +69 -0
  10. package/dist/components/app/aside-panel/asidePreference.d.ts +28 -0
  11. package/dist/components/composite/adaptive-panel/AdaptivePanel.vue.d.ts +61 -0
  12. package/dist/components/composite/connection-topology/ConnectionTopology.vue.d.ts +1 -1
  13. package/dist/components/composite/file-picker/FilePicker.vue.d.ts +1 -1
  14. package/dist/components/composite/mention-list/MentionList.vue.d.ts +2 -2
  15. package/dist/components/composite/overflow-toolbar/OverflowToolbar.vue.d.ts +2 -2
  16. package/dist/components/composite/record-panel/RecordPanel.vue.d.ts +77 -0
  17. package/dist/components/composite/record-panel/recordPanelWidth.d.ts +54 -0
  18. package/dist/components/composite/summary-card/SummaryCard.vue.d.ts +1 -1
  19. package/dist/components/composite/tag-editor/TagEditor.vue.d.ts +2 -2
  20. package/dist/components/composite/tree-view/TreeView.vue.d.ts +1 -1
  21. package/dist/components/composite/wizard/Wizard.vue.d.ts +2 -2
  22. package/dist/components/composite/wizard/WizardDialog.vue.d.ts +2 -2
  23. package/dist/components/containers/card/Card.vue.d.ts +1 -1
  24. package/dist/components/containers/card/CardField.vue.d.ts +26 -0
  25. package/dist/components/containers/card-grid/CardCover.vue.d.ts +16 -0
  26. package/dist/components/containers/card-grid/CardGrid.vue.d.ts +1 -1
  27. package/dist/components/containers/card-grid/VirtualCardGrid.vue.d.ts +71 -0
  28. package/dist/components/containers/expandable-item/ExpandableItem.vue.d.ts +1 -1
  29. package/dist/components/containers/fieldset/Fieldset.vue.d.ts +1 -1
  30. package/dist/components/containers/list-detail/ListDetail.vue.d.ts +1 -1
  31. package/dist/components/containers/split-pane/SplitPane.vue.d.ts +1 -1
  32. package/dist/components/feedback/notification/Notification.vue.d.ts +1 -1
  33. package/dist/components/feedback/notification/NotificationProvider.vue.d.ts +1 -1
  34. package/dist/components/primitives/breadcrumb/Breadcrumb.vue.d.ts +2 -2
  35. package/dist/components/primitives/context-menu/ContextMenu.vue.d.ts +3 -0
  36. package/dist/components/primitives/context-menu/ContextMenuItems.vue.d.ts +4 -5
  37. package/dist/components/primitives/dialog/Dialog.vue.d.ts +2 -2
  38. package/dist/components/primitives/dropdown-menu/DropdownMenu.vue.d.ts +4 -0
  39. package/dist/components/primitives/dropdown-menu/DropdownMenuItems.vue.d.ts +6 -3
  40. package/dist/components/primitives/popover/Popover.vue.d.ts +10 -2
  41. package/dist/components/primitives/popover/floating.d.ts +27 -0
  42. package/dist/components/primitives/popover/overlay.d.ts +36 -0
  43. package/dist/components/primitives/segment-control/SegmentControl.vue.d.ts +4 -1
  44. package/dist/components/primitives/segment-control/context.d.ts +3 -0
  45. package/dist/components/primitives/select/Select.vue.d.ts +4 -0
  46. package/dist/components/primitives/select/internal/ComboboxField.vue.d.ts +1 -0
  47. package/dist/components/primitives/select/internal/types.d.ts +2 -0
  48. package/dist/components/primitives/skeleton/SectionSkeleton.vue.d.ts +25 -4
  49. package/dist/components/primitives/skeleton/Skeleton.vue.d.ts +3 -0
  50. package/dist/components/primitives/tag/Tag.vue.d.ts +2 -2
  51. package/dist/components/primitives/toast/ToastProvider.vue.d.ts +0 -2
  52. package/dist/components/primitives/toast/toast.d.ts +21 -1
  53. package/dist/components/primitives/tooltip/Tooltip.vue.d.ts +8 -3
  54. package/dist/components/primitives/tooltip/tooltipStyle.d.ts +11 -1
  55. package/dist/composables/backDismiss.d.ts +19 -0
  56. package/dist/composables/phone.d.ts +8 -0
  57. package/dist/composables/softKeyboard.d.ts +26 -4
  58. package/dist/composables/visualViewport.d.ts +31 -0
  59. package/dist/dnd/autoScroll.d.ts +57 -0
  60. package/dist/dnd/dragKit.d.ts +111 -0
  61. package/dist/dnd/index.d.ts +4 -0
  62. package/dist/dnd/layout.d.ts +57 -0
  63. package/dist/dnd/vue.d.ts +16 -0
  64. package/dist/feedback/StatusSlot.vue.d.ts +24 -0
  65. package/dist/feedback/showAfter.d.ts +15 -0
  66. package/dist/feedback/stackMotion.d.ts +13 -0
  67. package/dist/feedback/timing.d.ts +23 -0
  68. package/dist/grid/cells/draw.d.ts +57 -0
  69. package/dist/grid/cells/images.d.ts +5 -0
  70. package/dist/grid/cells/index.d.ts +7 -0
  71. package/dist/grid/cells/number.d.ts +5 -0
  72. package/dist/grid/cells/registry.d.ts +56 -0
  73. package/dist/grid/cells/renderers.d.ts +8 -0
  74. package/dist/grid/cells/status.d.ts +6 -0
  75. package/dist/grid/cells/types.d.ts +200 -0
  76. package/dist/grid/cells/use.d.ts +7 -0
  77. package/dist/grid/clipboard/copy.d.ts +17 -0
  78. package/dist/grid/clipboard/index.d.ts +4 -0
  79. package/dist/grid/clipboard/proposal.d.ts +35 -0
  80. package/dist/grid/clipboard/tsv.d.ts +14 -0
  81. package/dist/grid/clipboard/write.d.ts +21 -0
  82. package/dist/grid/contracts.d.ts +200 -0
  83. package/dist/grid/edit/cell-status.d.ts +33 -0
  84. package/dist/grid/edit/edit-session.d.ts +97 -0
  85. package/dist/grid/edit/use-grid-edit.d.ts +48 -0
  86. package/dist/grid/focus/editor-style.d.ts +67 -0
  87. package/dist/grid/host/GridHost.vue.d.ts +137 -0
  88. package/dist/grid/host/controller.d.ts +219 -0
  89. package/dist/grid/host/dom.d.ts +10 -0
  90. package/dist/grid/index.d.ts +8 -0
  91. package/dist/grid/range/block.d.ts +30 -0
  92. package/dist/grid/range/fill.d.ts +27 -0
  93. package/dist/grid/range/index.d.ts +2 -0
  94. package/dist/grid/theme.d.ts +61 -0
  95. package/dist/grid-core/auto-scroll.d.ts +67 -0
  96. package/dist/grid-core/column-resize.d.ts +43 -0
  97. package/dist/grid-core/config.d.ts +39 -0
  98. package/dist/grid-core/coordinate.d.ts +64 -0
  99. package/dist/grid-core/drag.d.ts +46 -0
  100. package/dist/grid-core/freeze.d.ts +11 -0
  101. package/dist/grid-core/index.d.ts +17 -0
  102. package/dist/grid-core/keyboard.d.ts +34 -0
  103. package/dist/grid-core/keys.d.ts +38 -0
  104. package/dist/grid-core/lru.d.ts +10 -0
  105. package/dist/grid-core/range.d.ts +28 -0
  106. package/dist/grid-core/region.d.ts +73 -0
  107. package/dist/grid-core/renderer/base.d.ts +92 -0
  108. package/dist/grid-core/renderer/layout.d.ts +129 -0
  109. package/dist/grid-core/selection-controller.d.ts +62 -0
  110. package/dist/grid-core/selection.d.ts +35 -0
  111. package/dist/grid-core/theme.d.ts +81 -0
  112. package/dist/grid-core/types.d.ts +178 -0
  113. package/dist/grid.js +6173 -0
  114. package/dist/i18n/text.d.ts +6 -0
  115. package/dist/index.d.ts +32 -2
  116. package/dist/index.js +17647 -13630
  117. package/dist/interaction/editSession.d.ts +49 -0
  118. package/dist/interaction/focus.d.ts +28 -0
  119. package/dist/interaction/gesture.d.ts +49 -0
  120. package/dist/interaction/ime.d.ts +55 -0
  121. package/dist/interaction/index.d.ts +6 -0
  122. package/dist/interaction/outside.d.ts +40 -0
  123. package/dist/interaction/vue.d.ts +21 -0
  124. package/dist/json-ai-prompt.md +1 -1
  125. package/dist/json-preview/preview.js +8523 -7814
  126. package/dist/json.js +10 -10
  127. package/dist/lib/adaptiveLayout.d.ts +32 -2
  128. package/dist/lib/deviceViewport.d.ts +2 -1
  129. package/dist/lib/motion.d.ts +12 -0
  130. package/dist/reka-runtime.json +1 -1
  131. package/dist/theme.css +1 -1
  132. package/dist/themes/dsm7-embedded-theme.css +1 -1
  133. package/dist/themes/dsm7-embedded.css +1 -1
  134. package/dist/themes/dsm7.css +1 -1
  135. package/dist/virtual/cardHeight.d.ts +39 -0
  136. package/dist/virtual/galleryColumns.d.ts +11 -0
  137. package/dist/virtual/layoutMotion.d.ts +30 -0
  138. package/docs/adaptive-layout.md +137 -16
  139. package/docs/callout.md +22 -1
  140. package/docs/list-detail.md +54 -0
  141. package/docs/mobile-native.md +214 -0
  142. package/docs/release-checks.md +23 -0
  143. package/docs/theme-hooks.md +28 -7
  144. package/docs/ux-foundation.md +133 -0
  145. package/docs/ux-grid.md +217 -0
  146. package/package.json +94 -3
@@ -0,0 +1,56 @@
1
+ import { GridCell, GridCellRenderer, GridCellTextGetter, GridHostExpose, GridRect } from '../contracts';
2
+ import { GridCellTheme } from '../theme';
3
+ import { GridCellAction, GridCellHit, GridCellKind, GridCellKindRenderer, GridCellLabels, GridCellStatus, GridCellValue } from './types';
4
+ export interface GridCellsOptions {
5
+ /** The value to draw for a cell; null or undefined draws nothing. */
6
+ getValue: (cell: GridCell) => GridCellValue | null | undefined;
7
+ /** Saving dot or failed mark for a cell. */
8
+ getStatus?: (cell: GridCell) => GridCellStatus | null | undefined;
9
+ /** Blocks `update` actions (a read-only column, record or grid). */
10
+ isReadonly?: (cell: GridCell) => boolean;
11
+ /** Translated words for the accessible text (`useGridCells` fills them). */
12
+ labels: GridCellLabels;
13
+ /** BCP 47 locale for number grouping. Default `en-US`. */
14
+ locale?: string;
15
+ /** Element whose tokens give the colours, re-read whenever the host's theme changes (usually the grid's wrapper). */
16
+ themeRoot?: () => Element | null | undefined;
17
+ /** Fixed colours instead of `themeRoot` (tests, previews). */
18
+ theme?: GridCellTheme;
19
+ /** Called once per batch of loaded avatars/thumbnails; pass the host's `invalidate`. */
20
+ onImageLoad?: () => void;
21
+ /** Replace or add renderers per kind. */
22
+ renderers?: Partial<{
23
+ [K in GridCellKind]: GridCellKindRenderer<Extract<GridCellValue, {
24
+ kind: K;
25
+ }>>;
26
+ }>;
27
+ }
28
+ export interface GridCells {
29
+ /** One renderer for every column: `:cell-renderer="cells.cellRenderer"`. */
30
+ renderer: GridCellRenderer;
31
+ cellRenderer: () => GridCellRenderer;
32
+ /** Plain text of a cell, for `:get-cell-text` (assistive tech and the focus owner). */
33
+ getCellText: GridCellTextGetter;
34
+ /** Target under a point in cell coordinates. */
35
+ hitTest: (cell: GridCell, point: {
36
+ x: number;
37
+ y: number;
38
+ }, rect: Pick<GridRect, 'width' | 'height'>, wasActive: boolean) => GridCellHit | null;
39
+ /** Keyboard equivalent on the active cell (Enter / Space toggles a checkbox, digits rate, Backspace clears a rating). */
40
+ keyAction: (cell: GridCell, key: string) => GridCellAction | null;
41
+ /**
42
+ * Handlers for an element wrapping `<GridHost>` that turn a click into a
43
+ * first-click action: the host selects the cell on pointerdown, the click
44
+ * then hits the area under the pointer. Bind `onPointerdown` in the capture
45
+ * phase (`@pointerdown.capture`).
46
+ */
47
+ clickHandlers: (host: () => GridHostExpose | null | undefined, onAction: (action: GridCellAction, cell: GridCell) => void) => {
48
+ onPointerdown: (event: PointerEvent) => void;
49
+ onClick: (event: MouseEvent) => void;
50
+ };
51
+ setLabels: (labels: GridCellLabels) => void;
52
+ setTheme: (theme: GridCellTheme) => void;
53
+ /** Drops loaded images. */
54
+ clearImages: () => void;
55
+ }
56
+ export declare const createGridCells: (options: GridCellsOptions) => GridCells;
@@ -0,0 +1,8 @@
1
+ import { GridCellKind, GridCellKindRenderer, GridCellValueOf } from './types';
2
+ type R<K extends GridCellKind> = GridCellKindRenderer<GridCellValueOf<K>>;
3
+ export declare const defaultGridCellRenderers: {
4
+ [K in GridCellKind]: R<K>;
5
+ };
6
+ /** Clears the hit regions remembered from earlier draws (tests, or after a font change). */
7
+ export declare const clearGridCellRegions: () => void;
8
+ export {};
@@ -0,0 +1,6 @@
1
+ import { GridRect } from '../contracts';
2
+ import { GridCellTheme } from '../theme';
3
+ import { GridCellStatus } from './types';
4
+ export declare const PENDING_DOT = 6;
5
+ /** 6 px dot 3 px in from the top-right corner, ringed with the surface colour; or a 2 px danger inset. */
6
+ export declare const drawGridCellStatus: (ctx: CanvasRenderingContext2D, rect: GridRect, status: GridCellStatus, theme: GridCellTheme) => void;
@@ -0,0 +1,200 @@
1
+ import { GridCellDrawArgs, GridRect } from '../contracts';
2
+ import { GridCellTheme } from '../theme';
3
+ /** Colour family of a chip: `--ui-{tone}-soft` / `--ui-{tone}-text`; scale names alias the matching tone. */
4
+ export type GridChipTone = 'neutral' | 'info' | 'success' | 'warning' | 'danger' | 'blue' | 'green' | 'orange' | 'red' | 'gray';
5
+ export interface GridChip {
6
+ label: string;
7
+ tone?: GridChipTone;
8
+ /** Explicit colours win over `tone` (for example a select option's own colour). */
9
+ fill?: string;
10
+ color?: string;
11
+ }
12
+ export interface GridPerson {
13
+ name: string;
14
+ /** Loaded once and drawn when ready; initials until then and on failure. */
15
+ avatarUrl?: string;
16
+ }
17
+ export interface GridRecordLink {
18
+ id: string;
19
+ label: string;
20
+ }
21
+ export interface GridAttachment {
22
+ id: string;
23
+ name: string;
24
+ /** Image thumbnail; files without one draw an extension badge. */
25
+ thumbnailUrl?: string;
26
+ }
27
+ /** Teable's number formatting (packages/core, MIT). */
28
+ export type GridNumberFormat = {
29
+ type: 'decimal';
30
+ precision?: number;
31
+ } | {
32
+ type: 'percent';
33
+ precision?: number;
34
+ } | {
35
+ type: 'currency';
36
+ precision?: number;
37
+ symbol?: string;
38
+ };
39
+ interface GridCellValueBase {
40
+ /** No first-click actions (checkbox, rating). Links and buttons still act. */
41
+ readonly?: boolean;
42
+ }
43
+ export type GridCellValue = GridCellValueBase & ({
44
+ kind: 'text';
45
+ text: string;
46
+ }
47
+ /** Multi-line text: one line in the row, newlines shown as spaces. */
48
+ | {
49
+ kind: 'longText';
50
+ text: string;
51
+ }
52
+ /** Right aligned. `text` overrides the formatted value. */
53
+ | {
54
+ kind: 'number';
55
+ value: number | null;
56
+ format?: GridNumberFormat;
57
+ text?: string;
58
+ }
59
+ /** Single or multiple select; chips in order. */
60
+ | {
61
+ kind: 'select';
62
+ options: GridChip[];
63
+ } | {
64
+ kind: 'person';
65
+ people: GridPerson[];
66
+ }
67
+ /** Already formatted for the viewer's locale and the field's format. */
68
+ | {
69
+ kind: 'date';
70
+ text: string;
71
+ } | {
72
+ kind: 'boolean';
73
+ value: boolean;
74
+ }
75
+ /** `value` 0 (empty) to `max` (default 5). */
76
+ | {
77
+ kind: 'rating';
78
+ value: number;
79
+ max?: number;
80
+ }
81
+ /** URL, email or phone: text with a link icon that opens on the first click. */
82
+ | {
83
+ kind: 'url';
84
+ text: string;
85
+ href: string;
86
+ }
87
+ /** Linked records as chips. */
88
+ | {
89
+ kind: 'link';
90
+ records: GridRecordLink[];
91
+ } | {
92
+ kind: 'attachment';
93
+ files: GridAttachment[];
94
+ }
95
+ /** Completion ring plus percentage; `value` from 0 to 1. */
96
+ | {
97
+ kind: 'progress';
98
+ value: number | null;
99
+ } | {
100
+ kind: 'button';
101
+ label: string;
102
+ disabled?: boolean;
103
+ }
104
+ /** Formula, lookup, rollup, created/modified: read-only text in the muted colour. */
105
+ | {
106
+ kind: 'derived';
107
+ text: string;
108
+ align?: 'start' | 'end';
109
+ });
110
+ export type GridCellKind = GridCellValue['kind'];
111
+ export type GridCellValueOf<K extends GridCellKind> = Extract<GridCellValue, {
112
+ kind: K;
113
+ }>;
114
+ /** Saving dot or failed mark drawn over the cell without changing its box. */
115
+ export type GridCellStatus = 'pending' | 'error';
116
+ /**
117
+ * What a hit area or key asks the caller to do. The renderers never write:
118
+ * `update` carries the new value (`null` clears) for the caller's optimistic write.
119
+ */
120
+ export type GridCellAction = {
121
+ type: 'update';
122
+ value: boolean | number | null;
123
+ } | {
124
+ type: 'open-url';
125
+ href: string;
126
+ } | {
127
+ type: 'open-record';
128
+ id: string;
129
+ } | {
130
+ type: 'open-attachment';
131
+ id: string;
132
+ } | {
133
+ type: 'press';
134
+ };
135
+ export interface GridCellHit {
136
+ action: GridCellAction;
137
+ /** The hit area in cell coordinates (0, 0 = the cell's top-left). */
138
+ area: GridRect;
139
+ }
140
+ /** Translated words the accessible text needs; `useGridCells` fills them from the UI locale. */
141
+ export interface GridCellLabels {
142
+ checked: string;
143
+ unchecked: string;
144
+ /** `{value}` and `{max}` placeholders. */
145
+ rating: string;
146
+ saving: string;
147
+ failed: string;
148
+ }
149
+ /** Sizes that follow the row height, so the same cell reads at every density. */
150
+ export interface GridCellMetrics {
151
+ rowHeight: number;
152
+ padding: number;
153
+ /** Chip and avatar height. */
154
+ chip: number;
155
+ /** Checkbox, star and link-icon size. */
156
+ icon: number;
157
+ fontSize: number;
158
+ chipFontSize: number;
159
+ }
160
+ /** What `describe` gets besides the value. */
161
+ export interface GridCellTextContext {
162
+ labels: GridCellLabels;
163
+ /** BCP 47 locale for number grouping. */
164
+ locale: string;
165
+ }
166
+ export interface GridCellPaintArgs extends GridCellDrawArgs, GridCellTextContext {
167
+ cellTheme: GridCellTheme;
168
+ metrics: GridCellMetrics;
169
+ images: GridImageSource;
170
+ }
171
+ /** Where a pointer landed, in cell coordinates, and whether the cell was already active before the press. */
172
+ export interface GridCellHitInput {
173
+ point: {
174
+ x: number;
175
+ y: number;
176
+ };
177
+ size: {
178
+ width: number;
179
+ height: number;
180
+ };
181
+ metrics: GridCellMetrics;
182
+ wasActive: boolean;
183
+ }
184
+ export interface GridImageSource {
185
+ /** A ready image, or undefined while it loads (the cache asks for a redraw when it lands). */
186
+ get: (url: string) => CanvasImageSource | undefined;
187
+ }
188
+ export interface GridCellKindRenderer<V extends GridCellValue = GridCellValue> {
189
+ draw: (ctx: CanvasRenderingContext2D, args: GridCellPaintArgs, value: V) => void;
190
+ /** Plain text for assistive tech and copy. */
191
+ describe: (value: V, context: GridCellTextContext) => string;
192
+ /**
193
+ * Target under the pointer, if any. Checkbox, rating, link icon and button
194
+ * act on the first click; chips and thumbnails only when `wasActive`.
195
+ */
196
+ hitTest?: (value: V, input: GridCellHitInput) => GridCellHit | null;
197
+ /** Keyboard equivalent of the hit areas (Enter, Space, digits, Backspace). */
198
+ keyAction?: (value: V, key: string) => GridCellAction | null;
199
+ }
200
+ export {};
@@ -0,0 +1,7 @@
1
+ import { GridCells, GridCellsOptions } from './registry';
2
+ import { GridCellLabels } from './types';
3
+ export type UseGridCellsOptions = Omit<GridCellsOptions, 'labels'> & {
4
+ /** Caller wording; missing words come from the UI locale. */
5
+ labels?: Partial<GridCellLabels>;
6
+ };
7
+ export declare const useGridCells: (options: UseGridCellsOptions) => GridCells;
@@ -0,0 +1,17 @@
1
+ import { GridCell } from '../contracts';
2
+ import { GridCellBlock } from '../range/block';
3
+ import { GridClipboardData } from './write';
4
+ /** Text of each cell of a block, row by row. */
5
+ export declare const readBlock: (block: GridCellBlock, getText: (cell: GridCell) => string) => string[][];
6
+ /** Clipboard data for rows of cell text: TSV, plus an HTML table when there is more than one cell. */
7
+ export declare const clipboardData: (rows: readonly (readonly string[])[]) => GridClipboardData;
8
+ /** True when every row of the block is loaded, so the copy can be synchronous. */
9
+ export declare const isBlockLoaded: (block: GridCellBlock, isRowLoaded?: (rowIndex: number) => boolean) => boolean;
10
+ /** A copy or cut from the grid finished. The caller shows feedback (for example a “Copied N cells” toast). */
11
+ export interface GridCopyEvent {
12
+ block: GridCellBlock;
13
+ cellCount: number;
14
+ cut: boolean;
15
+ /** False when the browser refused the write or rows could not be loaded; a cut then clears nothing. */
16
+ ok: boolean;
17
+ }
@@ -0,0 +1,4 @@
1
+ export * from './tsv';
2
+ export * from './write';
3
+ export * from './proposal';
4
+ export { readBlock, clipboardData, isBlockLoaded, type GridCopyEvent } from './copy';
@@ -0,0 +1,35 @@
1
+ import { GridCell, GridSelectionState } from '../contracts';
2
+ import { GridBounds, GridCellRange } from '../range/block';
3
+ export interface GridPasteProposal {
4
+ /** Top-left target cell: the start of the selection. */
5
+ start: GridCell;
6
+ /**
7
+ * Cell text, row by row, already fitted to the grid: columns past the last
8
+ * column are dropped; rows past the last row are kept (see `extraRows`).
9
+ * Plain data: a leading `=` is text, not a formula.
10
+ */
11
+ values: string[][];
12
+ /** The target block, which may reach past the last row. */
13
+ target: GridCellRange;
14
+ /** Cells in `values`. */
15
+ cellCount: number;
16
+ /** Rows of `values` past the last row; the caller may offer to add them. */
17
+ extraRows: number;
18
+ /** Clipboard columns dropped because they fall past the last column. */
19
+ droppedColumns: number;
20
+ /** Target columns that are read-only; the caller skips them (and may say so). */
21
+ readonlyColumns: number[];
22
+ /** True when one copied cell was repeated over the selected block. */
23
+ repeated: boolean;
24
+ }
25
+ export interface GridPasteContext extends GridBounds {
26
+ /** Whether a column takes no writes (the column's `readonly`, or the whole grid). */
27
+ isReadonlyColumn?: (columnIndex: number) => boolean;
28
+ }
29
+ /**
30
+ * The proposal for pasting `text` at `selection`, or null when there is
31
+ * nothing to paste or nowhere to paste it. One copied cell over a cell range
32
+ * fills the range, as spreadsheets do; anything else pastes from the start
33
+ * cell at its own size.
34
+ */
35
+ export declare const buildPasteProposal: (text: string, selection: GridSelectionState, context: GridPasteContext) => GridPasteProposal | null;
@@ -0,0 +1,14 @@
1
+ /** Rows of cell text to clipboard text. Rows end with CRLF between them, none at the end. */
2
+ export declare const toTsv: (rows: readonly (readonly string[])[]) => string;
3
+ /**
4
+ * Clipboard text to rows of cell text. Short rows are padded with empty cells
5
+ * so the result is rectangular; one trailing line break (Excel adds one) is
6
+ * dropped. Empty text gives no rows.
7
+ */
8
+ export declare const parseTsv: (text: string) => string[][];
9
+ /**
10
+ * An HTML table for rich targets (Sheets, Excel, Docs), or undefined for a
11
+ * single cell, as Baserow does (copyPasteHelper.js `prepareHTMLData`, MIT):
12
+ * one cell pastes better as plain text.
13
+ */
14
+ export declare const toHtmlTable: (rows: readonly (readonly string[])[]) => string | undefined;
@@ -0,0 +1,21 @@
1
+ export interface GridClipboardData {
2
+ /** Tab-separated text (`toTsv`). */
3
+ text: string;
4
+ /** Optional HTML table (`toHtmlTable`). */
5
+ html?: string;
6
+ }
7
+ /** Sets the data on a native copy or cut event. False when the event has no clipboard data. */
8
+ export declare const writeClipboardEvent: (event: ClipboardEvent, data: GridClipboardData) => boolean;
9
+ export interface GridClipboardEnvironment {
10
+ clipboard?: Pick<Clipboard, 'write' | 'writeText'>;
11
+ ClipboardItem?: typeof ClipboardItem;
12
+ hasFocus?: () => boolean;
13
+ /** Runs `retry` once when the window gets focus back. */
14
+ onFocus?: (retry: () => void) => void;
15
+ }
16
+ /**
17
+ * Writes data that may still be loading. Resolves once the clipboard holds it;
18
+ * rejects when the browser refuses or the data fails, so a cut clears nothing.
19
+ * Call it inside the user gesture (key or click handler).
20
+ */
21
+ export declare const writeClipboardAsync: (data: Promise<GridClipboardData>, environment?: GridClipboardEnvironment) => Promise<void>;
@@ -0,0 +1,200 @@
1
+ import { IGridTheme } from '../grid-core/theme';
2
+ import { GridPasteProposal } from './clipboard/proposal';
3
+ /** A cell as `[columnIndex, rowIndex]`; the row is the data row index. */
4
+ export type GridCell = readonly [columnIndex: number, rowIndex: number];
5
+ /** A run of rows or columns `[from, to]`, or a cell corner `[column, row]` for cell selections. */
6
+ export type GridRange = readonly [number, number];
7
+ export interface GridColumn {
8
+ /** Stable id, used in callbacks so a reorder does not confuse the caller. */
9
+ id: string;
10
+ /** Header text, already translated; also the column's accessible name. */
11
+ name: string;
12
+ /** Width in CSS px. Default 150. */
13
+ width?: number;
14
+ /** Smallest width a resize reaches. Default 100 (Teable). */
15
+ minWidth?: number;
16
+ /** No edit requests for this column (the grid can still select and copy it). */
17
+ readonly?: boolean;
18
+ /** Shows the header menu chevron; the caller opens the menu on `header-menu`. */
19
+ hasMenu?: boolean;
20
+ /** Reserves room for a type icon; drawn by `drawIcon`. */
21
+ hasIcon?: boolean;
22
+ isPrimary?: boolean;
23
+ description?: string;
24
+ /** Free tag for the caller's cell renderer lookup (for example a field type). */
25
+ type?: string;
26
+ /**
27
+ * Editor for this column when the host has `getEditText`: `text` (default),
28
+ * `long-text` (wraps, Shift+Enter for a newline), `number` (right aligned),
29
+ * or `custom` (the host emits `edit-request` and the caller opens its own
30
+ * editor, for example a select popover).
31
+ */
32
+ editor?: GridEditorKind;
33
+ }
34
+ /** Built-in editors run on the focus owner itself; `custom` is the caller's. */
35
+ export type GridEditorKind = 'text' | 'long-text' | 'number' | 'custom';
36
+ export type GridSelectionKind = 'none' | 'cells' | 'rows' | 'columns';
37
+ /**
38
+ * The selection the caller sees. `cells`: `ranges` is `[anchor, head]`, each
39
+ * `[column, row]`. `rows` / `columns`: `ranges` is a list of `[from, to]` runs.
40
+ */
41
+ export interface GridSelectionState {
42
+ kind: GridSelectionKind;
43
+ ranges: readonly GridRange[];
44
+ activeCell: GridCell | null;
45
+ }
46
+ /** Rows and columns that intersect the viewport, inclusive. */
47
+ export interface GridVisibleRange {
48
+ startRow: number;
49
+ stopRow: number;
50
+ startColumn: number;
51
+ stopColumn: number;
52
+ }
53
+ /** A rectangle in CSS px relative to the host's top-left corner. */
54
+ export interface GridRect {
55
+ x: number;
56
+ y: number;
57
+ width: number;
58
+ height: number;
59
+ }
60
+ /**
61
+ * Why the host asks for an editor. The host never opens one itself; the
62
+ * caller (or the grid edit layer) decides.
63
+ *
64
+ * - `key`: a printable key on a selected cell. The key was not cancelled, so
65
+ * its character is already in the focus owner; `replace` is true.
66
+ * - `composition`: an input method started composing on a selected cell.
67
+ * - `enter`, `f2`, `dblclick`: edit the current value with the caret at the end.
68
+ * - `tap`: a second finger tap on the selected cell (touch, spec §14). The
69
+ * grid edits `text` and `number` in place; `long-text` and `custom` come
70
+ * out as `edit-request` with this trigger, so a phone host opens its record
71
+ * sheet (or its own editor when it fits the screen).
72
+ */
73
+ export type GridEditTrigger = 'key' | 'composition' | 'enter' | 'f2' | 'dblclick' | 'tap';
74
+ export interface GridEditRequest {
75
+ cell: GridCell;
76
+ column: GridColumn;
77
+ trigger: GridEditTrigger;
78
+ /** True when the typed text replaces the value. */
79
+ replace: boolean;
80
+ }
81
+ /** Where the selection goes after a commit: Enter moves down, Tab right, Shift+Tab left. */
82
+ export type GridEditMove = 'down' | 'right' | 'left' | 'none';
83
+ /**
84
+ * What ended the edit with a commit: a key, a press on another cell or header
85
+ * (`pointer`), a press outside the grid, focus leaving (`blur`, including the
86
+ * window losing focus) or the selection changing by API (`selection`).
87
+ */
88
+ export type GridCellCommitReason = 'enter' | 'tab' | 'pointer' | 'outside' | 'blur' | 'selection';
89
+ /**
90
+ * A built-in editor committed a changed value. Write it to the row model
91
+ * inside the handler (the host repaints the cell, hides the editor and moves
92
+ * the selection right after, in the same task), then save in the background
93
+ * and report progress through `cellStatus`.
94
+ */
95
+ export interface GridCellCommit {
96
+ cell: GridCell;
97
+ column: GridColumn;
98
+ /** The editor's text; parsing it is the caller's job (`validateEdit` can reject it first). */
99
+ value: string;
100
+ previous: string;
101
+ reason: GridCellCommitReason;
102
+ }
103
+ /** A built-in edit ended; `committed` is false after Esc or when nothing changed. */
104
+ export interface GridEditEnd {
105
+ cell: GridCell;
106
+ column: GridColumn;
107
+ committed: boolean;
108
+ }
109
+ /**
110
+ * Save state of one cell, owned by the caller (the host never writes data):
111
+ * `saving` (with `createCellStatusStore`, only for saves slower than 300 ms)
112
+ * or `error` with its translated reason. The cell renderer draws the marks
113
+ * (`useGridCells` `getStatus`, mapped with `cellStatusMark`); the host shows
114
+ * an error's message under the active cell.
115
+ */
116
+ export type GridCellSaveStatus = {
117
+ state: 'saving';
118
+ } | {
119
+ state: 'error';
120
+ message: string;
121
+ } | null;
122
+ /** What a cell renderer gets. Coordinates are canvas CSS px. */
123
+ export interface GridCellDrawArgs extends GridRect {
124
+ cell: GridCell;
125
+ column: GridColumn;
126
+ theme: IGridTheme;
127
+ isActive: boolean;
128
+ /** The row has not loaded yet: draw a placeholder, not a value. */
129
+ isLoading: boolean;
130
+ }
131
+ /**
132
+ * Vendor extension point for custom cells (task 27 registers its renderers
133
+ * here). `draw` paints inside the cell rect; it must not read the DOM.
134
+ */
135
+ export interface GridCellRenderer {
136
+ draw: (ctx: CanvasRenderingContext2D, args: GridCellDrawArgs) => void;
137
+ }
138
+ export interface GridIconDrawArgs {
139
+ kind: 'drag' | 'expand' | 'add' | 'primary' | 'description' | 'column';
140
+ x: number;
141
+ y: number;
142
+ size: number;
143
+ theme: IGridTheme;
144
+ column?: GridColumn;
145
+ }
146
+ export type GridRowControl = 'drag' | 'expand' | 'checkbox';
147
+ export type GridDraggable = 'none' | 'column' | 'row' | 'all';
148
+ export type GridSelectable = 'none' | 'cell' | 'row' | 'column' | 'all';
149
+ /** The caller's text for each cell: drawn by the default renderer and read to assistive tech. */
150
+ export type GridCellTextGetter = (cell: GridCell) => string;
151
+ export interface GridContextMenuEvent {
152
+ selection: GridSelectionState;
153
+ /** Pointer position relative to the host. */
154
+ x: number;
155
+ y: number;
156
+ }
157
+ export interface GridReorderEvent {
158
+ /** The dragged runs (`[from, to]`), in index order. */
159
+ ranges: readonly GridRange[];
160
+ /** Where they land, counted before they are removed. */
161
+ dropIndex: number;
162
+ }
163
+ /** Imperative handle (`ref` on `<GridHost>`). */
164
+ export interface GridHostExpose {
165
+ /** Moves focus to the grid's focus owner, unless a foreign dialog holds focus. */
166
+ focus: () => boolean;
167
+ /** The hidden textarea that holds focus over the active cell; the edit layer may take it over. */
168
+ focusOwner: () => HTMLTextAreaElement | null;
169
+ /** Rect of a cell relative to the host, after scroll and frozen columns; null when out of range. */
170
+ getCellRect: (cell: GridCell) => GridRect | null;
171
+ /** Minimal instant scroll that brings the cell into view with a 16 px margin. */
172
+ scrollToCell: (cell: GridCell) => void;
173
+ getSelection: () => GridSelectionState;
174
+ /** Replaces the selection; `activeCell` defaults to the first cell of a cell selection. */
175
+ setSelection: (selection: Omit<GridSelectionState, 'activeCell'> & {
176
+ activeCell?: GridCell | null;
177
+ }) => void;
178
+ /** Redraws cell content (call after data changes that do not change props). */
179
+ invalidate: () => void;
180
+ /** Re-reads colour tokens, for example after the app switches theme. */
181
+ refreshTheme: () => void;
182
+ /** True while a built-in editor is open. */
183
+ isEditing: () => boolean;
184
+ /**
185
+ * Commits an open built-in editor (before a toolbar action, for example).
186
+ * False when the draft is invalid or an IME is still composing, so the
187
+ * editor stays open.
188
+ */
189
+ commitEdit: () => boolean;
190
+ /** Reverts and closes an open built-in editor, keeping the selection. */
191
+ cancelEdit: () => void;
192
+ /**
193
+ * Copies (or cuts) the selection through the async clipboard API, for a menu
194
+ * or toolbar command; call it inside the click handler. Emits
195
+ * `clipboard-copy`; resolves false when nothing was copied.
196
+ */
197
+ copy: (cut?: boolean) => Promise<boolean>;
198
+ /** Parses `text` against the selection and emits `paste-request`, for a paste command that read the clipboard itself. */
199
+ paste: (text: string) => GridPasteProposal | null;
200
+ }
@@ -0,0 +1,33 @@
1
+ import { GridCellStatus as GridCellMark } from '../cells/types';
2
+ import { GridCellSaveStatus } from '../contracts';
3
+ /** Saves faster than this never show the saving mark (spec §3.4). */
4
+ export declare const SAVING_MARK_DELAY_MS = 300;
5
+ export interface GridSaveTicket {
6
+ /** The save landed: drop the saving mark. */
7
+ done(): void;
8
+ /** The save failed; the caller has rolled the value back. Shows the error mark with this (translated) reason. */
9
+ fail(message: string): void;
10
+ }
11
+ export interface GridCellStatusStore {
12
+ /** Status for a key, as the host's `cellStatus` returns it. */
13
+ get(key: string): GridCellSaveStatus;
14
+ /** A save started for this key. A newer save for the same key replaces the older one. */
15
+ track(key: string): GridSaveTicket;
16
+ fail(key: string, message: string): void;
17
+ clear(key: string): void;
18
+ dispose(): void;
19
+ }
20
+ export interface GridCellStatusStoreOptions {
21
+ /** Something visible changed: call the host's `invalidate()`. */
22
+ onChange: () => void;
23
+ delayMs?: number;
24
+ setTimer?: (run: () => void, ms: number) => unknown;
25
+ clearTimer?: (handle: unknown) => void;
26
+ }
27
+ /**
28
+ * Keys are the caller's (for example `${rowId}:${fieldId}`), so marks stay on
29
+ * their record when rows are sorted or inserted.
30
+ */
31
+ export declare function createCellStatusStore(options: GridCellStatusStoreOptions): GridCellStatusStore;
32
+ /** The mark the cell renderer draws for a save state (`useGridCells` `getStatus`). */
33
+ export declare function cellStatusMark(status: GridCellSaveStatus): GridCellMark | null;