@vueye-table/styled 3.0.0-alpha.1

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/index.js ADDED
@@ -0,0 +1,343 @@
1
+ import { columnLabel } from "@vueye-table/core";
2
+ import { DataGridBody, DataGridRoot, DataTableBody, DataTableColumnVisibility, DataTableHeader, DataTableHeaderCell, DataTableHeaderRow, DataTablePageSize, DataTablePagination, DataTableRoot, DataTableSearch, DataTableSortButton, DataTableStatus } from "@vueye-table/headless";
3
+ import { injectDataTable } from "@vueye-table/vue";
4
+ import { defineComponent, h, mergeProps } from "vue";
5
+
6
+ //#region src/icons.ts
7
+ const paths = {
8
+ sortNone: "M7 9l5-5 5 5M7 15l5 5 5-5",
9
+ sortAsc: "M7 14l5-5 5 5",
10
+ sortDesc: "M7 10l5 5 5-5",
11
+ search: "M11 19a8 8 0 1 1 0-16 8 8 0 0 1 0 16zm10 2-4.35-4.35",
12
+ columns: "M4 4h6v16H4zM14 4h6v16h-6z",
13
+ empty: "M3 7h18M3 12h18M3 17h10"
14
+ };
15
+ /** A 24-pixel stroke icon that inherits the text color. */
16
+ function icon(name, className = "vt-icon") {
17
+ return h("svg", {
18
+ class: className,
19
+ viewBox: "0 0 24 24",
20
+ width: 16,
21
+ height: 16,
22
+ fill: "none",
23
+ stroke: "currentColor",
24
+ "stroke-width": 2,
25
+ "stroke-linecap": "round",
26
+ "stroke-linejoin": "round",
27
+ "aria-hidden": "true",
28
+ focusable: "false"
29
+ }, [h("path", { d: paths[name] })]);
30
+ }
31
+
32
+ //#endregion
33
+ //#region src/with-class.ts
34
+ /**
35
+ * Wrap a component so it always carries a class. Props, attributes, and slots pass through
36
+ * untouched, so the wrapper keeps the wrapped component's full API.
37
+ */
38
+ function withClass(component, className, name) {
39
+ const wrapper = (_props, { attrs, slots }) => h(component, mergeProps(attrs, { class: className }), slots);
40
+ wrapper.displayName = name;
41
+ wrapper.inheritAttrs = false;
42
+ return wrapper;
43
+ }
44
+
45
+ //#endregion
46
+ //#region src/components.ts
47
+ /** Visual options shared by the styled table and grid. */
48
+ const surfaceProps = {
49
+ density: {
50
+ type: String,
51
+ default: "comfortable"
52
+ },
53
+ striped: {
54
+ type: Boolean,
55
+ default: false
56
+ },
57
+ bordered: {
58
+ type: Boolean,
59
+ default: false
60
+ },
61
+ hover: {
62
+ type: Boolean,
63
+ default: true
64
+ },
65
+ stickyHeader: {
66
+ type: Boolean,
67
+ default: false
68
+ },
69
+ loading: {
70
+ type: Boolean,
71
+ default: false
72
+ },
73
+ /** Force a theme; by default the table follows `prefers-color-scheme`. */
74
+ theme: {
75
+ type: String,
76
+ default: void 0
77
+ }
78
+ };
79
+ function surfaceAttrs(props) {
80
+ return {
81
+ class: "vt-surface",
82
+ "data-density": props.density,
83
+ "data-striped": props.striped ? "" : void 0,
84
+ "data-bordered": props.bordered ? "" : void 0,
85
+ "data-hover": props.hover ? "" : void 0,
86
+ "data-sticky-header": props.stickyHeader ? "" : void 0,
87
+ "data-loading": props.loading ? "" : void 0,
88
+ "data-vt-theme": props.theme,
89
+ "aria-busy": props.loading ? "true" : void 0
90
+ };
91
+ }
92
+ /** An arrow showing a column's sort direction and, in a multi-column sort, its priority. */
93
+ const VtSortIndicator = defineComponent({
94
+ name: "VtSortIndicator",
95
+ props: { sort: {
96
+ type: Object,
97
+ default: void 0
98
+ } },
99
+ setup(props) {
100
+ const table = injectDataTable("<VtSortIndicator>");
101
+ return () => h("span", {
102
+ class: "vt-sort-indicator",
103
+ "data-active": props.sort ? "" : void 0
104
+ }, [icon(!props.sort ? "sortNone" : props.sort.direction === "asc" ? "sortAsc" : "sortDesc"), props.sort && table.state.sorting.length > 1 ? h("span", { class: "vt-sort-priority" }, String(props.sort.priority + 1)) : null]);
105
+ }
106
+ });
107
+ /** A header row of styled header cells with sort indicators. */
108
+ const VtHeader = defineComponent({
109
+ name: "VtHeader",
110
+ slots: Object,
111
+ setup(_props, { slots }) {
112
+ const table = injectDataTable("<VtHeader>");
113
+ return () => h(DataTableHeader, { class: "vt-head" }, () => h(DataTableHeaderRow, () => [
114
+ slots.before?.(),
115
+ ...table.columns.map((column) => h(DataTableHeaderCell, {
116
+ key: column.id,
117
+ column
118
+ }, { default: slots[`header.${column.id}`] ?? (() => column.sortable ? h(DataTableSortButton, {
119
+ column,
120
+ class: "vt-sort-button"
121
+ }, {
122
+ default: () => [slots.header?.({ column }) ?? column.header],
123
+ indicator: ({ sort }) => [h(VtSortIndicator, { sort })]
124
+ }) : [slots.header?.({ column }) ?? column.header]) })),
125
+ slots.after?.()
126
+ ]));
127
+ }
128
+ });
129
+ /**
130
+ * The styled table surface: a scroll container, a loading bar, and the table. Without a default
131
+ * slot it renders a styled header and body.
132
+ */
133
+ const VtTable = defineComponent({
134
+ name: "VtTable",
135
+ slots: Object,
136
+ props: {
137
+ table: {
138
+ type: Object,
139
+ required: true
140
+ },
141
+ ...surfaceProps
142
+ },
143
+ setup(props, { slots }) {
144
+ return () => h("div", surfaceAttrs(props), [h("div", {
145
+ class: "vt-progress",
146
+ role: "presentation"
147
+ }), h("div", { class: "vt-scroll" }, [h(DataTableRoot, {
148
+ table: props.table,
149
+ class: "vt-table"
150
+ }, { default: () => slots.default?.({ table: props.table }) ?? [h(VtHeader), h(VtBody)] })])]);
151
+ }
152
+ });
153
+ /** The styled body, with the empty state in a full-width row. */
154
+ const VtBody = defineComponent({
155
+ name: "VtBody",
156
+ slots: Object,
157
+ setup(_props, { slots }) {
158
+ return () => h(DataTableBody, { class: "vt-body" }, {
159
+ ...slots,
160
+ empty: slots.empty ?? (() => h(VtEmpty))
161
+ });
162
+ }
163
+ });
164
+ /** The default empty state. */
165
+ const VtEmpty = defineComponent({
166
+ name: "VtEmpty",
167
+ slots: Object,
168
+ props: { text: {
169
+ type: String,
170
+ default: "No matching rows"
171
+ } },
172
+ setup(props, { slots }) {
173
+ return () => h("div", { class: "vt-empty" }, [icon("empty", "vt-empty-icon"), slots.default?.() ?? props.text]);
174
+ }
175
+ });
176
+ /** A search field with an icon. */
177
+ const VtSearch = defineComponent({
178
+ name: "VtSearch",
179
+ inheritAttrs: false,
180
+ setup(_props, { attrs }) {
181
+ return () => h("label", { class: "vt-search" }, [icon("search"), h(DataTableSearch, attrs)]);
182
+ }
183
+ });
184
+ /** "Rows per page" with a picker. */
185
+ const VtPageSize = defineComponent({
186
+ name: "VtPageSize",
187
+ props: {
188
+ options: {
189
+ type: Array,
190
+ default: () => [
191
+ 5,
192
+ 10,
193
+ 20,
194
+ 50
195
+ ]
196
+ },
197
+ label: {
198
+ type: String,
199
+ default: "Rows per page"
200
+ }
201
+ },
202
+ setup(props) {
203
+ return () => h("label", { class: "vt-page-size" }, [h("span", props.label), h(DataTablePageSize, {
204
+ options: props.options,
205
+ label: props.label
206
+ })]);
207
+ }
208
+ });
209
+ /**
210
+ * A menu of column checkboxes behind a "Columns" button. Escape closes it and returns focus to
211
+ * the button, and so does moving focus out of it.
212
+ */
213
+ const VtColumnVisibility = defineComponent({
214
+ name: "VtColumnVisibility",
215
+ props: { label: {
216
+ type: String,
217
+ default: "Columns"
218
+ } },
219
+ setup(props) {
220
+ const close = (menu, refocus) => {
221
+ if (!menu.open) return;
222
+ menu.open = false;
223
+ if (refocus) menu.querySelector("summary")?.focus();
224
+ };
225
+ return () => h("details", {
226
+ class: "vt-menu",
227
+ onKeydown: (event) => {
228
+ if (event.key === "Escape") {
229
+ event.preventDefault();
230
+ close(event.currentTarget, true);
231
+ }
232
+ },
233
+ onFocusout: (event) => {
234
+ const menu = event.currentTarget;
235
+ const next = event.relatedTarget;
236
+ if (next !== null && !menu.contains(next)) close(menu, false);
237
+ }
238
+ }, [h("summary", { class: "vt-button" }, [icon("columns"), props.label]), h(DataTableColumnVisibility, {
239
+ as: "div",
240
+ class: "vt-menu-panel"
241
+ })]);
242
+ }
243
+ });
244
+ const VtPagination = withClass(DataTablePagination, "vt-pagination", "VtPagination");
245
+ const VtStatus = withClass(DataTableStatus, "vt-status", "VtStatus");
246
+ /** A horizontal bar for controls above or below a table. */
247
+ const VtToolbar = defineComponent({
248
+ name: "VtToolbar",
249
+ slots: Object,
250
+ setup(_props, { slots }) {
251
+ return () => h("div", {
252
+ class: "vt-theme vt-toolbar",
253
+ role: "toolbar"
254
+ }, slots.default?.());
255
+ }
256
+ });
257
+ const GridBody = defineComponent({
258
+ name: "VtGridBody",
259
+ props: {
260
+ rowNumbers: {
261
+ type: Boolean,
262
+ default: true
263
+ },
264
+ /** Content slots per column id, as `cell.<id>` on `<VtGrid>`. */
265
+ cells: {
266
+ type: Object,
267
+ default: () => ({})
268
+ }
269
+ },
270
+ setup(props) {
271
+ const table = injectDataTable("<VtGrid>");
272
+ return () => {
273
+ const cellSlots = props.cells;
274
+ const hasCellSlots = Object.keys(cellSlots).length > 0;
275
+ return h(DataGridBody, { class: "vt-body" }, {
276
+ rowHeader: ({ index }) => props.rowNumbers ? h("th", {
277
+ class: "vt-row-number",
278
+ scope: "row"
279
+ }, String(table.pageStart + index)) : null,
280
+ ...hasCellSlots ? { cell: (cellProps) => {
281
+ const slot = cellSlots[cellProps.column.id];
282
+ return slot ? slot(cellProps) : cellProps.display;
283
+ } } : {}
284
+ });
285
+ };
286
+ }
287
+ });
288
+ /**
289
+ * The styled spreadsheet grid, with optional row numbers and A, B, C column letters. A
290
+ * `cell.<column id>` slot draws that column's cells while they are not being edited.
291
+ */
292
+ const VtGrid = defineComponent({
293
+ name: "VtGrid",
294
+ slots: Object,
295
+ props: {
296
+ table: {
297
+ type: Object,
298
+ required: true
299
+ },
300
+ label: {
301
+ type: String,
302
+ default: void 0
303
+ },
304
+ rowNumbers: {
305
+ type: Boolean,
306
+ default: true
307
+ },
308
+ columnLetters: {
309
+ type: Boolean,
310
+ default: false
311
+ },
312
+ ...surfaceProps
313
+ },
314
+ setup(props, { slots }) {
315
+ const cellSlots = () => {
316
+ const found = {};
317
+ for (const [name, slot] of Object.entries(slots)) if (name.startsWith("cell.") && slot) found[name.slice(5)] = slot;
318
+ return found;
319
+ };
320
+ const header = () => h(VtHeader, null, {
321
+ before: () => props.rowNumbers ? h("th", {
322
+ class: "vt-row-number",
323
+ "aria-hidden": "true"
324
+ }) : null,
325
+ header: ({ column }) => props.columnLetters ? [h("span", { class: "vt-column-letter" }, columnLabel(props.table.columns.indexOf(column))), column.header] : column.header
326
+ });
327
+ return () => h("div", surfaceAttrs(props), [h("div", {
328
+ class: "vt-progress",
329
+ role: "presentation"
330
+ }), h("div", { class: "vt-scroll" }, [h(DataGridRoot, {
331
+ table: props.table,
332
+ label: props.label,
333
+ class: "vt-table vt-grid"
334
+ }, { default: (slotProps) => slots.default?.(slotProps) ?? [header(), h(GridBody, {
335
+ rowNumbers: props.rowNumbers,
336
+ cells: cellSlots()
337
+ })] })])]);
338
+ }
339
+ });
340
+
341
+ //#endregion
342
+ export { VtBody, VtColumnVisibility, VtEmpty, VtGrid, VtHeader, VtPageSize, VtPagination, VtSearch, VtSortIndicator, VtStatus, VtTable, VtToolbar, icon, withClass };
343
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/icons.ts","../src/with-class.ts","../src/components.ts"],"sourcesContent":["import { h, type VNode } from \"vue\";\n\nconst paths = {\n sortNone: \"M7 9l5-5 5 5M7 15l5 5 5-5\",\n sortAsc: \"M7 14l5-5 5 5\",\n sortDesc: \"M7 10l5 5 5-5\",\n search: \"M11 19a8 8 0 1 1 0-16 8 8 0 0 1 0 16zm10 2-4.35-4.35\",\n columns: \"M4 4h6v16H4zM14 4h6v16h-6z\",\n empty: \"M3 7h18M3 12h18M3 17h10\",\n} as const;\n\nexport type IconName = keyof typeof paths;\n\n/** A 24-pixel stroke icon that inherits the text color. */\nexport function icon(name: IconName, className = \"vt-icon\"): VNode {\n return h(\n \"svg\",\n {\n class: className,\n viewBox: \"0 0 24 24\",\n width: 16,\n height: 16,\n fill: \"none\",\n stroke: \"currentColor\",\n \"stroke-width\": 2,\n \"stroke-linecap\": \"round\",\n \"stroke-linejoin\": \"round\",\n \"aria-hidden\": \"true\",\n focusable: \"false\",\n },\n [h(\"path\", { d: paths[name] })],\n );\n}\n","import { h, mergeProps, type Component, type FunctionalComponent } from \"vue\";\n\n/**\n * Wrap a component so it always carries a class. Props, attributes, and slots pass through\n * untouched, so the wrapper keeps the wrapped component's full API.\n */\nexport function withClass<TComponent extends Component>(\n component: TComponent,\n className: string,\n name: string,\n): TComponent {\n const wrapper: FunctionalComponent = (_props, { attrs, slots }) =>\n h(component, mergeProps(attrs, { class: className }), slots);\n wrapper.displayName = name;\n wrapper.inheritAttrs = false;\n return wrapper as unknown as TComponent;\n}\n","import { columnLabel, type SortInfo, type TableColumn, type TableRow } from \"@vueye-table/core\";\nimport {\n DataGridBody,\n DataGridRoot,\n DataTableBody,\n DataTableColumnVisibility,\n DataTableHeader,\n DataTableHeaderCell,\n DataTableHeaderRow,\n DataTablePageSize,\n DataTablePagination,\n DataTableRoot,\n DataTableSearch,\n DataTableSortButton,\n DataTableStatus,\n type GridCellSlotProps,\n} from \"@vueye-table/headless\";\nimport { injectDataTable, type AnyDataTableBinding, type DataTableBinding } from \"@vueye-table/vue\";\nimport {\n defineComponent,\n h,\n type PropType,\n type SlotsType,\n type VNode,\n type VNodeChild,\n} from \"vue\";\n\nimport { icon } from \"./icons\";\nimport { withClass } from \"./with-class\";\n\nexport type Density = \"compact\" | \"comfortable\" | \"spacious\";\n\n/** Visual options shared by the styled table and grid. */\nconst surfaceProps = {\n density: { type: String as PropType<Density>, default: \"comfortable\" },\n striped: { type: Boolean, default: false },\n bordered: { type: Boolean, default: false },\n hover: { type: Boolean, default: true },\n stickyHeader: { type: Boolean, default: false },\n loading: { type: Boolean, default: false },\n /** Force a theme; by default the table follows `prefers-color-scheme`. */\n theme: { type: String as PropType<\"light\" | \"dark\" | undefined>, default: undefined },\n} as const;\n\nfunction surfaceAttrs(props: {\n readonly density: Density;\n readonly striped: boolean;\n readonly bordered: boolean;\n readonly hover: boolean;\n readonly stickyHeader: boolean;\n readonly loading: boolean;\n readonly theme: \"light\" | \"dark\" | undefined;\n}) {\n return {\n class: \"vt-surface\",\n \"data-density\": props.density,\n \"data-striped\": props.striped ? \"\" : undefined,\n \"data-bordered\": props.bordered ? \"\" : undefined,\n \"data-hover\": props.hover ? \"\" : undefined,\n \"data-sticky-header\": props.stickyHeader ? \"\" : undefined,\n \"data-loading\": props.loading ? \"\" : undefined,\n \"data-vt-theme\": props.theme,\n \"aria-busy\": props.loading ? \"true\" : undefined,\n };\n}\n\n/** An arrow showing a column's sort direction and, in a multi-column sort, its priority. */\nexport const VtSortIndicator = defineComponent({\n name: \"VtSortIndicator\",\n props: { sort: { type: Object as PropType<SortInfo | undefined>, default: undefined } },\n setup(props) {\n const table = injectDataTable(\"<VtSortIndicator>\");\n return () =>\n h(\"span\", { class: \"vt-sort-indicator\", \"data-active\": props.sort ? \"\" : undefined }, [\n icon(!props.sort ? \"sortNone\" : props.sort.direction === \"asc\" ? \"sortAsc\" : \"sortDesc\"),\n props.sort && table.state.sorting.length > 1\n ? h(\"span\", { class: \"vt-sort-priority\" }, String(props.sort.priority + 1))\n : null,\n ]);\n },\n});\n\n/** A header row of styled header cells with sort indicators. */\nexport const VtHeader = defineComponent({\n name: \"VtHeader\",\n slots: Object as SlotsType<\n {\n [key: `header.${string}`]: (props: {\n column: TableColumn<unknown>;\n sort: SortInfo | undefined;\n toggleSort: (multi?: boolean) => void;\n }) => VNode[];\n } & {\n before?: () => VNode[];\n after?: () => VNode[];\n header?: (props: { column: TableColumn<unknown> }) => VNodeChild;\n }\n >,\n setup(_props, { slots }) {\n const table = injectDataTable(\"<VtHeader>\");\n return () =>\n h(DataTableHeader, { class: \"vt-head\" }, () =>\n h(DataTableHeaderRow, () => [\n slots.before?.(),\n ...table.columns.map((column) =>\n h(\n DataTableHeaderCell,\n { key: column.id, column },\n {\n default:\n slots[`header.${column.id}`] ??\n (() =>\n column.sortable\n ? h(\n DataTableSortButton,\n { column, class: \"vt-sort-button\" },\n {\n default: () => [slots.header?.({ column }) ?? column.header],\n indicator: ({ sort }: { sort: SortInfo | undefined }) => [\n h(VtSortIndicator, { sort }),\n ],\n },\n )\n : [slots.header?.({ column }) ?? column.header]),\n },\n ),\n ),\n slots.after?.(),\n ]),\n );\n },\n});\n\n/**\n * The styled table surface: a scroll container, a loading bar, and the table. Without a default\n * slot it renders a styled header and body.\n */\nexport const VtTable = defineComponent({\n name: \"VtTable\",\n slots: Object as SlotsType<{\n default?: (props: { table: DataTableBinding<unknown> }) => VNode[];\n }>,\n props: {\n table: { type: Object as PropType<AnyDataTableBinding>, required: true },\n ...surfaceProps,\n },\n setup(props, { slots }) {\n return () =>\n h(\"div\", surfaceAttrs(props), [\n h(\"div\", { class: \"vt-progress\", role: \"presentation\" }),\n h(\"div\", { class: \"vt-scroll\" }, [\n h(\n DataTableRoot,\n { table: props.table, class: \"vt-table\" },\n {\n default: () => slots.default?.({ table: props.table }) ?? [h(VtHeader), h(VtBody)],\n },\n ),\n ]),\n ]);\n },\n});\n\n/** The styled body, with the empty state in a full-width row. */\nexport const VtBody = defineComponent({\n name: \"VtBody\",\n slots: Object as SlotsType<{\n default?: (props: { rows: readonly TableRow<unknown>[] }) => VNode[];\n empty?: () => VNode[];\n }>,\n setup(_props, { slots }) {\n return () =>\n h(\n DataTableBody,\n { class: \"vt-body\" },\n {\n ...slots,\n empty: slots.empty ?? (() => h(VtEmpty)),\n },\n );\n },\n});\n\n/** The default empty state. */\nexport const VtEmpty = defineComponent({\n name: \"VtEmpty\",\n slots: Object as SlotsType<{ default?: () => VNode[] }>,\n props: { text: { type: String, default: \"No matching rows\" } },\n setup(props, { slots }) {\n return () =>\n h(\"div\", { class: \"vt-empty\" }, [\n icon(\"empty\", \"vt-empty-icon\"),\n slots.default?.() ?? props.text,\n ]);\n },\n});\n\n/** A search field with an icon. */\nexport const VtSearch = defineComponent({\n name: \"VtSearch\",\n inheritAttrs: false,\n setup(_props, { attrs }) {\n return () => h(\"label\", { class: \"vt-search\" }, [icon(\"search\"), h(DataTableSearch, attrs)]);\n },\n});\n\n/** \"Rows per page\" with a picker. */\nexport const VtPageSize = defineComponent({\n name: \"VtPageSize\",\n props: {\n options: { type: Array as PropType<readonly number[]>, default: () => [5, 10, 20, 50] },\n label: { type: String, default: \"Rows per page\" },\n },\n setup(props) {\n return () =>\n h(\"label\", { class: \"vt-page-size\" }, [\n h(\"span\", props.label),\n h(DataTablePageSize, { options: props.options, label: props.label }),\n ]);\n },\n});\n\n/**\n * A menu of column checkboxes behind a \"Columns\" button. Escape closes it and returns focus to\n * the button, and so does moving focus out of it.\n */\nexport const VtColumnVisibility = defineComponent({\n name: \"VtColumnVisibility\",\n props: { label: { type: String, default: \"Columns\" } },\n setup(props) {\n const close = (menu: HTMLDetailsElement, refocus: boolean): void => {\n if (!menu.open) {\n return;\n }\n menu.open = false;\n if (refocus) {\n menu.querySelector(\"summary\")?.focus();\n }\n };\n return () =>\n h(\n \"details\",\n {\n class: \"vt-menu\",\n onKeydown: (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n close(event.currentTarget as HTMLDetailsElement, true);\n }\n },\n onFocusout: (event: FocusEvent) => {\n const menu = event.currentTarget as HTMLDetailsElement;\n const next = event.relatedTarget as Node | null;\n // Some browsers move no focus when a checkbox label is clicked; only a known\n // destination outside the menu closes it.\n if (next !== null && !menu.contains(next)) {\n close(menu, false);\n }\n },\n },\n [\n h(\"summary\", { class: \"vt-button\" }, [icon(\"columns\"), props.label]),\n h(DataTableColumnVisibility, { as: \"div\", class: \"vt-menu-panel\" }),\n ],\n );\n },\n});\n\nexport const VtPagination = withClass(DataTablePagination, \"vt-pagination\", \"VtPagination\");\nexport const VtStatus = withClass(DataTableStatus, \"vt-status\", \"VtStatus\");\n\n/** A horizontal bar for controls above or below a table. */\nexport const VtToolbar = defineComponent({\n name: \"VtToolbar\",\n slots: Object as SlotsType<{ default?: () => VNode[] }>,\n setup(_props, { slots }) {\n return () => h(\"div\", { class: \"vt-theme vt-toolbar\", role: \"toolbar\" }, slots.default?.());\n },\n});\n\ntype CellSlot = (props: GridCellSlotProps) => VNodeChild;\n\nconst GridBody = defineComponent({\n name: \"VtGridBody\",\n props: {\n rowNumbers: { type: Boolean, default: true },\n /** Content slots per column id, as `cell.<id>` on `<VtGrid>`. */\n cells: {\n type: Object as PropType<Readonly<Record<string, CellSlot | undefined>>>,\n default: () => ({}),\n },\n },\n setup(props) {\n const table = injectDataTable(\"<VtGrid>\");\n return () => {\n const cellSlots = props.cells;\n const hasCellSlots = Object.keys(cellSlots).length > 0;\n return h(\n DataGridBody,\n { class: \"vt-body\" },\n {\n rowHeader: ({ index }: { index: number }) =>\n props.rowNumbers\n ? h(\"th\", { class: \"vt-row-number\", scope: \"row\" }, String(table.pageStart + index))\n : null,\n ...(hasCellSlots\n ? {\n cell: (cellProps: GridCellSlotProps) => {\n const slot = cellSlots[cellProps.column.id];\n return slot ? slot(cellProps) : cellProps.display;\n },\n }\n : {}),\n },\n );\n };\n },\n});\n\n/**\n * The styled spreadsheet grid, with optional row numbers and A, B, C column letters. A\n * `cell.<column id>` slot draws that column's cells while they are not being edited.\n */\nexport const VtGrid = defineComponent({\n name: \"VtGrid\",\n slots: Object as SlotsType<\n { [key: `cell.${string}`]: GridCellSlotProps } & {\n default?: (props: Record<string, unknown>) => VNode[];\n }\n >,\n props: {\n table: { type: Object as PropType<AnyDataTableBinding>, required: true },\n label: { type: String as PropType<string | undefined>, default: undefined },\n rowNumbers: { type: Boolean, default: true },\n columnLetters: { type: Boolean, default: false },\n ...surfaceProps,\n },\n setup(props, { slots }) {\n const cellSlots = (): Record<string, CellSlot> => {\n const found: Record<string, CellSlot> = {};\n for (const [name, slot] of Object.entries(slots)) {\n if (name.startsWith(\"cell.\") && slot) {\n found[name.slice(\"cell.\".length)] = slot as CellSlot;\n }\n }\n return found;\n };\n const header = () =>\n h(VtHeader, null, {\n before: () =>\n props.rowNumbers ? h(\"th\", { class: \"vt-row-number\", \"aria-hidden\": \"true\" }) : null,\n header: ({ column }: { column: TableColumn<unknown> }) =>\n props.columnLetters\n ? [\n h(\n \"span\",\n { class: \"vt-column-letter\" },\n columnLabel(props.table.columns.indexOf(column)),\n ),\n column.header,\n ]\n : column.header,\n });\n return () =>\n h(\"div\", surfaceAttrs(props), [\n h(\"div\", { class: \"vt-progress\", role: \"presentation\" }),\n h(\"div\", { class: \"vt-scroll\" }, [\n h(\n DataGridRoot,\n { table: props.table, label: props.label, class: \"vt-table vt-grid\" },\n {\n default: (slotProps: Record<string, unknown>) =>\n slots.default?.(slotProps) ?? [\n header(),\n h(GridBody, { rowNumbers: props.rowNumbers, cells: cellSlots() }),\n ],\n },\n ),\n ]),\n ]);\n },\n});\n"],"mappings":";;;;;;AAEA,MAAM,QAAQ;CACZ,UAAU;CACV,SAAS;CACT,UAAU;CACV,QAAQ;CACR,SAAS;CACT,OAAO;AACT;;AAKA,SAAgB,KAAK,MAAgB,YAAY,WAAkB;CACjE,OAAO,EACL,OACA;EACE,OAAO;EACP,SAAS;EACT,OAAO;EACP,QAAQ;EACR,MAAM;EACN,QAAQ;EACR,gBAAgB;EAChB,kBAAkB;EAClB,mBAAmB;EACnB,eAAe;EACf,WAAW;CACb,GACA,CAAC,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,CAAC,CAChC;AACF;;;;;;;;AC1BA,SAAgB,UACd,WACA,WACA,MACY;CACZ,MAAM,WAAgC,QAAQ,EAAE,OAAO,YACrD,EAAE,WAAW,WAAW,OAAO,EAAE,OAAO,UAAU,CAAC,GAAG,KAAK;CAC7D,QAAQ,cAAc;CACtB,QAAQ,eAAe;CACvB,OAAO;AACT;;;;;ACiBA,MAAM,eAAe;CACnB,SAAS;EAAE,MAAM;EAA6B,SAAS;CAAc;CACrE,SAAS;EAAE,MAAM;EAAS,SAAS;CAAM;CACzC,UAAU;EAAE,MAAM;EAAS,SAAS;CAAM;CAC1C,OAAO;EAAE,MAAM;EAAS,SAAS;CAAK;CACtC,cAAc;EAAE,MAAM;EAAS,SAAS;CAAM;CAC9C,SAAS;EAAE,MAAM;EAAS,SAAS;CAAM;;CAEzC,OAAO;EAAE,MAAM;EAAkD,SAAS;CAAU;AACtF;AAEA,SAAS,aAAa,OAQnB;CACD,OAAO;EACL,OAAO;EACP,gBAAgB,MAAM;EACtB,gBAAgB,MAAM,UAAU,KAAK;EACrC,iBAAiB,MAAM,WAAW,KAAK;EACvC,cAAc,MAAM,QAAQ,KAAK;EACjC,sBAAsB,MAAM,eAAe,KAAK;EAChD,gBAAgB,MAAM,UAAU,KAAK;EACrC,iBAAiB,MAAM;EACvB,aAAa,MAAM,UAAU,SAAS;CACxC;AACF;;AAGA,MAAa,kBAAkB,gBAAgB;CAC7C,MAAM;CACN,OAAO,EAAE,MAAM;EAAE,MAAM;EAA0C,SAAS;CAAU,EAAE;CACtF,MAAM,OAAO;EACX,MAAM,QAAQ,gBAAgB,mBAAmB;EACjD,aACE,EAAE,QAAQ;GAAE,OAAO;GAAqB,eAAe,MAAM,OAAO,KAAK;EAAU,GAAG,CACpF,KAAK,CAAC,MAAM,OAAO,aAAa,MAAM,KAAK,cAAc,QAAQ,YAAY,UAAU,GACvF,MAAM,QAAQ,MAAM,MAAM,QAAQ,SAAS,IACvC,EAAE,QAAQ,EAAE,OAAO,mBAAmB,GAAG,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,IACxE,IACN,CAAC;CACL;AACF,CAAC;;AAGD,MAAa,WAAW,gBAAgB;CACtC,MAAM;CACN,OAAO;CAaP,MAAM,QAAQ,EAAE,SAAS;EACvB,MAAM,QAAQ,gBAAgB,YAAY;EAC1C,aACE,EAAE,iBAAiB,EAAE,OAAO,UAAU,SACpC,EAAE,0BAA0B;GAC1B,MAAM,SAAS;GACf,GAAG,MAAM,QAAQ,KAAK,WACpB,EACE,qBACA;IAAE,KAAK,OAAO;IAAI;GAAO,GACzB,EACE,SACE,MAAM,UAAU,OAAO,gBAErB,OAAO,WACH,EACE,qBACA;IAAE;IAAQ,OAAO;GAAiB,GAClC;IACE,eAAe,CAAC,MAAM,SAAS,EAAE,OAAO,CAAC,KAAK,OAAO,MAAM;IAC3D,YAAY,EAAE,WAA2C,CACvD,EAAE,iBAAiB,EAAE,KAAK,CAAC,CAC7B;GACF,CACF,IACA,CAAC,MAAM,SAAS,EAAE,OAAO,CAAC,KAAK,OAAO,MAAM,GACtD,CACF,CACF;GACA,MAAM,QAAQ;EAChB,CAAC,CACH;CACJ;AACF,CAAC;;;;;AAMD,MAAa,UAAU,gBAAgB;CACrC,MAAM;CACN,OAAO;CAGP,OAAO;EACL,OAAO;GAAE,MAAM;GAAyC,UAAU;EAAK;EACvE,GAAG;CACL;CACA,MAAM,OAAO,EAAE,SAAS;EACtB,aACE,EAAE,OAAO,aAAa,KAAK,GAAG,CAC5B,EAAE,OAAO;GAAE,OAAO;GAAe,MAAM;EAAe,CAAC,GACvD,EAAE,OAAO,EAAE,OAAO,YAAY,GAAG,CAC/B,EACE,eACA;GAAE,OAAO,MAAM;GAAO,OAAO;EAAW,GACxC,EACE,eAAe,MAAM,UAAU,EAAE,OAAO,MAAM,MAAM,CAAC,KAAK,CAAC,EAAE,QAAQ,GAAG,EAAE,MAAM,CAAC,EACnF,CACF,CACF,CAAC,CACH,CAAC;CACL;AACF,CAAC;;AAGD,MAAa,SAAS,gBAAgB;CACpC,MAAM;CACN,OAAO;CAIP,MAAM,QAAQ,EAAE,SAAS;EACvB,aACE,EACE,eACA,EAAE,OAAO,UAAU,GACnB;GACE,GAAG;GACH,OAAO,MAAM,gBAAgB,EAAE,OAAO;EACxC,CACF;CACJ;AACF,CAAC;;AAGD,MAAa,UAAU,gBAAgB;CACrC,MAAM;CACN,OAAO;CACP,OAAO,EAAE,MAAM;EAAE,MAAM;EAAQ,SAAS;CAAmB,EAAE;CAC7D,MAAM,OAAO,EAAE,SAAS;EACtB,aACE,EAAE,OAAO,EAAE,OAAO,WAAW,GAAG,CAC9B,KAAK,SAAS,eAAe,GAC7B,MAAM,UAAU,KAAK,MAAM,IAC7B,CAAC;CACL;AACF,CAAC;;AAGD,MAAa,WAAW,gBAAgB;CACtC,MAAM;CACN,cAAc;CACd,MAAM,QAAQ,EAAE,SAAS;EACvB,aAAa,EAAE,SAAS,EAAE,OAAO,YAAY,GAAG,CAAC,KAAK,QAAQ,GAAG,EAAE,iBAAiB,KAAK,CAAC,CAAC;CAC7F;AACF,CAAC;;AAGD,MAAa,aAAa,gBAAgB;CACxC,MAAM;CACN,OAAO;EACL,SAAS;GAAE,MAAM;GAAsC,eAAe;IAAC;IAAG;IAAI;IAAI;GAAE;EAAE;EACtF,OAAO;GAAE,MAAM;GAAQ,SAAS;EAAgB;CAClD;CACA,MAAM,OAAO;EACX,aACE,EAAE,SAAS,EAAE,OAAO,eAAe,GAAG,CACpC,EAAE,QAAQ,MAAM,KAAK,GACrB,EAAE,mBAAmB;GAAE,SAAS,MAAM;GAAS,OAAO,MAAM;EAAM,CAAC,CACrE,CAAC;CACL;AACF,CAAC;;;;;AAMD,MAAa,qBAAqB,gBAAgB;CAChD,MAAM;CACN,OAAO,EAAE,OAAO;EAAE,MAAM;EAAQ,SAAS;CAAU,EAAE;CACrD,MAAM,OAAO;EACX,MAAM,SAAS,MAA0B,YAA2B;GAClE,IAAI,CAAC,KAAK,MACR;GAEF,KAAK,OAAO;GACZ,IAAI,SACF,KAAK,cAAc,SAAS,CAAC,EAAE,MAAM;EAEzC;EACA,aACE,EACE,WACA;GACE,OAAO;GACP,YAAY,UAAyB;IACnC,IAAI,MAAM,QAAQ,UAAU;KAC1B,MAAM,eAAe;KACrB,MAAM,MAAM,eAAqC,IAAI;IACvD;GACF;GACA,aAAa,UAAsB;IACjC,MAAM,OAAO,MAAM;IACnB,MAAM,OAAO,MAAM;IAGnB,IAAI,SAAS,QAAQ,CAAC,KAAK,SAAS,IAAI,GACtC,MAAM,MAAM,KAAK;GAErB;EACF,GACA,CACE,EAAE,WAAW,EAAE,OAAO,YAAY,GAAG,CAAC,KAAK,SAAS,GAAG,MAAM,KAAK,CAAC,GACnE,EAAE,2BAA2B;GAAE,IAAI;GAAO,OAAO;EAAgB,CAAC,CACpE,CACF;CACJ;AACF,CAAC;AAED,MAAa,eAAe,UAAU,qBAAqB,iBAAiB,cAAc;AAC1F,MAAa,WAAW,UAAU,iBAAiB,aAAa,UAAU;;AAG1E,MAAa,YAAY,gBAAgB;CACvC,MAAM;CACN,OAAO;CACP,MAAM,QAAQ,EAAE,SAAS;EACvB,aAAa,EAAE,OAAO;GAAE,OAAO;GAAuB,MAAM;EAAU,GAAG,MAAM,UAAU,CAAC;CAC5F;AACF,CAAC;AAID,MAAM,WAAW,gBAAgB;CAC/B,MAAM;CACN,OAAO;EACL,YAAY;GAAE,MAAM;GAAS,SAAS;EAAK;;EAE3C,OAAO;GACL,MAAM;GACN,gBAAgB,CAAC;EACnB;CACF;CACA,MAAM,OAAO;EACX,MAAM,QAAQ,gBAAgB,UAAU;EACxC,aAAa;GACX,MAAM,YAAY,MAAM;GACxB,MAAM,eAAe,OAAO,KAAK,SAAS,CAAC,CAAC,SAAS;GACrD,OAAO,EACL,cACA,EAAE,OAAO,UAAU,GACnB;IACE,YAAY,EAAE,YACZ,MAAM,aACF,EAAE,MAAM;KAAE,OAAO;KAAiB,OAAO;IAAM,GAAG,OAAO,MAAM,YAAY,KAAK,CAAC,IACjF;IACN,GAAI,eACA,EACE,OAAO,cAAiC;KACtC,MAAM,OAAO,UAAU,UAAU,OAAO;KACxC,OAAO,OAAO,KAAK,SAAS,IAAI,UAAU;IAC5C,EACF,IACA,CAAC;GACP,CACF;EACF;CACF;AACF,CAAC;;;;;AAMD,MAAa,SAAS,gBAAgB;CACpC,MAAM;CACN,OAAO;CAKP,OAAO;EACL,OAAO;GAAE,MAAM;GAAyC,UAAU;EAAK;EACvE,OAAO;GAAE,MAAM;GAAwC,SAAS;EAAU;EAC1E,YAAY;GAAE,MAAM;GAAS,SAAS;EAAK;EAC3C,eAAe;GAAE,MAAM;GAAS,SAAS;EAAM;EAC/C,GAAG;CACL;CACA,MAAM,OAAO,EAAE,SAAS;EACtB,MAAM,kBAA4C;GAChD,MAAM,QAAkC,CAAC;GACzC,KAAK,MAAM,CAAC,MAAM,SAAS,OAAO,QAAQ,KAAK,GAC7C,IAAI,KAAK,WAAW,OAAO,KAAK,MAC9B,MAAM,KAAK,MAAM,CAAc,KAAK;GAGxC,OAAO;EACT;EACA,MAAM,eACJ,EAAE,UAAU,MAAM;GAChB,cACE,MAAM,aAAa,EAAE,MAAM;IAAE,OAAO;IAAiB,eAAe;GAAO,CAAC,IAAI;GAClF,SAAS,EAAE,aACT,MAAM,gBACF,CACE,EACE,QACA,EAAE,OAAO,mBAAmB,GAC5B,YAAY,MAAM,MAAM,QAAQ,QAAQ,MAAM,CAAC,CACjD,GACA,OAAO,MACT,IACA,OAAO;EACf,CAAC;EACH,aACE,EAAE,OAAO,aAAa,KAAK,GAAG,CAC5B,EAAE,OAAO;GAAE,OAAO;GAAe,MAAM;EAAe,CAAC,GACvD,EAAE,OAAO,EAAE,OAAO,YAAY,GAAG,CAC/B,EACE,cACA;GAAE,OAAO,MAAM;GAAO,OAAO,MAAM;GAAO,OAAO;EAAmB,GACpE,EACE,UAAU,cACR,MAAM,UAAU,SAAS,KAAK,CAC5B,OAAO,GACP,EAAE,UAAU;GAAE,YAAY,MAAM;GAAY,OAAO,UAAU;EAAE,CAAC,CAClE,EACJ,CACF,CACF,CAAC,CACH,CAAC;CACL;AACF,CAAC"}