@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.
Files changed (155) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/LICENSE.md +8 -0
  3. package/README.md +20 -0
  4. package/dist/bases-plugin.d.ts +10 -0
  5. package/dist/bases-plugin.js +118 -0
  6. package/dist/bases-view/app-database-query-source.d.ts +30 -0
  7. package/dist/bases-view/app-database-query-source.js +248 -0
  8. package/dist/bases-view/bases.svelte.d.ts +569 -0
  9. package/dist/bases-view/bases.svelte.js +910 -0
  10. package/dist/bases-view/card-view/components/card-placeholder.svelte +68 -0
  11. package/dist/bases-view/card-view/components/card-placeholder.svelte.d.ts +7 -0
  12. package/dist/bases-view/card-view/components/card.svelte +289 -0
  13. package/dist/bases-view/card-view/components/card.svelte.d.ts +7 -0
  14. package/dist/bases-view/card-view/index.d.ts +11 -0
  15. package/dist/bases-view/card-view/index.js +55 -0
  16. package/dist/bases-view/cell-editor-options.d.ts +2 -0
  17. package/dist/bases-view/cell-editor-options.js +26 -0
  18. package/dist/bases-view/cell-editor.svelte +206 -0
  19. package/dist/bases-view/cell-editor.svelte.d.ts +12 -0
  20. package/dist/bases-view/cell.svelte +132 -0
  21. package/dist/bases-view/cell.svelte.d.ts +16 -0
  22. package/dist/bases-view/column-definition.d.ts +22 -0
  23. package/dist/bases-view/column-definition.js +149 -0
  24. package/dist/bases-view/columns.d.ts +15 -0
  25. package/dist/bases-view/columns.js +103 -0
  26. package/dist/bases-view/components/Tag.svelte +14 -0
  27. package/dist/bases-view/components/Tag.svelte.d.ts +8 -0
  28. package/dist/bases-view/components/autocomplete.svelte +45 -0
  29. package/dist/bases-view/components/autocomplete.svelte.d.ts +17 -0
  30. package/dist/bases-view/components/card-image.svelte +121 -0
  31. package/dist/bases-view/components/card-image.svelte.d.ts +11 -0
  32. package/dist/bases-view/components/column-visibility.svelte +388 -0
  33. package/dist/bases-view/components/column-visibility.svelte.d.ts +13 -0
  34. package/dist/bases-view/components/datetime.svelte +35 -0
  35. package/dist/bases-view/components/datetime.svelte.d.ts +7 -0
  36. package/dist/bases-view/components/file.svelte +31 -0
  37. package/dist/bases-view/components/file.svelte.d.ts +8 -0
  38. package/dist/bases-view/components/filters/filter-editor.svelte +102 -0
  39. package/dist/bases-view/components/filters/filter-editor.svelte.d.ts +10 -0
  40. package/dist/bases-view/components/filters/filter-group.svelte +142 -0
  41. package/dist/bases-view/components/filters/filter-group.svelte.d.ts +11 -0
  42. package/dist/bases-view/components/filters/filter-properties.svelte +77 -0
  43. package/dist/bases-view/components/filters/filter-properties.svelte.d.ts +8 -0
  44. package/dist/bases-view/components/filters/filter-root.svelte +112 -0
  45. package/dist/bases-view/components/filters/filter-root.svelte.d.ts +12 -0
  46. package/dist/bases-view/components/filters/filter-row.svelte +351 -0
  47. package/dist/bases-view/components/filters/filter-row.svelte.d.ts +11 -0
  48. package/dist/bases-view/components/group/group-root.svelte +120 -0
  49. package/dist/bases-view/components/group/group-root.svelte.d.ts +8 -0
  50. package/dist/bases-view/components/limit.svelte +100 -0
  51. package/dist/bases-view/components/limit.svelte.d.ts +12 -0
  52. package/dist/bases-view/components/query-editor.svelte +230 -0
  53. package/dist/bases-view/components/query-editor.svelte.d.ts +15 -0
  54. package/dist/bases-view/components/sort/sort-direction-labels.d.ts +9 -0
  55. package/dist/bases-view/components/sort/sort-direction-labels.js +25 -0
  56. package/dist/bases-view/components/sort/sort-root.svelte +239 -0
  57. package/dist/bases-view/components/sort/sort-root.svelte.d.ts +11 -0
  58. package/dist/bases-view/components/sort/sort-row.svelte +190 -0
  59. package/dist/bases-view/components/sort/sort-row.svelte.d.ts +15 -0
  60. package/dist/bases-view/components/summary-strip.svelte +56 -0
  61. package/dist/bases-view/components/summary-strip.svelte.d.ts +8 -0
  62. package/dist/bases-view/components/tag-chip.svelte +47 -0
  63. package/dist/bases-view/components/tag-chip.svelte.d.ts +12 -0
  64. package/dist/bases-view/components/views.svelte +178 -0
  65. package/dist/bases-view/components/views.svelte.d.ts +12 -0
  66. package/dist/bases-view/data-table-adapter/data-table.svelte.d.ts +45 -0
  67. package/dist/bases-view/data-table-adapter/data-table.svelte.js +112 -0
  68. package/dist/bases-view/data-table-adapter/flex-render.svelte +43 -0
  69. package/dist/bases-view/data-table-adapter/flex-render.svelte.d.ts +30 -0
  70. package/dist/bases-view/data-table-adapter/index.d.ts +3 -0
  71. package/dist/bases-view/data-table-adapter/index.js +3 -0
  72. package/dist/bases-view/data-table-adapter/render-helpers.d.ts +101 -0
  73. package/dist/bases-view/data-table-adapter/render-helpers.js +110 -0
  74. package/dist/bases-view/db.d.ts +31 -0
  75. package/dist/bases-view/db.js +174 -0
  76. package/dist/bases-view/document-core.d.ts +2 -0
  77. package/dist/bases-view/document-core.js +166 -0
  78. package/dist/bases-view/export-core.d.ts +4 -0
  79. package/dist/bases-view/export-core.js +31 -0
  80. package/dist/bases-view/file-fields-core.d.ts +31 -0
  81. package/dist/bases-view/file-fields-core.js +114 -0
  82. package/dist/bases-view/filter-parser.d.ts +27 -0
  83. package/dist/bases-view/filter-parser.js +315 -0
  84. package/dist/bases-view/functions-core.d.ts +66 -0
  85. package/dist/bases-view/functions-core.js +265 -0
  86. package/dist/bases-view/functions.d.ts +5 -0
  87. package/dist/bases-view/functions.js +107 -0
  88. package/dist/bases-view/fuzzy-search.d.ts +6 -0
  89. package/dist/bases-view/fuzzy-search.js +15 -0
  90. package/dist/bases-view/hooks/useResizeObserver.svelte.d.ts +7 -0
  91. package/dist/bases-view/hooks/useResizeObserver.svelte.js +26 -0
  92. package/dist/bases-view/index.d.ts +66 -0
  93. package/dist/bases-view/index.js +231 -0
  94. package/dist/bases-view/list-view/index.d.ts +10 -0
  95. package/dist/bases-view/list-view/index.js +17 -0
  96. package/dist/bases-view/list-view/list.svelte +156 -0
  97. package/dist/bases-view/list-view/list.svelte.d.ts +7 -0
  98. package/dist/bases-view/map-view/index.d.ts +10 -0
  99. package/dist/bases-view/map-view/index.js +17 -0
  100. package/dist/bases-view/map-view/view.svelte +28 -0
  101. package/dist/bases-view/map-view/view.svelte.d.ts +7 -0
  102. package/dist/bases-view/metadata-invalidation-core.d.ts +34 -0
  103. package/dist/bases-view/metadata-invalidation-core.js +162 -0
  104. package/dist/bases-view/metadata-type-info.d.ts +7 -0
  105. package/dist/bases-view/metadata-type-info.js +10 -0
  106. package/dist/bases-view/models.d.ts +90 -0
  107. package/dist/bases-view/models.js +133 -0
  108. package/dist/bases-view/query-result-core.d.ts +8 -0
  109. package/dist/bases-view/query-result-core.js +16 -0
  110. package/dist/bases-view/resource-url.d.ts +2 -0
  111. package/dist/bases-view/resource-url.js +21 -0
  112. package/dist/bases-view/search-core.d.ts +9 -0
  113. package/dist/bases-view/search-core.js +20 -0
  114. package/dist/bases-view/summary-core.d.ts +7 -0
  115. package/dist/bases-view/summary-core.js +17 -0
  116. package/dist/bases-view/table-view/components/div-table.svelte +464 -0
  117. package/dist/bases-view/table-view/components/div-table.svelte.d.ts +32 -0
  118. package/dist/bases-view/table-view/components/dnd-style.d.ts +3 -0
  119. package/dist/bases-view/table-view/components/dnd-style.js +6 -0
  120. package/dist/bases-view/table-view/components/sort-header.svelte +48 -0
  121. package/dist/bases-view/table-view/components/sort-header.svelte.d.ts +11 -0
  122. package/dist/bases-view/table-view/components/table-column-tracks.d.ts +14 -0
  123. package/dist/bases-view/table-view/components/table-column-tracks.js +27 -0
  124. package/dist/bases-view/table-view/components/table-header.svelte +146 -0
  125. package/dist/bases-view/table-view/components/table-header.svelte.d.ts +10 -0
  126. package/dist/bases-view/table-view/components/table-placeholder.svelte +46 -0
  127. package/dist/bases-view/table-view/components/table-placeholder.svelte.d.ts +30 -0
  128. package/dist/bases-view/table-view/components/table-virtualizer-core.d.ts +13 -0
  129. package/dist/bases-view/table-view/components/table-virtualizer-core.js +12 -0
  130. package/dist/bases-view/table-view/components/table.svelte +997 -0
  131. package/dist/bases-view/table-view/components/table.svelte.d.ts +32 -0
  132. package/dist/bases-view/table-view/index.svelte.d.ts +10 -0
  133. package/dist/bases-view/table-view/index.svelte.js +30 -0
  134. package/dist/bases-view/unknown-view/index.d.ts +10 -0
  135. package/dist/bases-view/unknown-view/index.js +19 -0
  136. package/dist/bases-view/unknown-view/view.svelte +11 -0
  137. package/dist/bases-view/unknown-view/view.svelte.d.ts +6 -0
  138. package/dist/bases-view/view-header.svelte +142 -0
  139. package/dist/bases-view/view-header.svelte.d.ts +28 -0
  140. package/dist/bases-view/view-registration-inventory.d.ts +22 -0
  141. package/dist/bases-view/view-registration-inventory.js +7 -0
  142. package/dist/bases-view/view-settings.svelte +350 -0
  143. package/dist/bases-view/view-settings.svelte.d.ts +9 -0
  144. package/dist/bases-view/view.svelte +192 -0
  145. package/dist/bases-view/view.svelte.d.ts +15 -0
  146. package/dist/bases-view-surface.svelte +31 -0
  147. package/dist/bases-view-surface.svelte.d.ts +14 -0
  148. package/dist/index.d.ts +10 -0
  149. package/dist/index.js +8 -0
  150. package/dist/serialized-write-queue.d.ts +10 -0
  151. package/dist/serialized-write-queue.js +36 -0
  152. package/dist/styles.css +2164 -0
  153. package/manifest.json +33 -0
  154. package/package.json +90 -0
  155. 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,3 @@
1
+ type StyleValue = string | number | null | undefined | false;
2
+ export declare function styleObjectToString(styles: Record<string, StyleValue>): string;
3
+ export {};
@@ -0,0 +1,6 @@
1
+ export function styleObjectToString(styles) {
2
+ return Object.entries(styles)
3
+ .filter(([, value]) => value !== null && value !== undefined && value !== false)
4
+ .map(([property, value]) => `${property}: ${String(value)};`)
5
+ .join(" ");
6
+ }
@@ -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
+ }