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.
Files changed (93) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/ROADMAP.md +13 -0
  3. package/dist/admin/client/entry/entry-form.svelte +1 -0
  4. package/dist/admin/client/entry/entry.svelte +130 -123
  5. package/dist/admin/client/entry/hybrid/hybrid-preview.svelte +92 -9
  6. package/dist/admin/components/fields/blocks-field.svelte +142 -112
  7. package/dist/admin/components/fields/blocks-field.svelte.d.ts +10 -30
  8. package/dist/admin/components/fields/boolean-field.svelte +28 -38
  9. package/dist/admin/components/fields/boolean-field.svelte.d.ts +5 -27
  10. package/dist/admin/components/fields/checkboxes-field.svelte +12 -24
  11. package/dist/admin/components/fields/checkboxes-field.svelte.d.ts +5 -27
  12. package/dist/admin/components/fields/content-field.svelte +4 -17
  13. package/dist/admin/components/fields/content-field.svelte.d.ts +5 -27
  14. package/dist/admin/components/fields/date-field.svelte +8 -21
  15. package/dist/admin/components/fields/date-field.svelte.d.ts +5 -27
  16. package/dist/admin/components/fields/datetime-field.svelte +8 -21
  17. package/dist/admin/components/fields/datetime-field.svelte.d.ts +5 -27
  18. package/dist/admin/components/fields/field-renderer.svelte +32 -19
  19. package/dist/admin/components/fields/field-renderer.svelte.d.ts +1 -1
  20. package/dist/admin/components/fields/field-value-bridge.svelte +21 -0
  21. package/dist/admin/components/fields/field-value-bridge.svelte.d.ts +31 -0
  22. package/dist/admin/components/fields/fields-form.svelte +13 -10
  23. package/dist/admin/components/fields/file-field.svelte +12 -27
  24. package/dist/admin/components/fields/file-field.svelte.d.ts +5 -27
  25. package/dist/admin/components/fields/image-field.svelte +13 -28
  26. package/dist/admin/components/fields/image-field.svelte.d.ts +5 -27
  27. package/dist/admin/components/fields/media-field.svelte +15 -30
  28. package/dist/admin/components/fields/media-field.svelte.d.ts +5 -27
  29. package/dist/admin/components/fields/number-field.svelte +6 -20
  30. package/dist/admin/components/fields/number-field.svelte.d.ts +5 -27
  31. package/dist/admin/components/fields/object-field.svelte +26 -29
  32. package/dist/admin/components/fields/object-field.svelte.d.ts +11 -31
  33. package/dist/admin/components/fields/radio-field.svelte +8 -20
  34. package/dist/admin/components/fields/radio-field.svelte.d.ts +5 -27
  35. package/dist/admin/components/fields/relation-field.svelte +15 -30
  36. package/dist/admin/components/fields/relation-field.svelte.d.ts +5 -27
  37. package/dist/admin/components/fields/richtext-field.svelte +4 -17
  38. package/dist/admin/components/fields/richtext-field.svelte.d.ts +5 -27
  39. package/dist/admin/components/fields/select-field.svelte +14 -28
  40. package/dist/admin/components/fields/select-field.svelte.d.ts +5 -27
  41. package/dist/admin/components/fields/seo-field.svelte +5 -12
  42. package/dist/admin/components/fields/seo-field.svelte.d.ts +8 -28
  43. package/dist/admin/components/fields/simple-array-field.svelte +29 -42
  44. package/dist/admin/components/fields/simple-array-field.svelte.d.ts +5 -27
  45. package/dist/admin/components/fields/slug-field.svelte +6 -11
  46. package/dist/admin/components/fields/slug-field.svelte.d.ts +6 -26
  47. package/dist/admin/components/fields/text-field-wrapper.svelte +22 -40
  48. package/dist/admin/components/fields/text-field.svelte +7 -19
  49. package/dist/admin/components/fields/text-field.svelte.d.ts +5 -27
  50. package/dist/admin/components/fields/url-field-wrapper.svelte +8 -3
  51. package/dist/admin/components/fields/url-field.svelte +294 -128
  52. package/dist/admin/components/fields/url-field.svelte.d.ts +5 -27
  53. package/dist/admin/components/layout/layout-renderer.svelte +8 -6
  54. package/dist/admin/components/tiptap/InlineBlockNodeView.svelte +221 -31
  55. package/dist/admin/components/tiptap/content-editor.svelte +13 -2
  56. package/dist/admin/components/tiptap/inline-block-node.d.ts +1 -0
  57. package/dist/admin/components/tiptap/inline-block-node.js +18 -1
  58. package/dist/admin/components/tiptap/slash-command.js +2 -3
  59. package/dist/admin/components/tiptap/standalone-form.d.ts +7 -0
  60. package/dist/admin/components/tiptap/standalone-form.js +31 -0
  61. package/dist/admin/components/tiptap/tiptap-editor.svelte +7 -0
  62. package/dist/admin/remote/entry.remote.js +16 -0
  63. package/dist/admin/styles/admin.css +10 -0
  64. package/dist/admin/utils/fieldCondition.d.ts +6 -0
  65. package/dist/admin/utils/fieldCondition.js +20 -0
  66. package/dist/components/ui/switch/index.d.ts +2 -0
  67. package/dist/components/ui/switch/index.js +4 -0
  68. package/dist/components/ui/switch/switch.svelte +26 -0
  69. package/dist/components/ui/switch/switch.svelte.d.ts +4 -0
  70. package/dist/core/fields/fieldSchemaToTs.js +15 -3
  71. package/dist/core/fields/formFieldSchemaToTs.js +22 -6
  72. package/dist/core/fields/urlUtils.d.ts +14 -0
  73. package/dist/core/fields/urlUtils.js +21 -0
  74. package/dist/core/server/fields/populateEntry.js +43 -0
  75. package/dist/core/server/fields/resolveImageFields.js +33 -1
  76. package/dist/core/server/fields/resolveRelationFields.js +46 -0
  77. package/dist/core/server/fields/resolveRichtextLinks.js +15 -1
  78. package/dist/core/server/fields/resolveUrlFields.js +65 -0
  79. package/dist/core/server/generator/formFieldSchemaToString.js +40 -9
  80. package/dist/core/server/generator/formFields.js +2 -0
  81. package/dist/core/server/generator/generator.js +25 -1
  82. package/dist/schemas/field/url.d.ts +2 -0
  83. package/dist/schemas/field/url.js +4 -2
  84. package/dist/types/fields.d.ts +9 -0
  85. package/dist/types/formFields.d.ts +15 -2
  86. package/dist/types/index.d.ts +1 -0
  87. package/dist/types/index.js +1 -0
  88. package/dist/updates/0.5.3/index.d.ts +2 -0
  89. package/dist/updates/0.5.3/index.js +19 -0
  90. package/dist/updates/index.js +2 -1
  91. package/package.json +2 -1
  92. package/dist/admin/components/fields/standalone-field-renderer.svelte +0 -148
  93. 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; // trigger reactivity
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
- {...props}
191
- {field}
192
- {form}
193
- path={joinPath(path, lang) as FormPathLeaves<T, string | undefined>}
194
- />
195
- {:else if field.type === 'richtext'}
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" module>
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
- form: SuperForm<T>;
22
- path: FormPathLeaves<T, string | undefined>;
11
+ value: string | undefined;
23
12
  };
24
13
 
25
- let { field, form, path, ...props }: Props = $props();
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 ($value === undefined) {
32
- $value = '';
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={$value} placeholder={getLocalizedLabel(field.placeholder, interfaceLanguage.current)} minlength={field.minLength} maxlength={field.maxLength} />
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={$value} type="text" placeholder={getLocalizedLabel(field.placeholder, interfaceLanguage.current)} minlength={field.minLength} maxlength={field.maxLength} />
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
- import { type FormPathLeaves, type SuperForm } from 'sveltekit-superforms';
3
- declare function $$render<T extends Record<string, unknown>>(): {
4
- props: {
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 class __sveltets_Render<T extends Record<string, unknown>> {
15
- props(): ReturnType<typeof $$render<T>>['props'];
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 {form} {field} path={path as FormPathLeaves<T, UrlFieldData>} {...props} />
70
+ {#if fieldValid && $value}
71
+ <UrlFieldComponent {field} bind:value={$value} {...props} />
67
72
  {/if}