@aphexcms/cms-core 0.1.16 → 0.2.1
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/client.d.ts.map +1 -1
- package/dist/api/client.js +7 -1
- package/dist/api/types.d.ts +2 -0
- package/dist/api/types.d.ts.map +1 -1
- package/dist/cli/generate-types.js +62 -17
- package/dist/cli/index.js +1 -1
- package/dist/client/index.d.ts +0 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +0 -1
- package/dist/components/AdminApp.svelte +278 -45
- package/dist/components/AdminApp.svelte.d.ts +2 -0
- package/dist/components/AdminApp.svelte.d.ts.map +1 -1
- package/dist/components/admin/DocumentEditor.svelte +60 -13
- package/dist/components/admin/DocumentEditor.svelte.d.ts.map +1 -1
- package/dist/components/admin/ObjectModal.svelte +15 -4
- package/dist/components/admin/ObjectModal.svelte.d.ts +1 -0
- package/dist/components/admin/ObjectModal.svelte.d.ts.map +1 -1
- package/dist/components/admin/SchemaField.svelte +64 -5
- package/dist/components/admin/SchemaField.svelte.d.ts +1 -0
- package/dist/components/admin/SchemaField.svelte.d.ts.map +1 -1
- package/dist/components/admin/fields/ArrayField.svelte +402 -111
- package/dist/components/admin/fields/ArrayField.svelte.d.ts +1 -0
- package/dist/components/admin/fields/ArrayField.svelte.d.ts.map +1 -1
- package/dist/components/admin/fields/DateField.svelte +145 -0
- package/dist/components/admin/fields/DateField.svelte.d.ts +14 -0
- package/dist/components/admin/fields/DateField.svelte.d.ts.map +1 -0
- package/dist/components/admin/fields/DateTimeField.svelte +225 -0
- package/dist/components/admin/fields/DateTimeField.svelte.d.ts +14 -0
- package/dist/components/admin/fields/DateTimeField.svelte.d.ts.map +1 -0
- package/dist/components/admin/fields/ImageField.svelte +221 -110
- package/dist/components/admin/fields/ImageField.svelte.d.ts +2 -0
- package/dist/components/admin/fields/ImageField.svelte.d.ts.map +1 -1
- package/dist/components/admin/fields/ReferenceField.svelte +1 -1
- package/dist/components/admin/fields/SlugField.svelte +21 -13
- package/dist/components/admin/fields/SlugField.svelte.d.ts +2 -2
- package/dist/components/admin/fields/SlugField.svelte.d.ts.map +1 -1
- package/dist/components/admin/fields/StringField.svelte +156 -12
- package/dist/components/admin/fields/StringField.svelte.d.ts +3 -2
- package/dist/components/admin/fields/StringField.svelte.d.ts.map +1 -1
- package/dist/components/admin/fields/URLField.svelte +41 -0
- package/dist/components/admin/fields/URLField.svelte.d.ts +14 -0
- package/dist/components/admin/fields/URLField.svelte.d.ts.map +1 -0
- package/dist/components/index.d.ts +0 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +0 -1
- package/dist/db/interfaces/asset.d.ts.map +1 -1
- package/dist/db/interfaces/document.d.ts +0 -2
- package/dist/db/interfaces/document.d.ts.map +1 -1
- package/dist/db/interfaces/index.d.ts +2 -1
- package/dist/db/interfaces/index.d.ts.map +1 -1
- package/dist/db/interfaces/user.d.ts +2 -0
- package/dist/db/interfaces/user.d.ts.map +1 -1
- package/dist/db/utils/reference-resolver.js +1 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +3 -0
- package/dist/field-validation/date-utils.d.ts +30 -0
- package/dist/field-validation/date-utils.d.ts.map +1 -0
- package/dist/field-validation/date-utils.js +147 -0
- package/dist/field-validation/rule.d.ts +4 -0
- package/dist/field-validation/rule.d.ts.map +1 -1
- package/dist/field-validation/rule.js +170 -4
- package/dist/field-validation/utils.d.ts +7 -3
- package/dist/field-validation/utils.d.ts.map +1 -1
- package/dist/field-validation/utils.js +130 -38
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +38 -21
- package/dist/lib/field-validation/date-utils.js +147 -0
- package/dist/lib/field-validation/rule.js +170 -4
- package/dist/lib/field-validation/utils.js +130 -38
- package/dist/local-api/collection-api.d.ts +16 -4
- package/dist/local-api/collection-api.d.ts.map +1 -1
- package/dist/local-api/collection-api.js +51 -17
- package/dist/local-api/index.d.ts +1 -1
- package/dist/local-api/index.d.ts.map +1 -1
- package/dist/routes/assets-cdn.d.ts.map +1 -1
- package/dist/routes/assets-cdn.js +14 -7
- package/dist/routes/assets.d.ts.map +1 -1
- package/dist/routes/assets.js +6 -1
- package/dist/routes/documents-by-id.d.ts.map +1 -1
- package/dist/routes/documents-by-id.js +18 -7
- package/dist/routes/documents-publish.js +2 -2
- package/dist/routes/documents-query.d.ts +3 -1
- package/dist/routes/documents-query.d.ts.map +1 -1
- package/dist/routes/documents-query.js +6 -2
- package/dist/routes/documents.d.ts.map +1 -1
- package/dist/routes/documents.js +20 -4
- package/dist/routes/index.d.ts +1 -0
- package/dist/routes/index.d.ts.map +1 -1
- package/dist/routes/index.js +2 -0
- package/dist/routes/user-preferences.d.ts +4 -0
- package/dist/routes/user-preferences.d.ts.map +1 -0
- package/dist/routes/user-preferences.js +77 -0
- package/dist/schema-utils/utils.d.ts +4 -0
- package/dist/schema-utils/utils.d.ts.map +1 -1
- package/dist/schema-utils/utils.js +23 -2
- package/dist/schema-utils/validator.d.ts +4 -0
- package/dist/schema-utils/validator.d.ts.map +1 -1
- package/dist/schema-utils/validator.js +120 -0
- package/dist/types/filters.d.ts +13 -0
- package/dist/types/filters.d.ts.map +1 -1
- package/dist/types/organization.d.ts +3 -0
- package/dist/types/organization.d.ts.map +1 -1
- package/dist/types/schemas.d.ts +67 -7
- package/dist/types/schemas.d.ts.map +1 -1
- package/dist/utils/default-orderings.d.ts +10 -0
- package/dist/utils/default-orderings.d.ts.map +1 -0
- package/dist/utils/default-orderings.js +63 -0
- package/dist/utils/field-defaults.d.ts +8 -0
- package/dist/utils/field-defaults.d.ts.map +1 -0
- package/dist/utils/field-defaults.js +20 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/initial-value-helpers.d.ts +50 -0
- package/dist/utils/initial-value-helpers.d.ts.map +1 -0
- package/dist/utils/initial-value-helpers.js +70 -0
- package/package.json +6 -4
- package/dist/components/admin/DocumentTypesList.svelte +0 -97
- package/dist/components/admin/DocumentTypesList.svelte.d.ts +0 -14
- package/dist/components/admin/DocumentTypesList.svelte.d.ts.map +0 -1
|
@@ -21,6 +21,8 @@
|
|
|
21
21
|
schemaType?: string;
|
|
22
22
|
fieldPath?: string;
|
|
23
23
|
readonly?: boolean;
|
|
24
|
+
compact?: boolean; // Compact mode for arrays
|
|
25
|
+
organizationId?: string; // Document's organization ID for asset uploads
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
let {
|
|
@@ -30,7 +32,9 @@
|
|
|
30
32
|
validationClasses,
|
|
31
33
|
schemaType,
|
|
32
34
|
fieldPath,
|
|
33
|
-
readonly = false
|
|
35
|
+
readonly = false,
|
|
36
|
+
compact = false,
|
|
37
|
+
organizationId
|
|
34
38
|
}: Props = $props();
|
|
35
39
|
|
|
36
40
|
// Component state
|
|
@@ -48,6 +52,9 @@
|
|
|
48
52
|
const formData = new FormData();
|
|
49
53
|
formData.append('file', file);
|
|
50
54
|
|
|
55
|
+
// Add document's organization ID so asset belongs to document's org
|
|
56
|
+
if (organizationId) formData.append('organizationId', organizationId);
|
|
57
|
+
|
|
51
58
|
// Add field metadata for privacy checking
|
|
52
59
|
if (schemaType) formData.append('schemaType', schemaType);
|
|
53
60
|
if (fieldPath) formData.append('fieldPath', fieldPath);
|
|
@@ -81,7 +88,7 @@
|
|
|
81
88
|
async function handleFileSelect(files: FileList | null) {
|
|
82
89
|
if (readonly || !files || files.length === 0) return;
|
|
83
90
|
|
|
84
|
-
const file = files[0]
|
|
91
|
+
const file = files[0]!;
|
|
85
92
|
|
|
86
93
|
const imageValue = await uploadFile(file);
|
|
87
94
|
if (imageValue) {
|
|
@@ -169,6 +176,11 @@
|
|
|
169
176
|
|
|
170
177
|
// Get asset URL for preview
|
|
171
178
|
const previewUrl = $derived(assetData?.url || null);
|
|
179
|
+
|
|
180
|
+
// Get display name for the image
|
|
181
|
+
const displayName = $derived(
|
|
182
|
+
assetData?.originalFilename || assetData?.filename || value?.asset?._ref || 'Image'
|
|
183
|
+
);
|
|
172
184
|
</script>
|
|
173
185
|
|
|
174
186
|
<!-- Hidden file input -->
|
|
@@ -180,138 +192,237 @@
|
|
|
180
192
|
onchange={handleFileInputChange}
|
|
181
193
|
/>
|
|
182
194
|
|
|
183
|
-
{#if
|
|
184
|
-
<!--
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
195
|
+
{#if compact}
|
|
196
|
+
<!-- Compact mode for arrays -->
|
|
197
|
+
{#if value && value.asset}
|
|
198
|
+
<!-- Compact image row with thumbnail -->
|
|
199
|
+
<div class="border-border flex items-center gap-3 rounded-md border p-2 {validationClasses}">
|
|
200
|
+
<!-- Thumbnail -->
|
|
201
|
+
<div
|
|
202
|
+
class="bg-muted flex h-12 w-12 flex-shrink-0 items-center justify-center overflow-hidden rounded"
|
|
203
|
+
>
|
|
189
204
|
{#if loadingAsset}
|
|
190
|
-
<div class="
|
|
191
|
-
<div class="border-primary h-8 w-8 animate-spin rounded-full border-b-2"></div>
|
|
192
|
-
<span class="text-sm">Loading image...</span>
|
|
193
|
-
</div>
|
|
205
|
+
<div class="border-primary h-4 w-4 animate-spin rounded-full border-b-2"></div>
|
|
194
206
|
{:else if previewUrl}
|
|
195
207
|
<img
|
|
196
208
|
src={previewUrl}
|
|
197
|
-
alt={assetData?.alt ||
|
|
198
|
-
class="h-full w-full object-
|
|
209
|
+
alt={assetData?.alt || displayName}
|
|
210
|
+
class="h-full w-full object-cover"
|
|
199
211
|
loading="lazy"
|
|
200
212
|
/>
|
|
201
213
|
{:else}
|
|
202
|
-
<
|
|
203
|
-
<ImageIcon size={32} />
|
|
204
|
-
<span class="text-sm">Image: {value.asset._ref}</span>
|
|
205
|
-
<span class="text-xs">Failed to load preview</span>
|
|
206
|
-
</div>
|
|
214
|
+
<ImageIcon size={20} class="text-muted-foreground" />
|
|
207
215
|
{/if}
|
|
208
216
|
</div>
|
|
209
217
|
|
|
210
|
-
<!--
|
|
218
|
+
<!-- File name -->
|
|
219
|
+
<div class="flex-1 overflow-hidden">
|
|
220
|
+
<p class="truncate text-sm font-medium">{displayName}</p>
|
|
221
|
+
{#if assetData?.size}
|
|
222
|
+
<p class="text-muted-foreground text-xs">
|
|
223
|
+
{(assetData.size / 1024).toFixed(1)} KB
|
|
224
|
+
</p>
|
|
225
|
+
{/if}
|
|
226
|
+
</div>
|
|
227
|
+
|
|
228
|
+
<!-- Options menu -->
|
|
211
229
|
{#if !readonly}
|
|
212
|
-
<
|
|
213
|
-
<
|
|
214
|
-
<
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
230
|
+
<DropdownMenu>
|
|
231
|
+
<DropdownMenuTrigger>
|
|
232
|
+
<Button variant="ghost" size="sm" class="h-8 w-8 p-0">
|
|
233
|
+
<Ellipsis size={16} />
|
|
234
|
+
</Button>
|
|
235
|
+
</DropdownMenuTrigger>
|
|
236
|
+
<DropdownMenuContent align="end">
|
|
237
|
+
<DropdownMenuGroup>
|
|
238
|
+
<DropdownMenuLabel>
|
|
239
|
+
<Button
|
|
240
|
+
variant="ghost"
|
|
241
|
+
size="sm"
|
|
242
|
+
onclick={openFileDialog}
|
|
243
|
+
disabled={isUploading}
|
|
244
|
+
class="w-full justify-start"
|
|
227
245
|
>
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
246
|
+
<Upload size={16} class="mr-2" />
|
|
247
|
+
Replace
|
|
248
|
+
</Button>
|
|
249
|
+
</DropdownMenuLabel>
|
|
250
|
+
<DropdownMenuLabel>
|
|
251
|
+
<Button
|
|
252
|
+
variant="ghost"
|
|
253
|
+
size="sm"
|
|
254
|
+
onclick={removeImage}
|
|
255
|
+
disabled={isUploading}
|
|
256
|
+
class="text-destructive hover:text-destructive w-full justify-start"
|
|
238
257
|
>
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
258
|
+
<Trash2 size={16} class="mr-2" />
|
|
259
|
+
Remove
|
|
260
|
+
</Button>
|
|
261
|
+
</DropdownMenuLabel>
|
|
262
|
+
</DropdownMenuGroup>
|
|
263
|
+
</DropdownMenuContent>
|
|
264
|
+
</DropdownMenu>
|
|
243
265
|
{/if}
|
|
244
266
|
</div>
|
|
245
|
-
|
|
246
|
-
<!--
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
267
|
+
{:else}
|
|
268
|
+
<!-- Compact upload button -->
|
|
269
|
+
<Button
|
|
270
|
+
variant="outline"
|
|
271
|
+
class="w-full justify-start"
|
|
272
|
+
onclick={openFileDialog}
|
|
273
|
+
disabled={isUploading || readonly}
|
|
274
|
+
type="button"
|
|
275
|
+
>
|
|
276
|
+
{#if isUploading}
|
|
277
|
+
<div class="border-primary mr-2 h-4 w-4 animate-spin rounded-full border-b-2"></div>
|
|
278
|
+
Uploading...
|
|
279
|
+
{:else}
|
|
280
|
+
<Upload size={16} class="mr-2" />
|
|
281
|
+
Upload Image
|
|
282
|
+
{/if}
|
|
283
|
+
</Button>
|
|
284
|
+
{/if}
|
|
254
285
|
{:else}
|
|
255
|
-
<!--
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
<div
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
286
|
+
<!-- Full mode (original) -->
|
|
287
|
+
{#if value && value.asset}
|
|
288
|
+
<!-- Image preview with controls -->
|
|
289
|
+
<div class="border-border overflow-hidden rounded-md border {validationClasses}">
|
|
290
|
+
<div class="group relative">
|
|
291
|
+
<!-- Image preview (Sanity-style aspect ratio ~2.75:1) -->
|
|
292
|
+
<div class="bg-muted flex items-center justify-center" style="aspect-ratio: 2.75 / 1;">
|
|
293
|
+
{#if loadingAsset}
|
|
294
|
+
<div class="text-muted-foreground flex flex-col items-center gap-2">
|
|
295
|
+
<div class="border-primary h-8 w-8 animate-spin rounded-full border-b-2"></div>
|
|
296
|
+
<span class="text-sm">Loading image...</span>
|
|
297
|
+
</div>
|
|
298
|
+
{:else if previewUrl}
|
|
299
|
+
<img
|
|
300
|
+
src={previewUrl}
|
|
301
|
+
alt={assetData?.alt || 'Uploaded image'}
|
|
302
|
+
class="h-full w-full object-contain"
|
|
303
|
+
loading="lazy"
|
|
304
|
+
/>
|
|
305
|
+
{:else}
|
|
306
|
+
<div class="text-muted-foreground flex flex-col items-center gap-2">
|
|
307
|
+
<ImageIcon size={32} />
|
|
308
|
+
<span class="text-sm">Image: {value.asset._ref}</span>
|
|
309
|
+
<span class="text-xs">Failed to load preview</span>
|
|
310
|
+
</div>
|
|
311
|
+
{/if}
|
|
312
|
+
</div>
|
|
313
|
+
|
|
314
|
+
<!-- Overlay controls (hidden for read-only) -->
|
|
315
|
+
{#if !readonly}
|
|
316
|
+
<div class="absolute inset-2 flex items-start justify-end gap-2">
|
|
317
|
+
<DropdownMenu>
|
|
318
|
+
<DropdownMenuTrigger><Ellipsis /></DropdownMenuTrigger>
|
|
319
|
+
<DropdownMenuContent>
|
|
320
|
+
<DropdownMenuGroup>
|
|
321
|
+
<DropdownMenuLabel
|
|
322
|
+
><Button
|
|
323
|
+
variant="secondary"
|
|
324
|
+
size="sm"
|
|
325
|
+
onclick={openFileDialog}
|
|
326
|
+
disabled={isUploading}
|
|
327
|
+
>
|
|
328
|
+
<Upload size={16} class="mr-1" />
|
|
329
|
+
Replace
|
|
330
|
+
</Button></DropdownMenuLabel
|
|
331
|
+
>
|
|
332
|
+
<DropdownMenuLabel
|
|
333
|
+
><Button
|
|
334
|
+
variant="destructive"
|
|
335
|
+
size="sm"
|
|
336
|
+
onclick={removeImage}
|
|
337
|
+
disabled={isUploading}
|
|
338
|
+
>
|
|
339
|
+
<Trash2 size={16} class="mr-1" />
|
|
340
|
+
Remove
|
|
341
|
+
</Button></DropdownMenuLabel
|
|
342
|
+
>
|
|
343
|
+
</DropdownMenuGroup>
|
|
344
|
+
</DropdownMenuContent>
|
|
345
|
+
</DropdownMenu>
|
|
282
346
|
</div>
|
|
283
347
|
{/if}
|
|
284
348
|
</div>
|
|
285
349
|
|
|
286
|
-
<!--
|
|
287
|
-
|
|
288
|
-
<
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
350
|
+
<!-- Additional image controls/metadata could go here -->
|
|
351
|
+
{#if field.fields}
|
|
352
|
+
<div class="border-border space-y-2 border-t p-3">
|
|
353
|
+
<!-- Custom fields like caption, alt text, etc. would be rendered here -->
|
|
354
|
+
<p class="text-muted-foreground text-xs">Custom fields coming soon...</p>
|
|
355
|
+
</div>
|
|
356
|
+
{/if}
|
|
357
|
+
</div>
|
|
358
|
+
{:else}
|
|
359
|
+
<!-- Sanity-style upload bar -->
|
|
360
|
+
<div class="border-border overflow-hidden rounded-md border {validationClasses}">
|
|
361
|
+
<div class="flex flex-col items-center divide-y lg:flex-row lg:divide-x lg:divide-y-0">
|
|
362
|
+
<!-- Drag and drop area (left side) -->
|
|
363
|
+
<div
|
|
364
|
+
class="flex h-14 w-full px-3 py-4 transition-colors lg:flex-1 {readonly
|
|
365
|
+
? ''
|
|
366
|
+
: isDragging
|
|
367
|
+
? 'bg-primary/5'
|
|
368
|
+
: 'hover:bg-muted/50'}"
|
|
369
|
+
ondragover={readonly ? undefined : handleDragOver}
|
|
370
|
+
ondragleave={readonly ? undefined : handleDragLeave}
|
|
371
|
+
ondrop={readonly ? undefined : handleDrop}
|
|
372
|
+
tabindex={readonly ? -1 : 0}
|
|
373
|
+
role={readonly ? undefined : 'button'}
|
|
294
374
|
>
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
375
|
+
{#if isUploading}
|
|
376
|
+
<div class="flex items-center gap-3">
|
|
377
|
+
<div class="border-primary h-5 w-5 animate-spin rounded-full border-b-2"></div>
|
|
378
|
+
<span class="text-muted-foreground text-sm">Uploading...</span>
|
|
379
|
+
</div>
|
|
380
|
+
{:else}
|
|
381
|
+
<div class="flex items-center gap-3">
|
|
382
|
+
<FileImage size={20} class="text-muted-foreground" />
|
|
383
|
+
<span class="text-muted-foreground text-sm">
|
|
384
|
+
{readonly
|
|
385
|
+
? 'No image'
|
|
386
|
+
: isDragging
|
|
387
|
+
? 'Drop image here'
|
|
388
|
+
: 'Drag or paste image here'}
|
|
389
|
+
</span>
|
|
390
|
+
</div>
|
|
391
|
+
{/if}
|
|
392
|
+
</div>
|
|
393
|
+
|
|
394
|
+
<!-- Buttons (right side) -->
|
|
395
|
+
<div
|
|
396
|
+
class="border-border bg-muted/20 flex h-14 w-full items-center justify-center gap-2 px-3 py-4 lg:w-1/2"
|
|
308
397
|
>
|
|
309
|
-
<
|
|
310
|
-
|
|
311
|
-
|
|
398
|
+
<Button
|
|
399
|
+
variant="outline"
|
|
400
|
+
size="sm"
|
|
401
|
+
onclick={openFileDialog}
|
|
402
|
+
disabled={isUploading || readonly}
|
|
403
|
+
type="button"
|
|
404
|
+
>
|
|
405
|
+
<Upload size={16} class="mr-1" />
|
|
406
|
+
Upload
|
|
407
|
+
</Button>
|
|
408
|
+
|
|
409
|
+
<Button
|
|
410
|
+
variant="outline"
|
|
411
|
+
size="sm"
|
|
412
|
+
disabled={isUploading || readonly}
|
|
413
|
+
type="button"
|
|
414
|
+
onclick={() => {
|
|
415
|
+
// TODO: Open asset browser/selector
|
|
416
|
+
console.log('Open asset selector');
|
|
417
|
+
}}
|
|
418
|
+
>
|
|
419
|
+
<ImageIcon size={16} class="mr-1" />
|
|
420
|
+
Select
|
|
421
|
+
</Button>
|
|
422
|
+
</div>
|
|
312
423
|
</div>
|
|
313
424
|
</div>
|
|
314
|
-
|
|
425
|
+
{/if}
|
|
315
426
|
{/if}
|
|
316
427
|
|
|
317
428
|
<!-- Error display -->
|
|
@@ -8,6 +8,8 @@ interface Props {
|
|
|
8
8
|
schemaType?: string;
|
|
9
9
|
fieldPath?: string;
|
|
10
10
|
readonly?: boolean;
|
|
11
|
+
compact?: boolean;
|
|
12
|
+
organizationId?: string;
|
|
11
13
|
}
|
|
12
14
|
declare const ImageField: import("svelte").Component<Props, {}, "">;
|
|
13
15
|
type ImageField = ReturnType<typeof ImageField>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageField.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/admin/fields/ImageField.svelte.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,IAAI,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAY1E,UAAU,KAAK;IACd,KAAK,EAAE,cAAc,CAAC;IACtB,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,KAAK,IAAI,CAAC;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"ImageField.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/admin/fields/ImageField.svelte.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,IAAI,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAY1E,UAAU,KAAK;IACd,KAAK,EAAE,cAAc,CAAC;IACtB,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,KAAK,IAAI,CAAC;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAyVF,QAAA,MAAM,UAAU,2CAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { Input } from '@aphexcms/ui/shadcn/input';
|
|
3
3
|
import { Button } from '@aphexcms/ui/shadcn/button';
|
|
4
|
-
import type {
|
|
4
|
+
import type { SlugField } from '../../../types/schemas';
|
|
5
5
|
import { generateSlug } from '../../../utils/index';
|
|
6
6
|
|
|
7
7
|
interface Props {
|
|
8
|
-
field:
|
|
8
|
+
field: SlugField;
|
|
9
9
|
value: any;
|
|
10
10
|
documentData?: Record<string, any>;
|
|
11
11
|
onUpdate: (value: any) => void;
|
|
@@ -26,15 +26,21 @@
|
|
|
26
26
|
readonly = false
|
|
27
27
|
}: Props = $props();
|
|
28
28
|
|
|
29
|
+
// Get the source field name (default to 'title' for backwards compatibility)
|
|
30
|
+
const sourceField = $derived(field.source || 'title');
|
|
31
|
+
|
|
32
|
+
// Get the source value from document data
|
|
33
|
+
const sourceValue = $derived(documentData?.[sourceField]);
|
|
34
|
+
|
|
29
35
|
function handleInputChange(event: Event) {
|
|
30
36
|
const target = event.target as HTMLInputElement;
|
|
31
37
|
onUpdate(target.value);
|
|
32
38
|
}
|
|
33
39
|
|
|
34
|
-
// Generate slug from
|
|
35
|
-
function
|
|
36
|
-
if (
|
|
37
|
-
const generatedSlug = generateSlug(
|
|
40
|
+
// Generate slug from source field
|
|
41
|
+
function generateSlugFromSource() {
|
|
42
|
+
if (sourceValue && typeof sourceValue === 'string') {
|
|
43
|
+
const generatedSlug = generateSlug(sourceValue);
|
|
38
44
|
onUpdate(generatedSlug);
|
|
39
45
|
}
|
|
40
46
|
}
|
|
@@ -55,20 +61,22 @@
|
|
|
55
61
|
<Button
|
|
56
62
|
variant="outline"
|
|
57
63
|
size="sm"
|
|
58
|
-
onclick={
|
|
59
|
-
disabled={!
|
|
64
|
+
onclick={generateSlugFromSource}
|
|
65
|
+
disabled={!sourceValue || readonly}
|
|
60
66
|
class="shrink-0"
|
|
61
67
|
>
|
|
62
|
-
Generate
|
|
68
|
+
Generate
|
|
63
69
|
</Button>
|
|
64
70
|
</div>
|
|
65
|
-
{#if
|
|
71
|
+
{#if sourceValue}
|
|
66
72
|
<p class="text-muted-foreground text-xs">
|
|
67
|
-
Click "Generate
|
|
73
|
+
Click "Generate" to create slug from {sourceField}: "{sourceValue}"
|
|
68
74
|
</p>
|
|
69
|
-
{:else}
|
|
75
|
+
{:else if field.source}
|
|
70
76
|
<p class="text-muted-foreground text-xs">
|
|
71
|
-
Enter a
|
|
77
|
+
Enter a {sourceField} first to generate a slug automatically
|
|
72
78
|
</p>
|
|
79
|
+
{:else}
|
|
80
|
+
<p class="text-muted-foreground text-xs">Click "Generate" or enter a custom slug</p>
|
|
73
81
|
{/if}
|
|
74
82
|
</div>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SlugField.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/admin/fields/SlugField.svelte.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"SlugField.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/admin/fields/SlugField.svelte.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAIvD,UAAU,KAAK;IACd,KAAK,EAAE,SAAS,CAAC;IACjB,KAAK,EAAE,GAAG,CAAC;IACX,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACnC,QAAQ,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IAC/B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IAC9B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AA6DF,QAAA,MAAM,SAAS,2CAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
|