includio-cms 0.0.31 → 0.0.32

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.
@@ -14,13 +14,14 @@
14
14
  import Button, { buttonVariants } from '../../../components/ui/button/button.svelte';
15
15
  import { getCollectionEntryLabel } from '../../utils/entryLabel.js';
16
16
  import { getContentLanguage } from '../../state/content-language.svelte.js';
17
- import { tick } from 'svelte';
17
+ import { onMount, tick } from 'svelte';
18
18
  import { useId } from 'bits-ui';
19
19
  import * as Popover from '../../../components/ui/popover/index.js';
20
20
  import * as Command from '../../../components/ui/command/index.js';
21
21
  import { cn } from '../../../utils.js';
22
22
  import Selector from '@tabler/icons-svelte/icons/selector';
23
23
  import Check from '@tabler/icons-svelte/icons/check';
24
+ import type { CollectionConfigWithType } from '../../../types/collections.js';
24
25
 
25
26
  const remotes = getRemotes();
26
27
 
@@ -32,19 +33,32 @@
32
33
 
33
34
  let { field, form, path, ...props }: Props = $props();
34
35
 
35
- let collectionConfig = await remotes.getCollection(field.collection);
36
-
37
36
  const { value } = formFieldProxy(form, path) satisfies FormFieldProxy<RelationFieldData>;
38
37
 
39
- async function getOptionsQuery(): Promise<{ label: string; value: string }[]> {
38
+ let options = $state<{ label: string; value: string }[]>([]);
39
+ let collectionConfig = $state<CollectionConfigWithType | null>(null);
40
+
41
+ async function getCollectionConfig() {
42
+ collectionConfig = await remotes.getCollection(field.collection);
43
+
44
+ return collectionConfig;
45
+ }
46
+
47
+ async function getOptionsQuery(config: CollectionConfigWithType) {
40
48
  const entries = await remotes.getRawCollectionEntries(field.collection);
41
49
 
42
- return entries.map((entry) => ({
43
- label: getCollectionEntryLabel(entry, collectionConfig, getContentLanguage()),
50
+ options = entries.map((entry) => ({
51
+ label: getCollectionEntryLabel(entry, config, getContentLanguage()),
44
52
  value: entry.id
45
53
  }));
46
54
  }
47
55
 
56
+ onMount(() => {
57
+ getCollectionConfig().then((config) => {
58
+ getOptionsQuery(config);
59
+ });
60
+ });
61
+
48
62
  let open = $state(false);
49
63
 
50
64
  // We want to refocus the trigger button when the user selects
@@ -59,7 +73,7 @@
59
73
  const triggerId = useId();
60
74
  </script>
61
75
 
62
- {#await getOptionsQuery() then options}
76
+ {#if options.length > 0 && collectionConfig}
63
77
  <Popover.Root bind:open>
64
78
  <Popover.Trigger
65
79
  id={triggerId}
@@ -102,4 +116,4 @@
102
116
  </Command.Root>
103
117
  </Popover.Content>
104
118
  </Popover.Root>
105
- {/await}
119
+ {/if}
@@ -1,6 +1,6 @@
1
1
  import type { RelationFieldData, RelationField } from '../../../types/fields.js';
2
2
  import { type FormPathLeaves, type SuperForm } from 'sveltekit-superforms';
3
- declare function $$render<T extends Record<string, unknown>>(): Promise<{
3
+ declare function $$render<T extends Record<string, unknown>>(): {
4
4
  props: {
5
5
  field: RelationField;
6
6
  form: SuperForm<T>;
@@ -10,13 +10,13 @@ declare function $$render<T extends Record<string, unknown>>(): Promise<{
10
10
  bindings: "";
11
11
  slots: {};
12
12
  events: {};
13
- }>;
13
+ };
14
14
  declare class __sveltets_Render<T extends Record<string, unknown>> {
15
- props(): Awaited<ReturnType<typeof $$render<T>>>['props'];
16
- events(): Awaited<ReturnType<typeof $$render<T>>>['events'];
17
- slots(): Awaited<ReturnType<typeof $$render<T>>>['slots'];
15
+ props(): ReturnType<typeof $$render<T>>['props'];
16
+ events(): ReturnType<typeof $$render<T>>['events'];
17
+ slots(): ReturnType<typeof $$render<T>>['slots'];
18
18
  bindings(): "";
19
- exports(): Promise<{}>;
19
+ exports(): {};
20
20
  }
21
21
  interface $$IsomorphicComponent {
22
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']>> & {
@@ -13,6 +13,7 @@
13
13
  import { joinPath } from '../../utils/objectPath.js';
14
14
  import type {
15
15
  Field,
16
+ ImageField,
16
17
  ObjectFieldData,
17
18
  SeoField,
18
19
  SeoFieldData,
@@ -29,8 +30,6 @@
29
30
 
30
31
  let { field, form, path, ...props }: Props = $props();
31
32
 
32
- // const { value } = formFieldProxy(form, path) satisfies FormFieldProxy<SeoFieldData | undefined>;
33
-
34
33
  const slugField: TextField = {
35
34
  type: 'text',
36
35
  slug: 'slug',
@@ -38,6 +37,13 @@
38
37
  required: true
39
38
  };
40
39
 
40
+ const canonicalUrlField: TextField = {
41
+ type: 'text',
42
+ slug: 'canonicalUrl',
43
+ label: 'Canonical Url',
44
+ required: false
45
+ };
46
+
41
47
  const titleField: TextField = {
42
48
  type: 'text',
43
49
  slug: 'title',
@@ -53,7 +59,38 @@
53
59
  multiline: true
54
60
  };
55
61
 
56
- const fields: Field[] = [slugField, titleField, descriptionField];
62
+ const keyWordsField: TextField = {
63
+ type: 'text',
64
+ slug: 'keywords',
65
+ label: 'Keywords',
66
+ required: false,
67
+ multiline: true
68
+ };
69
+
70
+ const ogImageField: ImageField = {
71
+ type: 'image',
72
+ slug: 'ogImage',
73
+ label: 'Open Graph Image',
74
+ required: false
75
+ };
76
+
77
+ const customCodeField: TextField = {
78
+ type: 'text',
79
+ slug: 'customCode',
80
+ label: 'Custom Code',
81
+ required: false,
82
+ multiline: true
83
+ };
84
+
85
+ const fields: Field[] = [
86
+ slugField,
87
+ canonicalUrlField,
88
+ titleField,
89
+ descriptionField,
90
+ keyWordsField,
91
+ ogImageField,
92
+ customCodeField
93
+ ];
57
94
  </script>
58
95
 
59
96
  <Item.Root variant="outline">
@@ -87,8 +87,12 @@ export function generateZodSchemaFromField(field, languages, options = {
87
87
  case 'seo': {
88
88
  return z.object({
89
89
  slug: z.object(Object.fromEntries(languages.map((lang) => [lang, z.string()]))),
90
+ canonicalUrl: z.object(Object.fromEntries(languages.map((lang) => [lang, z.string().optional()]))),
90
91
  title: z.object(Object.fromEntries(languages.map((lang) => [lang, z.string()]))),
91
- description: z.object(Object.fromEntries(languages.map((lang) => [lang, z.string()])))
92
+ description: z.object(Object.fromEntries(languages.map((lang) => [lang, z.string()]))),
93
+ keywords: z.object(Object.fromEntries(languages.map((lang) => [lang, z.string().optional()]))),
94
+ ogImage: z.string(),
95
+ customCode: z.object(Object.fromEntries(languages.map((lang) => [lang, z.string().optional()])))
92
96
  });
93
97
  }
94
98
  case 'url': {
@@ -47,8 +47,12 @@ function getFieldTypeAsString(field) {
47
47
  case 'seo':
48
48
  return `{
49
49
  slug?: string;
50
+ canonicalUrl?: string;
50
51
  title?: string;
51
52
  description?: string;
53
+ ogImage?: string;
54
+ keywords?: string;
55
+ customCode?: string;
52
56
  }`;
53
57
  case 'url':
54
58
  return 'string';
@@ -58,6 +62,6 @@ function getFieldTypeAsString(field) {
58
62
  }
59
63
  export function generateTsTypeFromFields(fields) {
60
64
  return `{
61
- ${fields.map((f) => ` ${f.slug}${f.required ? '' : '?'}: ${getFieldTypeAsString(f)}`).join(';\n')};
65
+ ${fields.map((f) => ` ${f.slug}${f.required || f.type === 'seo' ? '' : '?'}: ${getFieldTypeAsString(f)}`).join(';\n')};
62
66
  }`;
63
67
  }
@@ -1,12 +1,12 @@
1
1
  <script lang="ts">
2
2
  import type { MediaFile } from '../../types/media.js';
3
+ import type { HTMLImgAttributes } from 'svelte/elements';
3
4
 
4
- type Props = {
5
- class?: string;
5
+ type Props = HTMLImgAttributes & {
6
6
  data: MediaFile;
7
7
  };
8
8
 
9
- let { class: className = undefined, data }: Props = $props();
9
+ let { class: className = undefined, data, ...restProps }: Props = $props();
10
10
  </script>
11
11
 
12
12
  <img
@@ -16,4 +16,5 @@
16
16
  width={data.width}
17
17
  height={data.height}
18
18
  loading="lazy"
19
+ {...restProps}
19
20
  />
@@ -1,6 +1,6 @@
1
1
  import type { MediaFile } from '../../types/media.js';
2
- type Props = {
3
- class?: string;
2
+ import type { HTMLImgAttributes } from 'svelte/elements';
3
+ type Props = HTMLImgAttributes & {
4
4
  data: MediaFile;
5
5
  };
6
6
  declare const Image: import("svelte").Component<Props, {}, "">;
@@ -1,10 +1,7 @@
1
1
  <script lang="ts">
2
- type Props = {
3
- title?: string;
4
- description?: string;
5
- };
2
+ import type { SeoFieldData } from '../../types/fields.js';
6
3
 
7
- let { title, description }: Props = $props();
4
+ let { title, description, keywords, ogImage, customCode, canonicalUrl }: SeoFieldData = $props();
8
5
  </script>
9
6
 
10
7
  <svelte:head>
@@ -15,4 +12,23 @@
15
12
  {#if description}
16
13
  <meta name="description" content={description} />
17
14
  {/if}
15
+ {#if keywords}
16
+ <meta name="keywords" content={keywords} />
17
+ {/if}
18
+ {#if canonicalUrl}
19
+ <link rel="canonical" href={canonicalUrl} />
20
+ {/if}
21
+ {#if title}
22
+ <meta property="og:title" content={title} />
23
+ {/if}
24
+ {#if description}
25
+ <meta property="og:description" content={description} />
26
+ {/if}
27
+ {#if ogImage}
28
+ <meta property="og:image" content={ogImage} />
29
+ <meta name="twitter:card" content="summary_large_image" />
30
+ {/if}
31
+ {#if customCode}
32
+ {@html customCode}
33
+ {/if}
18
34
  </svelte:head>
@@ -1,7 +1,4 @@
1
- type Props = {
2
- title?: string;
3
- description?: string;
4
- };
5
- declare const Seo: import("svelte").Component<Props, {}, "">;
1
+ import type { SeoFieldData } from '../../types/fields.js';
2
+ declare const Seo: import("svelte").Component<SeoFieldData, {}, "">;
6
3
  type Seo = ReturnType<typeof Seo>;
7
4
  export default Seo;
@@ -122,9 +122,13 @@ export interface SeoField extends BaseField {
122
122
  type: 'seo';
123
123
  }
124
124
  export interface SeoFieldData {
125
- slug: Record<string, string>;
126
- title: Record<string, string>;
127
- description: Record<string, string>;
125
+ slug: string;
126
+ canonicalUrl?: string;
127
+ title: string;
128
+ description?: string;
129
+ ogImage?: string;
130
+ keywords?: string;
131
+ customCode?: string;
128
132
  }
129
133
  export interface UrlField extends BaseField {
130
134
  type: 'url';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "includio-cms",
3
- "version": "0.0.31",
3
+ "version": "0.0.32",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build && npm run prepack",