payload 1.0.32 → 1.0.35

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 (76) hide show
  1. package/.eslintrc.js +1 -0
  2. package/CHANGELOG.md +33 -1
  3. package/components/index.js +2 -2
  4. package/dist/admin/components/elements/DeleteDocument/index.js +6 -6
  5. package/dist/admin/components/elements/DuplicateDocument/index.js +4 -4
  6. package/dist/admin/components/elements/GenerateConfirmation/index.js +7 -5
  7. package/dist/admin/components/elements/Popup/index.js +14 -13
  8. package/dist/admin/components/elements/Status/index.js +14 -9
  9. package/dist/admin/components/forms/Error/index.scss +2 -1
  10. package/dist/admin/components/forms/Label/index.scss +3 -1
  11. package/dist/admin/components/forms/field-types/Relationship/index.js +12 -1
  12. package/dist/admin/components/forms/field-types/Relationship/optionsReducer.js +1 -1
  13. package/dist/admin/components/forms/field-types/Relationship/types.d.ts +0 -1
  14. package/dist/admin/components/forms/field-types/RichText/RichText.d.ts +2 -2
  15. package/dist/admin/components/forms/field-types/RichText/RichText.js +4 -7
  16. package/dist/admin/components/forms/field-types/RichText/elements/indent/index.js +0 -3
  17. package/dist/admin/components/forms/field-types/RichText/elements/index.d.ts +6 -3
  18. package/dist/admin/components/forms/field-types/RichText/elements/link/Button.d.ts +4 -0
  19. package/dist/admin/components/forms/field-types/RichText/elements/link/Button.js +105 -0
  20. package/dist/admin/components/forms/field-types/RichText/elements/link/Element.d.ts +9 -0
  21. package/dist/admin/components/forms/field-types/RichText/elements/link/Element.js +120 -0
  22. package/dist/admin/components/forms/field-types/RichText/elements/link/Modal/baseFields.d.ts +3 -0
  23. package/dist/admin/components/forms/field-types/RichText/elements/link/Modal/baseFields.js +56 -0
  24. package/dist/admin/components/forms/field-types/RichText/elements/link/Modal/index.d.ts +4 -0
  25. package/dist/admin/components/forms/field-types/RichText/elements/link/Modal/index.js +22 -0
  26. package/dist/admin/components/forms/field-types/RichText/elements/link/Modal/index.scss +29 -0
  27. package/dist/admin/components/forms/field-types/RichText/elements/link/Modal/types.d.ts +9 -0
  28. package/dist/admin/components/forms/field-types/RichText/elements/link/Modal/types.js +1 -0
  29. package/dist/admin/components/forms/field-types/RichText/elements/link/index.d.ts +6 -5
  30. package/dist/admin/components/forms/field-types/RichText/elements/link/index.js +4 -67
  31. package/dist/admin/components/forms/field-types/RichText/elements/link/index.scss +36 -63
  32. package/dist/admin/components/forms/field-types/RichText/elements/link/shared.d.ts +1 -0
  33. package/dist/admin/components/forms/field-types/RichText/elements/link/shared.js +1 -0
  34. package/dist/admin/components/forms/field-types/RichText/elements/link/utilities.d.ts +1 -1
  35. package/dist/admin/components/forms/field-types/RichText/elements/link/utilities.js +13 -23
  36. package/dist/admin/components/forms/field-types/RichText/elements/relationship/Button/index.js +6 -10
  37. package/dist/admin/components/forms/field-types/RichText/elements/toggle.js +0 -3
  38. package/dist/admin/components/forms/field-types/RichText/elements/upload/Button/index.js +8 -12
  39. package/dist/admin/components/forms/field-types/RichText/elements/upload/Element/EditModal/index.js +2 -3
  40. package/dist/admin/components/forms/field-types/RichText/elements/upload/Element/index.js +6 -6
  41. package/dist/admin/components/forms/field-types/RichText/types.d.ts +0 -4
  42. package/dist/admin/components/forms/field-types/Text/Input.d.ts +2 -0
  43. package/dist/admin/components/forms/field-types/Text/Input.js +2 -3
  44. package/dist/admin/components/forms/field-types/Text/index.js +2 -2
  45. package/dist/admin/components/forms/field-types/Text/types.d.ts +3 -0
  46. package/dist/admin/components/forms/field-types/Upload/Add/index.js +4 -4
  47. package/dist/admin/components/forms/field-types/Upload/Input.js +3 -3
  48. package/dist/admin/components/forms/field-types/Upload/SelectExisting/index.js +6 -6
  49. package/dist/admin/components/modals/StayLoggedIn/index.js +4 -3
  50. package/dist/admin/components/utilities/Auth/index.js +1 -1
  51. package/dist/admin/components/views/Version/Restore/index.js +3 -3
  52. package/dist/admin/hooks/useThrottledEffect.js +15 -10
  53. package/dist/admin/index.js +1 -1
  54. package/dist/admin/scss/vars.scss +2 -2
  55. package/dist/auth/types.d.ts +1 -1
  56. package/dist/fields/config/schema.js +6 -3
  57. package/dist/fields/config/types.d.ts +3 -0
  58. package/dist/fields/config/types.js +1 -1
  59. package/dist/fields/hooks/afterRead/promise.js +3 -3
  60. package/dist/fields/richText/recurseNestedFields.js +3 -3
  61. package/dist/fields/richText/{relationshipPromise.d.ts → richTextRelationshipPromise.d.ts} +0 -0
  62. package/dist/fields/richText/richTextRelationshipPromise.js +104 -0
  63. package/dist/fields/validations.js +2 -2
  64. package/dist/graphql/schema/buildObjectType.js +3 -3
  65. package/dist/graphql/utilities/formatName.js +4 -1
  66. package/dist/graphql/utilities/formatName.spec.d.ts +1 -0
  67. package/dist/graphql/utilities/formatName.spec.js +23 -0
  68. package/dist/mongoose/sanitizeFormattedValue.js +1 -1
  69. package/dist/uploads/getBaseFields.js +3 -3
  70. package/dist/utilities/wordBoundariesRegex.js +5 -2
  71. package/docs/configuration/collections.mdx +1 -1
  72. package/docs/configuration/overview.mdx +1 -1
  73. package/docs/fields/rich-text.mdx +7 -0
  74. package/docs/getting-started/concepts.mdx +1 -1
  75. package/package.json +2 -2
  76. package/dist/fields/richText/relationshipPromise.js +0 -71
@@ -20,7 +20,7 @@ const sortOptions = (options) => options.sort((a, b) => {
20
20
  const optionsReducer = (state, action) => {
21
21
  switch (action.type) {
22
22
  case 'CLEAR': {
23
- return action.required ? [] : [{ value: 'null', label: 'None' }];
23
+ return [];
24
24
  }
25
25
  case 'ADD': {
26
26
  const { hasMultipleRelations, collection, relation, data, sort, ids = [] } = action;
@@ -12,7 +12,6 @@ export declare type Option = {
12
12
  };
13
13
  declare type CLEAR = {
14
14
  type: 'CLEAR';
15
- required: boolean;
16
15
  };
17
16
  declare type ADD = {
18
17
  type: 'ADD';
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import { BaseEditor } from 'slate';
3
3
  import { ReactEditor } from 'slate-react';
4
4
  import { HistoryEditor } from 'slate-history';
5
- import { Props, BlurSelectionEditor } from './types';
5
+ import { Props } from './types';
6
6
  import './index.scss';
7
7
  declare type CustomText = {
8
8
  text: string;
@@ -14,7 +14,7 @@ declare type CustomElement = {
14
14
  };
15
15
  declare module 'slate' {
16
16
  interface CustomTypes {
17
- Editor: BaseEditor & ReactEditor & HistoryEditor & BlurSelectionEditor;
17
+ Editor: BaseEditor & ReactEditor & HistoryEditor;
18
18
  Element: CustomElement;
19
19
  Text: CustomText;
20
20
  }
@@ -69,14 +69,11 @@ const RichText = (props) => {
69
69
  ].filter(Boolean).join(' ');
70
70
  const editor = useMemo(() => {
71
71
  let CreatedEditor = withEnterBreakOut(withHistory(withReact(createEditor())));
72
+ CreatedEditor = withHTML(CreatedEditor);
72
73
  CreatedEditor = enablePlugins(CreatedEditor, elements);
73
74
  CreatedEditor = enablePlugins(CreatedEditor, leaves);
74
- CreatedEditor = withHTML(CreatedEditor);
75
75
  return CreatedEditor;
76
76
  }, [elements, leaves]);
77
- const onBlur = useCallback(() => {
78
- editor.blurSelection = editor.selection;
79
- }, [editor]);
80
77
  useEffect(() => {
81
78
  if (!loaded) {
82
79
  const mergedElements = mergeCustomFunctions(elements, elementTypes);
@@ -128,7 +125,7 @@ const RichText = (props) => {
128
125
  const elementType = enabledElements[elementName];
129
126
  const Button = elementType === null || elementType === void 0 ? void 0 : elementType.Button;
130
127
  if (Button) {
131
- return (React.createElement(Button, { key: i, path: path }));
128
+ return (React.createElement(Button, { fieldProps: props, key: i, path: path }));
132
129
  }
133
130
  return null;
134
131
  }),
@@ -141,12 +138,12 @@ const RichText = (props) => {
141
138
  const leafType = enabledLeaves[leafName];
142
139
  const Button = leafType === null || leafType === void 0 ? void 0 : leafType.Button;
143
140
  if (Button) {
144
- return (React.createElement(Button, { key: i, path: path }));
141
+ return (React.createElement(Button, { fieldProps: props, key: i, path: path }));
145
142
  }
146
143
  return null;
147
144
  }))),
148
145
  React.createElement("div", { className: `${baseClass}__editor`, ref: editorRef },
149
- React.createElement(Editable, { id: `field-${path.replace(/\./gi, '__')}`, className: `${baseClass}__input`, renderElement: renderElement, renderLeaf: renderLeaf, placeholder: placeholder, spellCheck: true, readOnly: readOnly, onBlur: onBlur, onKeyDown: (event) => {
146
+ React.createElement(Editable, { id: `field-${path.replace(/\./gi, '__')}`, className: `${baseClass}__input`, renderElement: renderElement, renderLeaf: renderLeaf, placeholder: placeholder, spellCheck: true, readOnly: readOnly, onKeyDown: (event) => {
150
147
  if (event.key === 'Enter') {
151
148
  if (event.shiftKey) {
152
149
  event.preventDefault();
@@ -13,9 +13,6 @@ const indent = {
13
13
  const editor = useSlate();
14
14
  const handleIndent = useCallback((e, dir) => {
15
15
  e.preventDefault();
16
- if (editor.blurSelection) {
17
- Transforms.select(editor, editor.blurSelection);
18
- }
19
16
  if (dir === 'left') {
20
17
  Transforms.unwrapNodes(editor, {
21
18
  match: (n) => Element.isElement(n) && [indentType, ...listTypes].includes(n.type),
@@ -43,14 +43,17 @@ declare const elements: {
43
43
  }) => JSX.Element;
44
44
  };
45
45
  link: {
46
- Button: () => JSX.Element;
47
- Element: ({ attributes, children, element, editorRef }: {
46
+ Button: ({ fieldProps }: {
47
+ fieldProps: any;
48
+ }) => JSX.Element;
49
+ Element: ({ attributes, children, element, editorRef, fieldProps }: {
48
50
  attributes: any;
49
51
  children: any;
50
52
  element: any;
51
53
  editorRef: any;
54
+ fieldProps: any;
52
55
  }) => JSX.Element;
53
- plugins: ((incomingEditor: import("slate").BaseEditor & import("slate-react").ReactEditor & import("slate-history").HistoryEditor & import("../types").BlurSelectionEditor) => import("slate").BaseEditor & import("slate-react").ReactEditor & import("slate-history").HistoryEditor & import("../types").BlurSelectionEditor)[];
56
+ plugins: ((incomingEditor: import("slate").BaseEditor & import("slate-react").ReactEditor & import("slate-history").HistoryEditor) => import("slate").BaseEditor & import("slate-react").ReactEditor & import("slate-history").HistoryEditor)[];
54
57
  };
55
58
  ol: {
56
59
  Button: () => JSX.Element;
@@ -0,0 +1,4 @@
1
+ /// <reference types="react" />
2
+ export declare const LinkButton: ({ fieldProps }: {
3
+ fieldProps: any;
4
+ }) => JSX.Element;
@@ -0,0 +1,105 @@
1
+ import React, { Fragment, useState } from 'react';
2
+ import { ReactEditor, useSlate } from 'slate-react';
3
+ import { Transforms, Editor, Range } from 'slate';
4
+ import { useModal } from '@faceless-ui/modal';
5
+ import ElementButton from '../Button';
6
+ import { unwrapLink } from './utilities';
7
+ import LinkIcon from '../../../../../icons/Link';
8
+ import { EditModal } from './Modal';
9
+ import { modalSlug as baseModalSlug } from './shared';
10
+ import isElementActive from '../isActive';
11
+ import buildStateFromSchema from '../../../../Form/buildStateFromSchema';
12
+ import { useAuth } from '../../../../../utilities/Auth';
13
+ import { useLocale } from '../../../../../utilities/Locale';
14
+ import { useConfig } from '../../../../../utilities/Config';
15
+ import { getBaseFields } from './Modal/baseFields';
16
+ import reduceFieldsToValues from '../../../../Form/reduceFieldsToValues';
17
+ export const LinkButton = ({ fieldProps }) => {
18
+ var _a, _b;
19
+ const customFieldSchema = (_b = (_a = fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.admin) === null || _a === void 0 ? void 0 : _a.link) === null || _b === void 0 ? void 0 : _b.fields;
20
+ const modalSlug = `${baseModalSlug}-${fieldProps.path}`;
21
+ const config = useConfig();
22
+ const editor = useSlate();
23
+ const { user } = useAuth();
24
+ const locale = useLocale();
25
+ const { toggleModal } = useModal();
26
+ const [renderModal, setRenderModal] = useState(false);
27
+ const [initialState, setInitialState] = useState({});
28
+ const [fieldSchema] = useState(() => {
29
+ const fields = [
30
+ ...getBaseFields(config),
31
+ ];
32
+ if (customFieldSchema) {
33
+ fields.push({
34
+ name: 'fields',
35
+ type: 'group',
36
+ admin: {
37
+ style: {
38
+ margin: 0,
39
+ padding: 0,
40
+ borderTop: 0,
41
+ borderBottom: 0,
42
+ },
43
+ },
44
+ fields: customFieldSchema,
45
+ });
46
+ }
47
+ return fields;
48
+ });
49
+ return (React.createElement(Fragment, null,
50
+ React.createElement(ElementButton, { format: "link", onClick: async () => {
51
+ if (isElementActive(editor, 'link')) {
52
+ unwrapLink(editor);
53
+ }
54
+ else {
55
+ toggleModal(modalSlug);
56
+ setRenderModal(true);
57
+ const isCollapsed = editor.selection && Range.isCollapsed(editor.selection);
58
+ if (!isCollapsed) {
59
+ const data = {
60
+ text: editor.selection ? Editor.string(editor, editor.selection) : '',
61
+ };
62
+ const state = await buildStateFromSchema({ fieldSchema, data, user, operation: 'create', locale });
63
+ setInitialState(state);
64
+ }
65
+ }
66
+ } },
67
+ React.createElement(LinkIcon, null)),
68
+ renderModal && (React.createElement(EditModal, { modalSlug: modalSlug, fieldSchema: fieldSchema, initialState: initialState, close: () => {
69
+ toggleModal(modalSlug);
70
+ setRenderModal(false);
71
+ }, handleModalSubmit: (fields) => {
72
+ const isCollapsed = editor.selection && Range.isCollapsed(editor.selection);
73
+ const data = reduceFieldsToValues(fields, true);
74
+ const newLink = {
75
+ type: 'link',
76
+ linkType: data.linkType,
77
+ url: data.url,
78
+ doc: data.doc,
79
+ newTab: data.newTab,
80
+ fields: data.fields,
81
+ children: [],
82
+ };
83
+ if (isCollapsed || !editor.selection) {
84
+ // If selection anchor and focus are the same,
85
+ // Just inject a new node with children already set
86
+ Transforms.insertNodes(editor, {
87
+ ...newLink,
88
+ children: [{ text: String(data.text) }],
89
+ });
90
+ }
91
+ else if (editor.selection) {
92
+ // Otherwise we need to wrap the selected node in a link,
93
+ // Delete its old text,
94
+ // Move the selection one position forward into the link,
95
+ // And insert the text back into the new link
96
+ Transforms.wrapNodes(editor, newLink, { split: true });
97
+ Transforms.delete(editor, { at: editor.selection.focus.path, unit: 'word' });
98
+ Transforms.move(editor, { distance: 1, unit: 'offset' });
99
+ Transforms.insertText(editor, String(data.text), { at: editor.selection.focus.path });
100
+ }
101
+ toggleModal(modalSlug);
102
+ setRenderModal(false);
103
+ ReactEditor.focus(editor);
104
+ } }))));
105
+ };
@@ -0,0 +1,9 @@
1
+ /// <reference types="react" />
2
+ import './index.scss';
3
+ export declare const LinkElement: ({ attributes, children, element, editorRef, fieldProps }: {
4
+ attributes: any;
5
+ children: any;
6
+ element: any;
7
+ editorRef: any;
8
+ fieldProps: any;
9
+ }) => JSX.Element;
@@ -0,0 +1,120 @@
1
+ import React, { Fragment, useCallback, useEffect, useState } from 'react';
2
+ import { ReactEditor, useSlate } from 'slate-react';
3
+ import { Transforms, Node, Editor } from 'slate';
4
+ import { useModal } from '@faceless-ui/modal';
5
+ import { unwrapLink } from './utilities';
6
+ import Popup from '../../../../../elements/Popup';
7
+ import { EditModal } from './Modal';
8
+ import { modalSlug as baseModalSlug } from './shared';
9
+ import buildStateFromSchema from '../../../../Form/buildStateFromSchema';
10
+ import { useAuth } from '../../../../../utilities/Auth';
11
+ import { useLocale } from '../../../../../utilities/Locale';
12
+ import { useConfig } from '../../../../../utilities/Config';
13
+ import { getBaseFields } from './Modal/baseFields';
14
+ import reduceFieldsToValues from '../../../../Form/reduceFieldsToValues';
15
+ import deepCopyObject from '../../../../../../../utilities/deepCopyObject';
16
+ import Button from '../../../../../elements/Button';
17
+ import './index.scss';
18
+ const baseClass = 'rich-text-link';
19
+ // TODO: Multiple modal windows stacked go boom (rip). Edit Upload in fields -> rich text
20
+ export const LinkElement = ({ attributes, children, element, editorRef, fieldProps }) => {
21
+ var _a, _b;
22
+ const customFieldSchema = (_b = (_a = fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.admin) === null || _a === void 0 ? void 0 : _a.link) === null || _b === void 0 ? void 0 : _b.fields;
23
+ const editor = useSlate();
24
+ const config = useConfig();
25
+ const { user } = useAuth();
26
+ const locale = useLocale();
27
+ const { openModal, toggleModal } = useModal();
28
+ const [renderModal, setRenderModal] = useState(false);
29
+ const [renderPopup, setRenderPopup] = useState(false);
30
+ const [initialState, setInitialState] = useState({});
31
+ const [fieldSchema] = useState(() => {
32
+ const fields = [
33
+ ...getBaseFields(config),
34
+ ];
35
+ if (customFieldSchema) {
36
+ fields.push({
37
+ name: 'fields',
38
+ type: 'group',
39
+ admin: {
40
+ style: {
41
+ margin: 0,
42
+ padding: 0,
43
+ borderTop: 0,
44
+ borderBottom: 0,
45
+ },
46
+ },
47
+ fields: customFieldSchema,
48
+ });
49
+ }
50
+ return fields;
51
+ });
52
+ const modalSlug = `${baseModalSlug}-${fieldProps.path}`;
53
+ const handleTogglePopup = useCallback((render) => {
54
+ if (!render) {
55
+ setRenderPopup(render);
56
+ }
57
+ }, []);
58
+ useEffect(() => {
59
+ const awaitInitialState = async () => {
60
+ const data = {
61
+ text: Node.string(element),
62
+ linkType: element.linkType,
63
+ url: element.url,
64
+ doc: element.doc,
65
+ newTab: element.newTab,
66
+ fields: deepCopyObject(element.fields),
67
+ };
68
+ const state = await buildStateFromSchema({ fieldSchema, data, user, operation: 'update', locale });
69
+ setInitialState(state);
70
+ };
71
+ awaitInitialState();
72
+ }, [renderModal, element, fieldSchema, user, locale]);
73
+ return (React.createElement("span", { className: baseClass, ...attributes },
74
+ React.createElement("span", { style: { userSelect: 'none' }, contentEditable: false },
75
+ renderModal && (React.createElement(EditModal, { modalSlug: modalSlug, fieldSchema: fieldSchema, close: () => {
76
+ toggleModal(modalSlug);
77
+ setRenderModal(false);
78
+ }, handleModalSubmit: (fields) => {
79
+ toggleModal(modalSlug);
80
+ setRenderModal(false);
81
+ const data = reduceFieldsToValues(fields, true);
82
+ const [, parentPath] = Editor.above(editor);
83
+ const newNode = {
84
+ newTab: data.newTab,
85
+ url: data.url,
86
+ linkType: data.linkType,
87
+ doc: data.doc,
88
+ };
89
+ if (customFieldSchema) {
90
+ newNode.fields = data.fields;
91
+ }
92
+ Transforms.setNodes(editor, newNode, { at: parentPath });
93
+ Transforms.delete(editor, { at: editor.selection.focus.path, unit: 'block' });
94
+ Transforms.move(editor, { distance: 1, unit: 'offset' });
95
+ Transforms.insertText(editor, String(data.text), { at: editor.selection.focus.path });
96
+ ReactEditor.focus(editor);
97
+ }, initialState: initialState })),
98
+ React.createElement(Popup, { buttonType: "none", size: "small", forceOpen: renderPopup, onToggleOpen: handleTogglePopup, horizontalAlign: "left", verticalAlign: "bottom", boundingRef: editorRef, render: () => {
99
+ var _a, _b, _c, _d;
100
+ return (React.createElement("div", { className: `${baseClass}__popup` },
101
+ element.linkType === 'internal' && ((_a = element.doc) === null || _a === void 0 ? void 0 : _a.relationTo) && ((_b = element.doc) === null || _b === void 0 ? void 0 : _b.value) && (React.createElement(Fragment, null,
102
+ "Linked to\u00A0",
103
+ React.createElement("a", { className: `${baseClass}__link-label`, href: `${config.routes.admin}/collections/${element.doc.relationTo}/${element.doc.value}`, target: "_blank", rel: "noreferrer" }, (_d = (_c = config.collections.find(({ slug }) => slug === element.doc.relationTo)) === null || _c === void 0 ? void 0 : _c.labels) === null || _d === void 0 ? void 0 : _d.singular))),
104
+ (element.linkType === 'custom' || !element.linkType) && (React.createElement("a", { className: `${baseClass}__link-label`, href: element.url, target: "_blank", rel: "noreferrer" }, element.url)),
105
+ React.createElement(Button, { className: `${baseClass}__link-edit`, icon: "edit", round: true, buttonStyle: "icon-label", onClick: (e) => {
106
+ e.preventDefault();
107
+ setRenderPopup(false);
108
+ openModal(modalSlug);
109
+ setRenderModal(true);
110
+ }, tooltip: "Edit" }),
111
+ React.createElement(Button, { className: `${baseClass}__link-close`, icon: "x", round: true, buttonStyle: "icon-label", onClick: (e) => {
112
+ e.preventDefault();
113
+ unwrapLink(editor);
114
+ }, tooltip: "Remove" })));
115
+ } })),
116
+ React.createElement("span", { tabIndex: 0, role: "button", className: [
117
+ `${baseClass}__button`,
118
+ ].filter(Boolean).join(' '), onKeyDown: (e) => { if (e.key === 'Enter')
119
+ setRenderPopup(true); }, onClick: () => setRenderPopup(true) }, children)));
120
+ };
@@ -0,0 +1,3 @@
1
+ import { Config } from '../../../../../../../../config/types';
2
+ import { Field } from '../../../../../../../../fields/config/types';
3
+ export declare const getBaseFields: (config: Config) => Field[];
@@ -0,0 +1,56 @@
1
+ export const getBaseFields = (config) => [
2
+ {
3
+ name: 'text',
4
+ label: 'Text to display',
5
+ type: 'text',
6
+ required: true,
7
+ },
8
+ {
9
+ name: 'linkType',
10
+ label: 'Link Type',
11
+ type: 'radio',
12
+ required: true,
13
+ admin: {
14
+ description: 'Choose between entering a custom text URL or linking to another document.',
15
+ },
16
+ defaultValue: 'custom',
17
+ options: [
18
+ {
19
+ label: 'Custom URL',
20
+ value: 'custom',
21
+ },
22
+ {
23
+ label: 'Internal Link',
24
+ value: 'internal',
25
+ },
26
+ ],
27
+ },
28
+ {
29
+ name: 'url',
30
+ label: 'Enter a URL',
31
+ type: 'text',
32
+ required: true,
33
+ admin: {
34
+ condition: ({ linkType, url }) => {
35
+ return (typeof linkType === 'undefined' && url) || linkType === 'custom';
36
+ },
37
+ },
38
+ },
39
+ {
40
+ name: 'doc',
41
+ label: 'Choose a document to link to',
42
+ type: 'relationship',
43
+ required: true,
44
+ relationTo: config.collections.map(({ slug }) => slug),
45
+ admin: {
46
+ condition: ({ linkType }) => {
47
+ return linkType === 'internal';
48
+ },
49
+ },
50
+ },
51
+ {
52
+ name: 'newTab',
53
+ label: 'Open in new tab',
54
+ type: 'checkbox',
55
+ },
56
+ ];
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import { Props } from './types';
3
+ import './index.scss';
4
+ export declare const EditModal: React.FC<Props>;
@@ -0,0 +1,22 @@
1
+ import { Modal } from '@faceless-ui/modal';
2
+ import React from 'react';
3
+ import { MinimalTemplate } from '../../../../../..';
4
+ import Button from '../../../../../../elements/Button';
5
+ import X from '../../../../../../icons/X';
6
+ import Form from '../../../../../Form';
7
+ import FormSubmit from '../../../../../Submit';
8
+ import fieldTypes from '../../../..';
9
+ import RenderFields from '../../../../../RenderFields';
10
+ import './index.scss';
11
+ const baseClass = 'rich-text-link-edit-modal';
12
+ export const EditModal = ({ close, handleModalSubmit, initialState, fieldSchema, modalSlug, }) => {
13
+ return (React.createElement(Modal, { slug: modalSlug, className: baseClass },
14
+ React.createElement(MinimalTemplate, { className: `${baseClass}__template` },
15
+ React.createElement("header", { className: `${baseClass}__header` },
16
+ React.createElement("h3", null, "Edit Link"),
17
+ React.createElement(Button, { buttonStyle: "none", onClick: close },
18
+ React.createElement(X, null))),
19
+ React.createElement(Form, { onSubmit: handleModalSubmit, initialState: initialState },
20
+ React.createElement(RenderFields, { fieldTypes: fieldTypes, readOnly: false, fieldSchema: fieldSchema, forceRender: true }),
21
+ React.createElement(FormSubmit, null, "Confirm")))));
22
+ };
@@ -0,0 +1,29 @@
1
+ @import '../../../../../../../scss/styles.scss';
2
+
3
+ .rich-text-link-edit-modal {
4
+ @include blur-bg;
5
+ display: flex;
6
+ align-items: center;
7
+ height: 100%;
8
+
9
+ &__template {
10
+ position: relative;
11
+ z-index: 1;
12
+ }
13
+
14
+ &__header {
15
+ width: 100%;
16
+ margin-bottom: $baseline;
17
+ display: flex;
18
+ justify-content: space-between;
19
+
20
+ h3 {
21
+ margin: 0;
22
+ }
23
+
24
+ svg {
25
+ width: base(1.5);
26
+ height: base(1.5);
27
+ }
28
+ }
29
+ }
@@ -0,0 +1,9 @@
1
+ import { Field } from '../../../../../../../../fields/config/types';
2
+ import { Fields } from '../../../../../Form/types';
3
+ export declare type Props = {
4
+ modalSlug: string;
5
+ close: () => void;
6
+ handleModalSubmit: (fields: Fields, data: Record<string, unknown>) => void;
7
+ initialState?: Fields;
8
+ fieldSchema: Field[];
9
+ };
@@ -1,14 +1,15 @@
1
1
  /// <reference types="react" />
2
- import { ReactEditor } from 'slate-react';
3
- import './index.scss';
4
2
  declare const link: {
5
- Button: () => JSX.Element;
6
- Element: ({ attributes, children, element, editorRef }: {
3
+ Button: ({ fieldProps }: {
4
+ fieldProps: any;
5
+ }) => JSX.Element;
6
+ Element: ({ attributes, children, element, editorRef, fieldProps }: {
7
7
  attributes: any;
8
8
  children: any;
9
9
  element: any;
10
10
  editorRef: any;
11
+ fieldProps: any;
11
12
  }) => JSX.Element;
12
- plugins: ((incomingEditor: import("slate").BaseEditor & ReactEditor & import("slate-history").HistoryEditor & import("../../types").BlurSelectionEditor) => import("slate").BaseEditor & ReactEditor & import("slate-history").HistoryEditor & import("../../types").BlurSelectionEditor)[];
13
+ plugins: ((incomingEditor: import("slate").BaseEditor & import("slate-react").ReactEditor & import("slate-history").HistoryEditor) => import("slate").BaseEditor & import("slate-react").ReactEditor & import("slate-history").HistoryEditor)[];
13
14
  };
14
15
  export default link;
@@ -1,72 +1,9 @@
1
- import React, { Fragment, useCallback, useState } from 'react';
2
- import { ReactEditor, useSlate } from 'slate-react';
3
- import { Transforms } from 'slate';
4
- import ElementButton from '../Button';
5
- import { withLinks, wrapLink } from './utilities';
6
- import LinkIcon from '../../../../../icons/Link';
7
- import Popup from '../../../../../elements/Popup';
8
- import Button from '../../../../../elements/Button';
9
- import Check from '../../../../../icons/Check';
10
- import Error from '../../../../Error';
11
- import './index.scss';
12
- const baseClass = 'rich-text-link';
13
- const Link = ({ attributes, children, element, editorRef }) => {
14
- const editor = useSlate();
15
- const [error, setError] = useState(false);
16
- const [open, setOpen] = useState(element.url === undefined);
17
- const handleToggleOpen = useCallback((newOpen) => {
18
- setOpen(newOpen);
19
- if (element.url === undefined && !newOpen) {
20
- const path = ReactEditor.findPath(editor, element);
21
- Transforms.setNodes(editor, { url: '' }, { at: path });
22
- }
23
- }, [editor, element]);
24
- return (React.createElement("span", { className: baseClass, ...attributes },
25
- React.createElement("span", { style: { userSelect: 'none' }, contentEditable: false },
26
- React.createElement(Popup, { initActive: element.url === undefined, buttonType: "none", size: "small", horizontalAlign: "center", forceOpen: open, onToggleOpen: handleToggleOpen, boundingRef: editorRef, render: ({ close }) => (React.createElement(Fragment, null,
27
- React.createElement("div", { className: `${baseClass}__url-wrap` },
28
- React.createElement("input", { value: element.url || '', className: `${baseClass}__url`, placeholder: "Enter a URL", onChange: (e) => {
29
- const { value } = e.target;
30
- if (value && error) {
31
- setError(false);
32
- }
33
- const path = ReactEditor.findPath(editor, element);
34
- Transforms.setNodes(editor, { url: value }, { at: path });
35
- }, onKeyDown: (e) => {
36
- if (e.key === 'Enter') {
37
- e.preventDefault();
38
- close();
39
- }
40
- } }),
41
- React.createElement(Button, { className: `${baseClass}__confirm`, buttonStyle: "none", icon: "chevron", onClick: (e) => {
42
- e.preventDefault();
43
- if (element.url) {
44
- close();
45
- }
46
- else {
47
- setError(true);
48
- }
49
- } }),
50
- error && (React.createElement(Error, { showError: error, message: "Please enter a valid URL." }))),
51
- React.createElement(Button, { className: [`${baseClass}__new-tab`, element.newTab && `${baseClass}__new-tab--checked`].filter(Boolean).join(' '), buttonStyle: "none", onClick: () => {
52
- const path = ReactEditor.findPath(editor, element);
53
- Transforms.setNodes(editor, { newTab: !element.newTab }, { at: path });
54
- } },
55
- React.createElement(Check, null),
56
- "Open link in new tab"))) })),
57
- React.createElement("button", { className: [
58
- `${baseClass}__button`,
59
- open && `${baseClass}__button--open`,
60
- ].filter(Boolean).join(' '), type: "button", onClick: () => setOpen(true) }, children)));
61
- };
62
- const LinkButton = () => {
63
- const editor = useSlate();
64
- return (React.createElement(ElementButton, { format: "link", onClick: () => wrapLink(editor) },
65
- React.createElement(LinkIcon, null)));
66
- };
1
+ import { withLinks } from './utilities';
2
+ import { LinkButton } from './Button';
3
+ import { LinkElement } from './Element';
67
4
  const link = {
68
5
  Button: LinkButton,
69
- Element: Link,
6
+ Element: LinkElement,
70
7
  plugins: [
71
8
  withLinks,
72
9
  ],