@lapis-notes/bases 0.1.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.
- package/CHANGELOG.md +6 -0
- package/LICENSE.md +8 -0
- package/README.md +20 -0
- package/dist/bases-plugin.d.ts +10 -0
- package/dist/bases-plugin.js +118 -0
- package/dist/bases-view/app-database-query-source.d.ts +30 -0
- package/dist/bases-view/app-database-query-source.js +248 -0
- package/dist/bases-view/bases.svelte.d.ts +569 -0
- package/dist/bases-view/bases.svelte.js +910 -0
- package/dist/bases-view/card-view/components/card-placeholder.svelte +68 -0
- package/dist/bases-view/card-view/components/card-placeholder.svelte.d.ts +7 -0
- package/dist/bases-view/card-view/components/card.svelte +289 -0
- package/dist/bases-view/card-view/components/card.svelte.d.ts +7 -0
- package/dist/bases-view/card-view/index.d.ts +11 -0
- package/dist/bases-view/card-view/index.js +55 -0
- package/dist/bases-view/cell-editor-options.d.ts +2 -0
- package/dist/bases-view/cell-editor-options.js +26 -0
- package/dist/bases-view/cell-editor.svelte +206 -0
- package/dist/bases-view/cell-editor.svelte.d.ts +12 -0
- package/dist/bases-view/cell.svelte +132 -0
- package/dist/bases-view/cell.svelte.d.ts +16 -0
- package/dist/bases-view/column-definition.d.ts +22 -0
- package/dist/bases-view/column-definition.js +149 -0
- package/dist/bases-view/columns.d.ts +15 -0
- package/dist/bases-view/columns.js +103 -0
- package/dist/bases-view/components/Tag.svelte +14 -0
- package/dist/bases-view/components/Tag.svelte.d.ts +8 -0
- package/dist/bases-view/components/autocomplete.svelte +45 -0
- package/dist/bases-view/components/autocomplete.svelte.d.ts +17 -0
- package/dist/bases-view/components/card-image.svelte +121 -0
- package/dist/bases-view/components/card-image.svelte.d.ts +11 -0
- package/dist/bases-view/components/column-visibility.svelte +388 -0
- package/dist/bases-view/components/column-visibility.svelte.d.ts +13 -0
- package/dist/bases-view/components/datetime.svelte +35 -0
- package/dist/bases-view/components/datetime.svelte.d.ts +7 -0
- package/dist/bases-view/components/file.svelte +31 -0
- package/dist/bases-view/components/file.svelte.d.ts +8 -0
- package/dist/bases-view/components/filters/filter-editor.svelte +102 -0
- package/dist/bases-view/components/filters/filter-editor.svelte.d.ts +10 -0
- package/dist/bases-view/components/filters/filter-group.svelte +142 -0
- package/dist/bases-view/components/filters/filter-group.svelte.d.ts +11 -0
- package/dist/bases-view/components/filters/filter-properties.svelte +77 -0
- package/dist/bases-view/components/filters/filter-properties.svelte.d.ts +8 -0
- package/dist/bases-view/components/filters/filter-root.svelte +112 -0
- package/dist/bases-view/components/filters/filter-root.svelte.d.ts +12 -0
- package/dist/bases-view/components/filters/filter-row.svelte +351 -0
- package/dist/bases-view/components/filters/filter-row.svelte.d.ts +11 -0
- package/dist/bases-view/components/group/group-root.svelte +120 -0
- package/dist/bases-view/components/group/group-root.svelte.d.ts +8 -0
- package/dist/bases-view/components/limit.svelte +100 -0
- package/dist/bases-view/components/limit.svelte.d.ts +12 -0
- package/dist/bases-view/components/query-editor.svelte +230 -0
- package/dist/bases-view/components/query-editor.svelte.d.ts +15 -0
- package/dist/bases-view/components/sort/sort-direction-labels.d.ts +9 -0
- package/dist/bases-view/components/sort/sort-direction-labels.js +25 -0
- package/dist/bases-view/components/sort/sort-root.svelte +239 -0
- package/dist/bases-view/components/sort/sort-root.svelte.d.ts +11 -0
- package/dist/bases-view/components/sort/sort-row.svelte +190 -0
- package/dist/bases-view/components/sort/sort-row.svelte.d.ts +15 -0
- package/dist/bases-view/components/summary-strip.svelte +56 -0
- package/dist/bases-view/components/summary-strip.svelte.d.ts +8 -0
- package/dist/bases-view/components/tag-chip.svelte +47 -0
- package/dist/bases-view/components/tag-chip.svelte.d.ts +12 -0
- package/dist/bases-view/components/views.svelte +178 -0
- package/dist/bases-view/components/views.svelte.d.ts +12 -0
- package/dist/bases-view/data-table-adapter/data-table.svelte.d.ts +45 -0
- package/dist/bases-view/data-table-adapter/data-table.svelte.js +112 -0
- package/dist/bases-view/data-table-adapter/flex-render.svelte +43 -0
- package/dist/bases-view/data-table-adapter/flex-render.svelte.d.ts +30 -0
- package/dist/bases-view/data-table-adapter/index.d.ts +3 -0
- package/dist/bases-view/data-table-adapter/index.js +3 -0
- package/dist/bases-view/data-table-adapter/render-helpers.d.ts +101 -0
- package/dist/bases-view/data-table-adapter/render-helpers.js +110 -0
- package/dist/bases-view/db.d.ts +31 -0
- package/dist/bases-view/db.js +174 -0
- package/dist/bases-view/document-core.d.ts +2 -0
- package/dist/bases-view/document-core.js +166 -0
- package/dist/bases-view/export-core.d.ts +4 -0
- package/dist/bases-view/export-core.js +31 -0
- package/dist/bases-view/file-fields-core.d.ts +31 -0
- package/dist/bases-view/file-fields-core.js +114 -0
- package/dist/bases-view/filter-parser.d.ts +27 -0
- package/dist/bases-view/filter-parser.js +315 -0
- package/dist/bases-view/functions-core.d.ts +66 -0
- package/dist/bases-view/functions-core.js +265 -0
- package/dist/bases-view/functions.d.ts +5 -0
- package/dist/bases-view/functions.js +107 -0
- package/dist/bases-view/fuzzy-search.d.ts +6 -0
- package/dist/bases-view/fuzzy-search.js +15 -0
- package/dist/bases-view/hooks/useResizeObserver.svelte.d.ts +7 -0
- package/dist/bases-view/hooks/useResizeObserver.svelte.js +26 -0
- package/dist/bases-view/index.d.ts +66 -0
- package/dist/bases-view/index.js +231 -0
- package/dist/bases-view/list-view/index.d.ts +10 -0
- package/dist/bases-view/list-view/index.js +17 -0
- package/dist/bases-view/list-view/list.svelte +156 -0
- package/dist/bases-view/list-view/list.svelte.d.ts +7 -0
- package/dist/bases-view/map-view/index.d.ts +10 -0
- package/dist/bases-view/map-view/index.js +17 -0
- package/dist/bases-view/map-view/view.svelte +28 -0
- package/dist/bases-view/map-view/view.svelte.d.ts +7 -0
- package/dist/bases-view/metadata-invalidation-core.d.ts +34 -0
- package/dist/bases-view/metadata-invalidation-core.js +162 -0
- package/dist/bases-view/metadata-type-info.d.ts +7 -0
- package/dist/bases-view/metadata-type-info.js +10 -0
- package/dist/bases-view/models.d.ts +90 -0
- package/dist/bases-view/models.js +133 -0
- package/dist/bases-view/query-result-core.d.ts +8 -0
- package/dist/bases-view/query-result-core.js +16 -0
- package/dist/bases-view/resource-url.d.ts +2 -0
- package/dist/bases-view/resource-url.js +21 -0
- package/dist/bases-view/search-core.d.ts +9 -0
- package/dist/bases-view/search-core.js +20 -0
- package/dist/bases-view/summary-core.d.ts +7 -0
- package/dist/bases-view/summary-core.js +17 -0
- package/dist/bases-view/table-view/components/div-table.svelte +464 -0
- package/dist/bases-view/table-view/components/div-table.svelte.d.ts +32 -0
- package/dist/bases-view/table-view/components/dnd-style.d.ts +3 -0
- package/dist/bases-view/table-view/components/dnd-style.js +6 -0
- package/dist/bases-view/table-view/components/sort-header.svelte +48 -0
- package/dist/bases-view/table-view/components/sort-header.svelte.d.ts +11 -0
- package/dist/bases-view/table-view/components/table-column-tracks.d.ts +14 -0
- package/dist/bases-view/table-view/components/table-column-tracks.js +27 -0
- package/dist/bases-view/table-view/components/table-header.svelte +146 -0
- package/dist/bases-view/table-view/components/table-header.svelte.d.ts +10 -0
- package/dist/bases-view/table-view/components/table-placeholder.svelte +46 -0
- package/dist/bases-view/table-view/components/table-placeholder.svelte.d.ts +30 -0
- package/dist/bases-view/table-view/components/table-virtualizer-core.d.ts +13 -0
- package/dist/bases-view/table-view/components/table-virtualizer-core.js +12 -0
- package/dist/bases-view/table-view/components/table.svelte +997 -0
- package/dist/bases-view/table-view/components/table.svelte.d.ts +32 -0
- package/dist/bases-view/table-view/index.svelte.d.ts +10 -0
- package/dist/bases-view/table-view/index.svelte.js +30 -0
- package/dist/bases-view/unknown-view/index.d.ts +10 -0
- package/dist/bases-view/unknown-view/index.js +19 -0
- package/dist/bases-view/unknown-view/view.svelte +11 -0
- package/dist/bases-view/unknown-view/view.svelte.d.ts +6 -0
- package/dist/bases-view/view-header.svelte +142 -0
- package/dist/bases-view/view-header.svelte.d.ts +28 -0
- package/dist/bases-view/view-registration-inventory.d.ts +22 -0
- package/dist/bases-view/view-registration-inventory.js +7 -0
- package/dist/bases-view/view-settings.svelte +350 -0
- package/dist/bases-view/view-settings.svelte.d.ts +9 -0
- package/dist/bases-view/view.svelte +192 -0
- package/dist/bases-view/view.svelte.d.ts +15 -0
- package/dist/bases-view-surface.svelte +31 -0
- package/dist/bases-view-surface.svelte.d.ts +14 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +8 -0
- package/dist/serialized-write-queue.d.ts +10 -0
- package/dist/serialized-write-queue.js +36 -0
- package/dist/styles.css +2164 -0
- package/manifest.json +33 -0
- package/package.json +90 -0
- package/styles.css +1 -0
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
<script lang="ts" generics="TData, TValue">
|
|
2
|
+
import {
|
|
3
|
+
getCoreRowModel,
|
|
4
|
+
getSortedRowModel,
|
|
5
|
+
type ColumnDef,
|
|
6
|
+
type ColumnOrderState,
|
|
7
|
+
type ColumnSizingInfoState,
|
|
8
|
+
type ColumnSizingState,
|
|
9
|
+
type Header,
|
|
10
|
+
type VisibilityState,
|
|
11
|
+
} from "@tanstack/table-core";
|
|
12
|
+
import * as Table from "@lapismd/design-core/shadcn/table";
|
|
13
|
+
import TableHeader from "./table-header.svelte";
|
|
14
|
+
import { DragDropProvider } from "@dnd-kit/svelte";
|
|
15
|
+
import type { DragEndEvent } from "@dnd-kit/dom";
|
|
16
|
+
import { arrayMove } from "@dnd-kit/helpers";
|
|
17
|
+
import { styleObjectToString } from "./dnd-style";
|
|
18
|
+
import { createVirtualizer, type MetadataType } from "@lapis-notes/api";
|
|
19
|
+
import Cell from "../../cell.svelte";
|
|
20
|
+
import {
|
|
21
|
+
BasesEntry,
|
|
22
|
+
type BasesPropertyId,
|
|
23
|
+
type BasesView,
|
|
24
|
+
type QueryController,
|
|
25
|
+
} from "../../bases.svelte";
|
|
26
|
+
import {
|
|
27
|
+
createSvelteTable,
|
|
28
|
+
renderComponent,
|
|
29
|
+
} from "../../data-table-adapter";
|
|
30
|
+
import { getMetadataTypeInfo } from "../../metadata-type-info";
|
|
31
|
+
import type { SortColumn } from "../../models";
|
|
32
|
+
import SortHeader from "./sort-header.svelte";
|
|
33
|
+
import { onMount } from "svelte";
|
|
34
|
+
import TablePlaceholder from "./table-placeholder.svelte";
|
|
35
|
+
|
|
36
|
+
type DataTableProps = {
|
|
37
|
+
view: BasesView;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
let { view }: DataTableProps = $props();
|
|
41
|
+
|
|
42
|
+
let queryResults = $derived(view.data);
|
|
43
|
+
|
|
44
|
+
let columnSizingInfo: ColumnSizingInfoState = $state({
|
|
45
|
+
columnSizingStart: [],
|
|
46
|
+
deltaOffset: null,
|
|
47
|
+
deltaPercentage: null,
|
|
48
|
+
isResizingColumn: false,
|
|
49
|
+
startOffset: null,
|
|
50
|
+
startSize: null,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
let types = $derived.by(() => {
|
|
54
|
+
return queryResults.properties
|
|
55
|
+
.filter((it) => it.startsWith("note."))
|
|
56
|
+
.reduce<Record<string, { type: MetadataType; icon: string }>>(
|
|
57
|
+
(acc, id) => {
|
|
58
|
+
const key = id.substring(5);
|
|
59
|
+
const { type, icon } = getMetadataTypeInfo(
|
|
60
|
+
key,
|
|
61
|
+
"text",
|
|
62
|
+
view.controller.app,
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
acc[id] = { type, icon };
|
|
66
|
+
return acc;
|
|
67
|
+
},
|
|
68
|
+
{},
|
|
69
|
+
);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const FILE_ICONS: Record<string, string> = {
|
|
73
|
+
file: "lucide-file",
|
|
74
|
+
"file.name": "lucide-text",
|
|
75
|
+
"file.basename": "lucide-text",
|
|
76
|
+
"file.fullname": "lucide-text",
|
|
77
|
+
"file.folder": "lucide-text",
|
|
78
|
+
"file.path": "lucide-text",
|
|
79
|
+
"file.ext": "lucide-text",
|
|
80
|
+
"file.ctime": "lucide-clock",
|
|
81
|
+
"file.mtime": "lucide-clock",
|
|
82
|
+
"file.size": "lucide-binary",
|
|
83
|
+
"file.tags": "lucide-tags",
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
function getIcon(id: BasesPropertyId) {
|
|
87
|
+
if (id.startsWith("formula.")) {
|
|
88
|
+
return "lucide-square-function";
|
|
89
|
+
} else if (id.startsWith("file.")) {
|
|
90
|
+
return FILE_ICONS[id] || "lucide-file";
|
|
91
|
+
}
|
|
92
|
+
return types[id]?.icon || "lucide-file";
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function estimateTextWidth(
|
|
96
|
+
text: string,
|
|
97
|
+
font: string = '16px ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"',
|
|
98
|
+
): number {
|
|
99
|
+
if (!text) return 0;
|
|
100
|
+
// Reuse a single offscreen canvas for performance
|
|
101
|
+
const canvas: HTMLCanvasElement =
|
|
102
|
+
(estimateTextWidth as any)._canvas ||
|
|
103
|
+
((estimateTextWidth as any)._canvas = document.createElement("canvas"));
|
|
104
|
+
const context = canvas.getContext("2d");
|
|
105
|
+
if (!context) throw new Error("2D context not available on this browser.");
|
|
106
|
+
|
|
107
|
+
context.font = font;
|
|
108
|
+
const metrics = context.measureText(text);
|
|
109
|
+
return metrics.width;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
let columns: Array<ColumnDef<BasesEntry, any>> = $derived.by(() => {
|
|
113
|
+
return view.allProperties.map((id) => {
|
|
114
|
+
return {
|
|
115
|
+
id: id,
|
|
116
|
+
accessorKey: id,
|
|
117
|
+
accessorFn: (row) => {
|
|
118
|
+
return row.getValue(id);
|
|
119
|
+
},
|
|
120
|
+
header: ({ column }) => {
|
|
121
|
+
return renderComponent(SortHeader, {
|
|
122
|
+
text: view.config.getDisplayName(id),
|
|
123
|
+
icon: getIcon(id),
|
|
124
|
+
direction: column.getIsSorted(),
|
|
125
|
+
onclick: column.getToggleSortingHandler(),
|
|
126
|
+
});
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
let widths: Record<string, number> = $derived.by(() => {
|
|
133
|
+
const sizes: Record<string, number> = {};
|
|
134
|
+
for (const row of queryResults.data) {
|
|
135
|
+
for (const column of columns) {
|
|
136
|
+
const id = column.id!;
|
|
137
|
+
if (sizes[id] === 300) continue;
|
|
138
|
+
const size = estimateTextWidth(row.getValue(id)?.value?.toString());
|
|
139
|
+
if (!size) continue;
|
|
140
|
+
sizes[id] = Math.min(size, 300);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
console.log("sizes", sizes);
|
|
144
|
+
return sizes;
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
let columnOrder = $derived(view.config.getOrder());
|
|
148
|
+
|
|
149
|
+
const table = createSvelteTable({
|
|
150
|
+
get data() {
|
|
151
|
+
return queryResults.data;
|
|
152
|
+
},
|
|
153
|
+
get columns() {
|
|
154
|
+
return columns;
|
|
155
|
+
},
|
|
156
|
+
defaultColumn: {
|
|
157
|
+
minSize: 60,
|
|
158
|
+
size: 300,
|
|
159
|
+
maxSize: 800,
|
|
160
|
+
},
|
|
161
|
+
manualPagination: true,
|
|
162
|
+
manualSorting: true,
|
|
163
|
+
columnResizeMode: "onChange",
|
|
164
|
+
enableSortingRemoval: true,
|
|
165
|
+
isMultiSortEvent: (e) => true,
|
|
166
|
+
getCoreRowModel: getCoreRowModel(),
|
|
167
|
+
getSortedRowModel: getSortedRowModel(),
|
|
168
|
+
onSortingChange: (updater) => {
|
|
169
|
+
let sorting = view.config.getSort().map((s) => ({
|
|
170
|
+
id: s.property as string,
|
|
171
|
+
desc: s.direction === "DESC",
|
|
172
|
+
}));
|
|
173
|
+
if (typeof updater === "function") {
|
|
174
|
+
sorting = updater(sorting);
|
|
175
|
+
} else {
|
|
176
|
+
sorting = updater;
|
|
177
|
+
}
|
|
178
|
+
view.config.set(
|
|
179
|
+
"sort",
|
|
180
|
+
sorting.map((s) => ({
|
|
181
|
+
property: s.id,
|
|
182
|
+
direction: s.desc ? "DESC" : "ASC",
|
|
183
|
+
})) as Array<SortColumn>,
|
|
184
|
+
);
|
|
185
|
+
},
|
|
186
|
+
onColumnVisibilityChange: (updater) => {
|
|
187
|
+
let columnVisibility: VisibilityState = columns.reduce<VisibilityState>(
|
|
188
|
+
(acc, value) => {
|
|
189
|
+
const id = value.id as BasesPropertyId;
|
|
190
|
+
if (id) {
|
|
191
|
+
acc[id] = view.config.getOrder().includes(id);
|
|
192
|
+
}
|
|
193
|
+
return acc;
|
|
194
|
+
},
|
|
195
|
+
{},
|
|
196
|
+
);
|
|
197
|
+
if (typeof updater === "function") {
|
|
198
|
+
columnVisibility = updater(columnVisibility);
|
|
199
|
+
} else {
|
|
200
|
+
columnVisibility = updater;
|
|
201
|
+
}
|
|
202
|
+
const order: string[] = [];
|
|
203
|
+
view.config.getOrder().forEach((id) => {
|
|
204
|
+
if (columnVisibility[id]) {
|
|
205
|
+
order.push(id);
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
const newColumns = Object.keys(columnVisibility).filter(
|
|
209
|
+
(k) => columnVisibility[k] && !order.includes(k),
|
|
210
|
+
);
|
|
211
|
+
view.config.set("order", [...order, ...newColumns]);
|
|
212
|
+
},
|
|
213
|
+
onColumnSizingInfoChange: (updater) => {
|
|
214
|
+
if (typeof updater === "function") {
|
|
215
|
+
columnSizingInfo = updater(columnSizingInfo);
|
|
216
|
+
} else {
|
|
217
|
+
columnSizingInfo = updater;
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
onColumnSizingChange: (updater) => {
|
|
221
|
+
let columnSizing: ColumnSizingState = {
|
|
222
|
+
...(view.config.get("columnSize") || {}),
|
|
223
|
+
};
|
|
224
|
+
if (typeof updater === "function") {
|
|
225
|
+
columnSizing = updater(columnSizing);
|
|
226
|
+
} else {
|
|
227
|
+
columnSizing = updater;
|
|
228
|
+
}
|
|
229
|
+
view.config.set("columnSize", columnSizing);
|
|
230
|
+
},
|
|
231
|
+
onColumnOrderChange: (updater) => {
|
|
232
|
+
let columnOrder: ColumnOrderState = [...view.config.getOrder()];
|
|
233
|
+
if (typeof updater === "function") {
|
|
234
|
+
columnOrder = updater(columnOrder);
|
|
235
|
+
} else {
|
|
236
|
+
columnOrder = updater;
|
|
237
|
+
}
|
|
238
|
+
view.config.set("order", columnOrder);
|
|
239
|
+
},
|
|
240
|
+
state: {
|
|
241
|
+
get sorting() {
|
|
242
|
+
return view.config
|
|
243
|
+
.getSort()
|
|
244
|
+
.map((s) => ({ id: s.property, desc: s.direction === "DESC" }));
|
|
245
|
+
},
|
|
246
|
+
get columnSizingInfo() {
|
|
247
|
+
return columnSizingInfo;
|
|
248
|
+
},
|
|
249
|
+
get columnSizing() {
|
|
250
|
+
return (view.config.get("columnSize") || {}) as ColumnSizingState;
|
|
251
|
+
},
|
|
252
|
+
get columnVisibility() {
|
|
253
|
+
return columns.reduce<VisibilityState>((acc, value) => {
|
|
254
|
+
const id = value.id as BasesPropertyId;
|
|
255
|
+
if (id) {
|
|
256
|
+
acc[id] = view.config.getOrder().includes(id);
|
|
257
|
+
}
|
|
258
|
+
return acc;
|
|
259
|
+
}, {});
|
|
260
|
+
},
|
|
261
|
+
get columnOrder() {
|
|
262
|
+
return columnOrder;
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
function handleDragEnd(event: DragEndEvent) {
|
|
268
|
+
const active = event.operation.source;
|
|
269
|
+
const over = event.operation.target;
|
|
270
|
+
if (active && over && active.id !== over.id) {
|
|
271
|
+
const oldIndex = view.config
|
|
272
|
+
.getOrder()
|
|
273
|
+
.indexOf(active.id as BasesPropertyId);
|
|
274
|
+
const newIndex = view.config
|
|
275
|
+
.getOrder()
|
|
276
|
+
.indexOf(over.id as BasesPropertyId);
|
|
277
|
+
view.config.set(
|
|
278
|
+
"order",
|
|
279
|
+
arrayMove(view.config.getOrder(), oldIndex, newIndex),
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
let columnSizeVars = $derived.by(() => {
|
|
285
|
+
const headers = table.getFlatHeaders();
|
|
286
|
+
const colSizes: { [key: string]: number } = {};
|
|
287
|
+
for (const header of headers) {
|
|
288
|
+
if (!view.config.getOrder().includes(header.id as BasesPropertyId))
|
|
289
|
+
continue;
|
|
290
|
+
colSizes[`--header-${CSS.escape(header.id)}-size`] = header.getSize();
|
|
291
|
+
colSizes[`--col-${CSS.escape(header.column.id)}-size`] =
|
|
292
|
+
header.column.getSize();
|
|
293
|
+
}
|
|
294
|
+
return colSizes;
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
let totalSize: string | number = $derived.by(() => {
|
|
298
|
+
if (Object.keys(view.config.get("columnSize") || {}).length > 0) {
|
|
299
|
+
return table.getTotalSize();
|
|
300
|
+
}
|
|
301
|
+
return "auto";
|
|
302
|
+
});
|
|
303
|
+
const rowHeights: Record<string, number> = {
|
|
304
|
+
short: 30,
|
|
305
|
+
medium: 60,
|
|
306
|
+
tall: 120,
|
|
307
|
+
extra: 240,
|
|
308
|
+
};
|
|
309
|
+
let rowHeight: number = $derived(
|
|
310
|
+
rowHeights[view.config.get("rowHeight") as string] ?? 30,
|
|
311
|
+
);
|
|
312
|
+
let tableContainerRef: HTMLDivElement | null = $state(null);
|
|
313
|
+
let headers = $derived(view.config.getOrder());
|
|
314
|
+
let headerMap = $derived.by(() => {
|
|
315
|
+
return table
|
|
316
|
+
.getFlatHeaders()
|
|
317
|
+
.reduce<Record<string, Header<BasesEntry, any>>>((acc, value) => {
|
|
318
|
+
acc[value.id] = value;
|
|
319
|
+
return acc;
|
|
320
|
+
}, {});
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
let colSpan = $derived(
|
|
324
|
+
table.getAllColumns().filter((it) => it.getIsVisible()).length,
|
|
325
|
+
);
|
|
326
|
+
let virtualItemEls: Array<HTMLDivElement | null> = $state([]);
|
|
327
|
+
let virtualizer = createVirtualizer({
|
|
328
|
+
get count() {
|
|
329
|
+
return queryResults.data.length;
|
|
330
|
+
},
|
|
331
|
+
getScrollElement: () => tableContainerRef,
|
|
332
|
+
estimateSize: () => rowHeight,
|
|
333
|
+
measureElement:
|
|
334
|
+
typeof window !== "undefined" &&
|
|
335
|
+
navigator.userAgent.indexOf("Firefox") === -1
|
|
336
|
+
? (element) => element?.getBoundingClientRect().height
|
|
337
|
+
: undefined,
|
|
338
|
+
overscan: 5,
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
$effect(() => {
|
|
342
|
+
virtualizer.setOptions({ count: queryResults.data.length });
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
let [paddingTop, paddingBottom] = $derived.by(() => {
|
|
346
|
+
const items = virtualizer.getVirtualItems();
|
|
347
|
+
return items.length > 0
|
|
348
|
+
? [
|
|
349
|
+
Math.max(0, items[0].start - virtualizer.options.scrollMargin),
|
|
350
|
+
Math.max(0, virtualizer.getTotalSize() - items[items.length - 1].end),
|
|
351
|
+
]
|
|
352
|
+
: [0, 0];
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
$effect(() => {
|
|
356
|
+
virtualItemEls.forEach((el) => virtualizer.measureElement(el));
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
let show = $state(false);
|
|
360
|
+
onMount(() => {
|
|
361
|
+
setTimeout(() => {
|
|
362
|
+
show = true;
|
|
363
|
+
});
|
|
364
|
+
});
|
|
365
|
+
</script>
|
|
366
|
+
|
|
367
|
+
{#if show}
|
|
368
|
+
<DragDropProvider onDragEnd={handleDragEnd}>
|
|
369
|
+
<div
|
|
370
|
+
class="bases-style-h-full-668b21 bases-style-w-full-6da6a3 bases-style-flex-grow-95a3df bases-style-overflow-auto-73fc3f bases-style-pb-16-db15dd"
|
|
371
|
+
style="scrollbar-gutter: stable; transform: translate3d(0,0,0)"
|
|
372
|
+
data-layout="table"
|
|
373
|
+
bind:this={tableContainerRef}
|
|
374
|
+
>
|
|
375
|
+
<div
|
|
376
|
+
class="relative bases-style-pb-100px-03c580"
|
|
377
|
+
style={styleObjectToString({
|
|
378
|
+
...columnSizeVars,
|
|
379
|
+
"--ui-bases-table-row-height": rowHeight,
|
|
380
|
+
width: totalSize,
|
|
381
|
+
height: virtualizer.getTotalSize() + 2 * rowHeight,
|
|
382
|
+
})}
|
|
383
|
+
>
|
|
384
|
+
<Table.Root class="bases-style-overflow-visible-5b5e83 contain-layout">
|
|
385
|
+
<Table.Header class="bases-style-bg-secondary-ba939e sticky bases-style-top-0-216740 bases-style-z-100-db5a36">
|
|
386
|
+
<Table.Row class="bases-style-th-td-last-border-r-0-7a1990">
|
|
387
|
+
{#each headers as id}
|
|
388
|
+
{#if headerMap[id]}
|
|
389
|
+
<TableHeader header={headerMap[id]} />
|
|
390
|
+
{/if}
|
|
391
|
+
{/each}
|
|
392
|
+
</Table.Row>
|
|
393
|
+
</Table.Header>
|
|
394
|
+
<Table.Body>
|
|
395
|
+
{#if paddingTop}
|
|
396
|
+
<Table.Row>
|
|
397
|
+
<Table.Cell colspan={colSpan} style="height: {paddingTop}px;}"
|
|
398
|
+
></Table.Cell>
|
|
399
|
+
</Table.Row>
|
|
400
|
+
{/if}
|
|
401
|
+
{#each virtualizer.getVirtualItems() as virtualRow (virtualRow.key)}
|
|
402
|
+
{@const row = queryResults.data[virtualRow.index]}
|
|
403
|
+
{#if row}
|
|
404
|
+
<Table.Row
|
|
405
|
+
data-index={virtualRow.index}
|
|
406
|
+
bind:ref={
|
|
407
|
+
() => {
|
|
408
|
+
virtualItemEls[virtualRow.index] ||= null;
|
|
409
|
+
return virtualItemEls[virtualRow.index];
|
|
410
|
+
},
|
|
411
|
+
(value) => {
|
|
412
|
+
virtualItemEls[virtualRow.index] = value;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
class="bases-style-h-var-bases-table-row-height-c8d78a bases-style-th-td-last-border-r-0-7a1990"
|
|
416
|
+
>
|
|
417
|
+
{#each headers as id, idx (`${id}_${virtualRow.key}_${idx}`)}
|
|
418
|
+
<Table.Cell
|
|
419
|
+
class="bases-style-overflow-hidden-2cd02d bases-style-border-r-5ceb63 bases-style-p-2px-2fa1f0 bases-style-text-nowrap-621d3b bases-style-overflow-ellipsis-5b2ef5"
|
|
420
|
+
style={`width: var(--col-${CSS.escape(id)}-size); height: var(--ui-bases-table-row-height)`}
|
|
421
|
+
>
|
|
422
|
+
<div
|
|
423
|
+
class="bases-style-focus-within-bg-secondary-14f262 bases-style-h-full-668b21 bases-style-w-full-6da6a3 bases-style-px-2-d5eab2 bases-style-py-1-660d2e bases-style-outline-2-4b7397 bases-style-outline-transparent-61b539 bases-style-focus-within-rounded-sm-668937 bases-style-focus-within-outline-var-interactive-accen-08be01"
|
|
424
|
+
>
|
|
425
|
+
<Cell
|
|
426
|
+
app={view.controller.app}
|
|
427
|
+
name={id}
|
|
428
|
+
file={row.file}
|
|
429
|
+
type={types[id]?.type}
|
|
430
|
+
value={row.getValue(id as BasesPropertyId)}
|
|
431
|
+
style={`width: var(--col-${CSS.escape(id)}-size)`}
|
|
432
|
+
class="bases-style-z-1-0bcb04 bases-style-h-full-668b21 bases-style-w-full-6da6a3 bases-style-min-w-full-a1e7a8 bases-style-overflow-hidden-2cd02d bases-style-text-nowrap-621d3b bases-style-overflow-ellipsis-5b2ef5"
|
|
433
|
+
/>
|
|
434
|
+
</div>
|
|
435
|
+
</Table.Cell>
|
|
436
|
+
{/each}
|
|
437
|
+
</Table.Row>
|
|
438
|
+
{/if}
|
|
439
|
+
{:else}
|
|
440
|
+
<Table.Row class="bases-style-h-var-bases-table-row-height-c8d78a">
|
|
441
|
+
<Table.Cell colspan={colSpan} class="bases-style-h-24-9678c6 bases-style-text-center-ca6bf6">
|
|
442
|
+
No results.
|
|
443
|
+
</Table.Cell>
|
|
444
|
+
</Table.Row>
|
|
445
|
+
{/each}
|
|
446
|
+
{#if paddingBottom}
|
|
447
|
+
<Table.Row>
|
|
448
|
+
<Table.Cell colspan={colSpan} style="height: {paddingBottom}px;"
|
|
449
|
+
></Table.Cell>
|
|
450
|
+
</Table.Row>
|
|
451
|
+
{:else}
|
|
452
|
+
<Table.Row>
|
|
453
|
+
<Table.Cell colspan={colSpan} style="height: 100px;"
|
|
454
|
+
></Table.Cell>
|
|
455
|
+
</Table.Row>
|
|
456
|
+
{/if}
|
|
457
|
+
</Table.Body>
|
|
458
|
+
</Table.Root>
|
|
459
|
+
</div>
|
|
460
|
+
</div>
|
|
461
|
+
</DragDropProvider>
|
|
462
|
+
{:else}
|
|
463
|
+
<TablePlaceholder {table} {view} />
|
|
464
|
+
{/if}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type BasesView } from "../../bases.svelte";
|
|
2
|
+
type DataTableProps = {
|
|
3
|
+
view: BasesView;
|
|
4
|
+
};
|
|
5
|
+
declare function $$render<TData, TValue>(): {
|
|
6
|
+
props: DataTableProps;
|
|
7
|
+
exports: {
|
|
8
|
+
estimateTextWidth: (text: string, font?: string) => number;
|
|
9
|
+
};
|
|
10
|
+
bindings: "";
|
|
11
|
+
slots: {};
|
|
12
|
+
events: {};
|
|
13
|
+
};
|
|
14
|
+
declare class __sveltets_Render<TData, TValue> {
|
|
15
|
+
props(): ReturnType<typeof $$render<TData, TValue>>['props'];
|
|
16
|
+
events(): ReturnType<typeof $$render<TData, TValue>>['events'];
|
|
17
|
+
slots(): ReturnType<typeof $$render<TData, TValue>>['slots'];
|
|
18
|
+
bindings(): "";
|
|
19
|
+
exports(): {
|
|
20
|
+
estimateTextWidth: (text: string, font?: string) => number;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
interface $$IsomorphicComponent {
|
|
24
|
+
new <TData, TValue>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<TData, TValue>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<TData, TValue>['props']>, ReturnType<__sveltets_Render<TData, TValue>['events']>, ReturnType<__sveltets_Render<TData, TValue>['slots']>> & {
|
|
25
|
+
$$bindings?: ReturnType<__sveltets_Render<TData, TValue>['bindings']>;
|
|
26
|
+
} & ReturnType<__sveltets_Render<TData, TValue>['exports']>;
|
|
27
|
+
<TData, TValue>(internal: unknown, props: ReturnType<__sveltets_Render<TData, TValue>['props']> & {}): ReturnType<__sveltets_Render<TData, TValue>['exports']>;
|
|
28
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any, any>['bindings']>;
|
|
29
|
+
}
|
|
30
|
+
declare const DivTable: $$IsomorphicComponent;
|
|
31
|
+
type DivTable<TData, TValue> = InstanceType<typeof DivTable<TData, TValue>>;
|
|
32
|
+
export default DivTable;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Button } from "@lapismd/design-core/shadcn/button";
|
|
3
|
+
import type { ComponentProps } from "svelte";
|
|
4
|
+
import ArrowUpDownIcon from "@lucide/svelte/icons/arrow-up-down";
|
|
5
|
+
import type { SortDirection } from "@tanstack/table-core";
|
|
6
|
+
import ArrowDown from "@lucide/svelte/icons/chevron-down";
|
|
7
|
+
import ArrowUp from "@lucide/svelte/icons/chevron-up";
|
|
8
|
+
import { Icon } from "@lapis-notes/api/icon";
|
|
9
|
+
|
|
10
|
+
let {
|
|
11
|
+
variant = "ghost",
|
|
12
|
+
icon,
|
|
13
|
+
direction,
|
|
14
|
+
text,
|
|
15
|
+
children,
|
|
16
|
+
...restProps
|
|
17
|
+
}: ComponentProps<typeof Button> & {
|
|
18
|
+
direction: false | SortDirection;
|
|
19
|
+
text?: string;
|
|
20
|
+
icon: string;
|
|
21
|
+
} = $props();
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<Button
|
|
25
|
+
class="bases-style-flex-60fbb7 bases-style-h-full-668b21 bases-style-w-full-6da6a3 bases-style-justify-between-8ef226 bases-style-rounded-none-0c5e91 bases-style-p-2-7660b4"
|
|
26
|
+
{variant}
|
|
27
|
+
{...restProps}
|
|
28
|
+
>
|
|
29
|
+
<span class="bases-style-flex-60fbb7 bases-style-items-center-3960ff">
|
|
30
|
+
<Icon name={[icon, "lucide-info"]} class="bases-style-mr-1-618162" />
|
|
31
|
+
<span>
|
|
32
|
+
{#if text}
|
|
33
|
+
{text}
|
|
34
|
+
{:else}
|
|
35
|
+
{@render children?.()}
|
|
36
|
+
{/if}
|
|
37
|
+
</span>
|
|
38
|
+
</span>
|
|
39
|
+
<span>
|
|
40
|
+
{#if direction === "asc"}
|
|
41
|
+
<ArrowUp class="bases-style-ml-2-c68af9" />
|
|
42
|
+
{:else if direction === "desc"}
|
|
43
|
+
<ArrowDown class="bases-style-ml-2-c68af9" />
|
|
44
|
+
{:else}
|
|
45
|
+
<ArrowUpDownIcon class="bases-style-ml-2-c68af9" />
|
|
46
|
+
{/if}
|
|
47
|
+
</span>
|
|
48
|
+
</Button>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Button } from "@lapismd/design-core/shadcn/button";
|
|
2
|
+
import type { ComponentProps } from "svelte";
|
|
3
|
+
import type { SortDirection } from "@tanstack/table-core";
|
|
4
|
+
type $$ComponentProps = ComponentProps<typeof Button> & {
|
|
5
|
+
direction: false | SortDirection;
|
|
6
|
+
text?: string;
|
|
7
|
+
icon: string;
|
|
8
|
+
};
|
|
9
|
+
declare const SortHeader: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
10
|
+
type SortHeader = ReturnType<typeof SortHeader>;
|
|
11
|
+
export default SortHeader;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type TableColumnTrack = {
|
|
2
|
+
id: string;
|
|
3
|
+
index: number;
|
|
4
|
+
start: number;
|
|
5
|
+
startCss: string;
|
|
6
|
+
width: number;
|
|
7
|
+
widthCss: string;
|
|
8
|
+
};
|
|
9
|
+
export type TableColumnTrackModel = {
|
|
10
|
+
tracks: TableColumnTrack[];
|
|
11
|
+
totalWidth: number;
|
|
12
|
+
totalWidthCss: string;
|
|
13
|
+
};
|
|
14
|
+
export declare function resolveTableColumnTracks(order: readonly string[], widthFor: (id: string, index: number) => number): TableColumnTrackModel;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
function normalizeWidth(width) {
|
|
2
|
+
return Number.isFinite(width) ? Math.max(0, width) : 0;
|
|
3
|
+
}
|
|
4
|
+
function pixels(value) {
|
|
5
|
+
return `${value}px`;
|
|
6
|
+
}
|
|
7
|
+
export function resolveTableColumnTracks(order, widthFor) {
|
|
8
|
+
let start = 0;
|
|
9
|
+
const tracks = order.map((id, index) => {
|
|
10
|
+
const width = normalizeWidth(widthFor(id, index));
|
|
11
|
+
const track = {
|
|
12
|
+
id,
|
|
13
|
+
index,
|
|
14
|
+
start,
|
|
15
|
+
startCss: pixels(start),
|
|
16
|
+
width,
|
|
17
|
+
widthCss: pixels(width),
|
|
18
|
+
};
|
|
19
|
+
start += width;
|
|
20
|
+
return track;
|
|
21
|
+
});
|
|
22
|
+
return {
|
|
23
|
+
tracks,
|
|
24
|
+
totalWidth: start,
|
|
25
|
+
totalWidthCss: pixels(start),
|
|
26
|
+
};
|
|
27
|
+
}
|