rimecms 0.27.0 → 0.27.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.
Files changed (50) hide show
  1. package/README.md +26 -24
  2. package/dist/core/collections/auth/fields.d.ts +40 -40
  3. package/dist/core/fields/builders/select.js +1 -0
  4. package/dist/core/i18n/en/fields.d.ts +1 -0
  5. package/dist/core/i18n/en/fields.js +2 -1
  6. package/dist/core/i18n/fr/fields.d.ts +1 -0
  7. package/dist/core/i18n/fr/fields.js +2 -1
  8. package/dist/core/operations/hooks/before-read/set-document-thumbnail.server.js +2 -2
  9. package/dist/core/operations/hooks/before-read/sort-document-props.server.js +3 -1
  10. package/dist/fields/relation/component/Relation.svelte +16 -9
  11. package/dist/fields/relation/component/Relation.svelte.d.ts +2 -1
  12. package/dist/fields/relation/index.d.ts +1 -1
  13. package/dist/fields/rich-text/client.d.ts +9 -16
  14. package/dist/fields/rich-text/client.js +1 -1
  15. package/dist/fields/rich-text/component/RichText.svelte +1 -1
  16. package/dist/fields/rich-text/core/{config-builders.js → build-editor-config.js} +4 -0
  17. package/dist/fields/rich-text/core/features/fields/extension.js +2 -2
  18. package/dist/fields/rich-text/core/features/fields/index.d.ts +1 -1
  19. package/dist/fields/rich-text/core/features/fields/index.js +4 -2
  20. package/dist/fields/rich-text/core/features/link/component/link-selector.svelte +7 -7
  21. package/dist/fields/rich-text/core/features/link/index.d.ts +1 -4
  22. package/dist/fields/rich-text/core/features/resource/index.js +17 -11
  23. package/dist/fields/rich-text/core/features/resource/resource-extension.d.ts +2 -2
  24. package/dist/fields/rich-text/core/features/resource/resource-extension.js +5 -3
  25. package/dist/fields/rich-text/core/features/resource/resource.svelte +17 -19
  26. package/dist/fields/rich-text/core/features/upload/index.d.ts +2 -5
  27. package/dist/fields/rich-text/core/features/upload/index.js +15 -11
  28. package/dist/fields/rich-text/core/features/upload/upload-extension.d.ts +1 -2
  29. package/dist/fields/rich-text/core/features/upload/upload-extension.js +4 -1
  30. package/dist/fields/rich-text/core/features/upload/upload.svelte +13 -8
  31. package/dist/fields/types.d.ts +3 -0
  32. package/dist/panel/components/Root.svelte +2 -2
  33. package/dist/panel/components/fields/FieldsPreviewTrigger.svelte +1 -1
  34. package/dist/panel/components/fields/index.d.ts +2 -2
  35. package/dist/panel/components/sections/collection/upload-thumb-cell/UploadThumbCell.svelte +3 -2
  36. package/dist/panel/components/sections/document/upload-header/UploadHeader.svelte +2 -7
  37. package/dist/panel/components/sections/live/SidePanel.svelte +2 -2
  38. package/dist/panel/components/ui/breadcrumb/BreadCrumb.svelte +12 -6
  39. package/dist/panel/components/ui/card-document/card-document.svelte +2 -2
  40. package/dist/panel/components/ui/command/command-dialog.svelte +3 -1
  41. package/dist/panel/components/ui/command/command-dialog.svelte.d.ts +1 -0
  42. package/dist/panel/context/api-proxy.svelte.d.ts +2 -0
  43. package/dist/panel/context/api-proxy.svelte.js +9 -1
  44. package/dist/panel/context/documentForm.svelte.js +5 -4
  45. package/dist/panel/context/title.d.ts +7 -0
  46. package/dist/panel/context/title.js +9 -0
  47. package/dist/panel/pages/collection/Collection.svelte +2 -2
  48. package/dist/types.d.ts +1 -1
  49. package/package.json +3 -3
  50. /package/dist/fields/rich-text/core/{config-builders.d.ts → build-editor-config.d.ts} +0 -0
package/README.md CHANGED
@@ -3,12 +3,13 @@
3
3
 
4
4
  Headless CMS powered by SvelteKit.
5
5
 
6
- > [!NOTE]
7
- > Not ready for production
6
+ ![NPM Version](https://img.shields.io/npm/v/rimecms)
7
+ ![NPM Downloads](https://img.shields.io/npm/dm/rimecms)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/bienbiendev/rime/blob/main/LICENSE)
8
9
 
9
10
  ![alt backend capture](https://github.com/bienbiendev/rime/blob/main/assets/preview.png?raw=true)
10
11
 
11
- [Documentation (in progress)](https://github.com/bienbiendev/rime-doc/tree/master/docs)
12
+ [Documentation](https://github.com/bienbiendev/rime-doc/tree/master/docs)
12
13
 
13
14
  ## Features
14
15
 
@@ -85,7 +86,7 @@ import { sveltekit } from '@sveltejs/kit/vite';
85
86
  import { rime } from 'rimecms/vite';
86
87
 
87
88
  export default defineConfig({
88
- plugins: [rime(), sveltekit()]
89
+ plugins: [rime(), sveltekit()]
89
90
  });
90
91
  ```
91
92
 
@@ -200,21 +201,21 @@ export default rime({
200
201
 
201
202
  ```ts
202
203
  export const load = async (event: LayoutServerLoadEvent) => {
203
- const { rime } = event.locals;
204
- // Get an Area document
205
- const menu = await rime.area('menu').find();
206
- // Get all pages documents
207
- const pages = await rime.collection('pages').findAll({ locale: 'en' });
208
- // Get a page byId
209
- const home = await rime.collection('pages').findById({ locale: 'en', id: 'some-id' });
210
- // Get a user with a query
211
- const [user] = await rime.collection('users').find({
212
- query: `where[email][equals]=some@email.com` // qs query or ParsedQsQuery
213
- });
214
- // Get some config values
215
- const languages = rime.config.getLocalesCodes();
216
- const collections = rime.config.collections;
217
- //...
204
+ const { rime } = event.locals;
205
+ // Get an Area document
206
+ const menu = await rime.area('menu').find();
207
+ // Get all pages documents
208
+ const pages = await rime.collection('pages').findAll({ locale: 'en' });
209
+ // Get a page byId
210
+ const home = await rime.collection('pages').findById({ locale: 'en', id: 'some-id' });
211
+ // Get a user with a query
212
+ const [user] = await rime.collection('users').find({
213
+ query: `where[email][equals]=some@email.com` // qs query or ParsedQsQuery
214
+ });
215
+ // Get some config values
216
+ const languages = rime.config.getLocalesCodes();
217
+ const collections = rime.config.collections;
218
+ //...
218
219
  };
219
220
  ```
220
221
 
@@ -223,13 +224,13 @@ export const load = async (event: LayoutServerLoadEvent) => {
223
224
  ```ts
224
225
  const { docs } = await fetch('http://localhost:5173/api/pages').then((r) => r.json());
225
226
  const { docs } = await fetch('http://localhost:5173/api/pages?sort=title&limit=1').then((r) =>
226
- r.json()
227
+ r.json()
227
228
  );
228
229
  const { docs } = await fetch(
229
- 'http://localhost:5173/api/pages?where[author][equals]=some-id&locale=en`;'
230
+ 'http://localhost:5173/api/pages?where[author][equals]=some-id&locale=en`;'
230
231
  ).then((r) => r.json());
231
232
  const { docs } = await fetch(
232
- 'http://localhost:5173/api/pages?where[author.email][equals]=some@email.com&locale=en`;'
233
+ 'http://localhost:5173/api/pages?where[author.email][equals]=some@email.com&locale=en`;'
233
234
  ).then((r) => r.json());
234
235
  ```
235
236
 
@@ -260,10 +261,11 @@ It's doing bascically `vite build` under the hood and create the polka server fi
260
261
  - [x] more better-auth integration
261
262
  - [x] Handle relation poperties in queries
262
263
  - [~] Documentation
263
- - [ ] Live Edit system in practice
264
+ - [ ] configurable files storage adapter (local, s3, etc)
265
+ - [ ] other storage adapter (postgress, turso, etc)
264
266
  - [ ] auto-saved draft
267
+ - [ ] Live Edit system in practice
265
268
  - [ ] Put bin commands in a separate package ex: @rime/kit
266
- - [ ] configurable medias/config path
267
269
 
268
270
  ## Acknowledgments
269
271
 
@@ -3,7 +3,7 @@ declare const emailField: {
3
3
  layout(layout: "compact" | "default"): /*elided*/ any;
4
4
  readonly component: import("svelte").Component<import("../../../fields/email/component/props").EmailFieldProps, {}, "">;
5
5
  unique(bool?: boolean): /*elided*/ any;
6
- defaultValue(value: string | import("../../../fields/types").DefaultValueFn<string>): /*elided*/ any;
6
+ defaultValue(value: string | import("../../../types").DefaultValueFn<string>): /*elided*/ any;
7
7
  isTitle(): /*elided*/ any;
8
8
  _generateSchema: null | ((args: {
9
9
  camel: string;
@@ -14,17 +14,17 @@ declare const emailField: {
14
14
  label(label: string): /*elided*/ any;
15
15
  hidden(): /*elided*/ any;
16
16
  localized(): /*elided*/ any;
17
- validate(validateFunction: import("../../../fields/types").FieldValidationFunc<import("../../../fields/email/index.js").EmailField>): /*elided*/ any;
17
+ validate(validateFunction: import("../../../types").FieldValidationFunc<import("../../../fields/email/index.js").EmailField>): /*elided*/ any;
18
18
  condition(conditionFunction: (doc: import("../../../util/types").Dic, siblings: import("../../../util/types").Dic) => boolean): /*elided*/ any;
19
19
  table(params?: import("../../../types").FieldPanelTableConfig | number): /*elided*/ any;
20
- width(value: import("../../../fields/types").FieldWidth): /*elided*/ any;
20
+ width(value: import("../../../types").FieldWidth): /*elided*/ any;
21
21
  required(bool?: boolean): /*elided*/ any;
22
22
  access(access: {
23
- create?: import("../../../fields/types").FieldAccess;
24
- read?: import("../../../fields/types").FieldAccess;
25
- update?: import("../../../fields/types").FieldAccess;
23
+ create?: import("../../../types").FieldAccess;
24
+ read?: import("../../../types").FieldAccess;
25
+ update?: import("../../../types").FieldAccess;
26
26
  }): /*elided*/ any;
27
- onChange(hook: import("../../../fields/types").FieldHookClient): /*elided*/ any;
27
+ onChange(hook: import("../../../types").FieldHookClient): /*elided*/ any;
28
28
  hint(hint: string): /*elided*/ any;
29
29
  clone(): /*elided*/ any;
30
30
  $generateSchema(fn: (args: {
@@ -32,27 +32,27 @@ declare const emailField: {
32
32
  snake: string;
33
33
  suffix: string;
34
34
  }) => string): /*elided*/ any;
35
- $beforeRead(hook: import("../../../fields/types").FieldHook<import("../../../fields/email/index.js").EmailField>): /*elided*/ any;
36
- $beforeSave(hook: import("../../../fields/types").FieldHook<import("../../../fields/email/index.js").EmailField>): /*elided*/ any;
37
- beforeValidate(hook: import("../../../fields/types").FieldHookShared): /*elided*/ any;
35
+ $beforeRead(hook: import("../../../types").FieldHook<import("../../../fields/email/index.js").EmailField>): /*elided*/ any;
36
+ $beforeSave(hook: import("../../../types").FieldHook<import("../../../fields/email/index.js").EmailField>): /*elided*/ any;
37
+ beforeValidate(hook: import("../../../types").FieldHookShared): /*elided*/ any;
38
38
  field: import("../../../fields/email/index.js").EmailField;
39
39
  className(str: string): /*elided*/ any;
40
40
  compile(): {
41
41
  type: "email";
42
42
  live?: boolean | undefined;
43
43
  condition?: ((doc: any, siblings: any) => boolean) | undefined;
44
- width?: import("../../../fields/types").FieldWidth | undefined;
44
+ width?: import("../../../types").FieldWidth | undefined;
45
45
  className?: string | undefined;
46
46
  component: import("svelte").Component<any>;
47
47
  cell: import("svelte").Component<any> | undefined;
48
48
  access: {
49
- create: import("../../../fields/types").FieldAccess;
50
- read: import("../../../fields/types").FieldAccess;
51
- update: import("../../../fields/types").FieldAccess;
49
+ create: import("../../../types").FieldAccess;
50
+ read: import("../../../types").FieldAccess;
51
+ update: import("../../../types").FieldAccess;
52
52
  };
53
53
  name: string;
54
54
  hidden?: boolean | undefined;
55
- validate?: import("../../../fields/types").FieldValidationFunc<any> | undefined;
55
+ validate?: import("../../../types").FieldValidationFunc<any> | undefined;
56
56
  required?: boolean | undefined;
57
57
  localized?: boolean | undefined;
58
58
  label?: string | undefined;
@@ -65,12 +65,12 @@ declare const emailField: {
65
65
  position: number;
66
66
  } | undefined;
67
67
  hooks?: {
68
- beforeRead?: import("../../../fields/types").FieldHook<any>[] | undefined;
69
- beforeSave?: import("../../../fields/types").FieldHook<any>[] | undefined;
70
- beforeValidate?: import("../../../fields/types").FieldHookShared<any>[] | undefined;
71
- onChange?: import("../../../fields/types").FieldHookClient[] | undefined;
68
+ beforeRead?: import("../../../types").FieldHook<any>[] | undefined;
69
+ beforeSave?: import("../../../types").FieldHook<any>[] | undefined;
70
+ beforeValidate?: import("../../../types").FieldHookShared<any>[] | undefined;
71
+ onChange?: import("../../../types").FieldHookClient[] | undefined;
72
72
  } | undefined;
73
- defaultValue?: string | import("../../../fields/types").DefaultValueFn<string> | undefined;
73
+ defaultValue?: string | import("../../../types").DefaultValueFn<string> | undefined;
74
74
  isEmpty: (value: unknown) => boolean;
75
75
  placeholder?: string | undefined;
76
76
  layout?: "compact" | "default" | undefined;
@@ -99,7 +99,7 @@ export declare const usersFields: {
99
99
  layout(layout: "compact" | "default"): /*elided*/ any;
100
100
  readonly component: import("svelte").Component<import("../../../fields/email/component/props").EmailFieldProps, {}, "">;
101
101
  unique(bool?: boolean): /*elided*/ any;
102
- defaultValue(value: string | import("../../../fields/types").DefaultValueFn<string>): /*elided*/ any;
102
+ defaultValue(value: string | import("../../../types").DefaultValueFn<string>): /*elided*/ any;
103
103
  isTitle(): /*elided*/ any;
104
104
  _generateSchema: null | ((args: {
105
105
  camel: string;
@@ -110,17 +110,17 @@ export declare const usersFields: {
110
110
  label(label: string): /*elided*/ any;
111
111
  hidden(): /*elided*/ any;
112
112
  localized(): /*elided*/ any;
113
- validate(validateFunction: import("../../../fields/types").FieldValidationFunc<import("../../../fields/email/index.js").EmailField>): /*elided*/ any;
113
+ validate(validateFunction: import("../../../types").FieldValidationFunc<import("../../../fields/email/index.js").EmailField>): /*elided*/ any;
114
114
  condition(conditionFunction: (doc: import("../../../util/types").Dic, siblings: import("../../../util/types").Dic) => boolean): /*elided*/ any;
115
115
  table(params?: import("../../../types").FieldPanelTableConfig | number): /*elided*/ any;
116
- width(value: import("../../../fields/types").FieldWidth): /*elided*/ any;
116
+ width(value: import("../../../types").FieldWidth): /*elided*/ any;
117
117
  required(bool?: boolean): /*elided*/ any;
118
118
  access(access: {
119
- create?: import("../../../fields/types").FieldAccess;
120
- read?: import("../../../fields/types").FieldAccess;
121
- update?: import("../../../fields/types").FieldAccess;
119
+ create?: import("../../../types").FieldAccess;
120
+ read?: import("../../../types").FieldAccess;
121
+ update?: import("../../../types").FieldAccess;
122
122
  }): /*elided*/ any;
123
- onChange(hook: import("../../../fields/types").FieldHookClient): /*elided*/ any;
123
+ onChange(hook: import("../../../types").FieldHookClient): /*elided*/ any;
124
124
  hint(hint: string): /*elided*/ any;
125
125
  clone(): /*elided*/ any;
126
126
  $generateSchema(fn: (args: {
@@ -128,27 +128,27 @@ export declare const usersFields: {
128
128
  snake: string;
129
129
  suffix: string;
130
130
  }) => string): /*elided*/ any;
131
- $beforeRead(hook: import("../../../fields/types").FieldHook<import("../../../fields/email/index.js").EmailField>): /*elided*/ any;
132
- $beforeSave(hook: import("../../../fields/types").FieldHook<import("../../../fields/email/index.js").EmailField>): /*elided*/ any;
133
- beforeValidate(hook: import("../../../fields/types").FieldHookShared): /*elided*/ any;
131
+ $beforeRead(hook: import("../../../types").FieldHook<import("../../../fields/email/index.js").EmailField>): /*elided*/ any;
132
+ $beforeSave(hook: import("../../../types").FieldHook<import("../../../fields/email/index.js").EmailField>): /*elided*/ any;
133
+ beforeValidate(hook: import("../../../types").FieldHookShared): /*elided*/ any;
134
134
  field: import("../../../fields/email/index.js").EmailField;
135
135
  className(str: string): /*elided*/ any;
136
136
  compile(): {
137
137
  type: "email";
138
138
  live?: boolean | undefined;
139
139
  condition?: ((doc: any, siblings: any) => boolean) | undefined;
140
- width?: import("../../../fields/types").FieldWidth | undefined;
140
+ width?: import("../../../types").FieldWidth | undefined;
141
141
  className?: string | undefined;
142
142
  component: import("svelte").Component<any>;
143
143
  cell: import("svelte").Component<any> | undefined;
144
144
  access: {
145
- create: import("../../../fields/types").FieldAccess;
146
- read: import("../../../fields/types").FieldAccess;
147
- update: import("../../../fields/types").FieldAccess;
145
+ create: import("../../../types").FieldAccess;
146
+ read: import("../../../types").FieldAccess;
147
+ update: import("../../../types").FieldAccess;
148
148
  };
149
149
  name: string;
150
150
  hidden?: boolean | undefined;
151
- validate?: import("../../../fields/types").FieldValidationFunc<any> | undefined;
151
+ validate?: import("../../../types").FieldValidationFunc<any> | undefined;
152
152
  required?: boolean | undefined;
153
153
  localized?: boolean | undefined;
154
154
  label?: string | undefined;
@@ -161,12 +161,12 @@ export declare const usersFields: {
161
161
  position: number;
162
162
  } | undefined;
163
163
  hooks?: {
164
- beforeRead?: import("../../../fields/types").FieldHook<any>[] | undefined;
165
- beforeSave?: import("../../../fields/types").FieldHook<any>[] | undefined;
166
- beforeValidate?: import("../../../fields/types").FieldHookShared<any>[] | undefined;
167
- onChange?: import("../../../fields/types").FieldHookClient[] | undefined;
164
+ beforeRead?: import("../../../types").FieldHook<any>[] | undefined;
165
+ beforeSave?: import("../../../types").FieldHook<any>[] | undefined;
166
+ beforeValidate?: import("../../../types").FieldHookShared<any>[] | undefined;
167
+ onChange?: import("../../../types").FieldHookClient[] | undefined;
168
168
  } | undefined;
169
- defaultValue?: string | import("../../../fields/types").DefaultValueFn<string> | undefined;
169
+ defaultValue?: string | import("../../../types").DefaultValueFn<string> | undefined;
170
170
  isEmpty: (value: unknown) => boolean;
171
171
  placeholder?: string | undefined;
172
172
  layout?: "compact" | "default" | undefined;
@@ -31,6 +31,7 @@ class PickFieldBuilder extends FormFieldBuilder {
31
31
  const hasNoLabel = !('label' in option);
32
32
  if (hasNoLabel) {
33
33
  return {
34
+ ...option,
34
35
  value: option.value,
35
36
  label: capitalize(option.value)
36
37
  };
@@ -10,5 +10,6 @@ declare namespace _default {
10
10
  let get_data_from: string;
11
11
  let filter_by_type: string;
12
12
  let all_types: string;
13
+ let select: string;
13
14
  }
14
15
  export default _default;
@@ -9,5 +9,6 @@ export default {
9
9
  generate_from: 'Generate from $1',
10
10
  get_data_from: 'Get data from',
11
11
  filter_by_type: 'Filter by type',
12
- all_types: 'All types'
12
+ all_types: 'All types',
13
+ select: 'Select'
13
14
  };
@@ -10,5 +10,6 @@ declare namespace _default {
10
10
  let get_data_from: string;
11
11
  let filter_by_type: string;
12
12
  let all_types: string;
13
+ let select: string;
13
14
  }
14
15
  export default _default;
@@ -9,5 +9,6 @@ export default {
9
9
  generate_from: 'Générer à partir du champs $1',
10
10
  get_data_from: 'Importer les données',
11
11
  filter_by_type: 'Filtrer par type',
12
- all_types: 'Tous les types'
12
+ all_types: 'Tous les types',
13
+ select: 'Sélectionner'
13
14
  };
@@ -6,7 +6,7 @@ export const setDocumentThumbnail = Hooks.beforeRead(async (args) => {
6
6
  const config = args.config;
7
7
  let doc = args.doc;
8
8
  const hasThumbnail = (c) => {
9
- return config.type === 'collection' && !!config.asThumbnail;
9
+ return c.type === 'collection' && !!c.asThumbnail;
10
10
  };
11
11
  const paramSelect = args.context.params.select;
12
12
  const hasSelect = Array.isArray(paramSelect) && paramSelect.length;
@@ -15,7 +15,7 @@ export const setDocumentThumbnail = Hooks.beforeRead(async (args) => {
15
15
  (!hasSelect || (hasSelect && paramSelect.includes('_thumbnail')));
16
16
  if (shouldSetThumbnail) {
17
17
  const relationValue = getValueAtPath(config.asThumbnail, doc);
18
- if (!relationValue)
18
+ if (!relationValue || (Array.isArray(relationValue) && relationValue.length === 0))
19
19
  return args;
20
20
  const unwraped = Array.isArray(relationValue) ? relationValue[0] : relationValue;
21
21
  if (typeof unwraped === 'string')
@@ -16,8 +16,10 @@ function sortDocumentKeys(obj) {
16
16
  '_prototype',
17
17
  '_live',
18
18
  '_children',
19
+ '_path',
19
20
  '_parent',
20
- '_position'
21
+ '_position',
22
+ '_thumbnail'
21
23
  ];
22
24
  function sortObjectKeys(obj) {
23
25
  // If not an object or is null, return the value as-is
@@ -7,6 +7,7 @@
7
7
  import { getCollectionContext } from '../../../panel/context/collection.svelte.js';
8
8
  import { getConfigContext } from '../../../panel/context/config.svelte.js';
9
9
  import { type DocumentFormContext } from '../../../panel/context/documentForm.svelte.js';
10
+ import type { FormContext } from '../../../panel/context/form.svelte.js';
10
11
  import { getLocaleContext } from '../../../panel/context/locale.svelte';
11
12
  import { panelUrl } from '../../../panel/util/url.js';
12
13
  import { moveItem } from '../../../util/array.js';
@@ -18,7 +19,7 @@
18
19
  import Upload from './upload/Upload.svelte';
19
20
 
20
21
  // Props
21
- type Props = { path: string; config: RelationField; form: DocumentFormContext };
22
+ type Props = { path: string; config: RelationField; form: DocumentFormContext | FormContext };
22
23
  const { path, config, form }: Props = $props();
23
24
 
24
25
  // Context
@@ -77,7 +78,7 @@
77
78
  item.url = doc._thumbnail;
78
79
  }
79
80
  }
80
- if (form.isLive) {
81
+ if ('isLive' in form && form.isLive) {
81
82
  item.livePreview = doc;
82
83
  }
83
84
  return item;
@@ -88,7 +89,7 @@
88
89
  const url = new URL(apiUrl(relationConfig.kebab));
89
90
 
90
91
  // Add depth parameter if in live context
91
- if (form.isLive) {
92
+ if ('isLive' in form && form.isLive) {
92
93
  url.searchParams.append('depth', '1');
93
94
  }
94
95
 
@@ -109,7 +110,7 @@
109
110
  });
110
111
  }
111
112
  }
112
- return url.href + url.search;
113
+ return url.href;
113
114
  }
114
115
 
115
116
  const ressourceURL = makeRessourceURL();
@@ -166,7 +167,7 @@
166
167
  if (config.localized) {
167
168
  relation.locale = locale.code;
168
169
  }
169
- if (form.isLive) {
170
+ if ('isLive' in form && form.isLive) {
170
171
  if (item && item.livePreview) {
171
172
  relation.livePreview = snapshot(item.livePreview);
172
173
  }
@@ -181,17 +182,23 @@
181
182
  // So when user save the nested doc
182
183
  // it doesn't save this one
183
184
  const onRelationCreation = () => {
184
- form.isDisabled = true;
185
+ if ('isDisabled' in form) {
186
+ form.isDisabled = true;
187
+ }
185
188
  };
186
189
 
187
190
  // Enable the form on cancel
188
191
  const onRelationCreationCanceled = () => {
189
- form.isDisabled = false;
192
+ if ('isDisabled' in form) {
193
+ form.isDisabled = false;
194
+ }
190
195
  };
191
196
 
192
197
  const onRelationCreated = async (doc: GenericDoc) => {
193
198
  // Enabled the form
194
- form.isDisabled = false;
199
+ if ('isDisabled' in form) {
200
+ form.isDisabled = false;
201
+ }
195
202
  // update resssource
196
203
  ressource.data?.docs.push(doc);
197
204
  // update collection if present
@@ -237,7 +244,7 @@
237
244
  {path}
238
245
  many={!!config.many}
239
246
  hasError={!!field.error}
240
- formNestedLevel={form.nestedLevel}
247
+ formNestedLevel={'nestedLevel' in form ? form.nestedLevel : 0}
241
248
  readOnly={form.readOnly}
242
249
  {nothingToSelect}
243
250
  {onRelationCreated}
@@ -1,9 +1,10 @@
1
1
  import { type DocumentFormContext } from '../../../panel/context/documentForm.svelte.js';
2
+ import type { FormContext } from '../../../panel/context/form.svelte.js';
2
3
  import type { Relation, RelationField } from '../index.js';
3
4
  type Props = {
4
5
  path: string;
5
6
  config: RelationField;
6
- form: DocumentFormContext;
7
+ form: DocumentFormContext | FormContext;
7
8
  };
8
9
  declare const Relation: import("svelte").Component<Props, {}, "">;
9
10
  type Relation = ReturnType<typeof Relation>;
@@ -10,7 +10,7 @@ export declare class RelationFieldBuilder<Doc extends GenericDoc> extends FormFi
10
10
  get component(): import("svelte").Component<{
11
11
  path: string;
12
12
  config: RelationField;
13
- form: import("../../panel").DocumentFormContext;
13
+ form: import("../../panel").DocumentFormContext | import("../../panel/context/form.svelte").FormContext;
14
14
  }, {}, "">;
15
15
  get cell(): import("svelte").Component<{
16
16
  value: {
@@ -1,32 +1,25 @@
1
- import type { FieldBuilder } from '../../core/fields/builders/index.js';
2
1
  import type { Level } from '@tiptap/extension-heading';
3
- import type { Component } from 'svelte';
4
- import type { FieldsPreviewProps } from '../types.js';
5
- import { LinkFeature } from './core/features/link/index.js';
6
- import { ResourceFeature } from './core/features/resource/index.js';
2
+ import { type FieldsFeatureOptions } from './core/features/fields/index.js';
3
+ import { type LinkFeatureOptions } from './core/features/link/index.js';
4
+ import type { ResourceFeatureExtensionOptions } from './core/features/resource/resource-extension.js';
7
5
  import type { RichTextResource } from './core/features/resource/types.js';
8
- import { UploadFeature } from './core/features/upload/index.js';
6
+ import type { UploadFeatureExtensionOptions } from './core/features/upload/upload-extension.js';
9
7
  import RenderRichText from './core/render-rich-text.svelte';
10
8
  import SvelteNodeViewRenderer from './core/svelte/node-view-renderer.svelte';
11
9
  import NodeViewWrapper from './core/svelte/node-view-wrapper.svelte';
12
10
  import type { RichTextNodeRenderer, RichTextNodeRendererProps } from './core/types.js';
13
11
  import { richTextJSONToText } from './index.js';
14
- export declare const fields: (args: {
15
- name: string;
16
- label: string;
17
- fields: FieldBuilder[];
18
- preview: Component<FieldsPreviewProps>;
19
- }) => import("./core/types.js").RichTextFeature;
12
+ export declare const fields: (args: FieldsFeatureOptions) => import("./core/types.js").RichTextFeature;
20
13
  export declare const bold: () => import("./core/types.js").RichTextFeature;
21
14
  export declare const bulletList: () => import("./core/types.js").RichTextFeature;
22
15
  export declare const heading: (...levels: Level[]) => import("./core/types.js").RichTextFeature;
23
16
  export declare const hr: () => import("./core/types.js").RichTextFeature;
24
- export declare const link: (options?: Parameters<typeof LinkFeature>[0]) => import("./core/types.js").RichTextFeature;
17
+ export declare const link: (options?: Partial<LinkFeatureOptions>) => import("./core/types.js").RichTextFeature;
25
18
  export declare const paragraph: () => import("./core/types.js").RichTextFeature;
26
- export declare const orederedList: () => import("./core/types.js").RichTextFeature;
19
+ export declare const orderedList: () => import("./core/types.js").RichTextFeature;
27
20
  export declare const blockquote: () => import("./core/types.js").RichTextFeature;
28
21
  export declare const italic: () => import("./core/types.js").RichTextFeature;
29
- export declare const upload: (args: Parameters<typeof UploadFeature>[0]) => import("./core/types.js").RichTextFeature;
30
- export declare const resource: (args: Parameters<typeof ResourceFeature>[0]) => import("./core/types.js").RichTextFeature;
22
+ export declare const upload: (args: UploadFeatureExtensionOptions) => import("./core/types.js").RichTextFeature;
23
+ export declare const resource: (args: ResourceFeatureExtensionOptions) => import("./core/types.js").RichTextFeature;
31
24
  export { NodeViewWrapper, RenderRichText, richTextJSONToText, SvelteNodeViewRenderer };
32
25
  export type { RichTextNodeRenderer, RichTextNodeRendererProps, RichTextResource };
@@ -21,7 +21,7 @@ export const heading = (...levels) => HeadingFeature(...levels);
21
21
  export const hr = () => HorizontalRuleFeature;
22
22
  export const link = (options) => LinkFeature(options);
23
23
  export const paragraph = () => ParagraphFeature;
24
- export const orederedList = () => OrderedListFeature;
24
+ export const orderedList = () => OrderedListFeature;
25
25
  export const blockquote = () => BlockquoteFeature;
26
26
  export const italic = () => ItalicFeature;
27
27
  export const upload = (args) => UploadFeature(args);
@@ -3,7 +3,7 @@
3
3
  import { root } from '../../../panel/components/fields/root.svelte.js';
4
4
  import { Editor, type JSONContent } from '@tiptap/core';
5
5
  import { onMount } from 'svelte';
6
- import { buildEditorConfig } from '../core/config-builders.js';
6
+ import { buildEditorConfig } from '../core/build-editor-config.js';
7
7
  import type { RichTextFeature } from '../core/types';
8
8
  import { hasSuggestion } from '../util.js';
9
9
  import EditorBubbleMenu from './bubble-menu/bubble-menu.svelte';
@@ -1,4 +1,5 @@
1
1
  import { t__ } from '../../../core/i18n/index.js';
2
+ import { getTitleContext, TITLE_CTX } from '../../../panel/context/title.js';
2
3
  import Document from '@tiptap/extension-document';
3
4
  import HardBreak from '@tiptap/extension-hard-break';
4
5
  import { ListItem } from '@tiptap/extension-list';
@@ -65,6 +66,9 @@ export function buildEditorConfig(args) {
65
66
  const configContext = getConfigContext();
66
67
  const apiProxyContext = getAPIProxyContext();
67
68
  const userContext = getUserContext();
69
+ const titleContext = getTitleContext();
70
+ contexts.set(TITLE_CTX, titleContext);
71
+ contexts.set(CONFIG_CTX, configContext);
68
72
  contexts.set(CONFIG_CTX, configContext);
69
73
  contexts.set(API_PROXY.ROOT, apiProxyContext);
70
74
  contexts.set(USER_CTX, userContext);
@@ -24,10 +24,10 @@ export const FieldsExtension = Node.create({
24
24
  };
25
25
  },
26
26
  parseHTML() {
27
- return [{ tag: 'richt-text-fields' }];
27
+ return [{ tag: this.name }];
28
28
  },
29
29
  renderHTML({ HTMLAttributes }) {
30
- return ['richt-text-fields', mergeAttributes(HTMLAttributes)];
30
+ return [this.name, mergeAttributes(HTMLAttributes)];
31
31
  },
32
32
  addNodeView() {
33
33
  return SvelteNodeViewRenderer(FieldsComponent);
@@ -4,7 +4,7 @@ import type { Component } from 'svelte';
4
4
  import type { RichTextFeature } from '../../../../../types.js';
5
5
  export interface FieldsFeatureOptions {
6
6
  name: string;
7
- label: string;
7
+ label?: string;
8
8
  fields: FieldBuilder[];
9
9
  preview?: Component<FieldsPreviewProps>;
10
10
  }
@@ -3,12 +3,14 @@ import { FieldsExtension } from './extension.js';
3
3
  const fieldsFeatureNode = (args) => ({
4
4
  label: args.label || args.name,
5
5
  icon: SheetIcon,
6
- isActive: ({ editor }) => editor.isActive('richt-text-fields'),
6
+ isActive: ({ editor }) => editor.isActive('richt-text-fields-' + args.name),
7
7
  suggestion: {
8
8
  command: ({ editor }) => editor.chain().focus().insertSheet().run()
9
9
  }
10
10
  });
11
11
  export const FieldsFeature = (args) => ({
12
- extension: FieldsExtension.configure({ fields: args.fields, preview: args.preview }),
12
+ extension: FieldsExtension.configure({ fields: args.fields, preview: args.preview }).extend({
13
+ name: 'richt-text-fields-' + args.name
14
+ }),
13
15
  nodes: [fieldsFeatureNode(args)]
14
16
  });
@@ -40,14 +40,14 @@
40
40
  const locale = getLocaleContext();
41
41
  let resources = $state<Resource<LinkResource[]>[]>([]);
42
42
  let resourcesFlatMap = $state<LinkResource[]>();
43
+
43
44
  $effect(() => {
44
- if (Array.isArray(options?.resources) && !resources.length) {
45
- resources = options.resources.map((resourceOption) => {
46
- let params = resourceOption.query
47
- ? `?${resourceOption.query}&select=title,url`
48
- : '?select=title,url';
45
+ if (Array.isArray(options?.sources) && !resources.length) {
46
+ resources = options.sources.map((source) => {
47
+ const [slug, query] = source.split('?');
48
+ let params = query || '' ? `?${query}&select=title,url` : '?select=title,url';
49
49
  params = locale.code ? `${params}&locale=${locale.code}` : params;
50
- const url = `${apiUrl(resourceOption.slug)}${params}`;
50
+ const url = `${apiUrl(slug)}${params}`;
51
51
  return APIProxy.getRessource<LinkResource[]>(url, {
52
52
  transformData: (data) => {
53
53
  return 'docs' in data ? data.docs : 'doc' in data ? [data.doc] : data;
@@ -208,7 +208,7 @@
208
208
  />
209
209
  <Button size="icon-sm" variant="ghost" icon={Trash} onclick={onDelete} />
210
210
  {:else}
211
- {#if options?.resources?.length}
211
+ {#if options?.sources?.length}
212
212
  <Button
213
213
  onclick={() => (resourceDialogOpen = true)}
214
214
  size="icon-sm"
@@ -2,9 +2,6 @@ import type { PrototypeSlug } from '../../../../../types.js';
2
2
  import { type LinkOptions } from '@tiptap/extension-link';
3
3
  import type { RichTextFeature } from '../../types.js';
4
4
  export type LinkFeatureOptions = LinkOptions & {
5
- resources?: Array<{
6
- slug: PrototypeSlug;
7
- query?: string;
8
- }>;
5
+ sources?: Array<`${PrototypeSlug}${string}`>;
9
6
  };
10
7
  export declare const LinkFeature: (options?: Partial<LinkFeatureOptions>) => RichTextFeature;