@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,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,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,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;
|