includio-cms 0.5.2 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/ROADMAP.md +13 -0
- package/dist/admin/client/entry/entry-form.svelte +1 -0
- package/dist/admin/client/entry/entry.svelte +130 -123
- package/dist/admin/client/entry/hybrid/hybrid-preview.svelte +92 -9
- package/dist/admin/components/fields/blocks-field.svelte +142 -112
- package/dist/admin/components/fields/blocks-field.svelte.d.ts +10 -30
- package/dist/admin/components/fields/boolean-field.svelte +28 -38
- package/dist/admin/components/fields/boolean-field.svelte.d.ts +5 -27
- package/dist/admin/components/fields/checkboxes-field.svelte +12 -24
- package/dist/admin/components/fields/checkboxes-field.svelte.d.ts +5 -27
- package/dist/admin/components/fields/content-field.svelte +4 -17
- package/dist/admin/components/fields/content-field.svelte.d.ts +5 -27
- package/dist/admin/components/fields/date-field.svelte +8 -21
- package/dist/admin/components/fields/date-field.svelte.d.ts +5 -27
- package/dist/admin/components/fields/datetime-field.svelte +8 -21
- package/dist/admin/components/fields/datetime-field.svelte.d.ts +5 -27
- package/dist/admin/components/fields/field-renderer.svelte +32 -19
- package/dist/admin/components/fields/field-renderer.svelte.d.ts +1 -1
- package/dist/admin/components/fields/field-value-bridge.svelte +21 -0
- package/dist/admin/components/fields/field-value-bridge.svelte.d.ts +31 -0
- package/dist/admin/components/fields/fields-form.svelte +13 -10
- package/dist/admin/components/fields/file-field.svelte +12 -27
- package/dist/admin/components/fields/file-field.svelte.d.ts +5 -27
- package/dist/admin/components/fields/image-field.svelte +13 -28
- package/dist/admin/components/fields/image-field.svelte.d.ts +5 -27
- package/dist/admin/components/fields/media-field.svelte +15 -30
- package/dist/admin/components/fields/media-field.svelte.d.ts +5 -27
- package/dist/admin/components/fields/number-field.svelte +6 -20
- package/dist/admin/components/fields/number-field.svelte.d.ts +5 -27
- package/dist/admin/components/fields/object-field.svelte +26 -29
- package/dist/admin/components/fields/object-field.svelte.d.ts +11 -31
- package/dist/admin/components/fields/radio-field.svelte +8 -20
- package/dist/admin/components/fields/radio-field.svelte.d.ts +5 -27
- package/dist/admin/components/fields/relation-field.svelte +15 -30
- package/dist/admin/components/fields/relation-field.svelte.d.ts +5 -27
- package/dist/admin/components/fields/richtext-field.svelte +4 -17
- package/dist/admin/components/fields/richtext-field.svelte.d.ts +5 -27
- package/dist/admin/components/fields/select-field.svelte +14 -28
- package/dist/admin/components/fields/select-field.svelte.d.ts +5 -27
- package/dist/admin/components/fields/seo-field.svelte +5 -12
- package/dist/admin/components/fields/seo-field.svelte.d.ts +8 -28
- package/dist/admin/components/fields/simple-array-field.svelte +29 -42
- package/dist/admin/components/fields/simple-array-field.svelte.d.ts +5 -27
- package/dist/admin/components/fields/slug-field.svelte +6 -11
- package/dist/admin/components/fields/slug-field.svelte.d.ts +6 -26
- package/dist/admin/components/fields/text-field-wrapper.svelte +22 -40
- package/dist/admin/components/fields/text-field.svelte +7 -19
- package/dist/admin/components/fields/text-field.svelte.d.ts +5 -27
- package/dist/admin/components/fields/url-field-wrapper.svelte +8 -3
- package/dist/admin/components/fields/url-field.svelte +294 -128
- package/dist/admin/components/fields/url-field.svelte.d.ts +5 -27
- package/dist/admin/components/layout/layout-renderer.svelte +8 -6
- package/dist/admin/components/tiptap/InlineBlockNodeView.svelte +221 -31
- package/dist/admin/components/tiptap/content-editor.svelte +13 -2
- package/dist/admin/components/tiptap/inline-block-node.d.ts +1 -0
- package/dist/admin/components/tiptap/inline-block-node.js +18 -1
- package/dist/admin/components/tiptap/slash-command.js +2 -3
- package/dist/admin/components/tiptap/standalone-form.d.ts +7 -0
- package/dist/admin/components/tiptap/standalone-form.js +31 -0
- package/dist/admin/components/tiptap/tiptap-editor.svelte +7 -0
- package/dist/admin/remote/entry.remote.js +16 -0
- package/dist/admin/styles/admin.css +10 -0
- package/dist/admin/utils/fieldCondition.d.ts +6 -0
- package/dist/admin/utils/fieldCondition.js +20 -0
- package/dist/components/ui/switch/index.d.ts +2 -0
- package/dist/components/ui/switch/index.js +4 -0
- package/dist/components/ui/switch/switch.svelte +26 -0
- package/dist/components/ui/switch/switch.svelte.d.ts +4 -0
- package/dist/core/fields/fieldSchemaToTs.js +15 -3
- package/dist/core/fields/formFieldSchemaToTs.js +22 -6
- package/dist/core/fields/urlUtils.d.ts +14 -0
- package/dist/core/fields/urlUtils.js +21 -0
- package/dist/core/server/fields/populateEntry.js +43 -0
- package/dist/core/server/fields/resolveImageFields.js +33 -1
- package/dist/core/server/fields/resolveRelationFields.js +46 -0
- package/dist/core/server/fields/resolveRichtextLinks.js +15 -1
- package/dist/core/server/fields/resolveUrlFields.js +65 -0
- package/dist/core/server/generator/formFieldSchemaToString.js +40 -9
- package/dist/core/server/generator/formFields.js +2 -0
- package/dist/core/server/generator/generator.js +25 -1
- package/dist/schemas/field/url.d.ts +2 -0
- package/dist/schemas/field/url.js +4 -2
- package/dist/types/fields.d.ts +9 -0
- package/dist/types/formFields.d.ts +15 -2
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/updates/0.5.3/index.d.ts +2 -0
- package/dist/updates/0.5.3/index.js +19 -0
- package/dist/updates/index.js +2 -1
- package/package.json +2 -1
- package/dist/admin/components/fields/standalone-field-renderer.svelte +0 -148
- package/dist/admin/components/fields/standalone-field-renderer.svelte.d.ts +0 -9
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
import RequiredLabel from './required-label.svelte';
|
|
20
20
|
import ClipboardIcon from '@tabler/icons-svelte/icons/clipboard';
|
|
21
21
|
import type { InterfaceLanguage } from '../../../types/languages.js';
|
|
22
|
+
import FieldValueBridge from './field-value-bridge.svelte';
|
|
22
23
|
|
|
23
24
|
const contentLanguage = getContentLanguage();
|
|
24
25
|
const interfaceLanguage = useInterfaceLanguage();
|
|
@@ -39,7 +40,6 @@
|
|
|
39
40
|
);
|
|
40
41
|
const isMultiLang = $derived(contentLanguage.all.length > 1);
|
|
41
42
|
const defaultLang = $derived(contentLanguage.all[0]);
|
|
42
|
-
const isEditingNonDefault = $derived(isMultiLang && contentLanguage.current !== defaultLang);
|
|
43
43
|
|
|
44
44
|
const copyLang: Record<InterfaceLanguage, { copyFrom: (lang: string) => string }> = {
|
|
45
45
|
en: { copyFrom: (lang: string) => `Copy from ${lang.toUpperCase()}` },
|
|
@@ -55,7 +55,6 @@
|
|
|
55
55
|
return dotPath.split('.').reduce<unknown>((obj, key) => (obj as Record<string, unknown>)?.[key], data);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
/** Check if a value is empty for copy-from logic. */
|
|
59
58
|
function isValueEmpty(value: unknown): boolean {
|
|
60
59
|
if (value == null) return true;
|
|
61
60
|
if (typeof value === 'string') return value.length === 0;
|
|
@@ -66,12 +65,10 @@
|
|
|
66
65
|
return false;
|
|
67
66
|
}
|
|
68
67
|
|
|
69
|
-
/** Get source language value for a given field. */
|
|
70
68
|
function getSourceValue(lang: string): unknown {
|
|
71
69
|
return resolvePathValue($formData, joinPath(path, lang));
|
|
72
70
|
}
|
|
73
71
|
|
|
74
|
-
/** Find first language that has content (for copy-from). */
|
|
75
72
|
function findSourceLang(currentLang: string): string | null {
|
|
76
73
|
for (const l of contentLanguage.all) {
|
|
77
74
|
if (l === currentLang) continue;
|
|
@@ -81,7 +78,6 @@
|
|
|
81
78
|
return null;
|
|
82
79
|
}
|
|
83
80
|
|
|
84
|
-
/** Copy value from source language to current language. */
|
|
85
81
|
function copyFrom(sourceLang: string, targetLang: string) {
|
|
86
82
|
const sourceVal = getSourceValue(sourceLang);
|
|
87
83
|
if (sourceVal == null) return;
|
|
@@ -92,15 +88,13 @@
|
|
|
92
88
|
? structuredClone(sourceVal)
|
|
93
89
|
: sourceVal;
|
|
94
90
|
setAtPath($formData as Record<string, unknown>, targetPath, value);
|
|
95
|
-
$formData = $formData;
|
|
91
|
+
$formData = $formData;
|
|
96
92
|
}
|
|
97
93
|
|
|
98
|
-
/** Get reference text for display. */
|
|
99
94
|
function getReferenceText(lang: string): string {
|
|
100
95
|
const val = getSourceValue(lang);
|
|
101
96
|
if (typeof val === 'string') return val;
|
|
102
97
|
if (val && typeof val === 'object' && 'type' in (val as Record<string, unknown>)) {
|
|
103
|
-
// Content field — show placeholder
|
|
104
98
|
return interfaceLanguage.current === 'pl'
|
|
105
99
|
? '(treść w edytorze)'
|
|
106
100
|
: '(editor content)';
|
|
@@ -108,7 +102,6 @@
|
|
|
108
102
|
return '';
|
|
109
103
|
}
|
|
110
104
|
|
|
111
|
-
/** Get per-language fill status for status dots. */
|
|
112
105
|
function getLangFillStatus(lang: string): boolean {
|
|
113
106
|
const val = getSourceValue(lang);
|
|
114
107
|
return !isValueEmpty(val);
|
|
@@ -138,6 +131,19 @@
|
|
|
138
131
|
});
|
|
139
132
|
return parts.join(', ');
|
|
140
133
|
}
|
|
134
|
+
|
|
135
|
+
// Lazy-load richtext and content field components
|
|
136
|
+
let RichtextField: typeof TextField | null = $state(null);
|
|
137
|
+
let ContentField: typeof TextField | null = $state(null);
|
|
138
|
+
|
|
139
|
+
$effect(() => {
|
|
140
|
+
if (field.type === 'richtext' && !RichtextField) {
|
|
141
|
+
import('./richtext-field.svelte').then((m) => { RichtextField = m.default; });
|
|
142
|
+
}
|
|
143
|
+
if (field.type === 'content' && !ContentField) {
|
|
144
|
+
import('./content-field.svelte').then((m) => { ContentField = m.default; });
|
|
145
|
+
}
|
|
146
|
+
});
|
|
141
147
|
</script>
|
|
142
148
|
|
|
143
149
|
<Tabs.Root
|
|
@@ -154,7 +160,6 @@
|
|
|
154
160
|
{#if field.label}
|
|
155
161
|
<div class="flex items-center gap-1.5">
|
|
156
162
|
<RequiredLabel required={field.required}>{getLocalizedLabel(field.label, interfaceLanguage.current)}</RequiredLabel>
|
|
157
|
-
<!-- Status dots -->
|
|
158
163
|
{#if isMultiLang && (field.required || contentLanguage.all.some(l => getLangFillStatus(l)))}
|
|
159
164
|
<span
|
|
160
165
|
class="inline-flex items-center gap-1"
|
|
@@ -171,7 +176,6 @@
|
|
|
171
176
|
</div>
|
|
172
177
|
{/if}
|
|
173
178
|
|
|
174
|
-
<!-- Reference block -->
|
|
175
179
|
{#if contentLanguage.referenceMode && isMultiLang}
|
|
176
180
|
{@const refSource = findSourceLang(lang)}
|
|
177
181
|
{#if refSource}
|
|
@@ -186,37 +190,15 @@
|
|
|
186
190
|
{/if}
|
|
187
191
|
|
|
188
192
|
{#if field.type === 'text'}
|
|
189
|
-
<TextField
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
{#await import('./richtext-field.svelte') then { default: RichtextField }}
|
|
197
|
-
<RichtextField
|
|
198
|
-
{...props}
|
|
199
|
-
{field}
|
|
200
|
-
{form}
|
|
201
|
-
path={joinPath(path, lang) as FormPathLeaves<T, string | undefined>}
|
|
202
|
-
/>
|
|
203
|
-
{:catch}
|
|
204
|
-
<div class="h-32 animate-pulse rounded-md bg-accent"></div>
|
|
205
|
-
{/await}
|
|
206
|
-
{:else if field.type === 'content'}
|
|
207
|
-
{#await import('./content-field.svelte') then { default: ContentField }}
|
|
208
|
-
<ContentField
|
|
209
|
-
{...props}
|
|
210
|
-
{field}
|
|
211
|
-
{form}
|
|
212
|
-
path={joinPath(path, lang) as FormPathLeaves<T, string | undefined>}
|
|
213
|
-
/>
|
|
214
|
-
{:catch}
|
|
215
|
-
<div class="h-32 animate-pulse rounded-md bg-accent"></div>
|
|
216
|
-
{/await}
|
|
193
|
+
<FieldValueBridge {form} path={joinPath(path, lang) as FormPathLeaves<T>} component={TextField} {field} {...props} />
|
|
194
|
+
{:else if field.type === 'richtext' && RichtextField}
|
|
195
|
+
<FieldValueBridge {form} path={joinPath(path, lang) as FormPathLeaves<T>} component={RichtextField} {field} {...props} />
|
|
196
|
+
{:else if field.type === 'content' && ContentField}
|
|
197
|
+
<FieldValueBridge {form} path={joinPath(path, lang) as FormPathLeaves<T>} component={ContentField} {field} {...props} />
|
|
198
|
+
{:else}
|
|
199
|
+
<div class="h-32 animate-pulse rounded-md bg-accent"></div>
|
|
217
200
|
{/if}
|
|
218
201
|
|
|
219
|
-
<!-- Copy from button -->
|
|
220
202
|
{#if isMultiLang}
|
|
221
203
|
{@const currentVal = resolvePathValue($formData, joinPath(path, lang))}
|
|
222
204
|
{@const sourceLang = isValueEmpty(currentVal) ? findSourceLang(lang) : null}
|
|
@@ -1,41 +1,29 @@
|
|
|
1
|
-
<script lang="ts"
|
|
2
|
-
type T = Record<string, unknown>;
|
|
3
|
-
</script>
|
|
4
|
-
|
|
5
|
-
<script lang="ts" generics="T extends Record<string, unknown>">
|
|
1
|
+
<script lang="ts">
|
|
6
2
|
import Input from '../../../components/ui/input/input.svelte';
|
|
7
3
|
import Textarea from '../../../components/ui/textarea/textarea.svelte';
|
|
8
4
|
import type { TextField } from '../../../types/fields.js';
|
|
9
5
|
import { onMount } from 'svelte';
|
|
10
|
-
import {
|
|
11
|
-
formFieldProxy,
|
|
12
|
-
type FormFieldProxy,
|
|
13
|
-
type FormPathLeaves,
|
|
14
|
-
type SuperForm
|
|
15
|
-
} from 'sveltekit-superforms';
|
|
16
6
|
import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
|
|
17
7
|
import { getLocalizedLabel } from '../../utils/collectionLabel.js';
|
|
18
8
|
|
|
19
9
|
type Props = {
|
|
20
10
|
field: TextField;
|
|
21
|
-
|
|
22
|
-
path: FormPathLeaves<T, string | undefined>;
|
|
11
|
+
value: string | undefined;
|
|
23
12
|
};
|
|
24
13
|
|
|
25
|
-
let { field,
|
|
14
|
+
let { field, value = $bindable(), ...props }: Props = $props();
|
|
26
15
|
|
|
27
16
|
const interfaceLanguage = useInterfaceLanguage();
|
|
28
|
-
const { value } = formFieldProxy(form, path) satisfies FormFieldProxy<string | undefined>;
|
|
29
17
|
|
|
30
18
|
onMount(() => {
|
|
31
|
-
if (
|
|
32
|
-
|
|
19
|
+
if (value === undefined) {
|
|
20
|
+
value = '';
|
|
33
21
|
}
|
|
34
22
|
});
|
|
35
23
|
</script>
|
|
36
24
|
|
|
37
25
|
{#if field.multiline}
|
|
38
|
-
<Textarea {...props} bind:value
|
|
26
|
+
<Textarea {...props} bind:value placeholder={getLocalizedLabel(field.placeholder, interfaceLanguage.current)} minlength={field.minLength} maxlength={field.maxLength} />
|
|
39
27
|
{:else}
|
|
40
|
-
<Input {...props} bind:value
|
|
28
|
+
<Input {...props} bind:value type="text" placeholder={getLocalizedLabel(field.placeholder, interfaceLanguage.current)} minlength={field.minLength} maxlength={field.maxLength} />
|
|
41
29
|
{/if}
|
|
@@ -1,30 +1,8 @@
|
|
|
1
1
|
import type { TextField } from '../../../types/fields.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
field: TextField;
|
|
6
|
-
form: SuperForm<T>;
|
|
7
|
-
path: FormPathLeaves<T, string | undefined>;
|
|
8
|
-
};
|
|
9
|
-
exports: {};
|
|
10
|
-
bindings: "";
|
|
11
|
-
slots: {};
|
|
12
|
-
events: {};
|
|
2
|
+
type Props = {
|
|
3
|
+
field: TextField;
|
|
4
|
+
value: string | undefined;
|
|
13
5
|
};
|
|
14
|
-
declare
|
|
15
|
-
|
|
16
|
-
events(): ReturnType<typeof $$render<T>>['events'];
|
|
17
|
-
slots(): ReturnType<typeof $$render<T>>['slots'];
|
|
18
|
-
bindings(): "";
|
|
19
|
-
exports(): {};
|
|
20
|
-
}
|
|
21
|
-
interface $$IsomorphicComponent {
|
|
22
|
-
new <T extends Record<string, unknown>>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
|
|
23
|
-
$$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
|
|
24
|
-
} & ReturnType<__sveltets_Render<T>['exports']>;
|
|
25
|
-
<T extends Record<string, unknown>>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
|
|
26
|
-
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
27
|
-
}
|
|
28
|
-
declare const TextField: $$IsomorphicComponent;
|
|
29
|
-
type TextField<T extends Record<string, unknown>> = InstanceType<typeof TextField<T>>;
|
|
6
|
+
declare const TextField: import("svelte").Component<Props, {}, "value">;
|
|
7
|
+
type TextField = ReturnType<typeof TextField>;
|
|
30
8
|
export default TextField;
|
|
@@ -47,12 +47,17 @@
|
|
|
47
47
|
$value = { ...$value, newTab: false };
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
if (field.rel && $value.rel === undefined) {
|
|
51
|
+
$value = { ...$value, rel: '' };
|
|
52
|
+
}
|
|
53
|
+
|
|
50
54
|
if (!urlFieldDataSchema.safeParse($value).success) {
|
|
51
55
|
$value = {
|
|
52
56
|
id: '',
|
|
53
57
|
url: {},
|
|
54
58
|
...(field.text ? { text: {} } : {}),
|
|
55
|
-
...(field.newTab ? { newTab: false } : {})
|
|
59
|
+
...(field.newTab ? { newTab: false } : {}),
|
|
60
|
+
...(field.rel ? { rel: '' } : {})
|
|
56
61
|
};
|
|
57
62
|
}
|
|
58
63
|
|
|
@@ -62,6 +67,6 @@
|
|
|
62
67
|
let fieldValid = $state(false);
|
|
63
68
|
</script>
|
|
64
69
|
|
|
65
|
-
{#if fieldValid}
|
|
66
|
-
<UrlFieldComponent {
|
|
70
|
+
{#if fieldValid && $value}
|
|
71
|
+
<UrlFieldComponent {field} bind:value={$value} {...props} />
|
|
67
72
|
{/if}
|