@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,388 @@
1
+ <script lang="ts">
2
+ import * as Popover from "@lapismd/design-core/shadcn/popover";
3
+ import * as Command from "@lapismd/design-core/shadcn/command";
4
+ import * as DropdownMenu from "@lapismd/design-core/shadcn/dropdown-menu";
5
+
6
+ import CheckIcon from "@lucide/svelte/icons/check";
7
+ import ChevronRight from "@lucide/svelte/icons/chevron-right";
8
+ import ChevronLeft from "@lucide/svelte/icons/chevron-left";
9
+ import Ellipsis from "@lucide/svelte/icons/ellipsis";
10
+ import LucideList from "@lucide/svelte/icons/list";
11
+ import FunctionIcon from "@lucide/svelte/icons/square-function";
12
+ import EyeOff from "@lucide/svelte/icons/eye-off";
13
+
14
+ import { cn } from "@lapis-notes/api";
15
+ import { Button } from "@lapismd/design-core/shadcn/button";
16
+ import { Icon } from "@lapis-notes/api/icon";
17
+ import { Label } from "@lapismd/design-core/shadcn/label";
18
+ import { Input } from "@lapismd/design-core/shadcn/input";
19
+ import * as Select from "@lapismd/design-core/shadcn/select";
20
+ import { tick } from "svelte";
21
+ import QueryEditor from "./query-editor.svelte";
22
+ import { formulaColumn, isFilterColumn } from "../filter-parser";
23
+ import type { BasesPropertyId } from "@lapis-notes/api";
24
+ import type { QueryController } from "../bases.svelte";
25
+ import type { ColumnDefinition } from "../columns";
26
+
27
+ let {
28
+ table,
29
+ controller = table as QueryController,
30
+ properties = $bindable(),
31
+ formulas = $bindable(),
32
+ order = $bindable(),
33
+ }: {
34
+ controller?: QueryController;
35
+ table?: any;
36
+ properties: Record<string, { displayName: string }>;
37
+ formulas: Record<string, string>;
38
+ order: Array<string>;
39
+ } = $props();
40
+
41
+ let selected: ColumnDefinition | null = $state(null);
42
+ let selectedFormula = $derived.by(() => {
43
+ if (!selected?.id) return "";
44
+ const [isFilter, filterKey] = isFilterColumn(selected.id);
45
+ return isFilter ? filterKey : "";
46
+ });
47
+ let addedFormula = $state({ id: "", invalid: false, value: "" });
48
+ let sortedColumns = $state(getSortedColumns());
49
+ let open = $state(false);
50
+ const COUNT_SUMMARY_OPTIONS = [
51
+ { label: "None", value: "none" },
52
+ { label: "Count", value: "count" },
53
+ { label: "Count empty", value: "count-empty" },
54
+ { label: "Count filled", value: "count-filled" },
55
+ ];
56
+ const NUMBER_SUMMARY_OPTIONS = [
57
+ ...COUNT_SUMMARY_OPTIONS,
58
+ { label: "Sum", value: "sum" },
59
+ { label: "Average", value: "avg" },
60
+ { label: "Min", value: "min" },
61
+ { label: "Max", value: "max" },
62
+ ];
63
+
64
+ $effect(() => {
65
+ if (!open) {
66
+ sortedColumns = getSortedColumns();
67
+ }
68
+ });
69
+
70
+ function normalizeName(name: string) {
71
+ return name.replaceAll(/[^a-zA-Z0-9 ]/g, " ").trim();
72
+ }
73
+
74
+ let summaryOptions = $derived.by(() => {
75
+ if (!selected) return COUNT_SUMMARY_OPTIONS;
76
+ return selected.type === "number"
77
+ ? NUMBER_SUMMARY_OPTIONS
78
+ : COUNT_SUMMARY_OPTIONS;
79
+ });
80
+
81
+ function getSortedColumns() {
82
+ return controller.getAllColumns().sort((ca, cb) => {
83
+ const a = controller.isVisible(ca.id) ? 1 : 0;
84
+ const b = controller.isVisible(cb.id) ? 1 : 0;
85
+ return b - a;
86
+ });
87
+ }
88
+
89
+ function editColumn(evt: MouseEvent, column: ColumnDefinition) {
90
+ selected = column;
91
+ evt.preventDefault();
92
+ evt.stopImmediatePropagation();
93
+ evt.stopPropagation();
94
+ }
95
+
96
+ function changeDisplayName(event: FocusEvent) {
97
+ const target = event.target as HTMLInputElement;
98
+ const value = target.value;
99
+ if (target && selected && value && value !== selected?.displayName) {
100
+ const [isFilter, filterKey] = isFilterColumn(selected.id);
101
+ if (isFilter && addedFormula.id === selected.id) {
102
+ if (formulas[value]) {
103
+ addedFormula.invalid = true;
104
+ addedFormula.value = value;
105
+ return;
106
+ }
107
+ addedFormula.invalid = false;
108
+ const index = order.findIndex((c) => c === selected!.id);
109
+ const previous = formulas[filterKey];
110
+ if (index !== -1) {
111
+ order[index] = formulaColumn(filterKey);
112
+ }
113
+ delete formulas[filterKey];
114
+ formulas[value] = previous;
115
+ selected.id = formulaColumn(value);
116
+ selected.displayName = value;
117
+ return;
118
+ }
119
+ properties[selected.id] ||= { displayName: value };
120
+ properties[selected.id].displayName = value;
121
+ selected.displayName = value;
122
+ }
123
+ }
124
+
125
+ function addFormula(evt: MouseEvent) {
126
+ let id = "Untitled";
127
+ let count = 1;
128
+ while (id in formulas) {
129
+ id = `Untitiled ${count}`;
130
+ count++;
131
+ }
132
+ formulas[id] = "";
133
+ addedFormula.id = formulaColumn(id);
134
+ order = [...new Set([...order, addedFormula.id])];
135
+ tick().then(() => {
136
+ setTimeout(() => {
137
+ selected =
138
+ controller.getColumn(addedFormula.id as BasesPropertyId) ?? null;
139
+ });
140
+ });
141
+ }
142
+
143
+ function deleteFormula(column: ColumnDefinition) {
144
+ const [isFilter, filterKey] = isFilterColumn(column.id);
145
+ if (!isFilter) return;
146
+ delete formulas[filterKey];
147
+ order = order.filter((o) => o !== column.id);
148
+ selected = null;
149
+ }
150
+
151
+ function updateFormula(content: string) {
152
+ if (!selected) return;
153
+ const [isFilter, filterKey] = isFilterColumn(selected.id);
154
+ if (!isFilter) return;
155
+ formulas[filterKey] = content;
156
+ }
157
+
158
+ function getBaseSummary() {
159
+ if (!selected) return "none";
160
+ return controller.doc.summaries?.[selected.id] ?? "none";
161
+ }
162
+
163
+ function setBaseSummary(value: string) {
164
+ if (!selected) return;
165
+ const summaries = { ...(controller.doc.summaries ?? {}) };
166
+ if (!value || value === "none") {
167
+ delete summaries[selected.id];
168
+ } else {
169
+ summaries[selected.id] = value;
170
+ }
171
+ controller.doc.summaries = Object.keys(summaries).length
172
+ ? summaries
173
+ : undefined;
174
+ }
175
+
176
+ function getViewSummary() {
177
+ if (!selected) return "none";
178
+ return controller.selectedView.summaries?.[selected.id] ?? "none";
179
+ }
180
+
181
+ function setViewSummary(value: string) {
182
+ if (!selected) return;
183
+ const summaries = { ...(controller.selectedView.summaries ?? {}) };
184
+ if (!value || value === "none") {
185
+ delete summaries[selected.id];
186
+ } else {
187
+ summaries[selected.id] = value;
188
+ }
189
+ controller.selectedView.summaries = Object.keys(summaries).length
190
+ ? summaries
191
+ : undefined;
192
+ }
193
+ </script>
194
+
195
+ <Popover.Root bind:open>
196
+ <Popover.Trigger>
197
+ {#snippet child({ props }: { props: Record<string, unknown> })}
198
+ <Button {...props} variant="outline" size="sm" class="bases-style-h-8-ed8a5d bases-style-border-dashed-a29b7a">
199
+ <LucideList /> Properties
200
+ </Button>
201
+ {/snippet}
202
+ </Popover.Trigger>
203
+ <Popover.Content class="bases-style-w-max-2f935d bases-style-p-0-8a539c" align="start">
204
+ {#if selected}
205
+ {@const name = selected.displayName ?? normalizeName(selected.id)}
206
+ <Command.Root>
207
+ <div class="bases-style-p-2-7660b4">
208
+ <div class="bases-style-flex-60fbb7 bases-style-justify-between-8ef226">
209
+ <Button
210
+ variant="ghost"
211
+ size="sm"
212
+ class="bases-style-flex-60fbb7 grow bases-style-justify-start-4b5cc1"
213
+ onclick={(evt) => {
214
+ selected = null;
215
+ addedFormula = { id: "", invalid: false, value: "" };
216
+ }}
217
+ >
218
+ <ChevronLeft /> Edit {name}
219
+ </Button>
220
+ <DropdownMenu.Root>
221
+ <DropdownMenu.Trigger>
222
+ {#snippet child({ props }: { props: Record<string, unknown> })}
223
+ <Button {...props} size="sm" variant="ghost"
224
+ ><Ellipsis /></Button
225
+ >
226
+ {/snippet}
227
+ </DropdownMenu.Trigger>
228
+ <DropdownMenu.Content>
229
+ <DropdownMenu.Item
230
+ onclick={() => controller.toggleVisibility(selected!.id)}
231
+ >Hide property</DropdownMenu.Item
232
+ >
233
+ {#if selected.id.startsWith("formula.")}
234
+ <DropdownMenu.Separator />
235
+ <DropdownMenu.Item onclick={() => deleteFormula(selected!)}
236
+ >Delete formula</DropdownMenu.Item
237
+ >
238
+ {/if}
239
+ </DropdownMenu.Content>
240
+ </DropdownMenu.Root>
241
+ </div>
242
+ <div class="bases-style-grid-f3c543 bases-style-grid-cols-1-d7c833 bases-style-items-center-3960ff bases-style-gap-2-77a2a2 bases-style-px-2-d5eab2 bases-style-pt-1-6b7d6e">
243
+ <Label for="column_name" class="bases-style-text-sm-fc7473 bases-style-opacity-50-0b8c50">
244
+ Display name
245
+ </Label>
246
+ <Input
247
+ aria-invalid={addedFormula.invalid}
248
+ id="column_name"
249
+ onblur={(evt) => changeDisplayName(evt)}
250
+ value={name}
251
+ class={cn("bases-style-col-span-2-40efc0 bases-style-h-8-ed8a5d", {
252
+ "bases-style-bg-destructive-20-82a978": addedFormula.invalid,
253
+ })}
254
+ />
255
+ {#if addedFormula.invalid}
256
+ <Label
257
+ aria-invalid
258
+ for="column_name"
259
+ class="bases-style-text-destructive-811148 bases-style-text-xs-359090 bases-style-opacity-50-0b8c50"
260
+ >
261
+ Formula with id '{addedFormula.value}' already exists
262
+ </Label>
263
+ {/if}
264
+ </div>
265
+ {#if selectedFormula}
266
+ <div class="bases-style-grid-f3c543 bases-style-grid-cols-1-d7c833 bases-style-items-center-3960ff bases-style-gap-2-77a2a2 bases-style-px-2-d5eab2 bases-style-pt-1-6b7d6e">
267
+ <Label for="formula" class="bases-style-text-sm-fc7473 bases-style-opacity-50-0b8c50">Formula</Label>
268
+ <QueryEditor
269
+ {controller}
270
+ class="bases-style-rounded-md-421ac2 bases-style-border-2-65935d bases-style-p-1-eb6a3c bases-style-pb-20px-112bf7"
271
+ content={formulas[selectedFormula]}
272
+ placeholder="x + y"
273
+ id="formula"
274
+ onBlur={(evt) => updateFormula(evt)}
275
+ />
276
+ </div>
277
+ {/if}
278
+ <div class="bases-style-grid-f3c543 bases-style-grid-cols-1-d7c833 bases-style-items-center-3960ff bases-style-gap-2-77a2a2 bases-style-px-2-d5eab2 bases-style-pt-3-ce335a">
279
+ <Label class="bases-style-text-sm-fc7473 bases-style-opacity-50-0b8c50">Summary in all views</Label>
280
+ <Select.Root
281
+ type="single"
282
+ bind:value={getBaseSummary, setBaseSummary}
283
+ >
284
+ <Select.Trigger
285
+ size="sm"
286
+ class="bases-style-bg-background-e6f9e3 bases-style-h-8-ed8a5d bases-style-justify-between-8ef226"
287
+ >
288
+ {summaryOptions.find(
289
+ (option) => option.value === getBaseSummary(),
290
+ )?.label ?? "None"}
291
+ </Select.Trigger>
292
+ <Select.Content>
293
+ {#each summaryOptions as option (option.value)}
294
+ <Select.Item value={option.value} label={option.label}
295
+ >{option.label}</Select.Item
296
+ >
297
+ {/each}
298
+ </Select.Content>
299
+ </Select.Root>
300
+ </div>
301
+ <div class="bases-style-grid-f3c543 bases-style-grid-cols-1-d7c833 bases-style-items-center-3960ff bases-style-gap-2-77a2a2 bases-style-px-2-d5eab2 bases-style-pt-1-6b7d6e">
302
+ <Label class="bases-style-text-sm-fc7473 bases-style-opacity-50-0b8c50">Summary in this view</Label>
303
+ <Select.Root
304
+ type="single"
305
+ bind:value={getViewSummary, setViewSummary}
306
+ >
307
+ <Select.Trigger
308
+ size="sm"
309
+ class="bases-style-bg-background-e6f9e3 bases-style-h-8-ed8a5d bases-style-justify-between-8ef226"
310
+ >
311
+ {summaryOptions.find(
312
+ (option) => option.value === getViewSummary(),
313
+ )?.label ?? "None"}
314
+ </Select.Trigger>
315
+ <Select.Content>
316
+ {#each summaryOptions as option (option.value)}
317
+ <Select.Item value={option.value} label={option.label}
318
+ >{option.label}</Select.Item
319
+ >
320
+ {/each}
321
+ </Select.Content>
322
+ </Select.Root>
323
+ </div>
324
+ </div>
325
+ </Command.Root>
326
+ {:else}
327
+ <Command.Root>
328
+ <Command.Input placeholder="Find or create" />
329
+ <Command.List class="bases-style-p-1-eb6a3c">
330
+ <Command.Empty>No results found.</Command.Empty>
331
+ {#each sortedColumns as column (column.id)}
332
+ <Command.Item
333
+ onSelect={() => {
334
+ controller.toggleVisibility(column.id);
335
+ }}
336
+ >
337
+ <div
338
+ data-ui-part="bases-option-indicator"
339
+ data-selected={controller.isVisible(column.id)}
340
+ class={cn(
341
+ "bases-style-mr-2-d2347e bases-style-flex-60fbb7 bases-style-size-4-f7b5fa bases-style-items-center-3960ff bases-style-justify-center-86843c bases-style-rounded-sm-36d446 border bases-style-border-var-interactive-accent-f46c93",
342
+ controller.isVisible(column.id)
343
+ ? "bases-style-ring-ring-3e1868 bases-style-border-none-4a5f0e bases-style-bg-var-interactive-accent-c58cc0 bases-style-text-var-text-on-accent-22b2b1 hover:ring bases-style-hover-ring-2-8a0edf"
344
+ : "bases-style-opacity-50-0b8c50 [&_svg]:invisible",
345
+ )}
346
+ >
347
+ <CheckIcon class="bases-style-size-4-f7b5fa" />
348
+ </div>
349
+ <Icon name={[column.icon ?? "lucide-info"]} />
350
+ <span
351
+ class={cn({ "bases-style-opacity-40-2a2db4": !controller.isVisible(column.id) })}
352
+ >{column.displayName ?? normalizeName(column.id)}</span
353
+ >
354
+ <Command.Shortcut>
355
+ <button
356
+ class="bases-style-hover-bg-border-2e3f11 bases-style-rounded-sm-36d446 bases-style-p-1-eb6a3c"
357
+ onclick={(evt) => editColumn(evt, column)}
358
+ >
359
+ <ChevronRight />
360
+ </button>
361
+ </Command.Shortcut>
362
+ </Command.Item>
363
+ {/each}
364
+ </Command.List>
365
+ </Command.Root>
366
+ {/if}
367
+ {#if !selected}
368
+ <div class="bases-style-flex-60fbb7 bases-style-w-full-6da6a3 bases-style-flex-col-8dddea bases-style-gap-1-44ee8b bases-style-border-t-b950dd bases-style-p-1-eb6a3c">
369
+ <Button
370
+ size="sm"
371
+ onclick={(evt) => addFormula(evt)}
372
+ class="bases-style-w-full-6da6a3 bases-style-justify-start-4b5cc1"
373
+ variant="ghost"
374
+ >
375
+ <FunctionIcon /> Add formula
376
+ </Button>
377
+ <Button
378
+ size="sm"
379
+ onclick={() => (order = [])}
380
+ class="bases-style-w-full-6da6a3 bases-style-justify-start-4b5cc1"
381
+ variant="ghost"
382
+ >
383
+ <EyeOff /> Hide all
384
+ </Button>
385
+ </div>
386
+ {/if}
387
+ </Popover.Content>
388
+ </Popover.Root>
@@ -0,0 +1,13 @@
1
+ import type { QueryController } from "../bases.svelte";
2
+ type $$ComponentProps = {
3
+ controller?: QueryController;
4
+ table?: any;
5
+ properties: Record<string, {
6
+ displayName: string;
7
+ }>;
8
+ formulas: Record<string, string>;
9
+ order: Array<string>;
10
+ };
11
+ declare const ColumnVisibility: import("svelte").Component<$$ComponentProps, {}, "order" | "properties" | "formulas">;
12
+ type ColumnVisibility = ReturnType<typeof ColumnVisibility>;
13
+ export default ColumnVisibility;
@@ -0,0 +1,35 @@
1
+ <script lang="ts">
2
+ import { DateTime } from "luxon";
3
+ import { parseDateTime } from "peaql";
4
+
5
+ let {
6
+ value,
7
+ }: {
8
+ value: number | DateTime | string;
9
+ } = $props();
10
+
11
+ let date = $derived.by(() => {
12
+ if (typeof value === "number") {
13
+ return DateTime.fromMillis(value).toISO()?.substring(0, 16);
14
+ } else if (typeof value === "string") {
15
+ const dt = parseDateTime(value);
16
+ if (dt) {
17
+ return dt.toISO()?.substring(0, 16);
18
+ }
19
+ return value.substring(0, 16);
20
+ } else if (value instanceof DateTime) {
21
+ return value.toISO()?.substring(0, 16);
22
+ }
23
+ return value;
24
+ });
25
+ </script>
26
+
27
+ <div class="bases-table-cell bases-rendered-value">
28
+ <input
29
+ class="metadata-input metadata-input-text mod-datetime !static !ps-0"
30
+ value={date}
31
+ step="any"
32
+ disabled={true}
33
+ type="datetime-local"
34
+ />
35
+ </div>
@@ -0,0 +1,7 @@
1
+ import { DateTime } from "luxon";
2
+ type $$ComponentProps = {
3
+ value: number | DateTime | string;
4
+ };
5
+ declare const Datetime: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ type Datetime = ReturnType<typeof Datetime>;
7
+ export default Datetime;
@@ -0,0 +1,31 @@
1
+ <script lang="ts">
2
+ import type { App, TFile } from "@lapis-notes/api";
3
+ let {
4
+ app,
5
+ file,
6
+ }: {
7
+ app: App;
8
+ file: TFile;
9
+ } = $props();
10
+
11
+ function openFile(evt: MouseEvent) {
12
+ if (evt.metaKey || evt.ctrlKey) {
13
+ const leaf = app.workspace.getLeaf("tab");
14
+ leaf.openFile(file).then(() => {
15
+ app.workspace.revealLeaf(leaf);
16
+ app.workspace.requestSaveLayout();
17
+ });
18
+
19
+ evt.preventDefault();
20
+ return;
21
+ }
22
+ app.openFile(file).then(() => app.workspace.requestSaveLayout());
23
+ evt.preventDefault();
24
+ }
25
+ </script>
26
+
27
+ <a
28
+ href="#/"
29
+ class="bases-style-text-var-text-accent-69c994 underline"
30
+ onclick={(evt) => openFile(evt)}>{file.name}</a
31
+ >
@@ -0,0 +1,8 @@
1
+ import type { App, TFile } from "@lapis-notes/api";
2
+ type $$ComponentProps = {
3
+ app: App;
4
+ file: TFile;
5
+ };
6
+ declare const File: import("svelte").Component<$$ComponentProps, {}, "">;
7
+ type File = ReturnType<typeof File>;
8
+ export default File;
@@ -0,0 +1,102 @@
1
+ <script lang="ts">
2
+ import Autocomplete from "../autocomplete.svelte";
3
+ import FilterProperties from "./filter-properties.svelte";
4
+ import ChipAutocomplete from "@lapismd/design-core/forms/ChipAutocomplete.svelte";
5
+ import type { QueryController } from "../../bases.svelte";
6
+
7
+ let {
8
+ type,
9
+ controller,
10
+ value = $bindable(),
11
+ }: {
12
+ type: string;
13
+ value: any;
14
+ class?: string;
15
+ controller: QueryController;
16
+ } = $props();
17
+
18
+ function fileOptions() {
19
+ return controller.app.vault.getFiles().map((f) => {
20
+ return { label: f.path, value: f.path };
21
+ });
22
+ }
23
+
24
+ function folderOptions() {
25
+ return controller.app.vault.getAllFolders().map((f) => {
26
+ return { label: f.path || "/", value: f.path || "/" };
27
+ });
28
+ }
29
+
30
+ function onChange(event: FocusEvent) {
31
+ value = (event.target as HTMLInputElement).value;
32
+ }
33
+
34
+ function onTagsChange(values: string[]) {
35
+ value = values;
36
+ }
37
+ </script>
38
+
39
+ <div
40
+ class="bases-filter-editor bases-style-min-h-inherit-05c993 bases-style-bg-background-e6f9e3 bases-style-hover-bg-accent-0557b8 bases-style-focus-within-bg-accent-2d7ab0 bases-style-focus-within-text-accent-foreground-b70724 bases-style-flex-60fbb7 bases-style-h-auto-b8f0a0 grow bases-style-items-center-3960ff bases-style-self-stretch-18069a"
41
+ >
42
+ {#if type === "file"}
43
+ <Autocomplete bind:value options={fileOptions()} />
44
+ {:else if type === "folder"}
45
+ <Autocomplete bind:value options={folderOptions()} />
46
+ {:else if type === "properties"}
47
+ <FilterProperties bind:value {controller} />
48
+ {:else if type === "none"}
49
+ <span class="grow"></span>
50
+ {:else if type === "datetime"}
51
+ <input
52
+ type="datetime-local"
53
+ placeholder="Empty"
54
+ {value}
55
+ onblur={(evt) => onChange(evt)}
56
+ class="bases-style-hover-bg-accent-0557b8 bases-style-focus-within-bg-accent-2d7ab0 bases-style-focus-within-text-accent-foreground-b70724 bases-style-dark-bg-input-30-afcf46 bases-style-dark-focus-within-bg-input-50-4a2c4b bases-style-h-full-668b21 grow bases-style-border-none-4a5f0e bases-style-pl-1-6ad214 bases-style-outline-none-df37b1"
57
+ />
58
+ {:else if type === "date"}
59
+ <input
60
+ type="date"
61
+ placeholder="Empty"
62
+ {value}
63
+ onblur={(evt) => onChange(evt)}
64
+ class="bases-style-hover-bg-accent-0557b8 bases-style-focus-within-bg-accent-2d7ab0 bases-style-focus-within-text-accent-foreground-b70724 bases-style-dark-bg-input-30-afcf46 bases-style-dark-focus-within-bg-input-50-4a2c4b bases-style-h-full-668b21 grow bases-style-border-none-4a5f0e bases-style-pl-1-6ad214 bases-style-outline-none-df37b1"
65
+ />
66
+ {:else if type === "number"}
67
+ <input
68
+ type="number"
69
+ placeholder="Empty"
70
+ {value}
71
+ onblur={(evt) => onChange(evt)}
72
+ class="bases-style-hover-bg-accent-0557b8 bases-style-focus-within-bg-accent-2d7ab0 bases-style-focus-within-text-accent-foreground-b70724 bases-style-dark-bg-input-30-afcf46 bases-style-dark-focus-within-bg-input-50-4a2c4b bases-style-h-full-668b21 grow bases-style-border-none-4a5f0e bases-style-pl-1-6ad214 bases-style-outline-none-df37b1"
73
+ />
74
+ {:else if type === "checkbox"}
75
+ <span class="grow">
76
+ <input
77
+ type="checkbox"
78
+ placeholder="Empty"
79
+ data-indeterminate={value === null || value === undefined}
80
+ bind:checked={value}
81
+ class="metadata-input-checkbox bases-style-flex-60fbb7 bases-style-items-center-3960ff bases-style-outline-none-df37b1"
82
+ />
83
+ </span>
84
+ {:else if type === "multitext"}
85
+ <ChipAutocomplete
86
+ value={Array.isArray(value) ? value : []}
87
+ label="Values"
88
+ showLabel={false}
89
+ embedded
90
+ uppercase={false}
91
+ onChange={onTagsChange}
92
+ />
93
+ {:else}
94
+ <input
95
+ type="text"
96
+ placeholder="Empty"
97
+ {value}
98
+ onblur={(evt) => onChange(evt)}
99
+ class="bases-style-hover-bg-accent-0557b8 bases-style-focus-within-bg-accent-2d7ab0 bases-style-focus-within-text-accent-foreground-b70724 bases-style-dark-bg-input-30-afcf46 bases-style-dark-focus-within-bg-input-50-4a2c4b bases-style-h-full-668b21 grow bases-style-border-none-4a5f0e bases-style-pl-1-6ad214 bases-style-outline-none-df37b1"
100
+ />
101
+ {/if}
102
+ </div>
@@ -0,0 +1,10 @@
1
+ import type { QueryController } from "../../bases.svelte";
2
+ type $$ComponentProps = {
3
+ type: string;
4
+ value: any;
5
+ class?: string;
6
+ controller: QueryController;
7
+ };
8
+ declare const FilterEditor: import("svelte").Component<$$ComponentProps, {}, "value">;
9
+ type FilterEditor = ReturnType<typeof FilterEditor>;
10
+ export default FilterEditor;