@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/LICENSE +21 -0
- package/README.md +15 -0
- package/dist/index.d.ts +397 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +343 -0
- package/dist/index.js.map +1 -0
- package/dist/style.css +537 -0
- package/package.json +65 -0
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":"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"}
|