@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,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
+ }