@aphexcms/cms-core 6.0.0 → 8.0.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/dist/api/documents.d.ts +19 -0
- package/dist/api/documents.d.ts.map +1 -1
- package/dist/api/documents.js +21 -0
- package/dist/api/schemas/documents.d.ts +3 -0
- package/dist/api/schemas/documents.d.ts.map +1 -1
- package/dist/api/schemas/documents.js +12 -0
- package/dist/cli/generate-types.d.ts.map +1 -1
- package/dist/cli/generate-types.js +133 -19
- package/dist/cli/generate-types.js.map +1 -1
- package/dist/components/AdminApp.svelte +74 -47
- package/dist/components/AdminApp.svelte.d.ts.map +1 -1
- package/dist/components/admin/DocumentEditor.svelte +65 -2
- package/dist/components/admin/DocumentEditor.svelte.d.ts.map +1 -1
- package/dist/components/admin/confirm-dialog/ConfirmDialogHost.svelte +8 -6
- package/dist/components/admin/confirm-dialog/ConfirmDialogHost.svelte.d.ts.map +1 -1
- package/dist/components/admin/fields/ArrayField.svelte +149 -2
- package/dist/components/admin/fields/ArrayField.svelte.d.ts.map +1 -1
- package/dist/components/admin/fields/ReferenceField.svelte +198 -125
- package/dist/components/admin/fields/ReferenceField.svelte.d.ts +9 -2
- package/dist/components/admin/fields/ReferenceField.svelte.d.ts.map +1 -1
- package/dist/components/layout/Sidebar.svelte +1 -1
- package/dist/components/layout/sidebar/AppSidebar.svelte +2 -1
- package/dist/components/layout/sidebar/AppSidebar.svelte.d.ts.map +1 -1
- package/dist/components/layout/sidebar/NavMain.svelte +9 -2
- package/dist/components/layout/sidebar/NavMain.svelte.d.ts +2 -0
- package/dist/components/layout/sidebar/NavMain.svelte.d.ts.map +1 -1
- package/dist/db/interfaces/index.d.ts +3 -1
- package/dist/db/interfaces/index.d.ts.map +1 -1
- package/dist/db/interfaces/reference.d.ts +43 -0
- package/dist/db/interfaces/reference.d.ts.map +1 -0
- package/dist/db/interfaces/reference.js +4 -0
- package/dist/db/utils/reference-resolver.d.ts +4 -6
- package/dist/db/utils/reference-resolver.d.ts.map +1 -1
- package/dist/db/utils/reference-resolver.js +33 -31
- package/dist/document-refresh.svelte.d.ts +3 -0
- package/dist/document-refresh.svelte.d.ts.map +1 -0
- package/dist/document-refresh.svelte.js +21 -0
- package/dist/graphql/resolvers.d.ts.map +1 -1
- package/dist/graphql/resolvers.js +61 -1
- package/dist/graphql/schema.d.ts.map +1 -1
- package/dist/graphql/schema.js +10 -0
- package/dist/lib/api/documents.d.ts +19 -0
- package/dist/lib/api/documents.d.ts.map +1 -1
- package/dist/lib/api/documents.js +21 -0
- package/dist/lib/api/documents.js.map +1 -1
- package/dist/lib/api/schemas/documents.d.ts +3 -0
- package/dist/lib/api/schemas/documents.d.ts.map +1 -1
- package/dist/lib/api/schemas/documents.js +12 -0
- package/dist/lib/api/schemas/documents.js.map +1 -1
- package/dist/lib/db/interfaces/index.d.ts +3 -1
- package/dist/lib/db/interfaces/index.d.ts.map +1 -1
- package/dist/lib/db/interfaces/reference.d.ts +43 -0
- package/dist/lib/db/interfaces/reference.d.ts.map +1 -0
- package/dist/lib/db/interfaces/reference.js +5 -0
- package/dist/lib/db/interfaces/reference.js.map +1 -0
- package/dist/lib/db/utils/reference-resolver.d.ts +4 -6
- package/dist/lib/db/utils/reference-resolver.d.ts.map +1 -1
- package/dist/lib/db/utils/reference-resolver.js +33 -31
- package/dist/lib/db/utils/reference-resolver.js.map +1 -1
- package/dist/lib/document-refresh.svelte.d.ts +3 -0
- package/dist/lib/document-refresh.svelte.d.ts.map +1 -0
- package/dist/lib/document-refresh.svelte.js +22 -0
- package/dist/lib/document-refresh.svelte.js.map +1 -0
- package/dist/lib/graphql/resolvers.d.ts.map +1 -1
- package/dist/lib/graphql/resolvers.js +61 -1
- package/dist/lib/graphql/resolvers.js.map +1 -1
- package/dist/lib/graphql/schema.d.ts.map +1 -1
- package/dist/lib/graphql/schema.js +10 -0
- package/dist/lib/graphql/schema.js.map +1 -1
- package/dist/lib/local-api/collection-api.d.ts +10 -1
- package/dist/lib/local-api/collection-api.d.ts.map +1 -1
- package/dist/lib/local-api/collection-api.js +39 -1
- package/dist/lib/local-api/collection-api.js.map +1 -1
- package/dist/lib/local-api/index.d.ts +29 -0
- package/dist/lib/local-api/index.d.ts.map +1 -1
- package/dist/lib/local-api/index.js +66 -2
- package/dist/lib/local-api/index.js.map +1 -1
- package/dist/lib/routes/assets-cdn.d.ts.map +1 -1
- package/dist/lib/routes/assets-cdn.js +14 -1
- package/dist/lib/routes/assets-cdn.js.map +1 -1
- package/dist/lib/schema-utils/validator.js +21 -11
- package/dist/lib/schema-utils/validator.js.map +1 -1
- package/dist/lib/server/api/index.d.ts.map +1 -1
- package/dist/lib/server/api/index.js +3 -1
- package/dist/lib/server/api/index.js.map +1 -1
- package/dist/lib/server/api/routes/documents-by-id.d.ts.map +1 -1
- package/dist/lib/server/api/routes/documents-by-id.js +23 -0
- package/dist/lib/server/api/routes/documents-by-id.js.map +1 -1
- package/dist/lib/server/api/routes/documents.d.ts.map +1 -1
- package/dist/lib/server/api/routes/documents.js +29 -1
- package/dist/lib/server/api/routes/documents.js.map +1 -1
- package/dist/lib/services/references-service.d.ts +35 -0
- package/dist/lib/services/references-service.d.ts.map +1 -0
- package/dist/lib/services/references-service.js +60 -0
- package/dist/lib/services/references-service.js.map +1 -0
- package/dist/lib/types/schemas.d.ts +8 -0
- package/dist/lib/types/schemas.d.ts.map +1 -1
- package/dist/lib/utils/preview.d.ts +2 -3
- package/dist/lib/utils/preview.d.ts.map +1 -1
- package/dist/lib/utils/preview.js +35 -8
- package/dist/lib/utils/preview.js.map +1 -1
- package/dist/lib/utils/reference-walk.d.ts +8 -0
- package/dist/lib/utils/reference-walk.d.ts.map +1 -0
- package/dist/lib/utils/reference-walk.js +39 -0
- package/dist/lib/utils/reference-walk.js.map +1 -0
- package/dist/local-api/collection-api.d.ts +10 -1
- package/dist/local-api/collection-api.d.ts.map +1 -1
- package/dist/local-api/collection-api.js +39 -1
- package/dist/local-api/index.d.ts +29 -0
- package/dist/local-api/index.d.ts.map +1 -1
- package/dist/local-api/index.js +66 -2
- package/dist/routes/assets-cdn.d.ts.map +1 -1
- package/dist/routes/assets-cdn.js +14 -1
- package/dist/schema-utils/validator.js +21 -11
- package/dist/server/api/index.d.ts.map +1 -1
- package/dist/server/api/index.js +3 -1
- package/dist/server/api/routes/documents-by-id.d.ts.map +1 -1
- package/dist/server/api/routes/documents-by-id.js +23 -0
- package/dist/server/api/routes/documents.d.ts.map +1 -1
- package/dist/server/api/routes/documents.js +29 -1
- package/dist/services/references-service.d.ts +35 -0
- package/dist/services/references-service.d.ts.map +1 -0
- package/dist/services/references-service.js +59 -0
- package/dist/types/schemas.d.ts +8 -0
- package/dist/types/schemas.d.ts.map +1 -1
- package/dist/utils/preview.d.ts +2 -3
- package/dist/utils/preview.d.ts.map +1 -1
- package/dist/utils/preview.js +35 -8
- package/dist/utils/reference-walk.d.ts +8 -0
- package/dist/utils/reference-walk.d.ts.map +1 -0
- package/dist/utils/reference-walk.js +38 -0
- package/package.json +3 -3
|
@@ -1,31 +1,45 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import CheckIcon from '@lucide/svelte/icons/check';
|
|
3
3
|
import PlusIcon from '@lucide/svelte/icons/plus';
|
|
4
|
-
import { tick } from 'svelte';
|
|
5
4
|
import * as Command from '@aphexcms/ui/shadcn/command';
|
|
6
|
-
import * as Popover from '@aphexcms/ui/shadcn/popover';
|
|
7
5
|
import * as DropdownMenu from '@aphexcms/ui/shadcn/dropdown-menu';
|
|
8
6
|
import { Button } from '@aphexcms/ui/shadcn/button';
|
|
7
|
+
import { Input } from '@aphexcms/ui/shadcn/input';
|
|
9
8
|
import { cn } from '@aphexcms/ui/utils';
|
|
10
|
-
import { ExternalLink, Ellipsis, Trash2, FileText } from '@lucide/svelte';
|
|
9
|
+
import { ChevronDown, ExternalLink, Ellipsis, Trash2, FileText } from '@lucide/svelte';
|
|
11
10
|
import type { Field, ReferenceField as ReferenceFieldType } from '../../../types/schemas';
|
|
12
11
|
import { documents } from '../../../api/documents';
|
|
13
12
|
import { getSchemaContext } from '../../../schema-context.svelte';
|
|
14
13
|
import { getSchemaByName } from '../../../schema-utils/utils';
|
|
15
14
|
import { toast } from 'svelte-sonner';
|
|
16
|
-
import { cmsLogger } from '../../../utils/logger';
|
|
17
15
|
import { pluralize } from '../../../utils/pluralize';
|
|
18
16
|
import { resolvePreviewTitle, resolvePreviewSubtitle } from '../../../utils/preview';
|
|
17
|
+
import { getDocumentVersion } from '../../../document-refresh.svelte';
|
|
18
|
+
|
|
19
|
+
type ReferenceValue = { _type: 'reference'; _ref: string; _key?: string };
|
|
19
20
|
|
|
20
21
|
interface Props {
|
|
21
22
|
field: Field;
|
|
22
|
-
value:
|
|
23
|
-
onUpdate: (value:
|
|
23
|
+
value: ReferenceValue | null; // Reference wrapper — singular and array share this shape
|
|
24
|
+
onUpdate: (value: ReferenceValue | null) => void;
|
|
24
25
|
onOpenReference?: (documentId: string, documentType: string) => void;
|
|
25
26
|
readonly?: boolean;
|
|
27
|
+
onRemove?: () => void; // When set, the "Remove" menu item calls this instead of clearing the value (used by array-of-references rows)
|
|
28
|
+
preloadedDoc?: unknown; // When provided AND its id matches `value._ref`, skip the per-row getById and use this doc as `selectedDocument` (used by ArrayField to batch-hydrate reference rows in one HTTP call)
|
|
26
29
|
}
|
|
27
30
|
|
|
28
|
-
let {
|
|
31
|
+
let {
|
|
32
|
+
field,
|
|
33
|
+
value,
|
|
34
|
+
onUpdate,
|
|
35
|
+
onOpenReference,
|
|
36
|
+
readonly = false,
|
|
37
|
+
onRemove,
|
|
38
|
+
preloadedDoc
|
|
39
|
+
}: Props = $props();
|
|
40
|
+
|
|
41
|
+
// Pull the target ID off the wrapper (or null when nothing's selected).
|
|
42
|
+
const refId = $derived(value?._ref ?? null);
|
|
29
43
|
|
|
30
44
|
// Cast to reference field type
|
|
31
45
|
const referenceField = field as ReferenceFieldType;
|
|
@@ -41,14 +55,26 @@
|
|
|
41
55
|
let selectedDocument = $state<any>(null);
|
|
42
56
|
let loading = $state(false);
|
|
43
57
|
let creating = $state(false);
|
|
44
|
-
let
|
|
58
|
+
let query = $state('');
|
|
45
59
|
|
|
46
|
-
// Load selected document details when value changes
|
|
60
|
+
// Load selected document details when value changes — and re-load whenever
|
|
61
|
+
// the referenced document is saved elsewhere (the version counter bumps),
|
|
62
|
+
// so the row reflects edits made in a side-panel editor without needing
|
|
63
|
+
// the user to navigate away and back. When the parent (e.g. ArrayField)
|
|
64
|
+
// hands us a preloaded doc whose id matches `value`, use it directly and
|
|
65
|
+
// skip the network call.
|
|
47
66
|
$effect(() => {
|
|
67
|
+
const id = refId;
|
|
68
|
+
// Subscribe to the document's version so this effect re-fires on save.
|
|
69
|
+
getDocumentVersion(id);
|
|
70
|
+
if (id && preloadedDoc && (preloadedDoc as any).id === id) {
|
|
71
|
+
selectedDocument = preloadedDoc;
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
48
74
|
async function loadDocument() {
|
|
49
|
-
if (
|
|
75
|
+
if (id) {
|
|
50
76
|
try {
|
|
51
|
-
const doc = await documents.getById(
|
|
77
|
+
const doc = await documents.getById(id);
|
|
52
78
|
if (doc.success) {
|
|
53
79
|
selectedDocument = doc.data;
|
|
54
80
|
}
|
|
@@ -63,46 +89,84 @@
|
|
|
63
89
|
loadDocument();
|
|
64
90
|
});
|
|
65
91
|
|
|
66
|
-
//
|
|
92
|
+
// Reset query whenever the popover closes so the next open starts empty.
|
|
67
93
|
$effect(() => {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
toast.error('Failed to load documents');
|
|
87
|
-
searchResults = [];
|
|
88
|
-
} finally {
|
|
89
|
-
loading = false;
|
|
90
|
-
}
|
|
94
|
+
if (!open) {
|
|
95
|
+
query = '';
|
|
96
|
+
searchResults = [];
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// All docs cache — fetched once when the dropdown opens, reused for
|
|
101
|
+
// empty-query browsing and client-side filtering while typing.
|
|
102
|
+
let allDocs = $state<any[]>([]);
|
|
103
|
+
let allDocsFetched = $state(false);
|
|
104
|
+
|
|
105
|
+
async function fetchAllDocs() {
|
|
106
|
+
if (allDocsFetched || !targetType) return;
|
|
107
|
+
loading = true;
|
|
108
|
+
try {
|
|
109
|
+
const result = await documents.list({ docType: targetType, limit: 20 });
|
|
110
|
+
if (result.success && result.data) {
|
|
111
|
+
allDocs = result.data;
|
|
91
112
|
}
|
|
113
|
+
} catch {
|
|
114
|
+
toast.error('Failed to load documents');
|
|
115
|
+
} finally {
|
|
116
|
+
allDocsFetched = true;
|
|
117
|
+
loading = false;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Fetch docs when dropdown opens; reset cache when it closes.
|
|
122
|
+
$effect(() => {
|
|
123
|
+
if (open) {
|
|
124
|
+
fetchAllDocs();
|
|
125
|
+
} else {
|
|
126
|
+
query = '';
|
|
127
|
+
searchResults = [];
|
|
128
|
+
allDocs = [];
|
|
129
|
+
allDocsFetched = false;
|
|
92
130
|
}
|
|
93
|
-
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// Filter results client-side as the user types. Empty query shows all.
|
|
134
|
+
$effect(() => {
|
|
135
|
+
const q = query.trim().toLowerCase();
|
|
136
|
+
if (!open) return;
|
|
137
|
+
if (!q) {
|
|
138
|
+
searchResults = allDocs;
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
searchResults = allDocs.filter((doc: any) => {
|
|
142
|
+
const title = resolvePreviewTitle(doc, targetSchema).toLowerCase();
|
|
143
|
+
const subtitle = (resolvePreviewSubtitle(doc, targetSchema) ?? '').toLowerCase();
|
|
144
|
+
return title.includes(q) || subtitle.includes(q);
|
|
145
|
+
});
|
|
94
146
|
});
|
|
95
147
|
|
|
96
148
|
function closeAndFocusTrigger() {
|
|
97
149
|
open = false;
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Tiny click-outside action for the inline results dropdown — closes the
|
|
153
|
+
// dropdown when the user clicks anywhere outside the wrapper. Cheaper
|
|
154
|
+
// than reaching for a Popover and avoids the focus-stealing problem.
|
|
155
|
+
function clickOutside(node: HTMLElement, callback: () => void) {
|
|
156
|
+
function handle(e: MouseEvent) {
|
|
157
|
+
if (!node.contains(e.target as Node)) callback();
|
|
158
|
+
}
|
|
159
|
+
document.addEventListener('mousedown', handle);
|
|
160
|
+
return {
|
|
161
|
+
destroy() {
|
|
162
|
+
document.removeEventListener('mousedown', handle);
|
|
163
|
+
}
|
|
164
|
+
};
|
|
101
165
|
}
|
|
102
166
|
|
|
103
167
|
function selectDocument(doc: any) {
|
|
104
168
|
if (readonly) return;
|
|
105
|
-
onUpdate(doc.id);
|
|
169
|
+
onUpdate({ _type: 'reference', _ref: doc.id });
|
|
106
170
|
closeAndFocusTrigger();
|
|
107
171
|
}
|
|
108
172
|
|
|
@@ -125,13 +189,11 @@
|
|
|
125
189
|
try {
|
|
126
190
|
const result = await documents.create({
|
|
127
191
|
type: targetType,
|
|
128
|
-
data: {
|
|
129
|
-
title: 'Untitled'
|
|
130
|
-
}
|
|
192
|
+
data: {}
|
|
131
193
|
});
|
|
132
194
|
|
|
133
195
|
if (result.success && result.data) {
|
|
134
|
-
onUpdate(result.data.id);
|
|
196
|
+
onUpdate({ _type: 'reference', _ref: result.data.id });
|
|
135
197
|
closeAndFocusTrigger();
|
|
136
198
|
}
|
|
137
199
|
} catch (err) {
|
|
@@ -179,9 +241,9 @@
|
|
|
179
241
|
>
|
|
180
242
|
{/if}
|
|
181
243
|
</span>
|
|
182
|
-
{#if selectedDocument.status === 'published'}
|
|
244
|
+
{#if selectedDocument._meta?.status === 'published'}
|
|
183
245
|
<span class="h-1.5 w-1.5 shrink-0 rounded-full bg-green-500" title="Published"></span>
|
|
184
|
-
{:else if selectedDocument.status === 'unpublished'}
|
|
246
|
+
{:else if selectedDocument._meta?.status === 'unpublished'}
|
|
185
247
|
<span class="bg-muted-foreground/60 h-1.5 w-1.5 shrink-0 rounded-full" title="Unpublished"
|
|
186
248
|
></span>
|
|
187
249
|
{:else}
|
|
@@ -210,7 +272,7 @@
|
|
|
210
272
|
<DropdownMenu.Separator />
|
|
211
273
|
<DropdownMenu.Item
|
|
212
274
|
class="text-destructive focus:text-destructive"
|
|
213
|
-
onclick={clearSelection}
|
|
275
|
+
onclick={() => (onRemove ? onRemove() : clearSelection())}
|
|
214
276
|
>
|
|
215
277
|
<Trash2 class="mr-2 h-4 w-4" />
|
|
216
278
|
Remove
|
|
@@ -227,86 +289,97 @@
|
|
|
227
289
|
<p class="text-muted-foreground text-sm">No reference selected</p>
|
|
228
290
|
</div>
|
|
229
291
|
{:else}
|
|
230
|
-
<!--
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
292
|
+
<!-- Inline empty state: search input + chevron + Create button. The input
|
|
293
|
+
is the primary focus target — the results dropdown is a sibling div
|
|
294
|
+
positioned absolutely under the input wrapper, with click-outside
|
|
295
|
+
closing it. No popover wrapping the input, so no double-click. -->
|
|
296
|
+
<div class="flex items-center gap-1">
|
|
297
|
+
<div class="relative min-w-0 flex-1" use:clickOutside={() => (open = false)}>
|
|
298
|
+
<div
|
|
299
|
+
class="border-input bg-background focus-within:ring-ring flex h-9 items-center rounded-md border focus-within:ring-1"
|
|
300
|
+
>
|
|
301
|
+
<Input
|
|
302
|
+
bind:value={query}
|
|
303
|
+
placeholder="Type to search..."
|
|
304
|
+
onfocus={() => (open = true)}
|
|
305
|
+
class="h-8 border-0 bg-transparent shadow-none focus-visible:ring-0"
|
|
306
|
+
/>
|
|
234
307
|
<button
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
aria-
|
|
308
|
+
type="button"
|
|
309
|
+
onclick={() => (open = !open)}
|
|
310
|
+
class="text-muted-foreground hover:text-foreground flex h-8 w-8 shrink-0 items-center justify-center"
|
|
311
|
+
aria-label="Toggle results"
|
|
239
312
|
>
|
|
240
|
-
<
|
|
241
|
-
Add {targetType || 'reference'}...
|
|
313
|
+
<ChevronDown class="h-4 w-4" />
|
|
242
314
|
</button>
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
{
|
|
249
|
-
<Command.
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
<
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
{creating ? 'Creating...' : `Create new ${targetType}`}
|
|
259
|
-
</Button>
|
|
260
|
-
</div>
|
|
261
|
-
</Command.Empty>
|
|
262
|
-
{:else}
|
|
263
|
-
<Command.Group>
|
|
264
|
-
{#each searchResults as doc (doc.id)}
|
|
265
|
-
<Command.Item
|
|
266
|
-
value={doc.id}
|
|
267
|
-
onSelect={() => selectDocument(doc)}
|
|
268
|
-
class="flex items-center justify-between"
|
|
269
|
-
>
|
|
270
|
-
<div class="flex min-w-0 flex-1 items-center gap-2">
|
|
271
|
-
<CheckIcon
|
|
272
|
-
class={cn('h-4 w-4 shrink-0', value !== doc.id && 'text-transparent')}
|
|
273
|
-
/>
|
|
274
|
-
<span class="flex min-w-0 flex-1 flex-col">
|
|
275
|
-
<span class="truncate text-sm">{getDocumentTitle(doc)}</span>
|
|
276
|
-
{#if getDocumentSubtitle(doc)}
|
|
277
|
-
<span class="text-muted-foreground truncate text-xs"
|
|
278
|
-
>{getDocumentSubtitle(doc)}</span
|
|
279
|
-
>
|
|
280
|
-
{/if}
|
|
281
|
-
</span>
|
|
315
|
+
</div>
|
|
316
|
+
{#if open}
|
|
317
|
+
<div
|
|
318
|
+
class="bg-popover text-popover-foreground absolute top-full left-0 z-[9999] mt-1 w-[400px] max-w-[min(400px,calc(100vw-2rem))] rounded-md border p-0 shadow-md"
|
|
319
|
+
>
|
|
320
|
+
<Command.Root shouldFilter={false}>
|
|
321
|
+
<Command.List class="max-h-[300px] overflow-y-auto">
|
|
322
|
+
{#if loading}
|
|
323
|
+
<Command.Loading>Loading...</Command.Loading>
|
|
324
|
+
{:else if searchResults.length === 0}
|
|
325
|
+
<Command.Empty>
|
|
326
|
+
<div class="text-muted-foreground py-4 text-center text-sm">
|
|
327
|
+
{query.trim()
|
|
328
|
+
? `No ${pluralize(targetType || '')} match "${query}"`
|
|
329
|
+
: `No ${pluralize(targetType || '')} found`}
|
|
282
330
|
</div>
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
{
|
|
287
|
-
<
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
331
|
+
</Command.Empty>
|
|
332
|
+
{:else}
|
|
333
|
+
<Command.Group>
|
|
334
|
+
{#each searchResults as doc (doc.id)}
|
|
335
|
+
<Command.Item
|
|
336
|
+
value={doc.id}
|
|
337
|
+
onSelect={() => selectDocument(doc)}
|
|
338
|
+
class="flex items-center justify-between"
|
|
339
|
+
>
|
|
340
|
+
<div class="flex min-w-0 flex-1 items-center gap-2">
|
|
341
|
+
<CheckIcon
|
|
342
|
+
class={cn('h-4 w-4 shrink-0', refId !== doc.id && 'text-transparent')}
|
|
343
|
+
/>
|
|
344
|
+
<span class="flex min-w-0 flex-1 flex-col">
|
|
345
|
+
<span class="truncate text-sm">{getDocumentTitle(doc)}</span>
|
|
346
|
+
{#if getDocumentSubtitle(doc)}
|
|
347
|
+
<span class="text-muted-foreground truncate text-xs"
|
|
348
|
+
>{getDocumentSubtitle(doc)}</span
|
|
349
|
+
>
|
|
350
|
+
{/if}
|
|
351
|
+
</span>
|
|
352
|
+
</div>
|
|
353
|
+
{#if doc._meta?.status === 'published'}
|
|
354
|
+
<span class="h-1.5 w-1.5 shrink-0 rounded-full bg-green-500" title="Published"
|
|
355
|
+
></span>
|
|
356
|
+
{:else if doc._meta?.status === 'unpublished'}
|
|
357
|
+
<span
|
|
358
|
+
class="bg-muted-foreground/60 h-1.5 w-1.5 shrink-0 rounded-full"
|
|
359
|
+
title="Unpublished"
|
|
360
|
+
></span>
|
|
361
|
+
{:else}
|
|
362
|
+
<span class="h-1.5 w-1.5 shrink-0 rounded-full bg-amber-500" title="Draft"
|
|
363
|
+
></span>
|
|
364
|
+
{/if}
|
|
365
|
+
</Command.Item>
|
|
366
|
+
{/each}
|
|
367
|
+
</Command.Group>
|
|
368
|
+
{/if}
|
|
369
|
+
</Command.List>
|
|
370
|
+
</Command.Root>
|
|
371
|
+
</div>
|
|
372
|
+
{/if}
|
|
373
|
+
</div>
|
|
374
|
+
<Button
|
|
375
|
+
variant="outline"
|
|
376
|
+
size="sm"
|
|
377
|
+
onclick={createNewDocument}
|
|
378
|
+
disabled={creating}
|
|
379
|
+
class="h-9 shrink-0 gap-1"
|
|
380
|
+
>
|
|
381
|
+
<PlusIcon class="h-4 w-4" />
|
|
382
|
+
{creating ? 'Creating...' : 'Create...'}
|
|
383
|
+
</Button>
|
|
384
|
+
</div>
|
|
312
385
|
{/if}
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import type { Field } from '../../../types/schemas.js';
|
|
2
|
+
type ReferenceValue = {
|
|
3
|
+
_type: 'reference';
|
|
4
|
+
_ref: string;
|
|
5
|
+
_key?: string;
|
|
6
|
+
};
|
|
2
7
|
interface Props {
|
|
3
8
|
field: Field;
|
|
4
|
-
value:
|
|
5
|
-
onUpdate: (value:
|
|
9
|
+
value: ReferenceValue | null;
|
|
10
|
+
onUpdate: (value: ReferenceValue | null) => void;
|
|
6
11
|
onOpenReference?: (documentId: string, documentType: string) => void;
|
|
7
12
|
readonly?: boolean;
|
|
13
|
+
onRemove?: () => void;
|
|
14
|
+
preloadedDoc?: unknown;
|
|
8
15
|
}
|
|
9
16
|
declare const ReferenceField: import("svelte").Component<Props, {}, "">;
|
|
10
17
|
type ReferenceField = ReturnType<typeof ReferenceField>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReferenceField.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/admin/fields/ReferenceField.svelte.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ReferenceField.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/admin/fields/ReferenceField.svelte.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,KAAK,EAAwC,MAAM,wBAAwB,CAAC;AAUzF,KAAK,cAAc,GAAG;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1E,UAAU,KAAK;IACd,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;IAC7B,QAAQ,EAAE,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,KAAK,IAAI,CAAC;IACjD,eAAe,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACrE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;CACvB;AAqUF,QAAA,MAAM,cAAc,2CAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AppSidebar.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/layout/sidebar/AppSidebar.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,OAAO,EAKP,MAAM,6BAA6B,CAAC;AAItC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAG5C,KAAK,KAAK,GAAG,cAAc,CAAC,OAAO,OAAO,CAAC,GAAG;IAC7C,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC,CAAC;
|
|
1
|
+
{"version":3,"file":"AppSidebar.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/layout/sidebar/AppSidebar.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,OAAO,EAKP,MAAM,6BAA6B,CAAC;AAItC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAG5C,KAAK,KAAK,GAAG,cAAc,CAAC,OAAO,OAAO,CAAC,GAAG;IAC7C,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC,CAAC;AAsDH,QAAA,MAAM,UAAU,2CAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
url: string;
|
|
20
20
|
icon?: typeof IconType;
|
|
21
21
|
isActive?: boolean;
|
|
22
|
+
exact?: boolean;
|
|
22
23
|
items?: {
|
|
23
24
|
title: string;
|
|
24
25
|
url: string;
|
|
@@ -28,9 +29,15 @@
|
|
|
28
29
|
type Props = {
|
|
29
30
|
items: NavItem[];
|
|
30
31
|
label?: string;
|
|
32
|
+
isActive?: (path: string, item: NavItem) => boolean;
|
|
31
33
|
};
|
|
32
34
|
|
|
33
|
-
let { items, label = 'Content' }: Props = $props();
|
|
35
|
+
let { items, label = 'Content', isActive: isActiveProp }: Props = $props();
|
|
36
|
+
|
|
37
|
+
function matchActive(item: NavItem): boolean {
|
|
38
|
+
if (isActiveProp) return isActiveProp(currentPath, item);
|
|
39
|
+
return item.exact ? currentPath === item.url : currentPath.startsWith(item.url);
|
|
40
|
+
}
|
|
34
41
|
|
|
35
42
|
let currentPath = $derived(page.url.pathname);
|
|
36
43
|
</script>
|
|
@@ -79,7 +86,7 @@
|
|
|
79
86
|
<SidebarMenuItem>
|
|
80
87
|
<SidebarMenuButton
|
|
81
88
|
onclick={() => goto(item.url)}
|
|
82
|
-
isActive={
|
|
89
|
+
isActive={matchActive(item)}
|
|
83
90
|
tooltipContent={item.title}
|
|
84
91
|
class="cursor-pointer"
|
|
85
92
|
>
|
|
@@ -4,6 +4,7 @@ type NavItem = {
|
|
|
4
4
|
url: string;
|
|
5
5
|
icon?: typeof IconType;
|
|
6
6
|
isActive?: boolean;
|
|
7
|
+
exact?: boolean;
|
|
7
8
|
items?: {
|
|
8
9
|
title: string;
|
|
9
10
|
url: string;
|
|
@@ -12,6 +13,7 @@ type NavItem = {
|
|
|
12
13
|
type Props = {
|
|
13
14
|
items: NavItem[];
|
|
14
15
|
label?: string;
|
|
16
|
+
isActive?: (path: string, item: NavItem) => boolean;
|
|
15
17
|
};
|
|
16
18
|
declare const NavMain: import("svelte").Component<Props, {}, "">;
|
|
17
19
|
type NavMain = ReturnType<typeof NavMain>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NavMain.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/layout/sidebar/NavMain.svelte.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAgB,KAAK,IAAI,IAAI,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAGpE,KAAK,OAAO,GAAG;IACd,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,OAAO,QAAQ,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,GAAG,EAAE,MAAM,CAAC;KACZ,EAAE,CAAC;CACJ,CAAC;AAEF,KAAK,KAAK,GAAG;IACZ,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"NavMain.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/layout/sidebar/NavMain.svelte.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAgB,KAAK,IAAI,IAAI,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAGpE,KAAK,OAAO,GAAG;IACd,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,OAAO,QAAQ,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,GAAG,EAAE,MAAM,CAAC;KACZ,EAAE,CAAC;CACJ,CAAC;AAEF,KAAK,KAAK,GAAG;IACZ,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC;CACpD,CAAC;AA2EH,QAAA,MAAM,OAAO,2CAAwC,CAAC;AACtD,KAAK,OAAO,GAAG,UAAU,CAAC,OAAO,OAAO,CAAC,CAAC;AAC1C,eAAe,OAAO,CAAC"}
|
|
@@ -5,6 +5,7 @@ import type { SchemaAdapter } from './schema.js';
|
|
|
5
5
|
import type { OrganizationAdapter } from './organization.js';
|
|
6
6
|
import type { InstanceAdapter } from './instance.js';
|
|
7
7
|
import type { RolesAdapter } from './role.js';
|
|
8
|
+
import type { ReferenceAdapter } from './reference.js';
|
|
8
9
|
export type { DocumentAdapter, DocumentFilters, CreateDocumentData, UpdateDocumentData } from './document.js';
|
|
9
10
|
export type { AssetAdapter, CreateAssetData, UpdateAssetData } from './asset.js';
|
|
10
11
|
export type { UserProfileAdapter, NewUserProfileData } from './user.js';
|
|
@@ -12,11 +13,12 @@ export type { SchemaAdapter } from './schema.js';
|
|
|
12
13
|
export type { OrganizationAdapter } from './organization.js';
|
|
13
14
|
export type { InstanceAdapter, InstanceSettings } from './instance.js';
|
|
14
15
|
export type { RolesAdapter } from './role.js';
|
|
16
|
+
export type { ReferenceAdapter, BackReferenceRow, BackReferenceLookup } from './reference.js';
|
|
15
17
|
/**
|
|
16
18
|
* Combined database adapter interface
|
|
17
19
|
* Extends all entity-specific adapters for full database functionality
|
|
18
20
|
*/
|
|
19
|
-
export interface DatabaseAdapter extends DocumentAdapter, AssetAdapter, UserProfileAdapter, SchemaAdapter, OrganizationAdapter, InstanceAdapter, RolesAdapter {
|
|
21
|
+
export interface DatabaseAdapter extends DocumentAdapter, AssetAdapter, UserProfileAdapter, SchemaAdapter, OrganizationAdapter, InstanceAdapter, RolesAdapter, ReferenceAdapter {
|
|
20
22
|
connect?(): Promise<void>;
|
|
21
23
|
disconnect?(): Promise<void>;
|
|
22
24
|
isHealthy(): Promise<boolean>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/db/interfaces/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/db/interfaces/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export interface BackReferenceRow {
|
|
2
|
+
id: string;
|
|
3
|
+
type: string;
|
|
4
|
+
status: string | null;
|
|
5
|
+
}
|
|
6
|
+
export interface BackReferenceLookup extends BackReferenceRow {
|
|
7
|
+
refId: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ReferenceAdapter {
|
|
10
|
+
/**
|
|
11
|
+
* Replace all back-reference rows for a given referencer atomically.
|
|
12
|
+
* Called by the references service after every doc save with the full
|
|
13
|
+
* set of refs extracted from the doc's data.
|
|
14
|
+
*/
|
|
15
|
+
replaceReferencesFor(organizationId: string, referencerId: string, refIds: string[]): Promise<void>;
|
|
16
|
+
/**
|
|
17
|
+
* Find all documents that reference the given target. Joins through the
|
|
18
|
+
* documents table so callers get type/status without a second round-trip.
|
|
19
|
+
*/
|
|
20
|
+
findBackReferences(organizationId: string, refId: string): Promise<BackReferenceRow[]>;
|
|
21
|
+
/**
|
|
22
|
+
* Bulk variant of findBackReferences — returns all back-refs for a set
|
|
23
|
+
* of target IDs, with `refId` included so callers can group by target.
|
|
24
|
+
*/
|
|
25
|
+
findBackReferencesForMany(organizationId: string, refIds: string[]): Promise<BackReferenceLookup[]>;
|
|
26
|
+
/**
|
|
27
|
+
* Whether the references table has any rows for this organization.
|
|
28
|
+
* Used by the boot path to decide whether a one-time backfill is needed.
|
|
29
|
+
*/
|
|
30
|
+
hasAnyReferences(organizationId: string): Promise<boolean>;
|
|
31
|
+
/**
|
|
32
|
+
* Bulk insert variant for the backfill path. Single INSERT for all rows
|
|
33
|
+
* — caller is responsible for ensuring the table is empty for this org
|
|
34
|
+
* (no DELETE step). Adapter implementations should ignore conflicts so
|
|
35
|
+
* the operation is idempotent if called twice.
|
|
36
|
+
*/
|
|
37
|
+
bulkInsertReferences(rows: Array<{
|
|
38
|
+
organizationId: string;
|
|
39
|
+
referencerId: string;
|
|
40
|
+
refId: string;
|
|
41
|
+
}>): Promise<void>;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=reference.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reference.d.ts","sourceRoot":"","sources":["../../../src/lib/db/interfaces/reference.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,gBAAgB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,mBAAoB,SAAQ,gBAAgB;IAC5D,KAAK,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAChC;;;;OAIG;IACH,oBAAoB,CACnB,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,EAAE,GACd,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB;;;OAGG;IACH,kBAAkB,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAEvF;;;OAGG;IACH,yBAAyB,CACxB,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM,EAAE,GACd,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAElC;;;OAGG;IACH,gBAAgB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAE3D;;;;;OAKG;IACH,oBAAoB,CACnB,IAAI,EAAE,KAAK,CAAC;QAAE,cAAc,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,GAC1E,OAAO,CAAC,IAAI,CAAC,CAAC;CACjB"}
|
|
@@ -6,12 +6,10 @@ interface ResolveOptions {
|
|
|
6
6
|
visited?: Set<string>;
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
|
-
* Recursively resolves reference fields in a document
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* @param options - Resolution options (depth, tracking)
|
|
14
|
-
* @returns Document with resolved references
|
|
9
|
+
* Recursively resolves reference fields in a document. Both singular and
|
|
10
|
+
* array refs share the on-disk shape `{ _type: 'reference', _ref }`, so the
|
|
11
|
+
* resolver finds them by that marker and replaces the entire object with
|
|
12
|
+
* the fetched document.
|
|
15
13
|
*/
|
|
16
14
|
export declare function resolveReferences(document: Document, adapter: DocumentAdapter, organizationId: string, options: ResolveOptions): Promise<Document>;
|
|
17
15
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reference-resolver.d.ts","sourceRoot":"","sources":["../../../src/lib/db/utils/reference-resolver.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D,UAAU,cAAc;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACtB;AAED
|
|
1
|
+
{"version":3,"file":"reference-resolver.d.ts","sourceRoot":"","sources":["../../../src/lib/db/utils/reference-resolver.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D,UAAU,cAAc;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACtC,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,eAAe,EACxB,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,cAAc,GACrB,OAAO,CAAC,QAAQ,CAAC,CA2CnB"}
|