@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,190 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { createDraggable, createDroppable } from "@dnd-kit/svelte";
|
|
3
|
+
import * as Popover from "@lapismd/design-core/shadcn/popover";
|
|
4
|
+
import * as Command from "@lapismd/design-core/shadcn/command";
|
|
5
|
+
import { Icon } from "@lapis-notes/api/icon";
|
|
6
|
+
import CheckIcon from "@lucide/svelte/icons/check";
|
|
7
|
+
import Trash from "@lucide/svelte/icons/trash-2";
|
|
8
|
+
import ArrowUpDown from "@lucide/svelte/icons/chevrons-up-down";
|
|
9
|
+
import * as Select from "@lapismd/design-core/shadcn/select";
|
|
10
|
+
import { Button } from "@lapismd/design-core/shadcn/button";
|
|
11
|
+
import type { SortColumn } from "../..";
|
|
12
|
+
import { cn } from "@lapis-notes/api";
|
|
13
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
14
|
+
import GripVertical from "@lucide/svelte/icons/grip-vertical";
|
|
15
|
+
import type { QueryController } from "../../bases.svelte";
|
|
16
|
+
import { getSortDirectionLabels } from "./sort-direction-labels";
|
|
17
|
+
|
|
18
|
+
type WithElementRef<T, U extends HTMLElement = HTMLElement> = T & {
|
|
19
|
+
ref?: U | null;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
let {
|
|
23
|
+
sort = $bindable(),
|
|
24
|
+
index,
|
|
25
|
+
controller,
|
|
26
|
+
deleteSort,
|
|
27
|
+
children,
|
|
28
|
+
class: className,
|
|
29
|
+
...rest
|
|
30
|
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
|
|
31
|
+
sort: SortColumn;
|
|
32
|
+
index?: number;
|
|
33
|
+
controller: QueryController;
|
|
34
|
+
deleteSort?: () => void;
|
|
35
|
+
} = $props();
|
|
36
|
+
|
|
37
|
+
let column = $derived(
|
|
38
|
+
sort.property ? controller.getColumn(sort.property) : undefined,
|
|
39
|
+
);
|
|
40
|
+
let filterTypes = $derived.by(() => {
|
|
41
|
+
return getSortDirectionLabels(column?.type);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const filterLabel = $derived(
|
|
45
|
+
filterTypes.find((f) => f.value === sort.direction)?.label ?? "",
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
$effect(() => {
|
|
49
|
+
if (!sort.direction) {
|
|
50
|
+
sort.direction = filterTypes[0].value;
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const draggable = createDraggable({
|
|
55
|
+
get id() {
|
|
56
|
+
return `bases-sort-row:${index ?? "empty"}`;
|
|
57
|
+
},
|
|
58
|
+
type: "bases-sort-row",
|
|
59
|
+
get disabled() {
|
|
60
|
+
return index === undefined;
|
|
61
|
+
},
|
|
62
|
+
get data() {
|
|
63
|
+
return {
|
|
64
|
+
type: "bases-sort-row",
|
|
65
|
+
index,
|
|
66
|
+
};
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const droppable = createDroppable({
|
|
71
|
+
get id() {
|
|
72
|
+
return `bases-sort-row-drop:${index ?? "empty"}`;
|
|
73
|
+
},
|
|
74
|
+
accept: "bases-sort-row",
|
|
75
|
+
get disabled() {
|
|
76
|
+
return index === undefined;
|
|
77
|
+
},
|
|
78
|
+
get data() {
|
|
79
|
+
return {
|
|
80
|
+
type: "bases-sort-row",
|
|
81
|
+
index,
|
|
82
|
+
};
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
</script>
|
|
86
|
+
|
|
87
|
+
<div
|
|
88
|
+
{@attach draggable.attach}
|
|
89
|
+
{@attach droppable.attach}
|
|
90
|
+
class={cn(className, {
|
|
91
|
+
"bases-style-ring-ring-3e1868 bases-style-rounded-md-421ac2 bases-style-ring-1-3daca9": droppable.isDropTarget,
|
|
92
|
+
"bases-style-opacity-75-f85473": draggable.isDragging,
|
|
93
|
+
})}
|
|
94
|
+
>
|
|
95
|
+
<div class="filter-row bases-style-mb-1-652817 bases-style-flex-60fbb7 bases-style-items-center-3960ff bases-style-gap-0-63a285" {...rest}>
|
|
96
|
+
<Button
|
|
97
|
+
{@attach draggable.attachHandle}
|
|
98
|
+
size="sm"
|
|
99
|
+
class="drag-handle bases-style-mr-0-5-1caf26"
|
|
100
|
+
variant="ghost"
|
|
101
|
+
>
|
|
102
|
+
<GripVertical />
|
|
103
|
+
</Button>
|
|
104
|
+
<div class="bases-style-flex-60fbb7 bases-style-h-9-e7a768 grow bases-style-items-center-3960ff bases-style-rounded-md-421ac2 bases-style-border-2-65935d">
|
|
105
|
+
<Popover.Root>
|
|
106
|
+
<Popover.Trigger class="">
|
|
107
|
+
{#snippet child({ props }: { props: Record<string, any> })}
|
|
108
|
+
<Button
|
|
109
|
+
{...props}
|
|
110
|
+
variant="outline"
|
|
111
|
+
size="sm"
|
|
112
|
+
class="bases-style-h-8-ed8a5d grow bases-style-rounded-none-0c5e91 bases-style-rounded-l-md-9b2e91 bases-style-border-none-4a5f0e bases-style-shadow-none-ad47d1 bases-style-outline-none-df37b1"
|
|
113
|
+
>
|
|
114
|
+
{#if column}
|
|
115
|
+
<Icon name={[column?.icon ?? "lucide-file"]} />
|
|
116
|
+
{column.displayName}
|
|
117
|
+
{:else}
|
|
118
|
+
<span class="bases-style-opacity-50-0b8c50">Property</span>
|
|
119
|
+
{/if}
|
|
120
|
+
<ArrowUpDown />
|
|
121
|
+
</Button>
|
|
122
|
+
{/snippet}
|
|
123
|
+
</Popover.Trigger>
|
|
124
|
+
<Popover.Content class="bases-style-w-max-2f935d bases-style-p-0-8a539c" align="start">
|
|
125
|
+
<Command.Root>
|
|
126
|
+
<Command.Input placeholder="Find or create" />
|
|
127
|
+
<Command.List class="bases-style-p-1-eb6a3c">
|
|
128
|
+
<Command.Empty>No results found.</Command.Empty>
|
|
129
|
+
{#each controller.getAllColumns() as column (column.id)}
|
|
130
|
+
<Command.Item
|
|
131
|
+
onSelect={() => {
|
|
132
|
+
sort.property = column.id;
|
|
133
|
+
}}
|
|
134
|
+
>
|
|
135
|
+
<div
|
|
136
|
+
data-ui-part="bases-option-indicator"
|
|
137
|
+
data-selected={sort.property === column.id}
|
|
138
|
+
class={cn(
|
|
139
|
+
"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",
|
|
140
|
+
sort.property === column.id
|
|
141
|
+
? "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"
|
|
142
|
+
: "bases-style-opacity-50-0b8c50 [&_svg]:invisible",
|
|
143
|
+
)}
|
|
144
|
+
>
|
|
145
|
+
<CheckIcon class="bases-style-size-4-f7b5fa" />
|
|
146
|
+
</div>
|
|
147
|
+
<Icon name={[column.icon ?? "lucide-info"]} />
|
|
148
|
+
<span class="bases-style-overflow-hidden-2cd02d bases-style-text-ellipsis-6e2e11"
|
|
149
|
+
>{column.displayName}</span
|
|
150
|
+
>
|
|
151
|
+
{#if !column.id.startsWith("note.")}
|
|
152
|
+
<Command.Shortcut class="bases-style-font-mono-0e6570 bases-style-text-0-75em-c425cc"
|
|
153
|
+
>{column.id}</Command.Shortcut
|
|
154
|
+
>
|
|
155
|
+
{/if}
|
|
156
|
+
</Command.Item>
|
|
157
|
+
{/each}
|
|
158
|
+
</Command.List>
|
|
159
|
+
</Command.Root>
|
|
160
|
+
</Popover.Content>
|
|
161
|
+
</Popover.Root>
|
|
162
|
+
<Select.Root type="single" bind:value={sort.direction}>
|
|
163
|
+
<Select.Trigger
|
|
164
|
+
size="sm"
|
|
165
|
+
class="bases-style-bg-background-e6f9e3 bases-style-h-8-ed8a5d bases-style-rounded-none-0c5e91 bases-style-border-none-4a5f0e bases-style-shadow-none-ad47d1 bases-style-outline-none-df37b1"
|
|
166
|
+
>
|
|
167
|
+
{filterLabel}
|
|
168
|
+
<ArrowUpDown />
|
|
169
|
+
</Select.Trigger>
|
|
170
|
+
<Select.Content>
|
|
171
|
+
{#each filterTypes as filterType (filterType.value)}
|
|
172
|
+
<Select.Item value={filterType.value} label={filterType.label}
|
|
173
|
+
>{filterType.label}</Select.Item
|
|
174
|
+
>
|
|
175
|
+
{/each}
|
|
176
|
+
</Select.Content>
|
|
177
|
+
</Select.Root>
|
|
178
|
+
{#if deleteSort}
|
|
179
|
+
<Button
|
|
180
|
+
variant="ghost"
|
|
181
|
+
size="sm"
|
|
182
|
+
class="bases-style-bg-background-e6f9e3 bases-style-h-8-ed8a5d bases-style-rounded-none-0c5e91 bases-style-rounded-r-md-d4eb07 bases-style-border-none-4a5f0e bases-style-shadow-none-ad47d1 bases-style-outline-none-df37b1"
|
|
183
|
+
onclick={() => deleteSort()}
|
|
184
|
+
>
|
|
185
|
+
<Trash />
|
|
186
|
+
</Button>
|
|
187
|
+
{/if}
|
|
188
|
+
</div>
|
|
189
|
+
</div>
|
|
190
|
+
</div>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { SortColumn } from "../..";
|
|
2
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
3
|
+
import type { QueryController } from "../../bases.svelte";
|
|
4
|
+
type WithElementRef<T, U extends HTMLElement = HTMLElement> = T & {
|
|
5
|
+
ref?: U | null;
|
|
6
|
+
};
|
|
7
|
+
type $$ComponentProps = WithElementRef<HTMLAttributes<HTMLDivElement>> & {
|
|
8
|
+
sort: SortColumn;
|
|
9
|
+
index?: number;
|
|
10
|
+
controller: QueryController;
|
|
11
|
+
deleteSort?: () => void;
|
|
12
|
+
};
|
|
13
|
+
declare const SortRow: import("svelte").Component<$$ComponentProps, {}, "sort">;
|
|
14
|
+
type SortRow = ReturnType<typeof SortRow>;
|
|
15
|
+
export default SortRow;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn } from "@lapis-notes/api";
|
|
3
|
+
import type { BasesPropertyId } from "../bases.svelte";
|
|
4
|
+
import type { BasesView } from "../bases.svelte";
|
|
5
|
+
import {
|
|
6
|
+
resolveConfiguredSummaries,
|
|
7
|
+
formatSummaryLabel,
|
|
8
|
+
} from "../summary-core";
|
|
9
|
+
|
|
10
|
+
let {
|
|
11
|
+
view,
|
|
12
|
+
class: className,
|
|
13
|
+
}: {
|
|
14
|
+
view: BasesView;
|
|
15
|
+
class?: string;
|
|
16
|
+
} = $props();
|
|
17
|
+
|
|
18
|
+
let queryResults = $derived(view.data);
|
|
19
|
+
let summaries = $derived.by(() => {
|
|
20
|
+
return resolveConfiguredSummaries(
|
|
21
|
+
view.config.getOrder(),
|
|
22
|
+
view.controller.doc.summaries,
|
|
23
|
+
view.config.get("summaries") as Record<string, string> | undefined,
|
|
24
|
+
).map(({ propertyId, summaryKey }) => ({
|
|
25
|
+
propertyId,
|
|
26
|
+
label: formatSummaryLabel(summaryKey),
|
|
27
|
+
displayName: view.config.getDisplayName(propertyId as BasesPropertyId),
|
|
28
|
+
value: queryResults
|
|
29
|
+
.getSummaryValue(
|
|
30
|
+
view.controller,
|
|
31
|
+
queryResults.data,
|
|
32
|
+
propertyId as BasesPropertyId,
|
|
33
|
+
summaryKey,
|
|
34
|
+
)
|
|
35
|
+
.toString(),
|
|
36
|
+
}));
|
|
37
|
+
});
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
{#if summaries.length}
|
|
41
|
+
<div class={cn("bases-style-flex-60fbb7 bases-style-flex-wrap-1eb5c6 bases-style-gap-2-77a2a2", className)}>
|
|
42
|
+
{#each summaries as summary (`${summary.propertyId}_${summary.label}`)}
|
|
43
|
+
<div
|
|
44
|
+
class="bases-summary-strip__item bases-style-min-w-28-4460ce bases-style-rounded-md-421ac2 border bases-style-px-3-0e17f2 bases-style-py-2-03b4dd bases-style-text-xs-359090"
|
|
45
|
+
>
|
|
46
|
+
<div class="bases-summary-strip__label truncate">
|
|
47
|
+
{summary.displayName}
|
|
48
|
+
{summary.label}
|
|
49
|
+
</div>
|
|
50
|
+
<div class="bases-summary-strip__value truncate bases-style-text-sm-fc7473 bases-style-font-medium-2689f3">
|
|
51
|
+
{summary.value}
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
{/each}
|
|
55
|
+
</div>
|
|
56
|
+
{/if}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { BasesView } from "../bases.svelte";
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
view: BasesView;
|
|
4
|
+
class?: string;
|
|
5
|
+
};
|
|
6
|
+
declare const SummaryStrip: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
7
|
+
type SummaryStrip = ReturnType<typeof SummaryStrip>;
|
|
8
|
+
export default SummaryStrip;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
let {
|
|
3
|
+
class: className,
|
|
4
|
+
name,
|
|
5
|
+
value,
|
|
6
|
+
hrefPrefix = "#",
|
|
7
|
+
target = "_blank",
|
|
8
|
+
rel = "noopener nofollow",
|
|
9
|
+
...props
|
|
10
|
+
}: {
|
|
11
|
+
class?: string;
|
|
12
|
+
name?: string;
|
|
13
|
+
value?: string;
|
|
14
|
+
hrefPrefix?: string;
|
|
15
|
+
target?: string;
|
|
16
|
+
rel?: string;
|
|
17
|
+
[key: string]: unknown;
|
|
18
|
+
} = $props();
|
|
19
|
+
|
|
20
|
+
let label = $derived((name ?? value ?? "").toString());
|
|
21
|
+
let parts = $derived(
|
|
22
|
+
label
|
|
23
|
+
.replace(/^#/, "")
|
|
24
|
+
.split("/")
|
|
25
|
+
.filter((part) => part.trim()),
|
|
26
|
+
);
|
|
27
|
+
let segments = $derived.by(() =>
|
|
28
|
+
parts.map((segment, index) => ({
|
|
29
|
+
name: segment,
|
|
30
|
+
path: parts.slice(0, index + 1).join("/"),
|
|
31
|
+
})),
|
|
32
|
+
);
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
<span
|
|
36
|
+
class={["bases-tag", className].filter(Boolean).join(" ")}
|
|
37
|
+
data-ui-component="bases-tag"
|
|
38
|
+
data-ui-part="root"
|
|
39
|
+
>
|
|
40
|
+
<span aria-hidden="true" data-ui-part="hash">#</span>
|
|
41
|
+
{#each segments as segment, index}
|
|
42
|
+
{#if index > 0}<span aria-hidden="true" data-ui-part="separator">/</span>{/if}
|
|
43
|
+
<a href={hrefPrefix + segment.path} {target} {rel} {...props}>
|
|
44
|
+
{segment.name}
|
|
45
|
+
</a>
|
|
46
|
+
{/each}
|
|
47
|
+
</span>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type $$ComponentProps = {
|
|
2
|
+
class?: string;
|
|
3
|
+
name?: string;
|
|
4
|
+
value?: string;
|
|
5
|
+
hrefPrefix?: string;
|
|
6
|
+
target?: string;
|
|
7
|
+
rel?: string;
|
|
8
|
+
[key: string]: unknown;
|
|
9
|
+
};
|
|
10
|
+
declare const TagChip: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
11
|
+
type TagChip = ReturnType<typeof TagChip>;
|
|
12
|
+
export default TagChip;
|
|
@@ -0,0 +1,178 @@
|
|
|
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 ChevronLeft from "@lucide/svelte/icons/chevron-left";
|
|
7
|
+
import Ellipsis from "@lucide/svelte/icons/ellipsis";
|
|
8
|
+
import Plus from "@lucide/svelte/icons/plus";
|
|
9
|
+
import ArrowUpDown from "@lucide/svelte/icons/chevrons-up-down";
|
|
10
|
+
|
|
11
|
+
import { cn } from "@lapis-notes/api";
|
|
12
|
+
import { Button } from "@lapismd/design-core/shadcn/button";
|
|
13
|
+
import { Icon } from "@lapis-notes/api/icon";
|
|
14
|
+
import { Input } from "@lapismd/design-core/shadcn/input";
|
|
15
|
+
import type { BasesViewBase } from "../models";
|
|
16
|
+
import type { QueryController } from "../bases.svelte";
|
|
17
|
+
import ViewSettings from "../view-settings.svelte";
|
|
18
|
+
|
|
19
|
+
let {
|
|
20
|
+
views = $bindable(),
|
|
21
|
+
value = $bindable(),
|
|
22
|
+
show = $bindable(),
|
|
23
|
+
table,
|
|
24
|
+
controller = table as QueryController,
|
|
25
|
+
}: {
|
|
26
|
+
views: BasesViewBase[];
|
|
27
|
+
value: BasesViewBase;
|
|
28
|
+
controller?: QueryController;
|
|
29
|
+
table?: any;
|
|
30
|
+
show: boolean;
|
|
31
|
+
} = $props();
|
|
32
|
+
|
|
33
|
+
let selected: BasesViewBase | null = $state(null);
|
|
34
|
+
let open: boolean = $state(false);
|
|
35
|
+
|
|
36
|
+
function addView(evt: MouseEvent) {
|
|
37
|
+
views.push({
|
|
38
|
+
name: "Table",
|
|
39
|
+
type: "table",
|
|
40
|
+
order: ["file.name"],
|
|
41
|
+
sort: [],
|
|
42
|
+
limit: null,
|
|
43
|
+
filter: { and: [] },
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function deleteView() {
|
|
48
|
+
const index = views.findIndex((v) => v == selected);
|
|
49
|
+
if (index !== -1) {
|
|
50
|
+
views.splice(index, 1);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function duplicateView() {
|
|
55
|
+
if (selected) {
|
|
56
|
+
const value = { ...$state.snapshot(selected) };
|
|
57
|
+
views.push(value);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function changeDisplayName(evt: FocusEvent) {
|
|
62
|
+
const target = evt.target as HTMLInputElement;
|
|
63
|
+
if (target && selected && target.value) {
|
|
64
|
+
selected.name = target.value;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function viewIcon(view?: BasesViewBase | null) {
|
|
69
|
+
if (!view) return "table";
|
|
70
|
+
const config = controller.views.get(view.type);
|
|
71
|
+
if (config) {
|
|
72
|
+
return config.icon;
|
|
73
|
+
}
|
|
74
|
+
return "table";
|
|
75
|
+
}
|
|
76
|
+
</script>
|
|
77
|
+
|
|
78
|
+
<Popover.Root bind:open>
|
|
79
|
+
<Popover.Trigger>
|
|
80
|
+
{#snippet child({ props }: { props: Record<string, unknown> })}
|
|
81
|
+
<Button {...props} variant="outline" size="sm" class="bases-style-h-8-ed8a5d bases-style-border-dashed-a29b7a">
|
|
82
|
+
<Icon name={viewIcon(selected)} />
|
|
83
|
+
{value.name}
|
|
84
|
+
<ArrowUpDown />
|
|
85
|
+
</Button>
|
|
86
|
+
{/snippet}
|
|
87
|
+
</Popover.Trigger>
|
|
88
|
+
<Popover.Content class="bases-style-w-270px-448793 bases-style-min-w-220px-cbc208 bases-style-p-0-8a539c" align="start">
|
|
89
|
+
{#if selected}
|
|
90
|
+
<Command.Root>
|
|
91
|
+
<div class="bases-style-p-2-7660b4">
|
|
92
|
+
<div class="bases-style-flex-60fbb7 bases-style-justify-between-8ef226">
|
|
93
|
+
<Button
|
|
94
|
+
variant="ghost"
|
|
95
|
+
size="sm"
|
|
96
|
+
class="bases-style-flex-60fbb7 grow bases-style-justify-start-4b5cc1"
|
|
97
|
+
onclick={(evt) => {
|
|
98
|
+
selected = null;
|
|
99
|
+
}}
|
|
100
|
+
>
|
|
101
|
+
<ChevronLeft /> Edit {selected.name}
|
|
102
|
+
</Button>
|
|
103
|
+
<DropdownMenu.Root>
|
|
104
|
+
<DropdownMenu.Trigger>
|
|
105
|
+
{#snippet child({ props }: { props: Record<string, unknown> })}
|
|
106
|
+
<Button {...props} size="sm" variant="ghost"
|
|
107
|
+
aria-label={`View actions for ${selected!.name}`}
|
|
108
|
+
><Ellipsis /></Button
|
|
109
|
+
>
|
|
110
|
+
{/snippet}
|
|
111
|
+
</DropdownMenu.Trigger>
|
|
112
|
+
<DropdownMenu.Content>
|
|
113
|
+
<DropdownMenu.Item onclick={() => deleteView()}
|
|
114
|
+
>Delete view</DropdownMenu.Item
|
|
115
|
+
>
|
|
116
|
+
<DropdownMenu.Separator />
|
|
117
|
+
<DropdownMenu.Item onclick={() => duplicateView()}
|
|
118
|
+
>Duplicate view</DropdownMenu.Item
|
|
119
|
+
>
|
|
120
|
+
</DropdownMenu.Content>
|
|
121
|
+
</DropdownMenu.Root>
|
|
122
|
+
</div>
|
|
123
|
+
<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">
|
|
124
|
+
<Input
|
|
125
|
+
id="column_name"
|
|
126
|
+
aria-label="View name"
|
|
127
|
+
onblur={(evt) => changeDisplayName(evt)}
|
|
128
|
+
value={selected.name}
|
|
129
|
+
class={cn("bases-style-col-span-2-40efc0 bases-style-h-8-ed8a5d")}
|
|
130
|
+
/>
|
|
131
|
+
</div>
|
|
132
|
+
<ViewSettings {controller} bind:view={selected} />
|
|
133
|
+
</div>
|
|
134
|
+
</Command.Root>
|
|
135
|
+
{:else}
|
|
136
|
+
<Command.Root>
|
|
137
|
+
<Command.Input placeholder="Find or create" aria-controls="bases-view-selector-list" />
|
|
138
|
+
<Command.List id="bases-view-selector-list" class="bases-style-p-1-eb6a3c">
|
|
139
|
+
<Command.Empty>No views found.</Command.Empty>
|
|
140
|
+
{#each views as view}
|
|
141
|
+
<Command.Item
|
|
142
|
+
class={cn("bases-style-mb-1-652817")}
|
|
143
|
+
onSelect={() => {
|
|
144
|
+
show = false;
|
|
145
|
+
open = false;
|
|
146
|
+
value = view;
|
|
147
|
+
setTimeout(() => (show = true));
|
|
148
|
+
}}
|
|
149
|
+
>
|
|
150
|
+
<Icon name={viewIcon(view)} />
|
|
151
|
+
<span>{view.name}</span>
|
|
152
|
+
</Command.Item>
|
|
153
|
+
{/each}
|
|
154
|
+
</Command.List>
|
|
155
|
+
</Command.Root>
|
|
156
|
+
{/if}
|
|
157
|
+
{#if !selected}
|
|
158
|
+
<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">
|
|
159
|
+
<Button
|
|
160
|
+
size="sm"
|
|
161
|
+
onclick={() => (selected = value)}
|
|
162
|
+
class="bases-style-w-full-6da6a3 bases-style-justify-start-4b5cc1"
|
|
163
|
+
variant="ghost"
|
|
164
|
+
>
|
|
165
|
+
<Ellipsis /> Edit current view
|
|
166
|
+
</Button>
|
|
167
|
+
<Button
|
|
168
|
+
size="sm"
|
|
169
|
+
onclick={(evt) => addView(evt)}
|
|
170
|
+
class="bases-style-w-full-6da6a3 bases-style-justify-start-4b5cc1"
|
|
171
|
+
variant="ghost"
|
|
172
|
+
>
|
|
173
|
+
<Plus /> Add view
|
|
174
|
+
</Button>
|
|
175
|
+
</div>
|
|
176
|
+
{/if}
|
|
177
|
+
</Popover.Content>
|
|
178
|
+
</Popover.Root>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { BasesViewBase } from "../models";
|
|
2
|
+
import type { QueryController } from "../bases.svelte";
|
|
3
|
+
type $$ComponentProps = {
|
|
4
|
+
views: BasesViewBase[];
|
|
5
|
+
value: BasesViewBase;
|
|
6
|
+
controller?: QueryController;
|
|
7
|
+
table?: any;
|
|
8
|
+
show: boolean;
|
|
9
|
+
};
|
|
10
|
+
declare const Views: import("svelte").Component<$$ComponentProps, {}, "value" | "show" | "views">;
|
|
11
|
+
type Views = ReturnType<typeof Views>;
|
|
12
|
+
export default Views;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { type RowData, type TableOptions } from "@tanstack/table-core";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a reactive TanStack table object for Svelte.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```svelte
|
|
7
|
+
* <script>
|
|
8
|
+
* const table = createSvelteTable({ ... })
|
|
9
|
+
* </script>
|
|
10
|
+
*
|
|
11
|
+
* <table>
|
|
12
|
+
* <thead>
|
|
13
|
+
* {#each table.getHeaderGroups() as headerGroup}
|
|
14
|
+
* <tr>
|
|
15
|
+
* {#each headerGroup.headers as header}
|
|
16
|
+
* <th colspan={header.colSpan}>
|
|
17
|
+
* <FlexRender content={header.column.columnDef.header} context={header.getContext()} />
|
|
18
|
+
* </th>
|
|
19
|
+
* {/each}
|
|
20
|
+
* </tr>
|
|
21
|
+
* {/each}
|
|
22
|
+
* </thead>
|
|
23
|
+
* <!-- ... -->
|
|
24
|
+
* </table>
|
|
25
|
+
* ```;
|
|
26
|
+
*
|
|
27
|
+
* @param options Table options to create the table with.
|
|
28
|
+
* @returns A reactive table object.
|
|
29
|
+
*/
|
|
30
|
+
export declare function createSvelteTable<TData extends RowData>(options: TableOptions<TData>): import("@tanstack/table-core").Table<TData>;
|
|
31
|
+
type MaybeThunk<T extends object> = T | (() => T | null | undefined);
|
|
32
|
+
type Intersection<T extends readonly unknown[]> = (T extends [
|
|
33
|
+
infer H,
|
|
34
|
+
...infer R
|
|
35
|
+
] ? H & Intersection<R> : unknown) & {};
|
|
36
|
+
/**
|
|
37
|
+
* Lazily merges several objects (or thunks) while preserving getter semantics
|
|
38
|
+
* from every source.
|
|
39
|
+
*
|
|
40
|
+
* Proxy-based to avoid known WebKit recursion issue.
|
|
41
|
+
*/
|
|
42
|
+
export declare function mergeObjects<Sources extends readonly MaybeThunk<any>[]>(...sources: Sources): Intersection<{
|
|
43
|
+
[K in keyof Sources]: Sources[K];
|
|
44
|
+
}>;
|
|
45
|
+
export {};
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { createTable, } from "@tanstack/table-core";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a reactive TanStack table object for Svelte.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```svelte
|
|
7
|
+
* <script>
|
|
8
|
+
* const table = createSvelteTable({ ... })
|
|
9
|
+
* </script>
|
|
10
|
+
*
|
|
11
|
+
* <table>
|
|
12
|
+
* <thead>
|
|
13
|
+
* {#each table.getHeaderGroups() as headerGroup}
|
|
14
|
+
* <tr>
|
|
15
|
+
* {#each headerGroup.headers as header}
|
|
16
|
+
* <th colspan={header.colSpan}>
|
|
17
|
+
* <FlexRender content={header.column.columnDef.header} context={header.getContext()} />
|
|
18
|
+
* </th>
|
|
19
|
+
* {/each}
|
|
20
|
+
* </tr>
|
|
21
|
+
* {/each}
|
|
22
|
+
* </thead>
|
|
23
|
+
* <!-- ... -->
|
|
24
|
+
* </table>
|
|
25
|
+
* ```;
|
|
26
|
+
*
|
|
27
|
+
* @param options Table options to create the table with.
|
|
28
|
+
* @returns A reactive table object.
|
|
29
|
+
*/
|
|
30
|
+
export function createSvelteTable(options) {
|
|
31
|
+
const resolvedOptions = mergeObjects({
|
|
32
|
+
state: {},
|
|
33
|
+
onStateChange() { },
|
|
34
|
+
renderFallbackValue: null,
|
|
35
|
+
mergeOptions: (defaultOptions, options) => {
|
|
36
|
+
return mergeObjects(defaultOptions, options);
|
|
37
|
+
},
|
|
38
|
+
}, options);
|
|
39
|
+
const table = createTable(resolvedOptions);
|
|
40
|
+
let state = $state(table.initialState);
|
|
41
|
+
function updateOptions() {
|
|
42
|
+
table.setOptions((prev) => {
|
|
43
|
+
return mergeObjects(prev, options, {
|
|
44
|
+
state: mergeObjects(state, options.state || {}),
|
|
45
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
46
|
+
onStateChange: (updater) => {
|
|
47
|
+
if (updater instanceof Function)
|
|
48
|
+
state = updater(state);
|
|
49
|
+
else
|
|
50
|
+
state = mergeObjects(state, updater);
|
|
51
|
+
options.onStateChange?.(updater);
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
updateOptions();
|
|
57
|
+
$effect.pre(() => {
|
|
58
|
+
updateOptions();
|
|
59
|
+
});
|
|
60
|
+
return table;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Lazily merges several objects (or thunks) while preserving getter semantics
|
|
64
|
+
* from every source.
|
|
65
|
+
*
|
|
66
|
+
* Proxy-based to avoid known WebKit recursion issue.
|
|
67
|
+
*/
|
|
68
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
69
|
+
export function mergeObjects(...sources) {
|
|
70
|
+
const resolve = (src) => typeof src === "function" ? (src() ?? undefined) : src;
|
|
71
|
+
const findSourceWithKey = (key) => {
|
|
72
|
+
for (let i = sources.length - 1; i >= 0; i--) {
|
|
73
|
+
const obj = resolve(sources[i]);
|
|
74
|
+
if (obj && key in obj)
|
|
75
|
+
return obj;
|
|
76
|
+
}
|
|
77
|
+
return undefined;
|
|
78
|
+
};
|
|
79
|
+
return new Proxy(Object.create(null), {
|
|
80
|
+
get(_, key) {
|
|
81
|
+
const src = findSourceWithKey(key);
|
|
82
|
+
return src?.[key];
|
|
83
|
+
},
|
|
84
|
+
has(_, key) {
|
|
85
|
+
return !!findSourceWithKey(key);
|
|
86
|
+
},
|
|
87
|
+
ownKeys() {
|
|
88
|
+
const all = new Set();
|
|
89
|
+
for (const s of sources) {
|
|
90
|
+
const obj = resolve(s);
|
|
91
|
+
if (obj) {
|
|
92
|
+
for (const k of Reflect.ownKeys(obj)) {
|
|
93
|
+
all.add(k);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return [...all];
|
|
98
|
+
},
|
|
99
|
+
getOwnPropertyDescriptor(_, key) {
|
|
100
|
+
const src = findSourceWithKey(key);
|
|
101
|
+
if (!src)
|
|
102
|
+
return undefined;
|
|
103
|
+
return {
|
|
104
|
+
configurable: true,
|
|
105
|
+
enumerable: true,
|
|
106
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
107
|
+
value: src[key],
|
|
108
|
+
writable: true,
|
|
109
|
+
};
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
}
|