rimecms 1.0.0 → 1.1.0
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/dist/adapter-sqlite/generate-schema/templates.server.d.ts +9 -9
- package/dist/adapter-sqlite/generate-schema/templates.server.js +9 -9
- package/dist/adapter-sqlite/paths.server.js +24 -15
- package/dist/adapter-sqlite/rows.server.d.ts +1 -1
- package/dist/core/adapter.d.ts +8 -4
- package/dist/core/boot.server.d.ts +2 -2
- package/dist/core/config/context.server.d.ts +2 -2
- package/dist/core/dev/codegen/routes/common.server.d.ts +2 -0
- package/dist/core/dev/codegen/routes/common.server.js +7 -3
- package/dist/core/dev/codegen/routes/util.server.d.ts +2 -1
- package/dist/core/dev/codegen/routes/util.server.js +4 -1
- package/dist/core/dev/config-memo.server.js +4 -0
- package/dist/core/i18n/en/fields.d.ts +1 -1
- package/dist/core/i18n/en/fields.js +1 -1
- package/dist/core/i18n/fr/fields.d.ts +1 -1
- package/dist/core/i18n/fr/fields.js +1 -1
- package/dist/core/prototype/collection/operations/duplicate.js +1 -1
- package/dist/core/prototype/collection/thumbnail/hooks/set-document-thumbnail.server.js +1 -1
- package/dist/core/prototype/shared/title/hooks/set-document-title.server.js +1 -1
- package/dist/core/prototype/shared/url/addresses.server.d.ts +10 -0
- package/dist/core/prototype/shared/url/addresses.server.js +17 -17
- package/dist/core/prototype/shared/url/hooks/detach-paths.server.d.ts +3 -2
- package/dist/core/prototype/shared/url/hooks/detach-paths.server.js +9 -8
- package/dist/core/prototype/shared/url/hooks/sync-paths.server.d.ts +3 -2
- package/dist/core/prototype/shared/url/hooks/sync-paths.server.js +5 -4
- package/dist/fields/blocks/component/AddBlockButton.svelte +1 -1
- package/dist/fields/blocks/component/Block.svelte +4 -5
- package/dist/fields/blocks/component/Blocks.svelte +17 -13
- package/dist/fields/blocks/component/focus/BlocksFocus.svelte +53 -65
- package/dist/fields/blocks/component/focus/DefaultRender.svelte +108 -0
- package/dist/fields/blocks/component/focus/{RenderPlaceholder.svelte.d.ts → DefaultRender.svelte.d.ts} +3 -3
- package/dist/fields/blocks/component/focus/Inspector.svelte +160 -0
- package/dist/fields/blocks/component/focus/Inspector.svelte.d.ts +7 -0
- package/dist/fields/blocks/component/focus/Layers.svelte +16 -3
- package/dist/fields/blocks/component/focus/LayersList.svelte +28 -11
- package/dist/fields/blocks/component/focus/LayersList.svelte.d.ts +2 -0
- package/dist/fields/blocks/component/focus/Palette.svelte +3 -3
- package/dist/fields/blocks/component/focus/Renders.svelte +66 -15
- package/dist/fields/blocks/component/focus/Renders.svelte.d.ts +5 -1
- package/dist/fields/blocks/component/focus/StagePlaceholder.svelte +1 -4
- package/dist/fields/blocks/component/focus/focus.svelte.d.ts +26 -12
- package/dist/fields/blocks/component/focus/focus.svelte.js +114 -57
- package/dist/fields/blocks/component/picker/BlockTile.svelte +3 -5
- package/dist/fields/combobox/component/ComboBox.svelte +1 -1
- package/dist/fields/combobox/component/combobox.css +1 -1
- package/dist/fields/date/component/Date.svelte +1 -1
- package/dist/fields/group/component/Group.svelte +4 -4
- package/dist/fields/link/component/Link.svelte +1 -1
- package/dist/fields/link/component/RessourceInput.svelte +2 -2
- package/dist/fields/link/index.d.ts +1 -1
- package/dist/fields/number/component/Number.svelte +1 -1
- package/dist/fields/relation/component/Cell.svelte +3 -1
- package/dist/fields/relation/component/RelationInline.svelte +51 -20
- package/dist/fields/relation/component/default/Default.svelte +3 -3
- package/dist/fields/relation/component/upload/Browse.svelte +2 -2
- package/dist/fields/relation/component/upload/Upload.svelte +2 -2
- package/dist/fields/relation/index.d.ts +1 -41
- package/dist/fields/relation/index.js +0 -67
- package/dist/fields/relation/util.d.ts +69 -0
- package/dist/fields/relation/util.js +103 -0
- package/dist/fields/rich-text/client.d.ts +2 -5
- package/dist/fields/rich-text/client.js +1 -3
- package/dist/fields/rich-text/component/Cell.svelte +1 -1
- package/dist/fields/rich-text/component/bubble-menu/bubble-menu.css +1 -1
- package/dist/fields/rich-text/component/bubble-menu/node-selector/node-selector.css +1 -1
- package/dist/fields/rich-text/core/features/link/component/link-selector.svelte +2 -2
- package/dist/fields/rich-text/core/features/resource/resource-extension.js +3 -3
- package/dist/fields/rich-text/core/features/resource/resource.svelte +2 -2
- package/dist/fields/rich-text/core/features/upload/upload-extension.js +3 -4
- package/dist/fields/rich-text/core/features/upload/upload.svelte +2 -2
- package/dist/fields/rich-text/index.d.ts +0 -17
- package/dist/fields/rich-text/index.js +0 -44
- package/dist/fields/rich-text/json.d.ts +18 -0
- package/dist/fields/rich-text/json.js +44 -0
- package/dist/fields/select/component/Select.svelte +2 -2
- package/dist/fields/text/component/TextInline.svelte +113 -0
- package/dist/fields/text/component/TextInline.svelte.d.ts +14 -0
- package/dist/fields/textarea/component/TextArea.svelte +1 -1
- package/dist/fields/tree/component/TreeBlock.svelte +4 -4
- package/dist/index.d.ts +2 -9
- package/dist/index.js +3 -8
- package/dist/{panel/components/sections/live → live}/Consumer.svelte +2 -2
- package/dist/{panel/components/sections/live → live}/Consumer.svelte.d.ts +1 -1
- package/dist/{panel/components/sections/live → live}/LiveEdit.svelte +2 -2
- package/dist/{panel/components/sections/live → live}/Provider.svelte +1 -1
- package/dist/{panel/context/live.svelte.d.ts → live/context.svelte.d.ts} +1 -1
- package/dist/{panel/context/live.svelte.js → live/context.svelte.js} +3 -3
- package/dist/panel/components/fields/Error.svelte +1 -1
- package/dist/panel/components/fields/FieldsPreview.svelte +1 -1
- package/dist/panel/components/fields/FieldsPreviewTrigger.svelte +1 -1
- package/dist/panel/components/fields/Hint.svelte +1 -1
- package/dist/panel/components/fields/setting.css +6 -6
- package/dist/panel/components/sections/auth/AuthForm.svelte +2 -2
- package/dist/panel/components/sections/collection/Avatar.svelte +1 -1
- package/dist/panel/components/sections/collection/bulk-upload/FileDrop.svelte +1 -1
- package/dist/panel/components/sections/collection/bulk-upload/PageDrop.svelte +3 -3
- package/dist/panel/components/sections/collection/bulk-upload/UploadProgress.svelte +1 -1
- package/dist/panel/components/sections/collection/folder/Folder.svelte +1 -1
- package/dist/panel/components/sections/collection/folder/FolderWithActions.svelte +2 -2
- package/dist/panel/components/sections/collection/grid/grid-item/GridItem.svelte +1 -1
- package/dist/panel/components/sections/collection/header/DisplayMode.svelte +1 -2
- package/dist/panel/components/sections/collection/list/CollectionList.svelte +2 -2
- package/dist/panel/components/sections/collection/list/header/Header.svelte +1 -1
- package/dist/panel/components/sections/collection/list/row/Row.svelte +1 -1
- package/dist/panel/components/sections/collection/tree/CollectionTree.svelte +1 -1
- package/dist/panel/components/sections/collection/tree/CollectionTreeNode.svelte +1 -1
- package/dist/panel/components/sections/collection/upload-thumb-cell/UploadThumbCell.svelte +1 -1
- package/dist/panel/components/sections/commands/CommandButton.svelte +1 -1
- package/dist/panel/components/sections/document/AuthAPIKeyDialog.svelte +1 -1
- package/dist/panel/components/sections/document/AuthFooter.svelte +2 -2
- package/dist/panel/components/sections/document/AutoSaveBanner.svelte +2 -2
- package/dist/panel/components/sections/document/ButtonStatus.svelte +1 -1
- package/dist/panel/components/sections/document/ChangeSlugDialog.svelte +1 -1
- package/dist/panel/components/sections/document/DocumentChildren.svelte +2 -2
- package/dist/panel/components/sections/document/upload-header/UploadHeader.svelte +2 -2
- package/dist/panel/components/sections/document/upload-header/drop-zone/DropZone.svelte +1 -1
- package/dist/panel/components/sections/document/upload-header/drop-zone/DropZone.svelte.d.ts +1 -1
- package/dist/panel/components/sections/live/LiveFloatingUI.svelte +2 -2
- package/dist/panel/components/ui/breadcrumb/BreadCrumb.svelte +1 -1
- package/dist/panel/components/ui/button/button.svelte +3 -4
- package/dist/panel/components/ui/calendar/calendar.svelte.d.ts +1 -1
- package/dist/panel/components/ui/card/card.svelte +2 -2
- package/dist/panel/components/ui/card-document/card-document.svelte +2 -2
- package/dist/panel/components/ui/card-resource/card-resource.svelte +2 -2
- package/dist/panel/components/ui/checkbox/checkbox.svelte.d.ts +1 -1
- package/dist/panel/components/ui/command/command-input.svelte +1 -1
- package/dist/panel/components/ui/context-menu/context-menu.css +1 -1
- package/dist/panel/components/ui/dialog/dialog-content.css +1 -1
- package/dist/panel/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +1 -1
- package/dist/panel/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte.d.ts +1 -1
- package/dist/panel/components/ui/dropdown-menu/dropdown-menu-content.css +1 -1
- package/dist/panel/components/ui/input/input.svelte +1 -1
- package/dist/panel/components/ui/nav/Nav.svelte +2 -3
- package/dist/panel/components/ui/nav/NavGroup.svelte +1 -1
- package/dist/panel/components/ui/nav/NavItemButton.svelte +1 -1
- package/dist/panel/components/ui/nav/UserButton.svelte +1 -1
- package/dist/panel/components/ui/page-header/PageHeader.svelte +1 -1
- package/dist/panel/components/ui/popover/popover-content.css +1 -1
- package/dist/panel/components/ui/radio-row-group/radio-row-group.css +0 -1
- package/dist/panel/components/ui/sheet/sheet.css +1 -1
- package/dist/panel/components/ui/sonner/sonner.css +1 -1
- package/dist/panel/components/ui/switch/switch.css +0 -2
- package/dist/panel/components/ui/switch/switch.svelte.d.ts +1 -1
- package/dist/panel/components/ui/tabs/tabs.css +2 -1
- package/dist/panel/components/ui/tag/tag.svelte +1 -1
- package/dist/panel/components/ui/tree/tree-rows.css +3 -3
- package/dist/panel/context/collection.svelte.d.ts +2 -2
- package/dist/panel/context/config.svelte.d.ts +2 -2
- package/dist/panel/context/documentForm.svelte.js +1 -1
- package/dist/panel/index.d.ts +3 -5
- package/dist/panel/index.js +4 -6
- package/dist/panel/pages/auth/forgot-password/ForgotPassword.svelte +1 -1
- package/dist/panel/pages/dashboard/Dashboard.svelte +1 -1
- package/dist/panel/pages/dashboard/DashboardCard.svelte +2 -2
- package/dist/panel/pages/dashboard/DashboardCollection.svelte +1 -1
- package/dist/panel/pages/dashboard/DashboardRow.svelte +1 -1
- package/dist/panel/public.d.ts +4 -0
- package/dist/panel/public.js +6 -0
- package/dist/panel/style/index.css +13 -37
- package/dist/panel/style/mixins/index.css +1 -1
- package/dist/panel/style/palette.css +3 -3
- package/dist/panel/style/scheme.css +10 -34
- package/dist/public.d.ts +13 -0
- package/dist/public.js +12 -0
- package/package.json +12 -6
- package/dist/fields/blocks/component/focus/RenderPlaceholder.svelte +0 -77
- package/dist/fields/blocks/component/focus/Stage.svelte +0 -190
- package/dist/fields/blocks/component/focus/Stage.svelte.d.ts +0 -8
- package/dist/fields/relation/client.d.ts +0 -28
- package/dist/fields/relation/client.js +0 -37
- /package/dist/{panel/util → fields/relation}/populate.d.ts +0 -0
- /package/dist/{panel/util → fields/relation}/populate.js +0 -0
- /package/dist/{panel/components/sections/live → live}/LiveEdit.svelte.d.ts +0 -0
- /package/dist/{panel/components/sections/live → live}/Provider.svelte.d.ts +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { DataType } from '../../core/fields/builders/form-field-builder.js';
|
|
2
2
|
import { FormFieldBuilder } from '../../core/fields/builders/form-field-builder.js';
|
|
3
3
|
import type { CollectionSlug, GenericDoc } from '../../core/prototype/types.js';
|
|
4
|
-
import type { DefaultValueFn, FormField
|
|
4
|
+
import type { DefaultValueFn, FormField } from '../types.js';
|
|
5
5
|
import type { RegisterCollection } from '../../index.js';
|
|
6
6
|
import type { WithOptional } from '../../util/types.js';
|
|
7
7
|
export declare class RelationFieldBuilder<Doc extends GenericDoc = GenericDoc> extends FormFieldBuilder<RelationField<Doc>> {
|
|
@@ -29,46 +29,6 @@ export declare class RelationFieldBuilder<Doc extends GenericDoc = GenericDoc> e
|
|
|
29
29
|
protected generateType(): string;
|
|
30
30
|
}
|
|
31
31
|
export declare const relation: (name: string) => RelationFieldBuilder<GenericDoc>;
|
|
32
|
-
/**
|
|
33
|
-
* Checks if a relation value is resolved (contains the actual referenced document).
|
|
34
|
-
*
|
|
35
|
-
* @example
|
|
36
|
-
* // Returns true for a resolved relation
|
|
37
|
-
* isRelationResolved({ title: 'Home Page', _prototype: 'collection', _type: 'pages' });
|
|
38
|
-
*/
|
|
39
|
-
export declare const isRelationResolved: <T>(value: any) => value is T;
|
|
40
|
-
/**
|
|
41
|
-
* Checks if a relation value is a reference (contains only the relationTo and documentId).
|
|
42
|
-
*
|
|
43
|
-
* @example
|
|
44
|
-
* // Returns true for a relation reference
|
|
45
|
-
* isRelationRef({ relationTo: 'pages', documentId: '123' });
|
|
46
|
-
*/
|
|
47
|
-
export declare const isRelationRef: (value: unknown) => value is RelationRef;
|
|
48
|
-
/**
|
|
49
|
-
* Checks if a relation value is unresolved (contains only reference information).
|
|
50
|
-
*
|
|
51
|
-
* @example
|
|
52
|
-
* // Returns true for an unresolved relation
|
|
53
|
-
* isRelationUnresolved({ relationTo: 'pages', documentId: '123' });
|
|
54
|
-
*/
|
|
55
|
-
export declare const isRelationUnresolved: (value: any) => value is Omit<Relation, "path" | "position" | "ownerId">;
|
|
56
|
-
/**
|
|
57
|
-
* Resolves a relation reference to the actual document it points to.
|
|
58
|
-
*
|
|
59
|
-
* @example
|
|
60
|
-
* // Resolves a relation reference to the actual document
|
|
61
|
-
* const doc = await resolveRelationRef({ relationTo: 'pages', documentId: '123' });
|
|
62
|
-
*/
|
|
63
|
-
export declare function resolveRelationRef<T>(item: T | RelationRef | string): Promise<T>;
|
|
64
|
-
/**
|
|
65
|
-
* Resolves a relation field value to the actual documents it points to.
|
|
66
|
-
*
|
|
67
|
-
* @example
|
|
68
|
-
* // Resolves a relation value to the actual documents
|
|
69
|
-
* const docs = await resolveRelation([{ relationTo: 'pages', documentId: '123' }]);
|
|
70
|
-
*/
|
|
71
|
-
export declare function resolveRelation<T>(value: RelationValue<T> | null | undefined): Promise<T[] | null | undefined>;
|
|
72
32
|
/****************************************************/
|
|
73
33
|
export type RelationField<Doc extends GenericDoc = GenericDoc> = FormField & {
|
|
74
34
|
type: 'relation';
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { FormFieldBuilder } from '../../core/fields/builders/form-field-builder.js';
|
|
2
|
-
import { hasProps, isObjectLiteral } from '../../util/object.js';
|
|
3
2
|
import { capitalize } from '../../util/string.js';
|
|
4
3
|
import { ensureRelationExists } from 'rimecms/fields/relation/module';
|
|
5
4
|
import dedent from 'dedent';
|
|
@@ -60,69 +59,3 @@ export class RelationFieldBuilder extends FormFieldBuilder {
|
|
|
60
59
|
}
|
|
61
60
|
}
|
|
62
61
|
export const relation = (name) => new RelationFieldBuilder(name);
|
|
63
|
-
/**
|
|
64
|
-
* Checks if a relation value is resolved (contains the actual referenced document).
|
|
65
|
-
*
|
|
66
|
-
* @example
|
|
67
|
-
* // Returns true for a resolved relation
|
|
68
|
-
* isRelationResolved({ title: 'Home Page', _prototype: 'collection', _type: 'pages' });
|
|
69
|
-
*/
|
|
70
|
-
export const isRelationResolved = (value) => {
|
|
71
|
-
return value && isObjectLiteral(value) && hasProps(['title', '_prototype', '_type'], value);
|
|
72
|
-
};
|
|
73
|
-
/**
|
|
74
|
-
* Checks if a relation value is a reference (contains only the relationTo and documentId).
|
|
75
|
-
*
|
|
76
|
-
* @example
|
|
77
|
-
* // Returns true for a relation reference
|
|
78
|
-
* isRelationRef({ relationTo: 'pages', documentId: '123' });
|
|
79
|
-
*/
|
|
80
|
-
export const isRelationRef = (value) => typeof value === 'object' &&
|
|
81
|
-
value !== null &&
|
|
82
|
-
typeof value.relationTo === 'string' &&
|
|
83
|
-
typeof value.documentId === 'string';
|
|
84
|
-
/**
|
|
85
|
-
* Checks if a relation value is unresolved (contains only reference information).
|
|
86
|
-
*
|
|
87
|
-
* @example
|
|
88
|
-
* // Returns true for an unresolved relation
|
|
89
|
-
* isRelationUnresolved({ relationTo: 'pages', documentId: '123' });
|
|
90
|
-
*/
|
|
91
|
-
export const isRelationUnresolved = (value) => {
|
|
92
|
-
return value && isObjectLiteral(value) && hasProps(['relationTo', 'documentId'], value);
|
|
93
|
-
};
|
|
94
|
-
/**
|
|
95
|
-
* Resolves a relation reference to the actual document it points to.
|
|
96
|
-
*
|
|
97
|
-
* @example
|
|
98
|
-
* // Resolves a relation reference to the actual document
|
|
99
|
-
* const doc = await resolveRelationRef({ relationTo: 'pages', documentId: '123' });
|
|
100
|
-
*/
|
|
101
|
-
export async function resolveRelationRef(item) {
|
|
102
|
-
if (isRelationRef(item)) {
|
|
103
|
-
return fetch(`api/${item.relationTo}/${item.documentId}`)
|
|
104
|
-
.then((r) => r.json())
|
|
105
|
-
.then((r) => r.doc);
|
|
106
|
-
}
|
|
107
|
-
if (typeof item === 'string') {
|
|
108
|
-
throw new Error(`Cannot resolve relation from a bare id ("${item}") — missing "relationTo". ` +
|
|
109
|
-
`resolveRelationRef only works on populated docs or { relationTo, documentId } objects.`);
|
|
110
|
-
}
|
|
111
|
-
if (isRelationResolved(item)) {
|
|
112
|
-
return item;
|
|
113
|
-
}
|
|
114
|
-
throw new Error(`Unrecognized relation shape: ${JSON.stringify(item)}`);
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Resolves a relation field value to the actual documents it points to.
|
|
118
|
-
*
|
|
119
|
-
* @example
|
|
120
|
-
* // Resolves a relation value to the actual documents
|
|
121
|
-
* const docs = await resolveRelation([{ relationTo: 'pages', documentId: '123' }]);
|
|
122
|
-
*/
|
|
123
|
-
export async function resolveRelation(value) {
|
|
124
|
-
if (value === null || value === undefined)
|
|
125
|
-
return value;
|
|
126
|
-
const items = Array.isArray(value) ? value : [value];
|
|
127
|
-
return Promise.all(items.map((item) => resolveRelationRef(item)));
|
|
128
|
-
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { RelationRef, RelationValue } from '../types.js';
|
|
2
|
+
import type { Relation } from './index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Checks if a relation field's value is populated with full documents.
|
|
5
|
+
*
|
|
6
|
+
* A relation is considered populated if it is an array of objects that do not
|
|
7
|
+
* contain only the relation identifiers (`id`, `relationTo`, `documentId`).
|
|
8
|
+
* If the value is a string or an array of relation identifier objects,
|
|
9
|
+
* it is considered not populated.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* // Returns: false
|
|
13
|
+
* isRelationPopulated('7674e91b-598a-4a72-a5cd-9594736a34dd');
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* // Returns: false
|
|
17
|
+
* isRelationPopulated([]);
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* // Returns: false
|
|
21
|
+
* isRelationPopulated([
|
|
22
|
+
* {
|
|
23
|
+
* id: '7674e91b-598a-4a72-a5cd-9594736a34dd',
|
|
24
|
+
* relationTo: 'articles',
|
|
25
|
+
* documentId: 'b674e91b-598a-4a72-a5cd-9594736a34dd'
|
|
26
|
+
* }
|
|
27
|
+
* ]);
|
|
28
|
+
*/
|
|
29
|
+
export declare const isRelationPopulated: <T>(value: RelationValue<T>) => value is T[];
|
|
30
|
+
/**
|
|
31
|
+
* Checks if a relation value is resolved (contains the actual referenced document).
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* // Returns true for a resolved relation
|
|
35
|
+
* isRelationResolved({ title: 'Home Page', _prototype: 'collection', _type: 'pages' });
|
|
36
|
+
*/
|
|
37
|
+
export declare const isRelationResolved: <T>(value: any) => value is T;
|
|
38
|
+
/**
|
|
39
|
+
* Checks if a relation value is a reference (contains only the relationTo and documentId).
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* // Returns true for a relation reference
|
|
43
|
+
* isRelationRef({ relationTo: 'pages', documentId: '123' });
|
|
44
|
+
*/
|
|
45
|
+
export declare const isRelationRef: (value: unknown) => value is RelationRef;
|
|
46
|
+
/**
|
|
47
|
+
* Checks if a relation value is unresolved (contains only reference information).
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* // Returns true for an unresolved relation
|
|
51
|
+
* isRelationUnresolved({ relationTo: 'pages', documentId: '123' });
|
|
52
|
+
*/
|
|
53
|
+
export declare const isRelationUnresolved: (value: any) => value is Omit<Relation, "path" | "position" | "ownerId">;
|
|
54
|
+
/**
|
|
55
|
+
* Resolves a relation reference to the actual document it points to.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* // Resolves a relation reference to the actual document
|
|
59
|
+
* const doc = await resolveRelationRef({ relationTo: 'pages', documentId: '123' });
|
|
60
|
+
*/
|
|
61
|
+
export declare function resolveRelationRef<T>(item: T | RelationRef | string): Promise<T>;
|
|
62
|
+
/**
|
|
63
|
+
* Resolves a relation field value to the actual documents it points to.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* // Resolves a relation value to the actual documents
|
|
67
|
+
* const docs = await resolveRelation([{ relationTo: 'pages', documentId: '123' }]);
|
|
68
|
+
*/
|
|
69
|
+
export declare function resolveRelation<T>(value: RelationValue<T> | null | undefined): Promise<T[] | null | undefined>;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { hasProps, isObjectLiteral } from '../../util/object.js';
|
|
2
|
+
/**
|
|
3
|
+
* Checks if a relation field's value is populated with full documents.
|
|
4
|
+
*
|
|
5
|
+
* A relation is considered populated if it is an array of objects that do not
|
|
6
|
+
* contain only the relation identifiers (`id`, `relationTo`, `documentId`).
|
|
7
|
+
* If the value is a string or an array of relation identifier objects,
|
|
8
|
+
* it is considered not populated.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* // Returns: false
|
|
12
|
+
* isRelationPopulated('7674e91b-598a-4a72-a5cd-9594736a34dd');
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* // Returns: false
|
|
16
|
+
* isRelationPopulated([]);
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* // Returns: false
|
|
20
|
+
* isRelationPopulated([
|
|
21
|
+
* {
|
|
22
|
+
* id: '7674e91b-598a-4a72-a5cd-9594736a34dd',
|
|
23
|
+
* relationTo: 'articles',
|
|
24
|
+
* documentId: 'b674e91b-598a-4a72-a5cd-9594736a34dd'
|
|
25
|
+
* }
|
|
26
|
+
* ]);
|
|
27
|
+
*/
|
|
28
|
+
export const isRelationPopulated = (value) => {
|
|
29
|
+
if (Array.isArray(value)) {
|
|
30
|
+
if (value.length === 0)
|
|
31
|
+
return false;
|
|
32
|
+
return value.every((v) => {
|
|
33
|
+
return isObjectLiteral(v) && !hasProps(['id', 'relationTo', 'documentId'], v);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
return typeof value !== 'string';
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Checks if a relation value is resolved (contains the actual referenced document).
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* // Returns true for a resolved relation
|
|
43
|
+
* isRelationResolved({ title: 'Home Page', _prototype: 'collection', _type: 'pages' });
|
|
44
|
+
*/
|
|
45
|
+
export const isRelationResolved = (value) => {
|
|
46
|
+
return value && isObjectLiteral(value) && hasProps(['title', '_prototype', '_type'], value);
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Checks if a relation value is a reference (contains only the relationTo and documentId).
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* // Returns true for a relation reference
|
|
53
|
+
* isRelationRef({ relationTo: 'pages', documentId: '123' });
|
|
54
|
+
*/
|
|
55
|
+
export const isRelationRef = (value) => typeof value === 'object' &&
|
|
56
|
+
value !== null &&
|
|
57
|
+
typeof value.relationTo === 'string' &&
|
|
58
|
+
typeof value.documentId === 'string';
|
|
59
|
+
/**
|
|
60
|
+
* Checks if a relation value is unresolved (contains only reference information).
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* // Returns true for an unresolved relation
|
|
64
|
+
* isRelationUnresolved({ relationTo: 'pages', documentId: '123' });
|
|
65
|
+
*/
|
|
66
|
+
export const isRelationUnresolved = (value) => {
|
|
67
|
+
return value && isObjectLiteral(value) && hasProps(['relationTo', 'documentId'], value);
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Resolves a relation reference to the actual document it points to.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* // Resolves a relation reference to the actual document
|
|
74
|
+
* const doc = await resolveRelationRef({ relationTo: 'pages', documentId: '123' });
|
|
75
|
+
*/
|
|
76
|
+
export async function resolveRelationRef(item) {
|
|
77
|
+
if (isRelationRef(item)) {
|
|
78
|
+
return fetch(`api/${item.relationTo}/${item.documentId}`)
|
|
79
|
+
.then((r) => r.json())
|
|
80
|
+
.then((r) => r.doc);
|
|
81
|
+
}
|
|
82
|
+
if (typeof item === 'string') {
|
|
83
|
+
throw new Error(`Cannot resolve relation from a bare id ("${item}") — missing "relationTo". ` +
|
|
84
|
+
`resolveRelationRef only works on populated docs or { relationTo, documentId } objects.`);
|
|
85
|
+
}
|
|
86
|
+
if (isRelationResolved(item)) {
|
|
87
|
+
return item;
|
|
88
|
+
}
|
|
89
|
+
throw new Error(`Unrecognized relation shape: ${JSON.stringify(item)}`);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Resolves a relation field value to the actual documents it points to.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* // Resolves a relation value to the actual documents
|
|
96
|
+
* const docs = await resolveRelation([{ relationTo: 'pages', documentId: '123' }]);
|
|
97
|
+
*/
|
|
98
|
+
export async function resolveRelation(value) {
|
|
99
|
+
if (value === null || value === undefined)
|
|
100
|
+
return value;
|
|
101
|
+
const items = Array.isArray(value) ? value : [value];
|
|
102
|
+
return Promise.all(items.map((item) => resolveRelationRef(item)));
|
|
103
|
+
}
|
|
@@ -5,11 +5,8 @@ import { type LinkFeatureOptions } from './core/features/link/index.js';
|
|
|
5
5
|
import type { ResourceFeatureExtensionOptions } from './core/features/resource/resource-extension.js';
|
|
6
6
|
import type { RichTextResource } from './core/features/resource/types.js';
|
|
7
7
|
import type { UploadFeatureExtensionOptions } from './core/features/upload/upload-extension.js';
|
|
8
|
-
import RenderRichText from './core/render-rich-text.svelte';
|
|
9
8
|
import SvelteNodeViewRenderer from './core/svelte/node-view-renderer.svelte';
|
|
10
9
|
import NodeViewWrapper from './core/svelte/node-view-wrapper.svelte';
|
|
11
|
-
import type { RichTextNodeRenderer, RichTextNodeRendererProps } from './core/types.js';
|
|
12
|
-
import { richTextJSONToText } from './index.js';
|
|
13
10
|
export declare const fields: (args: FieldsFeatureOptions) => import("./core/types.js").RichTextFeature;
|
|
14
11
|
export declare const bold: () => import("./core/types.js").RichTextFeature;
|
|
15
12
|
export declare const bulletList: () => import("./core/types.js").RichTextFeature;
|
|
@@ -22,5 +19,5 @@ export declare const blockquote: () => import("./core/types.js").RichTextFeature
|
|
|
22
19
|
export declare const italic: () => import("./core/types.js").RichTextFeature;
|
|
23
20
|
export declare const upload: (args: UploadFeatureExtensionOptions) => import("./core/types.js").RichTextFeature;
|
|
24
21
|
export declare const resource: (args: ResourceFeatureExtensionOptions) => import("./core/types.js").RichTextFeature;
|
|
25
|
-
export { NodeViewWrapper,
|
|
26
|
-
export type { JSONContent,
|
|
22
|
+
export { NodeViewWrapper, SvelteNodeViewRenderer };
|
|
23
|
+
export type { JSONContent, RichTextResource };
|
|
@@ -10,10 +10,8 @@ import { OrderedListFeature } from './core/features/ordered-list.js';
|
|
|
10
10
|
import { ParagraphFeature } from './core/features/paragraph.js';
|
|
11
11
|
import { ResourceFeature } from './core/features/resource/index.js';
|
|
12
12
|
import { UploadFeature } from './core/features/upload/index.js';
|
|
13
|
-
import RenderRichText from './core/render-rich-text.svelte';
|
|
14
13
|
import SvelteNodeViewRenderer from './core/svelte/node-view-renderer.svelte';
|
|
15
14
|
import NodeViewWrapper from './core/svelte/node-view-wrapper.svelte';
|
|
16
|
-
import { richTextJSONToText } from './index.js';
|
|
17
15
|
export const fields = (args) => FieldsFeature(args);
|
|
18
16
|
export const bold = () => BoldFeature;
|
|
19
17
|
export const bulletList = () => BulletListFeature;
|
|
@@ -26,4 +24,4 @@ export const blockquote = () => BlockquoteFeature;
|
|
|
26
24
|
export const italic = () => ItalicFeature;
|
|
27
25
|
export const upload = (args) => UploadFeature(args);
|
|
28
26
|
export const resource = (args) => ResourceFeature(args);
|
|
29
|
-
export { NodeViewWrapper,
|
|
27
|
+
export { NodeViewWrapper, SvelteNodeViewRenderer };
|
|
@@ -251,7 +251,7 @@
|
|
|
251
251
|
</Command.List>
|
|
252
252
|
</Command.Dialog>
|
|
253
253
|
|
|
254
|
-
<style>/* A level: its fill, a hairline, its shadow. raised, float. */
|
|
254
|
+
<style>/* A level: its fill, a hairline, and its shadow when it has one. raised has none, float does. */
|
|
255
255
|
|
|
256
256
|
/* A well: an input, a track, a dropzone. Its edge shows on hover. */
|
|
257
257
|
|
|
@@ -294,7 +294,7 @@
|
|
|
294
294
|
background-color: var(--rz-bg-float);
|
|
295
295
|
box-shadow:
|
|
296
296
|
0 0 0 1px var(--rz-border),
|
|
297
|
-
var(--rz-shadow-float);
|
|
297
|
+
var(--rz-shadow-float, 0 0 transparent);
|
|
298
298
|
animation: fadeInSlideFromTop 0.2s ease-out;
|
|
299
299
|
border-radius: var(--rz-radius-lg);
|
|
300
300
|
}
|
|
@@ -12,15 +12,15 @@ export const Resource = Node.create({
|
|
|
12
12
|
acc[key] = { default: null };
|
|
13
13
|
return acc;
|
|
14
14
|
},
|
|
15
|
-
//
|
|
16
|
-
{ _fresh: { default:
|
|
15
|
+
// A node just inserted opens its dialog; one read from stored content does not.
|
|
16
|
+
{ _fresh: { default: false } });
|
|
17
17
|
},
|
|
18
18
|
addCommands() {
|
|
19
19
|
return {
|
|
20
20
|
insertResource: (attributes = {}) => ({ commands }) => {
|
|
21
21
|
return commands.insertContent({
|
|
22
22
|
type: this.name,
|
|
23
|
-
attrs: attributes
|
|
23
|
+
attrs: { _fresh: true, ...attributes }
|
|
24
24
|
});
|
|
25
25
|
}
|
|
26
26
|
};
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
} else {
|
|
36
36
|
selected = null;
|
|
37
37
|
}
|
|
38
|
+
// A node just inserted opens its dialog.
|
|
38
39
|
if (node.attrs._fresh) {
|
|
39
|
-
// If the resource is fresh, we want to open the dialog to select a resource
|
|
40
40
|
isDialogOpen = true;
|
|
41
41
|
}
|
|
42
42
|
});
|
|
@@ -127,7 +127,7 @@
|
|
|
127
127
|
</Command.List>
|
|
128
128
|
</Command.Dialog>
|
|
129
129
|
|
|
130
|
-
<style>/* A level: its fill, a hairline, its shadow. raised, float. */
|
|
130
|
+
<style>/* A level: its fill, a hairline, and its shadow when it has one. raised has none, float does. */
|
|
131
131
|
|
|
132
132
|
/* A well: an input, a track, a dropzone. Its edge shows on hover. */
|
|
133
133
|
|
|
@@ -12,16 +12,15 @@ export const Upload = Node.create({
|
|
|
12
12
|
acc[key] = { default: null };
|
|
13
13
|
return acc;
|
|
14
14
|
},
|
|
15
|
-
//
|
|
16
|
-
|
|
17
|
-
{ _fresh: { default: true } });
|
|
15
|
+
// A node just inserted opens its dialog; one read from stored content does not.
|
|
16
|
+
{ _fresh: { default: false } });
|
|
18
17
|
},
|
|
19
18
|
addCommands() {
|
|
20
19
|
return {
|
|
21
20
|
insertUpload: (attributes = {}) => ({ commands }) => {
|
|
22
21
|
return commands.insertContent({
|
|
23
22
|
type: this.name,
|
|
24
|
-
attrs: attributes
|
|
23
|
+
attrs: { _fresh: true, ...attributes }
|
|
25
24
|
});
|
|
26
25
|
}
|
|
27
26
|
};
|
|
@@ -54,8 +54,8 @@
|
|
|
54
54
|
} else {
|
|
55
55
|
selected = null;
|
|
56
56
|
}
|
|
57
|
+
// A node just inserted opens its dialog.
|
|
57
58
|
if (node.attrs._fresh) {
|
|
58
|
-
// If the resource is fresh, we want to open the dialog to select a resource
|
|
59
59
|
isDialogOpen = true;
|
|
60
60
|
}
|
|
61
61
|
});
|
|
@@ -207,7 +207,7 @@
|
|
|
207
207
|
</Dialog.Content>
|
|
208
208
|
</Dialog.Root>
|
|
209
209
|
|
|
210
|
-
<style>/* A level: its fill, a hairline, its shadow. raised, float. */
|
|
210
|
+
<style>/* A level: its fill, a hairline, and its shadow when it has one. raised has none, float does. */
|
|
211
211
|
|
|
212
212
|
/* A well: an input, a track, a dropzone. Its edge shows on hover. */
|
|
213
213
|
|
|
@@ -32,23 +32,6 @@ export declare class RichTextFieldBuilder extends FormFieldBuilder<RichTextField
|
|
|
32
32
|
protected generateType(): string;
|
|
33
33
|
}
|
|
34
34
|
export declare const richText: (name: string) => RichTextFieldBuilder;
|
|
35
|
-
/**
|
|
36
|
-
* Type guard to check if a value is a JSONContent object.
|
|
37
|
-
*
|
|
38
|
-
* @example
|
|
39
|
-
* isJSONContent({ type: 'paragraph', content: [] }) // true
|
|
40
|
-
* isJSONContent('Just a string') // false
|
|
41
|
-
*/
|
|
42
|
-
export declare const isJSONContent: (value: any) => value is JSONContent;
|
|
43
|
-
/**
|
|
44
|
-
* Converts rich text JSON content to plain text.
|
|
45
|
-
* Extracts text content from a TipTap/ProseMirror JSON structure.
|
|
46
|
-
*
|
|
47
|
-
* @example
|
|
48
|
-
* // Returns "Hello world"
|
|
49
|
-
* richTextJSONToText('{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"Hello world"}]}]}');
|
|
50
|
-
*/
|
|
51
|
-
export declare const richTextJSONToText: (value: string | JSONContent | undefined) => string;
|
|
52
35
|
type RichTextContent = {
|
|
53
36
|
type: 'doc';
|
|
54
37
|
content: JSONContent[];
|
|
@@ -107,47 +107,3 @@ export class RichTextFieldBuilder extends FormFieldBuilder {
|
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
export const richText = (name) => new RichTextFieldBuilder(name);
|
|
110
|
-
/**
|
|
111
|
-
* Type guard to check if a value is a JSONContent object.
|
|
112
|
-
*
|
|
113
|
-
* @example
|
|
114
|
-
* isJSONContent({ type: 'paragraph', content: [] }) // true
|
|
115
|
-
* isJSONContent('Just a string') // false
|
|
116
|
-
*/
|
|
117
|
-
export const isJSONContent = (value) => {
|
|
118
|
-
return typeof value === 'object' && value !== null && 'content' in value;
|
|
119
|
-
};
|
|
120
|
-
/**
|
|
121
|
-
* Converts rich text JSON content to plain text.
|
|
122
|
-
* Extracts text content from a TipTap/ProseMirror JSON structure.
|
|
123
|
-
*
|
|
124
|
-
* @example
|
|
125
|
-
* // Returns "Hello world"
|
|
126
|
-
* richTextJSONToText('{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"Hello world"}]}]}');
|
|
127
|
-
*/
|
|
128
|
-
export const richTextJSONToText = (value) => {
|
|
129
|
-
if (!value)
|
|
130
|
-
return '';
|
|
131
|
-
let textValue;
|
|
132
|
-
const renderNodes = (nodes) => {
|
|
133
|
-
return nodes
|
|
134
|
-
.map((node) => {
|
|
135
|
-
if ('text' in node) {
|
|
136
|
-
return node.text;
|
|
137
|
-
}
|
|
138
|
-
else if ('content' in node) {
|
|
139
|
-
return renderNodes(node.content);
|
|
140
|
-
}
|
|
141
|
-
})
|
|
142
|
-
.join(' ');
|
|
143
|
-
};
|
|
144
|
-
try {
|
|
145
|
-
const jsonContent = typeof value === 'string' ? JSON.parse(value) : value;
|
|
146
|
-
textValue = renderNodes(jsonContent.content);
|
|
147
|
-
}
|
|
148
|
-
catch (err) {
|
|
149
|
-
console.error(err);
|
|
150
|
-
textValue = JSON.stringify(value);
|
|
151
|
-
}
|
|
152
|
-
return textValue;
|
|
153
|
-
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { JSONContent } from '@tiptap/core';
|
|
2
|
+
/**
|
|
3
|
+
* Type guard to check if a value is a JSONContent object.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* isJSONContent({ type: 'paragraph', content: [] }) // true
|
|
7
|
+
* isJSONContent('Just a string') // false
|
|
8
|
+
*/
|
|
9
|
+
export declare const isJSONContent: (value: any) => value is JSONContent;
|
|
10
|
+
/**
|
|
11
|
+
* Converts rich text JSON content to plain text.
|
|
12
|
+
* Extracts text content from a TipTap/ProseMirror JSON structure.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* // Returns "Hello world"
|
|
16
|
+
* richTextJSONToText('{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"Hello world"}]}]}');
|
|
17
|
+
*/
|
|
18
|
+
export declare const richTextJSONToText: (value: string | JSONContent | undefined) => string;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type guard to check if a value is a JSONContent object.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* isJSONContent({ type: 'paragraph', content: [] }) // true
|
|
6
|
+
* isJSONContent('Just a string') // false
|
|
7
|
+
*/
|
|
8
|
+
export const isJSONContent = (value) => {
|
|
9
|
+
return typeof value === 'object' && value !== null && 'content' in value;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Converts rich text JSON content to plain text.
|
|
13
|
+
* Extracts text content from a TipTap/ProseMirror JSON structure.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* // Returns "Hello world"
|
|
17
|
+
* richTextJSONToText('{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"Hello world"}]}]}');
|
|
18
|
+
*/
|
|
19
|
+
export const richTextJSONToText = (value) => {
|
|
20
|
+
if (!value)
|
|
21
|
+
return '';
|
|
22
|
+
let textValue;
|
|
23
|
+
const renderNodes = (nodes) => {
|
|
24
|
+
return nodes
|
|
25
|
+
.map((node) => {
|
|
26
|
+
if ('text' in node) {
|
|
27
|
+
return node.text;
|
|
28
|
+
}
|
|
29
|
+
else if ('content' in node) {
|
|
30
|
+
return renderNodes(node.content);
|
|
31
|
+
}
|
|
32
|
+
})
|
|
33
|
+
.join(' ');
|
|
34
|
+
};
|
|
35
|
+
try {
|
|
36
|
+
const jsonContent = typeof value === 'string' ? JSON.parse(value) : value;
|
|
37
|
+
textValue = renderNodes(jsonContent.content);
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
console.error(err);
|
|
41
|
+
textValue = JSON.stringify(value);
|
|
42
|
+
}
|
|
43
|
+
return textValue;
|
|
44
|
+
};
|
|
@@ -155,7 +155,7 @@
|
|
|
155
155
|
<Field.Hint {config} />
|
|
156
156
|
</fieldset>
|
|
157
157
|
|
|
158
|
-
<style>/* A level: its fill, a hairline, its shadow. raised, float. */
|
|
158
|
+
<style>/* A level: its fill, a hairline, and its shadow when it has one. raised has none, float does. */
|
|
159
159
|
|
|
160
160
|
/* A well: an input, a track, a dropzone. Its edge shows on hover. */
|
|
161
161
|
|
|
@@ -188,7 +188,7 @@
|
|
|
188
188
|
background-color: var(--rz-bg-float);
|
|
189
189
|
box-shadow:
|
|
190
190
|
0 0 0 1px var(--rz-border),
|
|
191
|
-
var(--rz-shadow-float);
|
|
191
|
+
var(--rz-shadow-float, 0 0 transparent);
|
|
192
192
|
position: absolute;
|
|
193
193
|
left: 0;
|
|
194
194
|
right: 0;
|