@svadmin/lite 0.3.3 → 0.3.5
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/package.json +18 -4
- package/src/components/LiteAlert.svelte +0 -19
- package/src/components/LiteArrayField.svelte +0 -113
- package/src/components/LiteAuditLog.svelte +0 -104
- package/src/components/LiteBreadcrumbs.svelte +0 -39
- package/src/components/LiteChatDialog.svelte +0 -101
- package/src/components/LiteConfirmDialog.svelte +0 -60
- package/src/components/LiteEmptyState.svelte +0 -39
- package/src/components/LiteForm.svelte +0 -138
- package/src/components/LiteLayout.svelte +0 -106
- package/src/components/LiteLogin.svelte +0 -41
- package/src/components/LitePagination.svelte +0 -73
- package/src/components/LitePermissionMatrix.svelte +0 -147
- package/src/components/LiteSearch.svelte +0 -41
- package/src/components/LiteShow.svelte +0 -61
- package/src/components/LiteShowField.svelte +0 -51
- package/src/components/LiteStatsCard.svelte +0 -70
- package/src/components/LiteTable.svelte +0 -132
- package/src/components/LiteTabs.svelte +0 -57
- package/src/components/advanced/LiteAutoSaveIndicator.svelte +0 -26
- package/src/components/advanced/LiteDraggableHeader.svelte +0 -33
- package/src/components/advanced/LiteDrawerForm.svelte +0 -42
- package/src/components/advanced/LiteInlineEdit.svelte +0 -32
- package/src/components/advanced/LiteModalForm.svelte +0 -44
- package/src/components/advanced/LiteToast.svelte +0 -34
- package/src/components/advanced/LiteUndoableNotification.svelte +0 -25
- package/src/components/advanced/LiteVirtualTable.svelte +0 -44
- package/src/components/buttons/LiteCloneButton.svelte +0 -33
- package/src/components/buttons/LiteCreateButton.svelte +0 -31
- package/src/components/buttons/LiteDeleteButton.svelte +0 -57
- package/src/components/buttons/LiteEditButton.svelte +0 -33
- package/src/components/buttons/LiteExportButton.svelte +0 -31
- package/src/components/buttons/LiteImportButton.svelte +0 -50
- package/src/components/buttons/LiteListButton.svelte +0 -31
- package/src/components/buttons/LiteRefreshButton.svelte +0 -27
- package/src/components/buttons/LiteSaveButton.svelte +0 -27
- package/src/components/buttons/LiteShowButton.svelte +0 -33
- package/src/components/fields/LiteBooleanField.svelte +0 -41
- package/src/components/fields/LiteDateField.svelte +0 -51
- package/src/components/fields/LiteEmailField.svelte +0 -40
- package/src/components/fields/LiteFileField.svelte +0 -53
- package/src/components/fields/LiteImageField.svelte +0 -57
- package/src/components/fields/LiteJsonField.svelte +0 -43
- package/src/components/fields/LiteMarkdownField.svelte +0 -33
- package/src/components/fields/LiteMultiSelectField.svelte +0 -57
- package/src/components/fields/LiteNumberField.svelte +0 -34
- package/src/components/fields/LiteRelationField.svelte +0 -66
- package/src/components/fields/LiteRichTextField.svelte +0 -45
- package/src/components/fields/LiteSelectField.svelte +0 -47
- package/src/components/fields/LiteTagField.svelte +0 -44
- package/src/components/fields/LiteTextField.svelte +0 -34
- package/src/components/fields/LiteUrlField.svelte +0 -40
- package/src/components/layout/LiteAuthenticated.svelte +0 -23
- package/src/components/layout/LiteCanAccess.svelte +0 -27
- package/src/components/layout/LiteCatchAllNavigate.svelte +0 -20
- package/src/components/layout/LiteErrorBoundary.svelte +0 -20
- package/src/components/layout/LiteErrorComponent.svelte +0 -37
- package/src/components/layout/LiteHeader.svelte +0 -19
- package/src/components/layout/LiteNavigateToResource.svelte +0 -25
- package/src/components/layout/LiteSidebar.svelte +0 -93
- package/src/components/pages/LiteCreatePage.svelte +0 -39
- package/src/components/pages/LiteEditPage.svelte +0 -54
- package/src/components/pages/LiteForgotPasswordPage.svelte +0 -60
- package/src/components/pages/LiteListPage.svelte +0 -81
- package/src/components/pages/LiteProfilePage.svelte +0 -61
- package/src/components/pages/LiteRegisterPage.svelte +0 -64
- package/src/components/pages/LiteShowPage.svelte +0 -61
- package/src/components/pages/LiteUpdatePasswordPage.svelte +0 -51
- package/src/components/widgets/LiteAnomalyBadge.svelte +0 -40
- package/src/components/widgets/LiteBarChart.svelte +0 -45
- package/src/components/widgets/LiteInsightCard.svelte +0 -28
- package/src/components/widgets/LiteLineChart.svelte +0 -48
- package/src/components/widgets/LitePieChart.svelte +0 -44
- package/src/lite.css +0 -708
- package/static/enhance.js +0 -56
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { t } from '@svadmin/core/i18n';
|
|
3
|
-
import { Upload } from '@lucide/svelte';
|
|
4
|
-
|
|
5
|
-
interface Props {
|
|
6
|
-
resource: string;
|
|
7
|
-
basePath?: string;
|
|
8
|
-
hideText?: boolean;
|
|
9
|
-
class?: string;
|
|
10
|
-
size?: 'sm' | 'default' | 'icon';
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
let {
|
|
14
|
-
resource,
|
|
15
|
-
basePath = '/lite',
|
|
16
|
-
hideText = false,
|
|
17
|
-
class: className = '',
|
|
18
|
-
size = 'default'
|
|
19
|
-
}: Props = $props();
|
|
20
|
-
</script>
|
|
21
|
-
|
|
22
|
-
<details class="lite-confirm-details {className}">
|
|
23
|
-
<summary
|
|
24
|
-
class="lite-btn {size === 'sm' ? 'lite-btn-sm' : ''}"
|
|
25
|
-
title={t('common.import') || 'Import'}
|
|
26
|
-
>
|
|
27
|
-
<Upload class="h-4 w-4" />
|
|
28
|
-
{#if !hideText}
|
|
29
|
-
<span style="marginLeft: 4px">{t('common.import') || 'Import'}</span>
|
|
30
|
-
{/if}
|
|
31
|
-
</summary>
|
|
32
|
-
<div class="lite-confirm-panel">
|
|
33
|
-
<p style="margin: 0 0 8px; font-size: 13px;">{t('common.importData') || 'Import data (CSV/JSON)'}</p>
|
|
34
|
-
<form method="POST" action="?/${resource}_import" enctype="multipart/form-data" style="display:flex; flex-direction: column; gap: 8px;">
|
|
35
|
-
<input type="file" name="file" accept=".csv,.json" required style="font-size: 13px;" />
|
|
36
|
-
<div style="display:flex; gap: 8px; justify-content: flex-end;">
|
|
37
|
-
<button
|
|
38
|
-
type="button"
|
|
39
|
-
class="lite-btn lite-btn-sm"
|
|
40
|
-
onclick={(e) => (e.currentTarget as HTMLElement).closest('details')?.removeAttribute('open')}
|
|
41
|
-
>
|
|
42
|
-
{t('common.cancel') || 'Cancel'}
|
|
43
|
-
</button>
|
|
44
|
-
<button type="submit" class="lite-btn lite-btn-sm lite-btn-primary">
|
|
45
|
-
{t('common.upload') || 'Upload'}
|
|
46
|
-
</button>
|
|
47
|
-
</div>
|
|
48
|
-
</form>
|
|
49
|
-
</div>
|
|
50
|
-
</details>
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { t } from '@svadmin/core/i18n';
|
|
3
|
-
import { List } from '@lucide/svelte';
|
|
4
|
-
|
|
5
|
-
interface Props {
|
|
6
|
-
resource: string;
|
|
7
|
-
basePath?: string;
|
|
8
|
-
hideText?: boolean;
|
|
9
|
-
class?: string;
|
|
10
|
-
size?: 'sm' | 'default' | 'icon';
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
let {
|
|
14
|
-
resource,
|
|
15
|
-
basePath = '/lite',
|
|
16
|
-
hideText = false,
|
|
17
|
-
class: className = '',
|
|
18
|
-
size = 'default'
|
|
19
|
-
}: Props = $props();
|
|
20
|
-
</script>
|
|
21
|
-
|
|
22
|
-
<a
|
|
23
|
-
href={`${basePath}/${resource}`}
|
|
24
|
-
class="lite-btn {size === 'sm' ? 'lite-btn-sm' : ''} {className}"
|
|
25
|
-
title={t('common.list') || 'List'}
|
|
26
|
-
>
|
|
27
|
-
<List class="h-4 w-4" />
|
|
28
|
-
{#if !hideText}
|
|
29
|
-
<span style="marginLeft: 4px">{t('common.list') || 'List'}</span>
|
|
30
|
-
{/if}
|
|
31
|
-
</a>
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { t } from '@svadmin/core/i18n';
|
|
3
|
-
import { RefreshCw } from '@lucide/svelte';
|
|
4
|
-
|
|
5
|
-
interface Props {
|
|
6
|
-
hideText?: boolean;
|
|
7
|
-
class?: string;
|
|
8
|
-
size?: 'sm' | 'default' | 'icon';
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
let {
|
|
12
|
-
hideText = false,
|
|
13
|
-
class: className = '',
|
|
14
|
-
size = 'default'
|
|
15
|
-
}: Props = $props();
|
|
16
|
-
</script>
|
|
17
|
-
|
|
18
|
-
<a
|
|
19
|
-
href=""
|
|
20
|
-
class="lite-btn {size === 'sm' ? 'lite-btn-sm' : ''} {className}"
|
|
21
|
-
title={t('common.refresh') || 'Refresh'}
|
|
22
|
-
>
|
|
23
|
-
<RefreshCw class="h-4 w-4" />
|
|
24
|
-
{#if !hideText}
|
|
25
|
-
<span style="marginLeft: 4px">{t('common.refresh') || 'Refresh'}</span>
|
|
26
|
-
{/if}
|
|
27
|
-
</a>
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { t } from '@svadmin/core/i18n';
|
|
3
|
-
import { Save } from '@lucide/svelte';
|
|
4
|
-
|
|
5
|
-
interface Props {
|
|
6
|
-
hideText?: boolean;
|
|
7
|
-
class?: string;
|
|
8
|
-
size?: 'sm' | 'default' | 'icon';
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
let {
|
|
12
|
-
hideText = false,
|
|
13
|
-
class: className = '',
|
|
14
|
-
size = 'default'
|
|
15
|
-
}: Props = $props();
|
|
16
|
-
</script>
|
|
17
|
-
|
|
18
|
-
<button
|
|
19
|
-
type="submit"
|
|
20
|
-
class="lite-btn lite-btn-primary {size === 'sm' ? 'lite-btn-sm' : ''} {className}"
|
|
21
|
-
title={t('common.save') || 'Save'}
|
|
22
|
-
>
|
|
23
|
-
<Save class="h-4 w-4" />
|
|
24
|
-
{#if !hideText}
|
|
25
|
-
<span style="marginLeft: 4px">{t('common.save') || 'Save'}</span>
|
|
26
|
-
{/if}
|
|
27
|
-
</button>
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { t } from '@svadmin/core/i18n';
|
|
3
|
-
import { Eye } from '@lucide/svelte';
|
|
4
|
-
|
|
5
|
-
interface Props {
|
|
6
|
-
resource: string;
|
|
7
|
-
recordItemId: string | number;
|
|
8
|
-
basePath?: string;
|
|
9
|
-
hideText?: boolean;
|
|
10
|
-
class?: string;
|
|
11
|
-
size?: 'sm' | 'default' | 'icon';
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
let {
|
|
15
|
-
resource,
|
|
16
|
-
recordItemId,
|
|
17
|
-
basePath = '/lite',
|
|
18
|
-
hideText = false,
|
|
19
|
-
class: className = '',
|
|
20
|
-
size = 'default'
|
|
21
|
-
}: Props = $props();
|
|
22
|
-
</script>
|
|
23
|
-
|
|
24
|
-
<a
|
|
25
|
-
href={`${basePath}/${resource}/show/${recordItemId}`}
|
|
26
|
-
class="lite-btn {size === 'sm' ? 'lite-btn-sm' : ''} {className}"
|
|
27
|
-
title={t('common.show') || 'Show'}
|
|
28
|
-
>
|
|
29
|
-
<Eye class="h-4 w-4" />
|
|
30
|
-
{#if !hideText}
|
|
31
|
-
<span style="marginLeft: 4px">{t('common.show') || 'Show'}</span>
|
|
32
|
-
{/if}
|
|
33
|
-
</a>
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { FieldDefinition } from '@svadmin/core';
|
|
3
|
-
|
|
4
|
-
interface Props {
|
|
5
|
-
field: FieldDefinition;
|
|
6
|
-
value?: unknown;
|
|
7
|
-
error?: string[];
|
|
8
|
-
mode?: 'show' | 'edit' | 'create';
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
let { field, value, error = [], mode = 'show' }: Props = $props();
|
|
12
|
-
let hasError = $derived(error.length > 0);
|
|
13
|
-
</script>
|
|
14
|
-
|
|
15
|
-
{#if mode === 'show'}
|
|
16
|
-
<div>
|
|
17
|
-
<span class="lite-bool {value ? 'lite-bool-true' : ''}"></span>
|
|
18
|
-
{value ? '✓ Yes' : '✗ No'}
|
|
19
|
-
</div>
|
|
20
|
-
{:else}
|
|
21
|
-
<div class="lite-checkbox-group">
|
|
22
|
-
<input
|
|
23
|
-
type="checkbox"
|
|
24
|
-
name={field.key}
|
|
25
|
-
id={field.key}
|
|
26
|
-
checked={!!value}
|
|
27
|
-
value="true"
|
|
28
|
-
/>
|
|
29
|
-
<!-- Fallback hidden input so unchecked boxes submit "false" -->
|
|
30
|
-
<input type="hidden" name={field.key} value="false" />
|
|
31
|
-
|
|
32
|
-
<label for={field.key}>
|
|
33
|
-
{(field as any).placeholder ?? (field.label || 'Yes')}
|
|
34
|
-
</label>
|
|
35
|
-
{#if hasError}
|
|
36
|
-
{#each error as err}
|
|
37
|
-
<div class="lite-error-text">{err}</div>
|
|
38
|
-
{/each}
|
|
39
|
-
{/if}
|
|
40
|
-
</div>
|
|
41
|
-
{/if}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { FieldDefinition } from '@svadmin/core';
|
|
3
|
-
|
|
4
|
-
interface Props {
|
|
5
|
-
field: FieldDefinition;
|
|
6
|
-
value?: unknown;
|
|
7
|
-
error?: string[];
|
|
8
|
-
mode?: 'show' | 'edit' | 'create';
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
let { field, value, error = [], mode = 'show' }: Props = $props();
|
|
12
|
-
let hasError = $derived(error.length > 0);
|
|
13
|
-
|
|
14
|
-
function formatDate(v: unknown): string {
|
|
15
|
-
if (!v) return '';
|
|
16
|
-
try {
|
|
17
|
-
return new Date(v as string).toISOString().substring(0, 16); // Formats for html datetime-local
|
|
18
|
-
} catch {
|
|
19
|
-
return '';
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function displayDate(v: unknown): string {
|
|
24
|
-
if (!v) return '—';
|
|
25
|
-
try {
|
|
26
|
-
return new Date(v as string).toLocaleString();
|
|
27
|
-
} catch {
|
|
28
|
-
return String(v);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
</script>
|
|
32
|
-
|
|
33
|
-
{#if mode === 'show'}
|
|
34
|
-
<span>{displayDate(value)}</span>
|
|
35
|
-
{:else}
|
|
36
|
-
<div>
|
|
37
|
-
<input
|
|
38
|
-
type="datetime-local"
|
|
39
|
-
name={field.key}
|
|
40
|
-
id={field.key}
|
|
41
|
-
value={formatDate(value)}
|
|
42
|
-
class="lite-input {hasError ? 'lite-input-error' : ''}"
|
|
43
|
-
{...field.required ? { required: true } : {}}
|
|
44
|
-
/>
|
|
45
|
-
{#if hasError}
|
|
46
|
-
{#each error as err}
|
|
47
|
-
<div class="lite-error-text">{err}</div>
|
|
48
|
-
{/each}
|
|
49
|
-
{/if}
|
|
50
|
-
</div>
|
|
51
|
-
{/if}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { FieldDefinition } from '@svadmin/core';
|
|
3
|
-
|
|
4
|
-
interface Props {
|
|
5
|
-
field: FieldDefinition;
|
|
6
|
-
value?: unknown;
|
|
7
|
-
error?: string[];
|
|
8
|
-
mode?: 'show' | 'edit' | 'create';
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
let { field, value, error = [], mode = 'show' }: Props = $props();
|
|
12
|
-
let hasError = $derived(error.length > 0);
|
|
13
|
-
</script>
|
|
14
|
-
|
|
15
|
-
{#if mode === 'show'}
|
|
16
|
-
<span>
|
|
17
|
-
{#if value}
|
|
18
|
-
<a href="mailto:{value}">{value}</a>
|
|
19
|
-
{:else}
|
|
20
|
-
—
|
|
21
|
-
{/if}
|
|
22
|
-
</span>
|
|
23
|
-
{:else}
|
|
24
|
-
<div>
|
|
25
|
-
<input
|
|
26
|
-
type="email"
|
|
27
|
-
name={field.key}
|
|
28
|
-
id={field.key}
|
|
29
|
-
value={String(value ?? '')}
|
|
30
|
-
class="lite-input {hasError ? 'lite-input-error' : ''}"
|
|
31
|
-
placeholder={(field as any).placeholder ?? field.label}
|
|
32
|
-
{...field.required ? { required: true } : {}}
|
|
33
|
-
/>
|
|
34
|
-
{#if hasError}
|
|
35
|
-
{#each error as err}
|
|
36
|
-
<div class="lite-error-text">{err}</div>
|
|
37
|
-
{/each}
|
|
38
|
-
{/if}
|
|
39
|
-
</div>
|
|
40
|
-
{/if}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { FieldDefinition } from '@svadmin/core';
|
|
3
|
-
|
|
4
|
-
interface Props {
|
|
5
|
-
field: FieldDefinition;
|
|
6
|
-
value?: unknown;
|
|
7
|
-
error?: string[];
|
|
8
|
-
mode?: 'show' | 'edit' | 'create';
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
let { field, value, error = [], mode = 'show' }: Props = $props();
|
|
12
|
-
let hasError = $derived(error.length > 0);
|
|
13
|
-
|
|
14
|
-
function getFiles(v: unknown): string[] {
|
|
15
|
-
if (!v) return [];
|
|
16
|
-
if (Array.isArray(v)) return v.map(String);
|
|
17
|
-
if (typeof v === 'string') return [v];
|
|
18
|
-
return [];
|
|
19
|
-
}
|
|
20
|
-
</script>
|
|
21
|
-
|
|
22
|
-
{#if mode === 'show'}
|
|
23
|
-
{@const files = getFiles(value)}
|
|
24
|
-
<div style="display:flex; flex-direction: column; gap: 4px;">
|
|
25
|
-
{#each files as f}
|
|
26
|
-
<a href={f} target="_blank" rel="noopener noreferrer">{f.split('/').pop() || 'Download'}</a>
|
|
27
|
-
{:else}
|
|
28
|
-
<span>—</span>
|
|
29
|
-
{/each}
|
|
30
|
-
</div>
|
|
31
|
-
{:else}
|
|
32
|
-
{@const files = getFiles(value)}
|
|
33
|
-
<div>
|
|
34
|
-
{#if files.length > 0 && mode === 'edit'}
|
|
35
|
-
<div style="margin-bottom: 8px;">
|
|
36
|
-
<span style="font-size: 12px;">Current files: {files.length}</span>
|
|
37
|
-
</div>
|
|
38
|
-
{/if}
|
|
39
|
-
<input
|
|
40
|
-
type="file"
|
|
41
|
-
name={field.key}
|
|
42
|
-
id={field.key}
|
|
43
|
-
class="lite-input {hasError ? 'lite-input-error' : ''}"
|
|
44
|
-
{...(field.type as string) === 'files' ? { multiple: true } : {}}
|
|
45
|
-
{...field.required && !files.length ? { required: true } : {}}
|
|
46
|
-
/>
|
|
47
|
-
{#if hasError}
|
|
48
|
-
{#each error as err}
|
|
49
|
-
<div class="lite-error-text">{err}</div>
|
|
50
|
-
{/each}
|
|
51
|
-
{/if}
|
|
52
|
-
</div>
|
|
53
|
-
{/if}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { FieldDefinition } from '@svadmin/core';
|
|
3
|
-
|
|
4
|
-
interface Props {
|
|
5
|
-
field: FieldDefinition;
|
|
6
|
-
value?: unknown;
|
|
7
|
-
error?: string[];
|
|
8
|
-
mode?: 'show' | 'edit' | 'create';
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
let { field, value, error = [], mode = 'show' }: Props = $props();
|
|
12
|
-
let hasError = $derived(error.length > 0);
|
|
13
|
-
|
|
14
|
-
function getUrls(v: unknown): string[] {
|
|
15
|
-
if (!v) return [];
|
|
16
|
-
if (Array.isArray(v)) return v.map(String);
|
|
17
|
-
if (typeof v === 'string') return [v];
|
|
18
|
-
return [];
|
|
19
|
-
}
|
|
20
|
-
</script>
|
|
21
|
-
|
|
22
|
-
{#if mode === 'show'}
|
|
23
|
-
{@const urls = getUrls(value)}
|
|
24
|
-
<div style="display:flex; gap: 8px; flex-wrap: wrap;">
|
|
25
|
-
{#each urls as url}
|
|
26
|
-
<img src={url} alt={field.label} style="max-height: 100px; border-radius: 4px; border: 1px solid #e5e7eb;" />
|
|
27
|
-
{:else}
|
|
28
|
-
<span>—</span>
|
|
29
|
-
{/each}
|
|
30
|
-
</div>
|
|
31
|
-
{:else}
|
|
32
|
-
{@const urls = getUrls(value)}
|
|
33
|
-
<div>
|
|
34
|
-
{#if urls.length > 0 && mode === 'edit'}
|
|
35
|
-
<div style="margin-bottom: 8px; display:flex; gap: 8px;">
|
|
36
|
-
{#each urls as url}
|
|
37
|
-
<img src={url} alt="Current" style="height: 60px; border-radius: 4px; border: 1px solid #e5e7eb; opacity: 0.6;" />
|
|
38
|
-
{/each}
|
|
39
|
-
</div>
|
|
40
|
-
<p style="font-size: 11px; color:#6b7280; margin: 0 0 4px;">Uploading new ones will overwrite.</p>
|
|
41
|
-
{/if}
|
|
42
|
-
<input
|
|
43
|
-
type="file"
|
|
44
|
-
name={field.key}
|
|
45
|
-
id={field.key}
|
|
46
|
-
accept="image/*"
|
|
47
|
-
class="lite-input {hasError ? 'lite-input-error' : ''}"
|
|
48
|
-
{...(field.type as string) === 'images' ? { multiple: true } : {}}
|
|
49
|
-
{...field.required && !urls.length ? { required: true } : {}}
|
|
50
|
-
/>
|
|
51
|
-
{#if hasError}
|
|
52
|
-
{#each error as err}
|
|
53
|
-
<div class="lite-error-text">{err}</div>
|
|
54
|
-
{/each}
|
|
55
|
-
{/if}
|
|
56
|
-
</div>
|
|
57
|
-
{/if}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { FieldDefinition } from '@svadmin/core';
|
|
3
|
-
|
|
4
|
-
interface Props {
|
|
5
|
-
field: FieldDefinition;
|
|
6
|
-
value?: unknown;
|
|
7
|
-
error?: string[];
|
|
8
|
-
mode?: 'show' | 'edit' | 'create';
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
let { field, value, error = [], mode = 'show' }: Props = $props();
|
|
12
|
-
let hasError = $derived(error.length > 0);
|
|
13
|
-
|
|
14
|
-
function getJsonString(v: unknown): string {
|
|
15
|
-
if (v == null) return '';
|
|
16
|
-
if (typeof v === 'string') return v;
|
|
17
|
-
try {
|
|
18
|
-
return JSON.stringify(v, null, 2);
|
|
19
|
-
} catch {
|
|
20
|
-
return String(v);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
</script>
|
|
24
|
-
|
|
25
|
-
{#if mode === 'show'}
|
|
26
|
-
<pre style="padding: 12px; background: #1e293b; color: #f8fafc; border-radius: 4px; overflow-x: auto; font-size: 13px;">{getJsonString(value)}</pre>
|
|
27
|
-
{:else}
|
|
28
|
-
<div>
|
|
29
|
-
<textarea
|
|
30
|
-
name={field.key}
|
|
31
|
-
id={field.key}
|
|
32
|
-
class="lite-input {hasError ? 'lite-input-error' : ''}"
|
|
33
|
-
style="min-height: 150px; font-family: monospace;"
|
|
34
|
-
placeholder="{}"
|
|
35
|
-
{...field.required ? { required: true } : {}}
|
|
36
|
-
>{getJsonString(value)}</textarea>
|
|
37
|
-
{#if hasError}
|
|
38
|
-
{#each error as err}
|
|
39
|
-
<div class="lite-error-text">{err}</div>
|
|
40
|
-
{/each}
|
|
41
|
-
{/if}
|
|
42
|
-
</div>
|
|
43
|
-
{/if}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { FieldDefinition } from '@svadmin/core';
|
|
3
|
-
|
|
4
|
-
interface Props {
|
|
5
|
-
field: FieldDefinition;
|
|
6
|
-
value?: unknown;
|
|
7
|
-
error?: string[];
|
|
8
|
-
mode?: 'show' | 'edit' | 'create';
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
let { field, value, error = [], mode = 'show' }: Props = $props();
|
|
12
|
-
let hasError = $derived(error.length > 0);
|
|
13
|
-
</script>
|
|
14
|
-
|
|
15
|
-
{#if mode === 'show'}
|
|
16
|
-
<pre style="white-space: pre-wrap; padding: 12px; background: #f8fafc; border: 1px solid #e5e7eb; border-radius: 4px;">{String(value ?? '—')}</pre>
|
|
17
|
-
{:else}
|
|
18
|
-
<div>
|
|
19
|
-
<textarea
|
|
20
|
-
name={field.key}
|
|
21
|
-
id={field.key}
|
|
22
|
-
class="lite-input {hasError ? 'lite-input-error' : ''}"
|
|
23
|
-
style="min-height: 200px; font-family: monospace;"
|
|
24
|
-
placeholder="Enter markdown..."
|
|
25
|
-
{...field.required ? { required: true } : {}}
|
|
26
|
-
>{String(value ?? '')}</textarea>
|
|
27
|
-
{#if hasError}
|
|
28
|
-
{#each error as err}
|
|
29
|
-
<div class="lite-error-text">{err}</div>
|
|
30
|
-
{/each}
|
|
31
|
-
{/if}
|
|
32
|
-
</div>
|
|
33
|
-
{/if}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { FieldDefinition } from '@svadmin/core';
|
|
3
|
-
|
|
4
|
-
interface Props {
|
|
5
|
-
field: FieldDefinition;
|
|
6
|
-
value?: unknown;
|
|
7
|
-
error?: string[];
|
|
8
|
-
mode?: 'show' | 'edit' | 'create';
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
let { field, value, error = [], mode = 'show' }: Props = $props();
|
|
12
|
-
let hasError = $derived(error.length > 0);
|
|
13
|
-
|
|
14
|
-
function displayOptions(valuesRaw: unknown): string[] {
|
|
15
|
-
if (!valuesRaw || !Array.isArray(valuesRaw)) return [];
|
|
16
|
-
return valuesRaw.map(v => {
|
|
17
|
-
const opt = field.options?.find(o => String(o.value) === String(v));
|
|
18
|
-
return opt?.label ?? String(v);
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const valuesArray = $derived(Array.isArray(value) ? value.map(String) : []);
|
|
23
|
-
</script>
|
|
24
|
-
|
|
25
|
-
{#if mode === 'show'}
|
|
26
|
-
<div style="display:flex; gap: 4px; flex-wrap: wrap;">
|
|
27
|
-
{#each displayOptions(value) as opt}
|
|
28
|
-
<span class="lite-badge">{opt}</span>
|
|
29
|
-
{:else}
|
|
30
|
-
<span>—</span>
|
|
31
|
-
{/each}
|
|
32
|
-
</div>
|
|
33
|
-
{:else}
|
|
34
|
-
<div>
|
|
35
|
-
<select
|
|
36
|
-
name={field.key}
|
|
37
|
-
id={field.key}
|
|
38
|
-
multiple
|
|
39
|
-
class="lite-select {hasError ? 'lite-input-error' : ''}"
|
|
40
|
-
style="height: 120px;"
|
|
41
|
-
{...field.required ? { required: true } : {}}
|
|
42
|
-
>
|
|
43
|
-
{#if field.options}
|
|
44
|
-
{#each field.options as opt}
|
|
45
|
-
<option value={String(opt.value)} selected={valuesArray.includes(String(opt.value))}>
|
|
46
|
-
{opt.label}
|
|
47
|
-
</option>
|
|
48
|
-
{/each}
|
|
49
|
-
{/if}
|
|
50
|
-
</select>
|
|
51
|
-
{#if hasError}
|
|
52
|
-
{#each error as err}
|
|
53
|
-
<div class="lite-error-text">{err}</div>
|
|
54
|
-
{/each}
|
|
55
|
-
{/if}
|
|
56
|
-
</div>
|
|
57
|
-
{/if}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { FieldDefinition } from '@svadmin/core';
|
|
3
|
-
|
|
4
|
-
interface Props {
|
|
5
|
-
field: FieldDefinition;
|
|
6
|
-
value?: unknown;
|
|
7
|
-
error?: string[];
|
|
8
|
-
mode?: 'show' | 'edit' | 'create';
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
let { field, value, error = [], mode = 'show' }: Props = $props();
|
|
12
|
-
let hasError = $derived(error.length > 0);
|
|
13
|
-
</script>
|
|
14
|
-
|
|
15
|
-
{#if mode === 'show'}
|
|
16
|
-
<span>{value == null ? '—' : Number(value).toLocaleString()}</span>
|
|
17
|
-
{:else}
|
|
18
|
-
<div>
|
|
19
|
-
<input
|
|
20
|
-
type="number"
|
|
21
|
-
name={field.key}
|
|
22
|
-
id={field.key}
|
|
23
|
-
value={value == null ? '' : Number(value)}
|
|
24
|
-
class="lite-input {hasError ? 'lite-input-error' : ''}"
|
|
25
|
-
placeholder={(field as any).placeholder ?? field.label}
|
|
26
|
-
{...field.required ? { required: true } : {}}
|
|
27
|
-
/>
|
|
28
|
-
{#if hasError}
|
|
29
|
-
{#each error as err}
|
|
30
|
-
<div class="lite-error-text">{err}</div>
|
|
31
|
-
{/each}
|
|
32
|
-
{/if}
|
|
33
|
-
</div>
|
|
34
|
-
{/if}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { FieldDefinition } from '@svadmin/core';
|
|
3
|
-
import { t } from '@svadmin/core/i18n';
|
|
4
|
-
|
|
5
|
-
interface Props {
|
|
6
|
-
field: FieldDefinition;
|
|
7
|
-
value?: unknown;
|
|
8
|
-
error?: string[];
|
|
9
|
-
mode?: 'show' | 'edit' | 'create';
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
let { field, value, error = [], mode = 'show' }: Props = $props();
|
|
13
|
-
let hasError = $derived(error.length > 0);
|
|
14
|
-
|
|
15
|
-
// In Lite version, relations might need to be rendered via server-side joined data
|
|
16
|
-
// passed through options, or just standard inputs requesting ID.
|
|
17
|
-
function displayRelation(v: unknown): string {
|
|
18
|
-
if (v == null) return '—';
|
|
19
|
-
if (typeof v === 'object' && v !== null && 'id' in v) {
|
|
20
|
-
// It's a populated relation object
|
|
21
|
-
const labelField = (field as any).relation?.labelField || 'name';
|
|
22
|
-
return String((v as Record<string, unknown>)[labelField] || (v as Record<string, unknown>).id);
|
|
23
|
-
}
|
|
24
|
-
// Try options
|
|
25
|
-
const opt = field.options?.find(o => String(o.value) === String(v));
|
|
26
|
-
return opt?.label ?? String(v);
|
|
27
|
-
}
|
|
28
|
-
</script>
|
|
29
|
-
|
|
30
|
-
{#if mode === 'show'}
|
|
31
|
-
<span class="lite-badge">{displayRelation(value)}</span>
|
|
32
|
-
{:else}
|
|
33
|
-
<div>
|
|
34
|
-
{#if field.options && field.options.length > 0}
|
|
35
|
-
<!-- Render as select if options provided by loader -->
|
|
36
|
-
<select
|
|
37
|
-
name={field.key}
|
|
38
|
-
id={field.key}
|
|
39
|
-
class="lite-select {hasError ? 'lite-input-error' : ''}"
|
|
40
|
-
>
|
|
41
|
-
<option value="">-- {t('common.select') || 'Select'} Reference --</option>
|
|
42
|
-
{#each field.options as opt}
|
|
43
|
-
<option value={String(opt.value)} selected={String(value) === String(opt.value)}>
|
|
44
|
-
{opt.label}
|
|
45
|
-
</option>
|
|
46
|
-
{/each}
|
|
47
|
-
</select>
|
|
48
|
-
{:else}
|
|
49
|
-
<!-- Fallback text input for target ID -->
|
|
50
|
-
<input
|
|
51
|
-
type="text"
|
|
52
|
-
name={field.key}
|
|
53
|
-
id={field.key}
|
|
54
|
-
value={typeof value === 'object' && value ? String((value as Record<string, unknown>).id || '') : String(value ?? '')}
|
|
55
|
-
class="lite-input {hasError ? 'lite-input-error' : ''}"
|
|
56
|
-
placeholder="Enter reference ID"
|
|
57
|
-
{...field.required ? { required: true } : {}}
|
|
58
|
-
/>
|
|
59
|
-
{/if}
|
|
60
|
-
{#if hasError}
|
|
61
|
-
{#each error as err}
|
|
62
|
-
<div class="lite-error-text">{err}</div>
|
|
63
|
-
{/each}
|
|
64
|
-
{/if}
|
|
65
|
-
</div>
|
|
66
|
-
{/if}
|