@jielga/tmdatagrid 2.0.0-beta.8 → 2.0.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.
Files changed (155) hide show
  1. package/README.md +5 -212
  2. package/dist/index.d.ts +1323 -796
  3. package/dist/index.js +4719 -3193
  4. package/dist/index.js.map +1 -1
  5. package/dist/styles.css +1 -1
  6. package/docs/adding-rows.md +132 -0
  7. package/docs/anatomy.md +119 -0
  8. package/docs/card-view.md +108 -0
  9. package/docs/cell-selection.md +194 -0
  10. package/docs/column-layout.md +182 -0
  11. package/docs/column-menu.md +66 -0
  12. package/docs/columns.md +268 -0
  13. package/docs/components.md +311 -0
  14. package/docs/draft-store.md +242 -0
  15. package/docs/editing.md +303 -0
  16. package/docs/editors.md +250 -0
  17. package/docs/export.md +319 -0
  18. package/docs/filtering.md +362 -0
  19. package/docs/getting-started.md +123 -0
  20. package/docs/grouping.md +165 -0
  21. package/docs/loading-and-empty.md +92 -0
  22. package/docs/localization.md +79 -0
  23. package/docs/menu.md +143 -0
  24. package/docs/migrating-to-2.md +163 -0
  25. package/docs/pagination.md +144 -0
  26. package/docs/persistence.md +114 -0
  27. package/docs/portfolio-rebalancer.md +94 -0
  28. package/docs/query-builder.md +179 -0
  29. package/docs/quick-search.md +84 -0
  30. package/docs/row-details.md +115 -0
  31. package/docs/row-interaction.md +149 -0
  32. package/docs/row-pinning.md +132 -0
  33. package/docs/row-selection.md +136 -0
  34. package/docs/row-styling.md +133 -0
  35. package/docs/scrolling.md +112 -0
  36. package/docs/server-query.md +246 -0
  37. package/docs/server-side.md +206 -0
  38. package/docs/sorting.md +101 -0
  39. package/docs/styling.md +126 -0
  40. package/docs/summary-row.md +76 -0
  41. package/docs/testing.md +744 -0
  42. package/docs/toolbar.md +161 -0
  43. package/docs/use-tm-data-grid.md +361 -0
  44. package/package.json +22 -46
  45. package/skills/appearance/SKILL.md +72 -19
  46. package/skills/cell-selection/SKILL.md +69 -78
  47. package/skills/columns/SKILL.md +90 -34
  48. package/skills/data/SKILL.md +86 -16
  49. package/skills/editing/SKILL.md +83 -50
  50. package/skills/editing/references/common-mistakes.md +77 -69
  51. package/skills/editing/references/editing-api.md +31 -23
  52. package/skills/editing/references/editors-and-validation.md +24 -17
  53. package/skills/filtering/SKILL.md +148 -40
  54. package/skills/getting-started/SKILL.md +17 -15
  55. package/skills/grouping/SKILL.md +31 -16
  56. package/skills/options/SKILL.md +8 -8
  57. package/skills/rows/SKILL.md +22 -18
  58. package/skills/server-side/SKILL.md +170 -17
  59. package/skills/testing/SKILL.md +150 -32
  60. package/skills/testing-components/SKILL.md +230 -0
  61. package/skills/testing-editing/SKILL.md +240 -0
  62. package/src/{tmdatagrid/TMDataGridContext.ts → TMDataGridContext.ts} +7 -19
  63. package/src/{tmdatagrid/components → components}/TMDataGrid.module.css +7 -1
  64. package/src/{tmdatagrid/components → components}/TMDataGrid.tsx +38 -21
  65. package/src/{tmdatagrid/components → components}/TMDataGridCellEditor.tsx +73 -7
  66. package/src/{tmdatagrid/components → components}/TMDataGridColumnsPanel.module.css +5 -1
  67. package/src/{tmdatagrid/components → components}/TMDataGridColumnsPanel.tsx +47 -55
  68. package/src/{tmdatagrid/components → components}/TMDataGridDetailsColumn.tsx +9 -55
  69. package/src/{tmdatagrid/components → components}/TMDataGridDraftActions.tsx +41 -24
  70. package/src/{tmdatagrid/components → components}/TMDataGridEditColumn.tsx +23 -63
  71. package/src/components/TMDataGridEntryRows.tsx +354 -0
  72. package/src/components/TMDataGridExportPicker.module.css +77 -0
  73. package/src/components/TMDataGridExportPicker.tsx +234 -0
  74. package/src/components/TMDataGridFilterPanel.module.css +54 -0
  75. package/src/components/TMDataGridFilterPanel.tsx +348 -0
  76. package/src/{tmdatagrid/components → components}/TMDataGridFilterPills.tsx +15 -8
  77. package/src/components/TMDataGridFilterSurface.module.css +54 -0
  78. package/src/components/TMDataGridFilterSurface.tsx +167 -0
  79. package/src/{tmdatagrid/components → components}/TMDataGridFooter.tsx +53 -90
  80. package/src/{tmdatagrid/components → components}/TMDataGridGroupColumn.tsx +9 -72
  81. package/src/{tmdatagrid/components → components}/TMDataGridHeaderCell.module.css +12 -2
  82. package/src/{tmdatagrid/components → components}/TMDataGridHeaderCell.tsx +58 -21
  83. package/src/components/TMDataGridHeaderFilterRow.module.css +51 -0
  84. package/src/components/TMDataGridHeaderFilterRow.tsx +301 -0
  85. package/src/components/TMDataGridMenu.tsx +357 -0
  86. package/src/{tmdatagrid/components → components}/TMDataGridSelectColumn.tsx +15 -53
  87. package/src/{tmdatagrid/components → components}/TMDataGridTable.module.css +88 -65
  88. package/src/{tmdatagrid/components → components}/TMDataGridTable.tsx +579 -165
  89. package/src/{tmdatagrid/components → components}/TMDataGridToolbar.module.css +5 -0
  90. package/src/components/TMDataGridToolbar.tsx +181 -0
  91. package/src/{tmdatagrid/components → components}/editors/TMDataGridBooleanEditor.tsx +3 -3
  92. package/src/{tmdatagrid/components → components}/editors/TMDataGridDateEditor.tsx +3 -3
  93. package/src/{tmdatagrid/components → components}/editors/TMDataGridMultiSelectEditor.tsx +3 -3
  94. package/src/{tmdatagrid/components → components}/editors/TMDataGridNumberEditor.tsx +3 -3
  95. package/src/{tmdatagrid/components → components}/editors/TMDataGridSelectEditor.tsx +3 -3
  96. package/src/{tmdatagrid/components → components}/editors/TMDataGridStringEditor.tsx +3 -3
  97. package/src/{tmdatagrid/components → components}/editors/editorShared.ts +16 -2
  98. package/src/{tmdatagrid/components → components}/filters/DgAutocompleteFilter.tsx +5 -4
  99. package/src/{tmdatagrid/components → components}/filters/DgDateRangeFilter.tsx +22 -5
  100. package/src/{tmdatagrid/components → components}/filters/DgRangeSliderFilter.tsx +5 -1
  101. package/src/{tmdatagrid/components → components}/filters/DgTriStateFilter.tsx +5 -1
  102. package/src/{tmdatagrid/components → components}/filters/TMDataGridFilterValueInput.tsx +44 -28
  103. package/src/components/filters/controlLayout.ts +32 -0
  104. package/src/components/filters/filterControlFor.ts +65 -0
  105. package/src/components/generatedColumns.tsx +187 -0
  106. package/src/{tmdatagrid/components → components}/icons.ts +1 -0
  107. package/src/{tmdatagrid/components → components}/sticky.module.css +44 -0
  108. package/src/components/useHideableColumns.ts +52 -0
  109. package/src/{tmdatagrid/core → core}/autosize.ts +5 -2
  110. package/src/{tmdatagrid/core → core}/capabilities.ts +5 -5
  111. package/src/{tmdatagrid/core → core}/columnOptions.ts +60 -8
  112. package/src/{tmdatagrid/core → core}/columnOrdering.ts +33 -14
  113. package/src/{tmdatagrid/core → core}/columnUtils.ts +44 -5
  114. package/src/core/controlledStateSync.ts +108 -0
  115. package/src/core/deletedRows.ts +34 -0
  116. package/src/core/dom.ts +74 -0
  117. package/src/{tmdatagrid/core → core}/editEngine.ts +1172 -388
  118. package/src/{tmdatagrid/core → core}/editorFocus.ts +8 -4
  119. package/src/core/export.ts +704 -0
  120. package/src/{tmdatagrid/core → core}/filterControls.ts +38 -1
  121. package/src/{tmdatagrid/core → core}/filterOperators.ts +64 -1
  122. package/src/core/filterSurface.ts +99 -0
  123. package/src/{tmdatagrid/core → core}/grouping.ts +21 -0
  124. package/src/{tmdatagrid/core → core}/labels.ts +51 -6
  125. package/src/{tmdatagrid/core → core}/labelsSv.ts +27 -6
  126. package/src/core/pageReset.ts +120 -0
  127. package/src/core/pagination.ts +81 -0
  128. package/src/{tmdatagrid/core → core}/persistence.ts +22 -5
  129. package/src/{tmdatagrid/core → core}/summary.ts +20 -4
  130. package/src/{tmdatagrid/index.ts → index.ts} +70 -36
  131. package/src/{tmdatagrid/useTMDataGrid.tsx → useTMDataGrid.tsx} +534 -123
  132. package/src/useTMDataGridExport.ts +78 -0
  133. package/src/tmdatagrid/components/TMDataGridEntryRows.tsx +0 -298
  134. package/src/tmdatagrid/components/TMDataGridFilterPanel.module.css +0 -35
  135. package/src/tmdatagrid/components/TMDataGridFilterPanel.tsx +0 -354
  136. package/src/tmdatagrid/components/TMDataGridToolbar.tsx +0 -161
  137. package/src/tmdatagrid/core/cellExport.ts +0 -320
  138. /package/src/{tmdatagrid/components → components}/TMDataGridDetailsColumn.module.css +0 -0
  139. /package/src/{tmdatagrid/components → components}/TMDataGridFilterPills.module.css +0 -0
  140. /package/src/{tmdatagrid/components → components}/TMDataGridFooter.module.css +0 -0
  141. /package/src/{tmdatagrid/components → components}/TMDataGridGroupColumn.module.css +0 -0
  142. /package/src/{tmdatagrid/components → components}/TMDataGridRowNumberColumn.tsx +0 -0
  143. /package/src/{tmdatagrid/components → components}/TMDataGridSearch.tsx +0 -0
  144. /package/src/{tmdatagrid/core → core}/cellNavigation.ts +0 -0
  145. /package/src/{tmdatagrid/core → core}/cellRange.ts +0 -0
  146. /package/src/{tmdatagrid/core → core}/controlledState.ts +0 -0
  147. /package/src/{tmdatagrid/core → core}/draftCellContext.ts +0 -0
  148. /package/src/{tmdatagrid/core → core}/expanding.ts +0 -0
  149. /package/src/{tmdatagrid/core → core}/matchHighlight.ts +0 -0
  150. /package/src/{tmdatagrid/core → core}/quickSearch.ts +0 -0
  151. /package/src/{tmdatagrid/core → core}/resizePreview.ts +0 -0
  152. /package/src/{tmdatagrid/core → core}/rowPinning.ts +0 -0
  153. /package/src/{tmdatagrid/core → core}/rowSelection.ts +0 -0
  154. /package/src/{tmdatagrid/core → core}/sizes.ts +0 -0
  155. /package/src/{tmdatagrid/core → core}/useSettledTableState.ts +0 -0
package/docs/export.md ADDED
@@ -0,0 +1,319 @@
1
+ # Export
2
+
3
+ Downloads the grid as a file: every filtered and sorted row across every page, or the selected rows, in the format the grid is configured with.
4
+ `TMDataGrid.Menu.Export` and `TMDataGrid.Menu.ExportSelected` are the built-in entry points; `useTMDataGridExport` is the same export as click handlers for a control of your own.
5
+
6
+ ```tsx
7
+ <TMDataGrid.Toolbar>
8
+ <TMDataGrid.SummaryCount />
9
+ <TMDataGrid.Spacer />
10
+ <TMDataGrid.Menu>
11
+ <TMDataGrid.Menu.Export />
12
+ <TMDataGrid.Menu.ExportSelected />
13
+ <Menu.Divider />
14
+ <TMDataGrid.Menu.Columns />
15
+ </TMDataGrid.Menu>
16
+ </TMDataGrid.Toolbar>
17
+ ```
18
+
19
+ ```demo
20
+ file: data/Export.tsx
21
+ hint: Tick a few rows, then open the menu. The Excel CSV opens straight into columns.
22
+ ```
23
+
24
+ ## What is written
25
+
26
+ By default the columns are the visible data columns in render order, so a hidden column is not exported and a pinned one keeps its place.
27
+ `columns` on `exportOptions`, on the menu items and on the functions picks another set:
28
+
29
+ - `"visible"` - the data columns on screen. The default.
30
+ - `"all"` - every exportable column, hidden ones in the place they would take if shown.
31
+ - a list of column ids - those columns, in render order.
32
+
33
+ The generated lanes (checkbox, details, edit, row numbers) are never exported, whichever is asked for.
34
+ Set `meta.enableExport: false` to leave a column of your own out the same way:
35
+
36
+ ```tsx
37
+ columnHelper.display({
38
+ id: "actions",
39
+ cell: ActionsCell,
40
+ meta: { enableExport: false },
41
+ });
42
+ ```
43
+
44
+ The rows are every row after filtering and sorting, across every page.
45
+ On a grouped grid the records under every group are written, whether the group is open or not, and the group rows are not.
46
+
47
+ Each cell is written as its **value**, `row.getValue(column.id)`, not as what the cell renders.
48
+ A cell showing `32 000 kr` exports `32000`; a select column exports the option's `value`.
49
+ Set `meta.exportValue` to write something else:
50
+
51
+ ```tsx
52
+ columnHelper.accessor("status", {
53
+ meta: {
54
+ type: "select",
55
+ options: STATUS_OPTIONS,
56
+ exportValue: ({ value }) => STATUS_LABELS[value as EmployeeStatus],
57
+ },
58
+ });
59
+ ```
60
+
61
+ `exportValue` receives `{ value, row, column }` and returns the value the format writes.
62
+ Both meta fields also apply to Ctrl+C under [cell selection](/docs/cell-selection#copy-and-export).
63
+
64
+ ## The exportOptions option
65
+
66
+ `exportOptions` on `useTMDataGrid` sets the format, the file name and whether the column labels go in as the first row:
67
+
68
+ ```tsx
69
+ const grid = useTMDataGrid({
70
+ data,
71
+ columns,
72
+ exportOptions: { format: csvFormat(), fileName: "employees" },
73
+ });
74
+ ```
75
+
76
+ | Field | Type | Default | Description |
77
+ | --- | --- | --- | --- |
78
+ | `format` | `TMDataGridExportFormat` | `csvExcelFormat()` | The file format. See [Formats](#formats). |
79
+ | `fileName` | `string` | `"export"` | The file name without extension; the format adds its own. |
80
+ | `includeHeaders` | `boolean` | `true` | Determines whether the column labels are written as the first row. |
81
+ | `columns` | `"visible" \| "all" \| Array<string>` | `"visible"` | Which columns are written. See [What is written](#what-is-written). |
82
+
83
+ The option is read field by field, so a literal is fine.
84
+ Every export of the grid reads it: the menu items, the hook, and the export item of the cell-range menu.
85
+
86
+ ## Formats
87
+
88
+ A format is a `TMDataGridExportFormat`, and the package ships four factories:
89
+
90
+ | Factory | File | Writes |
91
+ | --- | --- | --- |
92
+ | `csvExcelFormat()` | `.csv` | A CSV Excel opens straight into columns: UTF-8 BOM, a `sep=;` first line, CRLF endings, `;` between fields, `,` as the decimal mark. |
93
+ | `csvFormat()` | `.csv` | CSV as RFC 4180 has it: `,` between fields, `.` as the decimal mark, CRLF, a UTF-8 BOM, no `sep=` line. |
94
+ | `tsvFormat()` | `.tsv` | Tab-separated text, the clipboard shape as a file. |
95
+ | `jsonFormat()` | `.json` | An array with one object per row, keyed by column label, values as the data holds them. |
96
+
97
+ Excel xlsx is a separate package, since it needs a spreadsheet library the grid should not carry: see [Excel export (xlsx)](/docs/xlsx).
98
+
99
+ By default the grid writes `csvExcelFormat()` with the Nordic conventions, because an Excel running a Swedish, Norwegian, Danish or Finnish locale reads `;` as its list separator and `,` as its decimal mark, and a file written the other way opens as one column of text.
100
+ To write for an English-locale Excel, set the separator and the decimal mark on the format:
101
+
102
+ ```tsx
103
+ exportOptions: { format: csvExcelFormat({ separator: ",", decimalComma: false }) }
104
+ ```
105
+
106
+ The `sep=` line is Excel's alone; Google Sheets and Numbers show it as a first row.
107
+ Use `csvFormat()` for a file that goes there.
108
+
109
+ `csvExcelFormat`, `csvFormat` and `tsvFormat` write values through `formatExportValue`: numbers with the format's decimal mark, dates in the `sv-SE` form (`2026-07-31 14:05:00`, which Excel reads as a date), booleans as `true` / `false`, arrays joined with `, `, and any other object as JSON.
110
+ `jsonFormat` writes numbers as numbers, dates as ISO strings, and `undefined` as `null`.
111
+
112
+ | Option | Formats | Type | Default | Description |
113
+ | --- | --- | --- | --- | --- |
114
+ | `separator` | csvExcel, csv | `string` | `";"` for csvExcel, `","` for csv | The character between fields. |
115
+ | `decimalComma` | csvExcel, csv, tsv | `boolean` | `true` for csvExcel and tsv, `false` for csv | Determines whether numbers are written as `1,5` rather than `1.5`. |
116
+ | `escapeFormulas` | csvExcel, csv, tsv | `boolean` | `true` | Determines whether text a spreadsheet would run as a formula is prefixed. See [Formula guard](#formula-guard). |
117
+ | `space` | json | `number` | `2` | Indentation passed to `JSON.stringify`. |
118
+
119
+ ### Formula guard
120
+
121
+ Excel and Google Sheets run a cell that starts with `=`, `+`, `-` or `@` as a formula, so text one user typed into the grid would run in another user's spreadsheet when the file is opened.
122
+ By default the text formats prefix such a value with an apostrophe, which every spreadsheet reads as "text follows" and shows.
123
+ Text that parses as a number (`-5`, `+4670123456`) is not prefixed; a phone number written with spaces (`+46 70 123 45 67`) is.
124
+ To write every value as it is, set `escapeFormulas: false` on the format:
125
+
126
+ ```tsx
127
+ exportOptions: { format: csvExcelFormat({ escapeFormulas: false }) }
128
+ ```
129
+
130
+ `guardFormula(text)` is the rule as a function, for a format of your own.
131
+
132
+ ## TMDataGrid.Menu.Export
133
+
134
+ A menu item that downloads every filtered and sorted row, all pages, in the grid's format.
135
+ It needs a Mantine `Menu` around it and reads the grid from context, so it works in `TMDataGrid.Menu` and in any Mantine menu rendered inside `TMDataGrid`.
136
+ Its props override `exportOptions` for this item alone, which is how one menu offers two formats:
137
+
138
+ ```tsx
139
+ <TMDataGrid.Menu>
140
+ <TMDataGrid.Menu.Export />
141
+ <TMDataGrid.Menu.Export
142
+ format={csvFormat()}
143
+ fileName="employees-plain"
144
+ label="Export all rows as plain CSV"
145
+ />
146
+ </TMDataGrid.Menu>
147
+ ```
148
+
149
+ | Prop | Type | Default | Description |
150
+ | --- | --- | --- | --- |
151
+ | `format` | `TMDataGridExportFormat` | `exportOptions.format` | The file format for this item. |
152
+ | `fileName` | `string` | `exportOptions.fileName` | The file name for this item. |
153
+ | `includeHeaders` | `boolean` | `exportOptions.includeHeaders` | Determines whether this item writes the header row. |
154
+ | `columns` | `"visible" \| "all" \| Array<string> \| "custom"` | `exportOptions.columns` | Which columns the item writes. `"custom"` opens the column picker. |
155
+ | `label` | `ReactNode` | `labels.exportAll` | The item's text. |
156
+
157
+ ### The column picker
158
+
159
+ `columns="custom"` opens a dialog instead of downloading, titled with the format ("Export as CSV"): every exportable column as a checkbox, the visible ones ticked and the hidden ones marked **Hidden**, and an Export button that downloads the ticked columns in render order.
160
+ The line under the title names the selected rows when the item is `ExportSelected`.
161
+ A select-all row heads the list with a count of the ticked columns, a search box appears once there are six columns, and the list scrolls inside the dialog past half the viewport.
162
+ Under a search, select all ticks the matches and leaves the rest as they are.
163
+ Cancel closes it with no download.
164
+ The dialog follows the grid's `size`: its width, title and controls step with the toolbar's.
165
+
166
+ ```tsx
167
+ <TMDataGrid.Menu.Export columns="custom" label="Export all rows, choose columns" />
168
+ ```
169
+
170
+ The picker is rendered by the `TMDataGrid` root and driven by `ui.state.exportPicker`, which holds `{ rows, options }` while it is open and `null` otherwise.
171
+ `ui.actions.openExportPicker({ rows: "all", options })` opens it from a control of your own; `getExportableColumns(table)` is the list it shows.
172
+
173
+ ## TMDataGrid.Menu.ExportSelected
174
+
175
+ A menu item that downloads the selected rows of the current view, in grid order, with the same props as `TMDataGrid.Menu.Export`.
176
+ By default its text carries the count (`Export 3 selected rows`); `label` replaces it.
177
+ It is disabled while nothing is selected.
178
+ It renders nothing when row selection is off (`selectionMode: "highlight"` or `enableRowSelection: false`).
179
+
180
+ A selected row the filters have since hidden is not written and not counted.
181
+
182
+ ## useTMDataGridExport
183
+
184
+ The export as click handlers, for a button or an item of your own anywhere inside `TMDataGrid`:
185
+
186
+ ```tsx
187
+ import { useTMDataGridExport } from "@jielga/tmdatagrid";
188
+
189
+ function ExportButtons() {
190
+ const { exportAll, exportSelected, selectedCount, canExportSelected } =
191
+ useTMDataGridExport();
192
+
193
+ return (
194
+ <>
195
+ <Button size="xs" onClick={() => void exportAll()}>
196
+ Export
197
+ </Button>
198
+ {canExportSelected && (
199
+ <Button size="xs" disabled={selectedCount === 0} onClick={() => void exportSelected()}>
200
+ Export {selectedCount} selected
201
+ </Button>
202
+ )}
203
+ </>
204
+ );
205
+ }
206
+ ```
207
+
208
+ It takes a `TMDataGridExportOptions` argument, folded over the grid's `exportOptions` for this caller.
209
+ `exportAll` and `exportSelected` take one more, folded over both for that call, which is how a control passes a chosen set of columns.
210
+
211
+ | Field | Type | Description |
212
+ | --- | --- | --- |
213
+ | `exportAll` | `(overrides?) => Promise<void>` | Downloads every filtered and sorted row, all pages. |
214
+ | `exportSelected` | `(overrides?) => Promise<void>` | Downloads the selected rows of the current view. Resolves without a download when none is selected. |
215
+ | `selectedCount` | `number` | How many rows `exportSelected` would write. Subscribes to the selection. |
216
+ | `canExportSelected` | `boolean` | `true` while row selection is on. |
217
+
218
+ ## Exporting from outside the grid
219
+
220
+ `exportGrid` is the same export for code that holds the table and nothing else:
221
+
222
+ ```tsx
223
+ import { exportGrid, jsonFormat } from "@jielga/tmdatagrid";
224
+
225
+ await exportGrid({ table: grid.table, rows: "selected", options: { format: jsonFormat() } });
226
+ ```
227
+
228
+ `rows` is `"all"` (the default), `"selected"`, or an array of TanStack rows of your own; `options.columns` picks the columns.
229
+ `buildExportData({ table, rows, columns })` is the step before the file: the columns, their labels and the raw values as a `TMDataGridExportData`, for a format or a post-processing step of your own.
230
+ `writeExportFile(data, settings)` writes and downloads it.
231
+
232
+ ## Writing your own format
233
+
234
+ A format is an object with an id, a file extension, a MIME type and a `write` function.
235
+ `write` receives the `TMDataGridExportData` and `{ includeHeaders }`, and returns the file as a string or a `Blob`, or a promise of either:
236
+
237
+ ```tsx
238
+ import type { TMDataGridExportFormat } from "@jielga/tmdatagrid";
239
+
240
+ export function markdownFormat(): TMDataGridExportFormat {
241
+ return {
242
+ id: "markdown",
243
+ extension: "md",
244
+ mimeType: "text/markdown",
245
+ write: ({ headers, rows }, { includeHeaders }) => {
246
+ const line = (cells: Array<unknown>) => `| ${cells.map(String).join(" | ")} |`;
247
+ const head = includeHeaders
248
+ ? [line(headers), line(headers.map(() => "---"))]
249
+ : [];
250
+ return [...head, ...rows.map(line)].join("\n");
251
+ },
252
+ };
253
+ }
254
+ ```
255
+
256
+ Set `decimalComma` on the format when it writes text with a decimal mark, so Ctrl+C writes the same mark.
257
+ `formatExportValue(value, { decimalComma })` is the grid's own text rule, for a format that wants it.
258
+
259
+ ## Copy and the cell-range menu
260
+
261
+ Under `cellSelection: "range"`, Ctrl+C and the **Export cells** item of the right-click menu write the selected rectangle through the same `exportOptions`, column meta and format.
262
+ See [Copy and export](/docs/cell-selection#copy-and-export).
263
+
264
+ ## Labels
265
+
266
+ | Label | Default | Used by |
267
+ | --- | --- | --- |
268
+ | `exportAll` | `"Export all rows"` | `TMDataGrid.Menu.Export` |
269
+ | `exportSelected` | `(count) => "Export 3 selected rows"` | `TMDataGrid.Menu.ExportSelected` |
270
+ | `exportCells` | `"Export cells"` | The cell-range menu |
271
+ | `exportPickerTitle` | `` (format) => `Export as ${format}` `` | The column picker; `format` is the extension in upper case |
272
+ | `exportPickerHint` | `(selected) => "Select the columns to export"`, or `… for the ${selected} selected rows` | The line under the picker's title |
273
+ | `exportPickerConfirm` | `"Export"` | The column picker |
274
+ | `exportPickerCancel` | `"Cancel"` | The column picker |
275
+ | `exportPickerSelectAll` | `"Select all"` | The column picker |
276
+ | `exportPickerCount` | `` (checked, total) => `${checked} of ${total}` `` | The column picker |
277
+ | `exportPickerHidden` | `"Hidden"` | The column picker, on a column the grid hides |
278
+
279
+ See [Localization](/docs/localization).
280
+
281
+ ## Testing
282
+
283
+ `TMDataGrid.Menu.Export` is `data-dg-part="menu-export"` and `TMDataGrid.Menu.ExportSelected` is `data-dg-part="menu-export-selected"`.
284
+ The column picker is `export-picker`, its checkboxes `export-column` with `data-column-id`, its select-all row `export-column-all` with the count `export-picker-count`, its search box `export-picker-search`, the line under the title `export-picker-hint`, and its buttons `export-picker-confirm` and `export-picker-cancel`.
285
+ The search box and the picker share `columnsSearchPlaceholder` and `columnsNoMatch` with the column chooser.
286
+ A download is an anchor with an object URL, clicked; a jsdom test stubs `URL.createObjectURL` and `HTMLAnchorElement.prototype.click` to read the file back.
287
+ See [Testing](/docs/testing).
288
+
289
+ ## Reference
290
+
291
+ | Name | Kind | Type | Default | What it does |
292
+ | --- | --- | --- | --- | --- |
293
+ | `exportOptions` | Option | `TMDataGridExportOptions` | `DEFAULT_EXPORT_OPTIONS` | Format, file name and header row for every export of the grid. |
294
+ | `meta.enableExport` | Column meta | `boolean` | `true` | `false` leaves the column out of every export and of Ctrl+C. |
295
+ | `meta.exportValue` | Column meta | `({ value, row, column }) => unknown` | – | The value written in place of `row.getValue`. |
296
+ | `TMDataGridExportValueGetter` | Type | – | – | The type of `meta.exportValue`. |
297
+ | `TMDataGrid.Menu.Export` | Component | `TMDataGridMenuExportProps` | – | Menu item: every filtered row. `columns="custom"` opens the picker. |
298
+ | `TMDataGrid.Menu.ExportSelected` | Component | `TMDataGridMenuExportProps` | – | Menu item: the selected rows. Renders nothing when row selection is off. |
299
+ | `ui.state.exportPicker` | UI state | `{ rows, options } \| null` | `null` | The column picker while open. |
300
+ | `TMDataGridExportPickerRequest` | Type | `{ rows, options }` | – | The value of `ui.state.exportPicker` while the picker is open. |
301
+ | `ui.actions.openExportPicker` · `closeExportPicker` | UI actions | – | – | Open the picker from your own code. |
302
+ | `getExportableColumns` | Function | `(table) => Array<Column>` | – | Every column an export could take, hidden ones included. |
303
+ | `useTMDataGridExport` | Hook | `(overrides?) => TMDataGridExportApi` | – | `exportAll`, `exportSelected`, `selectedCount`, `canExportSelected`. |
304
+ | `exportGrid` | Function | `({ table, rows?, options? }) => Promise<void>` | – | Downloads the grid from outside a component. |
305
+ | `ExportGridArgs` | Type | `{ table, rows?, options? }` | – | What `exportGrid` takes. |
306
+ | `buildExportData` | Function | `({ table, rows?, columns?, bounds? }) => TMDataGridExportData` | – | The columns, labels and values a format writes. |
307
+ | `BuildExportDataArgs` | Type | `{ table, rows?, columns?, bounds? }` | – | What `buildExportData` takes. |
308
+ | `TMDataGridExportColumns` | Type | `"visible" \| "all" \| ReadonlyArray<string>` | – | Which columns an export takes. Generated lanes and `meta.enableExport: false` columns are never taken. |
309
+ | `writeExportFile` | Function | `(data, settings) => Promise<void>` | – | Writes export data in a format and downloads it. |
310
+ | `csvExcelFormat` · `csvFormat` · `tsvFormat` · `jsonFormat` | Functions | `(options?) => TMDataGridExportFormat` | – | The built-in formats. |
311
+ | `TMDataGridCsvFormatOptions` · `TMDataGridTsvFormatOptions` · `TMDataGridJsonFormatOptions` | Types | – | – | The options of `csvExcelFormat` and `csvFormat`, of `tsvFormat`, and of `jsonFormat`. |
312
+ | `TMDataGridExportWriteOptions` | Type | `{ includeHeaders }` | – | The second argument of a format's `write`. |
313
+ | `guardFormula` · `formatExportValue` | Functions | – | – | The formula guard and the text rule, for a format of your own. |
314
+ | `resolveExportOptions` | Function | `(...overrides) => TMDataGridExportSettings` | – | The defaults with overrides folded over, `undefined` fields skipped. |
315
+ | `countSelectedExportRows` | Function | `(table) => number` | – | How many rows `"selected"` would write. |
316
+ | `downloadFile` | Function | `({ fileName, content, mimeType }) => void` | – | Downloads a string or a `Blob`. |
317
+ | `DEFAULT_EXPORT_OPTIONS` | Constant | `TMDataGridExportSettings` | – | `csvExcelFormat()`, `"export"`, `true`. |
318
+ | `TMDataGridExportFormat` · `TMDataGridExportData` · `TMDataGridExportOptions` · `TMDataGridExportSettings` · `TMDataGridExportRows` · `TMDataGridExportApi` | Types | – | – | The export types. |
319
+ | `data-dg-part` | Data attribute | `menu-export`, `menu-export-selected` | – | On the menu items. |