@contentful/field-editor-rich-text 2.0.0-next.2 → 2.0.0-next.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/field-editor-rich-text.cjs.development.js +133 -116
  2. package/dist/field-editor-rich-text.cjs.development.js.map +1 -1
  3. package/dist/field-editor-rich-text.cjs.production.min.js +1 -1
  4. package/dist/field-editor-rich-text.cjs.production.min.js.map +1 -1
  5. package/dist/field-editor-rich-text.esm.js +23 -6
  6. package/dist/field-editor-rich-text.esm.js.map +1 -1
  7. package/dist/helpers/deserializer.d.ts +1 -1
  8. package/dist/helpers/editor.d.ts +1 -1
  9. package/dist/plugins/Bold/index.d.ts +1 -1
  10. package/dist/plugins/Code/index.d.ts +1 -1
  11. package/dist/plugins/DragAndDrop/index.d.ts +1 -1
  12. package/dist/plugins/EmbeddedEntityBlock/index.d.ts +1 -1
  13. package/dist/plugins/EmbeddedEntityInline/index.d.ts +1 -1
  14. package/dist/plugins/Heading/index.d.ts +1 -1
  15. package/dist/plugins/Hr/index.d.ts +1 -1
  16. package/dist/plugins/Hyperlink/HyperlinkModal.d.ts +1 -1
  17. package/dist/plugins/Hyperlink/index.d.ts +1 -1
  18. package/dist/plugins/InsertBeforeFirstVoidBlock/index.d.ts +1 -1
  19. package/dist/plugins/Italic/index.d.ts +1 -1
  20. package/dist/plugins/List/getListInsertFragment.d.ts +1 -1
  21. package/dist/plugins/List/index.d.ts +1 -1
  22. package/dist/plugins/NewLine/index.d.ts +1 -1
  23. package/dist/plugins/Paragraph/index.d.ts +1 -1
  24. package/dist/plugins/Paste/index.d.ts +1 -1
  25. package/dist/plugins/Paste/sanitizers/helpers.d.ts +1 -1
  26. package/dist/plugins/Quote/index.d.ts +1 -1
  27. package/dist/plugins/Table/actions/addColumn.d.ts +2 -1
  28. package/dist/plugins/Table/actions/addRow.d.ts +1 -1
  29. package/dist/plugins/Table/actions/setHeader.d.ts +1 -1
  30. package/dist/plugins/Table/helpers.d.ts +1 -1
  31. package/dist/plugins/Table/index.d.ts +168 -168
  32. package/dist/plugins/Table/normalizers.d.ts +1 -1
  33. package/dist/plugins/Text/index.d.ts +1 -1
  34. package/dist/plugins/TrailingParagraph/index.d.ts +1 -1
  35. package/dist/plugins/Underline/index.d.ts +1 -1
  36. package/dist/plugins/index.d.ts +171 -171
  37. package/dist/test-utils/createEditor.d.ts +1 -1
  38. package/dist/types.d.ts +1 -1
  39. package/package.json +14 -5
@@ -1 +1 @@
1
- {"version":3,"file":"field-editor-rich-text.cjs.production.min.js","sources":["../src/RichTextEditor.styles.ts","../src/constants/Schema.ts","../src/plugins/shared/ToolbarButton.tsx","../src/helpers/editor.ts","../src/helpers/deserializer.ts","../src/ContentfulEditorProvider.ts","../src/plugins/Hr/index.tsx","../src/helpers/validations.ts","../src/SdkProvider.tsx","../src/plugins/Heading/index.tsx","../src/plugins/Quote/index.tsx","../src/plugins/List/index.tsx","../src/plugins/List/getListInsertFragment.ts","../src/plugins/Bold/index.tsx","../src/plugins/Code/index.tsx","../src/plugins/Italic/index.tsx","../src/plugins/Underline/index.tsx","../../../node_modules/regenerator-runtime/runtime.js","../src/plugins/Hyperlink/EntryAssetTooltip.tsx","../src/helpers/truncate.ts","../src/plugins/shared/EntityStatusIcon.tsx","../src/plugins/shared/FetchingWrappedEntryCard.tsx","../src/plugins/shared/FetchingWrappedAssetCard.tsx","../src/helpers/getLinkedContentTypeIdsForNodeType.ts","../src/plugins/Hyperlink/HyperlinkModal.tsx","../src/plugins/Hyperlink/index.tsx","../src/plugins/Table/helpers.ts","../src/TrackingProvider.tsx","../src/plugins/Table/actions/addRow.ts","../src/plugins/Table/actions/addColumn.ts","../src/plugins/Table/TableActions.tsx","../src/plugins/Table/actions/setHeader.ts","../src/helpers/normalizers.ts","../src/plugins/Table/normalizers.ts","../src/plugins/Table/index.tsx","../src/plugins/EmbeddedEntity/index.tsx","../src/helpers/environment.ts","../src/plugins/EmbeddedEntityBlock/LinkedEntityBlock.tsx","../src/helpers/newEntitySelectorConfigFromRichTextField.ts","../src/plugins/EmbeddedEntityBlock/Util.ts","../src/plugins/EmbeddedEntityBlock/ToolbarIcon.tsx","../src/plugins/EmbeddedEntityBlock/index.tsx","../src/plugins/EmbeddedEntityInline/FetchingWrappedInlineEntryCard.tsx","../src/plugins/EmbeddedEntityInline/Util.ts","../src/plugins/EmbeddedEntityInline/index.tsx","../src/Toolbar/EmbedEntityWidget.tsx","../src/Toolbar/index.tsx","../src/Toolbar/StickyToolbarWrapper.tsx","../src/helpers/sanitizeSlateDoc.ts","../src/plugins/Paste/sanitizers/helpers.tsx","../src/plugins/Paste/sanitizers/removeComments.tsx","../src/plugins/Paste/sanitizers/sanitizeTables.tsx","../src/plugins/Paste/index.tsx","../src/plugins/Paste/sanitizers/sanitizeEntityBlocks.tsx","../src/plugins/Paragraph/index.tsx","../src/plugins/index.ts","../src/RichTextEditor.tsx","../src/plugins/DragAndDrop/index.tsx","../src/plugins/NewLine/index.tsx","../src/plugins/InsertBeforeFirstVoidBlock/index.tsx","../src/plugins/TrailingParagraph/index.ts","../src/plugins/Text/index.ts","../src/dialogs/HypelinkDialog/HyperlinkDialog.jsx","../src/dialogs/openRichTextDialog.tsx","../src/dialogs/renderRichTextDialog.tsx"],"sourcesContent":["import { css } from 'emotion';\nimport tokens from '@contentful/f36-tokens';\n\nconst STYLE_EDITOR_BORDER = `1px solid ${tokens.gray400}`;\n\nexport const styles = {\n root: css({\n position: 'relative',\n }),\n editor: css({\n borderRadius: `0 0 ${tokens.borderRadiusMedium} ${tokens.borderRadiusMedium}`,\n border: STYLE_EDITOR_BORDER,\n borderTop: 0,\n padding: '20px',\n fontSize: tokens.spacingM,\n fontFamily: tokens.fontStackPrimary,\n minHeight: '400px',\n background: tokens.colorWhite,\n outline: 'none',\n whiteSpace: 'pre-wrap',\n overflowWrap: 'break-word',\n webkitUserModify: 'read-write-plaintext-only',\n a: {\n span: {\n cursor: 'not-allowed',\n '&:hover': {\n cursor: 'not-allowed',\n },\n },\n },\n // We need to reset LIC style due to conflicts between PARAGRAPH styles\n 'ul > li > div': {\n margin: 0,\n },\n }),\n hiddenToolbar: css({\n borderTop: STYLE_EDITOR_BORDER,\n }),\n enabled: css({\n background: tokens.colorWhite,\n a: {\n span: {\n cursor: 'pointer',\n '&:hover': {\n cursor: 'pointer',\n },\n },\n },\n }),\n disabled: css({\n background: tokens.gray100,\n }),\n};\n","import {\n BLOCKS,\n INLINES,\n TOP_LEVEL_BLOCKS,\n VOID_BLOCKS,\n CONTAINERS,\n} from '@contentful/rich-text-types';\n\nconst inlines = Object.values(INLINES).map((type) => ({ type }));\n\nexport default {\n document: {\n nodes: [\n {\n types: TOP_LEVEL_BLOCKS.map((type) => ({ type })),\n },\n ],\n },\n\n blocks: {\n [BLOCKS.PARAGRAPH]: {\n nodes: [\n {\n match: [...inlines, { object: 'text' }],\n },\n ],\n },\n [BLOCKS.HEADING_1]: {\n nodes: [\n {\n match: [...inlines, { object: 'text' }],\n },\n ],\n },\n [BLOCKS.HEADING_2]: {\n nodes: [\n {\n match: [...inlines, { object: 'text' }],\n },\n ],\n },\n [BLOCKS.HEADING_3]: {\n nodes: [\n {\n match: [...inlines, { object: 'text' }],\n },\n ],\n },\n [BLOCKS.HEADING_4]: {\n nodes: [\n {\n match: [...inlines, { object: 'text' }],\n },\n ],\n },\n [BLOCKS.HEADING_5]: {\n nodes: [\n {\n match: [...inlines, { object: 'text' }],\n },\n ],\n },\n [BLOCKS.HEADING_6]: {\n nodes: [\n {\n match: [...inlines, { object: 'text' }],\n },\n ],\n },\n\n ...VOID_BLOCKS.reduce(\n (blocks, nodeType) => ({\n ...blocks,\n [nodeType]: { isVoid: true },\n }),\n {}\n ),\n\n // TODO: add list schema\n\n [BLOCKS.QUOTE]: {\n nodes: [\n {\n match: [CONTAINERS[BLOCKS.QUOTE].map((type) => ({ type }))],\n min: 1,\n },\n ],\n normalize: (editor, error) => {\n if (error.code === 'child_type_invalid') {\n return editor.unwrapBlockByKey(error.node.key, BLOCKS.QUOTE);\n }\n },\n },\n },\n\n inlines: {\n [INLINES.HYPERLINK]: {\n nodes: [\n {\n match: [{ object: 'text' }],\n },\n ],\n },\n [INLINES.ENTRY_HYPERLINK]: {\n nodes: [\n {\n match: [{ object: 'text' }],\n },\n ],\n },\n [INLINES.ASSET_HYPERLINK]: {\n nodes: [\n {\n match: [{ object: 'text' }],\n },\n ],\n },\n [INLINES.EMBEDDED_ENTRY]: {\n isVoid: true,\n },\n },\n};\n","import React from 'react';\nimport { css, cx } from 'emotion';\nimport { Button, Tooltip } from '@contentful/f36-components';\nimport tokens from '@contentful/f36-tokens';\n\nconst styles = {\n button: css({\n height: '30px',\n width: '30px',\n marginLeft: tokens.spacing2Xs,\n marginRight: tokens.spacing2Xs,\n }),\n\n tooltip: css({\n zIndex: Number(tokens.zIndexTooltip),\n }),\n};\n\ninterface ToolbarButtonProps {\n onClick: () => void;\n isActive?: boolean;\n isDisabled?: boolean;\n children: any;\n title: string;\n className?: string;\n testId?: string;\n}\n\nexport function ToolbarButton(props: ToolbarButtonProps) {\n const { title, testId, isActive, children, className, isDisabled = false } = props;\n const handleClick = (event) => {\n event.preventDefault();\n props.onClick();\n };\n\n const button = (\n <Button\n className={cx(styles.button, className)}\n isDisabled={isDisabled}\n startIcon={children}\n onClick={handleClick}\n testId={testId}\n variant={isActive ? 'secondary' : 'transparent'}\n size=\"small\"\n />\n );\n\n if (title) {\n return (\n <Tooltip className={styles.tooltip} placement=\"bottom\" content={title}>\n {button}\n </Tooltip>\n );\n }\n\n return button;\n}\n","import { PlateEditor, getText } from '@udecode/plate';\nimport { Link } from '@contentful/field-editor-reference/dist/types';\nimport { Text, Editor, Element, Transforms, Path, Range, Node, Location } from 'slate';\nimport { BLOCKS, INLINES, TABLE_BLOCKS, TEXT_CONTAINERS } from '@contentful/rich-text-types';\n\nimport { CustomElement } from '../types';\n\nexport const LINK_TYPES: INLINES[] = [\n INLINES.HYPERLINK,\n INLINES.ENTRY_HYPERLINK,\n INLINES.ASSET_HYPERLINK,\n];\n\nconst LIST_TYPES: BLOCKS[] = [BLOCKS.OL_LIST, BLOCKS.UL_LIST];\n\nexport function isBlockSelected(editor, type: string): boolean {\n const [match] = Array.from(\n Editor.nodes(editor, {\n match: (node) => Element.isElement(node) && (node as CustomElement).type === type,\n })\n );\n return !!match;\n}\n\nexport function isVoid(editor, element): boolean {\n const { isVoid: originalIsVoid } = editor;\n\n return element.isVoid || originalIsVoid(element);\n}\n\nexport function hasSelectionText(editor) {\n return editor.selection\n ? Editor.node(editor, editor.selection.focus.path).some(\n (node) => Text.isText(node) && node.text !== ''\n )\n : false;\n}\n\ntype NodeEntry = [CustomElement, Path];\ntype NodeType = BLOCKS | INLINES;\nexport function getNodeEntryFromSelection(\n editor,\n nodeTypeOrTypes: NodeType | NodeType[]\n): NodeEntry | [] {\n if (!editor.selection) return [];\n const nodeTypes = Array.isArray(nodeTypeOrTypes) ? nodeTypeOrTypes : [nodeTypeOrTypes];\n const { path } = editor.selection.focus;\n for (let i = 0; i < path.length; i++) {\n const nodeEntry = Editor.node(editor, path.slice(0, i + 1)) as NodeEntry;\n if (nodeTypes.includes(nodeEntry[0].type as NodeType)) return nodeEntry;\n }\n return [];\n}\n\nexport function isNodeTypeSelected(editor, nodeType: BLOCKS | INLINES): boolean {\n if (!editor) return false;\n const [node] = getNodeEntryFromSelection(editor, nodeType);\n return !!node;\n}\n\nexport function moveToTheNextLine(editor) {\n Transforms.move(editor, { distance: 1, unit: 'line' });\n}\n\nexport function moveToThePreviousLine(editor) {\n Transforms.move(editor, { distance: 1, unit: 'line', reverse: true });\n}\n\nexport function toggleBlock(editor, type: string): void {\n const isActive = isBlockSelected(editor, type);\n const isList = LIST_TYPES.includes(type as BLOCKS);\n const isQuote = type === BLOCKS.QUOTE;\n\n Transforms.unwrapNodes(editor, {\n match: (node) => {\n if (Editor.isEditor(node) || !Element.isElement(node)) {\n return false;\n }\n\n // Lists\n if (isList && LIST_TYPES.includes((node as CustomElement).type as BLOCKS)) {\n return true;\n }\n\n // Quotes\n if (isQuote && (node as CustomElement).type === BLOCKS.QUOTE) {\n return true;\n }\n\n return false;\n },\n split: true,\n });\n const newProperties: Partial<CustomElement> = {\n type: isActive\n ? BLOCKS.PARAGRAPH\n : isList\n ? BLOCKS.LIST_ITEM\n : isQuote\n ? BLOCKS.PARAGRAPH\n : type,\n };\n Transforms.setNodes(editor, newProperties);\n\n if (!isActive && (isList || isQuote)) {\n const block = {\n type,\n data: {},\n children: [],\n };\n Transforms.wrapNodes(editor, block);\n }\n}\n\nexport function getElementFromCurrentSelection(editor) {\n if (!editor.selection) return [];\n\n return Array.from(\n Editor.nodes(editor, {\n at: editor.selection.focus,\n match: (node) => Element.isElement(node),\n })\n ).flat();\n}\n\nexport function isList(editor) {\n const element = getElementFromCurrentSelection(editor);\n\n return element.some(\n (element) =>\n Element.isElement(element) && LIST_TYPES.includes((element as CustomElement).type as BLOCKS)\n );\n}\n\nexport function getTableSize(\n table: CustomElement\n): Record<'numRows' | 'numColumns', number> | null {\n const numRows = table.children.length;\n if (!numRows) return null;\n const [firstRow] = table.children;\n const numColumns = (firstRow as CustomElement).children?.length;\n return { numRows, numColumns };\n}\n\nexport function isFirstChild(path: Path) {\n return path[path.length - 1] === 0;\n}\n\ninterface InsertLinkOptions {\n text: string;\n type: INLINES.HYPERLINK | INLINES.ENTRY_HYPERLINK | INLINES.ASSET_HYPERLINK;\n url?: string;\n target?: Link;\n path?: Path;\n}\n\nexport function insertLink(editor, options: InsertLinkOptions) {\n if (editor.selection) {\n wrapLink(editor, options);\n }\n}\n\nexport function isLinkActive(editor) {\n const [link] = Array.from(\n Editor.nodes(editor, {\n match: (node) =>\n !Editor.isEditor(node) &&\n Element.isElement(node) &&\n LINK_TYPES.includes((node as CustomElement).type as INLINES),\n })\n );\n return !!link;\n}\n\nexport function unwrapLink(editor) {\n Transforms.unwrapNodes(editor, {\n match: (node) =>\n !Editor.isEditor(node) &&\n Element.isElement(node) &&\n LINK_TYPES.includes((node as CustomElement).type as INLINES),\n });\n}\n\nexport function wrapLink(editor, { text, url, target, type, path }: InsertLinkOptions) {\n if (isLinkActive(editor) && !path) {\n unwrapLink(editor);\n }\n\n const { selection } = editor;\n const isCollapsed = selection && Range.isCollapsed(selection);\n const link = {\n type,\n data: {},\n children: isCollapsed ? [{ text }] : [],\n };\n\n if (url) {\n link.data = { uri: url };\n }\n\n if (target) {\n link.data = { target };\n }\n\n // TODO: always set the selection to the end of the inserted link\n if (path) {\n Transforms.setNodes(editor, link, { at: path });\n Transforms.insertText(editor, text, { at: path });\n Transforms.select(editor, path);\n } else if (isCollapsed) {\n Transforms.insertNodes(editor, link);\n } else {\n Transforms.wrapNodes(editor, link, { split: true });\n Transforms.delete(editor);\n Transforms.insertText(editor, text);\n Transforms.collapse(editor, { edge: 'end' });\n }\n}\n\nexport function getAncestorPathFromSelection(editor: PlateEditor) {\n if (!editor.selection) return undefined;\n\n return Path.levels(editor.selection.focus.path).find((level) => level.length === 1);\n}\n\nexport function shouldUnwrapBlockquote(editor: PlateEditor, type: BLOCKS) {\n const isQuoteSelected = isBlockSelected(editor, BLOCKS.QUOTE);\n const isValidType = [\n BLOCKS.HEADING_1,\n BLOCKS.HEADING_2,\n BLOCKS.HEADING_3,\n BLOCKS.HEADING_4,\n BLOCKS.HEADING_5,\n BLOCKS.HEADING_6,\n\n BLOCKS.OL_LIST,\n BLOCKS.UL_LIST,\n\n BLOCKS.HR,\n ].includes(type);\n\n return isQuoteSelected && isValidType;\n}\n\nexport function unwrapFromRoot(editor: PlateEditor) {\n const ancestorPath = getAncestorPathFromSelection(editor);\n Transforms.unwrapNodes(editor, { at: ancestorPath });\n}\n\nexport const isAtEndOfTextSelection = (editor: PlateEditor) =>\n editor.selection?.focus.offset === getText(editor, editor.selection?.focus.path).length;\n\nexport function currentSelectionStartsTableCell(editor: PlateEditor): boolean {\n const [tableCellNode, path] = getNodeEntryFromSelection(editor, [\n BLOCKS.TABLE_CELL,\n BLOCKS.TABLE_HEADER_CELL,\n ]);\n return !!tableCellNode && (!getText(editor, path) || editor.selection?.focus.offset === 0);\n}\n\n/**\n * This traversal strategy is unfortunately necessary because Slate doesn't\n * expose something like Node.next(editor).\n */\nexport function getNextNode(editor: PlateEditor): CustomElement | null {\n if (!editor.selection) {\n return null;\n }\n const descendants = Node.descendants(editor, { from: editor.selection.focus.path });\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const { done, value } = descendants.next();\n if (done) {\n return null;\n }\n const [node, path] = value as NodeEntry;\n if (Path.isCommon(path, editor.selection.focus.path)) {\n continue;\n }\n return node as CustomElement;\n }\n}\n\nexport function currentSelectionPrecedesTableCell(editor: PlateEditor): boolean {\n const nextNode = getNextNode(editor);\n return (\n !!nextNode && TABLE_BLOCKS.includes(nextNode.type as BLOCKS) && isAtEndOfTextSelection(editor)\n );\n}\n\nexport const replaceNode = (editor: Editor, path: Location, replacement: Node | Node[]) => {\n Transforms.removeNodes(editor, { at: path });\n Transforms.insertNodes(editor, replacement, { at: path });\n};\n\n/**\n * It filters out all paragraphs and headings from a path and convert them into paragraphs.\n */\nexport function extractParagraphsAt(editor: PlateEditor, path: Path): CustomElement[] {\n const paragraphs: CustomElement[] = Array.from(\n Editor.nodes<CustomElement>(editor, {\n at: path,\n match: (node) => TEXT_CONTAINERS.includes((node as CustomElement).type as BLOCKS),\n mode: 'all',\n })\n ).map(([node]) => ({\n ...node,\n type: BLOCKS.PARAGRAPH,\n }));\n\n return paragraphs;\n}\n","import {\n getPlatePluginOptions,\n PlateEditor,\n Deserialize,\n GetNodeDeserializerRule,\n getLeafDeserializer,\n getElementDeserializer,\n} from '@udecode/plate';\n\nexport function deserializeLeaf(type: string, rules: GetNodeDeserializerRule[]): Deserialize {\n return function (editor: PlateEditor) {\n const pluginOptions = getPlatePluginOptions(editor, type);\n\n return {\n leaf: getLeafDeserializer({\n type,\n rules,\n ...pluginOptions.deserialize,\n }),\n };\n };\n}\n\nexport function deserializeElement(type: string, rules: GetNodeDeserializerRule[]): Deserialize {\n return function (editor: PlateEditor) {\n const pluginOptions = getPlatePluginOptions(editor, type);\n\n return {\n element: getElementDeserializer({\n type,\n rules,\n ...pluginOptions.deserialize,\n }),\n };\n };\n}\n","import constate from 'constate';\nimport { usePlateEditorRef } from '@udecode/plate';\nimport { FieldExtensionSDK } from '@contentful/app-sdk';\n\nexport function getContentfulEditorId(sdk: FieldExtensionSDK) {\n const { entry, field } = sdk;\n const entryId = entry.getSys().id;\n\n return `rich-text-editor-${entryId}-${field.id}-${field.locale}`;\n}\n\ninterface useContentfulEditorHookProps {\n sdk: FieldExtensionSDK;\n}\n\nfunction useContentfulEditorHook({ sdk }: useContentfulEditorHookProps) {\n const editorId = getContentfulEditorId(sdk);\n const editor = usePlateEditorRef(editorId);\n\n return editor;\n}\n\nexport const [ContentfulEditorProvider, useContentfulEditor] = constate(useContentfulEditorHook);\n","import * as React from 'react';\nimport * as Slate from 'slate-react';\nimport { css, cx } from 'emotion';\nimport tokens from '@contentful/f36-tokens';\nimport { HorizontalRuleIcon } from '@contentful/f36-icons';\nimport { ToolbarButton } from '../shared/ToolbarButton';\nimport { Transforms } from 'slate';\nimport { BLOCKS } from '@contentful/rich-text-types';\nimport {\n getPlatePluginTypes,\n getRenderElement,\n PlatePlugin,\n PlateEditor,\n getText,\n setNodes,\n} from '@udecode/plate';\nimport {\n getNodeEntryFromSelection,\n isBlockSelected,\n moveToTheNextLine,\n shouldUnwrapBlockquote,\n unwrapFromRoot,\n} from '../../helpers/editor';\nimport { CustomSlatePluginOptions } from '../../types';\nimport { deserializeElement } from '../../helpers/deserializer';\nimport { useContentfulEditor } from '../../ContentfulEditorProvider';\n\nconst styles = {\n container: css`\n margin: 0 0 ${tokens.spacingL};\n `,\n hr: css`\n margin: 0;\n height: ${tokens.spacingM};\n background: transparent;\n position: relative;\n border: 0;\n user-select: none;\n &:hover {\n cursor: pointer;\n }\n &::after {\n content: '';\n position: absolute;\n width: 100%;\n height: 1px;\n background: ${tokens.gray300};\n top: 50%;\n }\n `,\n hrSelected: css`\n &::after {\n background: ${tokens.colorPrimary};\n -webkit-box-shadow: 0px 0px 5px ${tokens.colorPrimary};\n box-shadow: 0px 0px 5px ${tokens.colorPrimary};\n }\n `,\n};\n\ninterface ToolbarHrButtonProps {\n isDisabled?: boolean;\n}\n\nexport function withHrEvents(editor: PlateEditor) {\n return (event: React.KeyboardEvent) => {\n if (!editor) return;\n\n const isEnter = event.keyCode === 13;\n const [, pathToSelectedHr] = getNodeEntryFromSelection(editor, BLOCKS.HR);\n\n if (pathToSelectedHr) {\n if (shouldUnwrapBlockquote(editor, BLOCKS.HR)) {\n unwrapFromRoot(editor);\n }\n\n if (isEnter) {\n event.preventDefault();\n moveToTheNextLine(editor);\n } else if (event.key === 'Backspace') {\n event.preventDefault();\n Transforms.removeNodes(editor, { at: pathToSelectedHr });\n }\n }\n };\n}\n\nexport function ToolbarHrButton(props: ToolbarHrButtonProps) {\n const editor = useContentfulEditor();\n\n function handleOnClick() {\n if (!editor?.selection) return;\n\n if (shouldUnwrapBlockquote(editor, BLOCKS.HR)) {\n unwrapFromRoot(editor);\n }\n\n const hr = {\n type: BLOCKS.HR,\n data: {},\n children: [{ text: '' }],\n isVoid: true,\n };\n\n const hasText = !!getText(editor, editor.selection.focus.path);\n hasText ? Transforms.insertNodes(editor, hr) : setNodes(editor, hr);\n\n // Move focus to the next paragraph (added by TrailingParagraph plugin)\n moveToTheNextLine(editor);\n\n Slate.ReactEditor.focus(editor);\n }\n\n if (!editor) return null;\n\n return (\n <ToolbarButton\n title=\"HR\"\n isDisabled={props.isDisabled}\n onClick={handleOnClick}\n testId=\"hr-toolbar-button\"\n isActive={isBlockSelected(editor, BLOCKS.HR)}>\n <HorizontalRuleIcon />\n </ToolbarButton>\n );\n}\n\nexport function Hr(props: Slate.RenderLeafProps) {\n const isSelected = Slate.useSelected();\n const isFocused = Slate.useFocused();\n\n return (\n <div {...props.attributes} className={styles.container}>\n <div contentEditable={false}>\n <hr className={cx(styles.hr, isSelected && isFocused ? styles.hrSelected : undefined)} />\n </div>\n {props.children}\n </div>\n );\n}\n\nexport function createHrPlugin(): PlatePlugin {\n return {\n renderElement: getRenderElement(BLOCKS.HR),\n pluginKeys: BLOCKS.HR,\n onKeyDown: withHrEvents,\n voidTypes: getPlatePluginTypes(BLOCKS.HR),\n deserialize: deserializeElement(BLOCKS.HR, [\n {\n nodeNames: ['HR'],\n },\n ]),\n };\n}\n\nexport const withHrOptions: CustomSlatePluginOptions = {\n [BLOCKS.HR]: {\n type: BLOCKS.HR,\n component: Hr,\n },\n};\n","/* eslint-disable you-dont-need-lodash-underscore/find */\nimport find from 'lodash/find';\nimport flow from 'lodash/flow';\nimport get from 'lodash/get';\nimport { BLOCKS, INLINES, TOP_LEVEL_BLOCKS } from '@contentful/rich-text-types';\nimport { FieldExtensionSDK } from '@contentful/app-sdk';\n\n// TODO: Move these into separate package (maybe rich-text-types) and share with FE.\nexport const VALIDATIONS = {\n ENABLED_MARKS: 'enabledMarks',\n ENABLED_NODE_TYPES: 'enabledNodeTypes',\n};\nexport const DEFAULT_ENABLED_NODE_TYPES = [BLOCKS.DOCUMENT, BLOCKS.PARAGRAPH, 'text'];\n\nexport const VALIDATABLE_NODE_TYPES = ([] as Array<BLOCKS | INLINES>)\n .concat(TOP_LEVEL_BLOCKS)\n .filter((type) => type !== BLOCKS.PARAGRAPH)\n .concat(Object.values(INLINES));\n\n// TODO: Memoize\nconst getRichTextValidation = (field, validationType) =>\n flow(\n (v) => find(v, validationType),\n (v) => get(v, validationType)\n )(field.validations);\n\nconst isFormattingOptionEnabled = (field, validationType, nodeTypeOrMark) => {\n const enabledFormattings = getRichTextValidation(field, validationType);\n\n // TODO: In the future, validations will always be opt-in. In that case\n // we don't need this step.\n if (enabledFormattings === undefined) {\n return true;\n }\n\n return DEFAULT_ENABLED_NODE_TYPES.concat(enabledFormattings).includes(nodeTypeOrMark);\n};\n\nexport const isNodeTypeEnabled = (field: FieldExtensionSDK['field'], nodeType): boolean =>\n isFormattingOptionEnabled(field, VALIDATIONS.ENABLED_NODE_TYPES, nodeType);\n\nexport const isMarkEnabled = (field: FieldExtensionSDK['field'], mark) =>\n isFormattingOptionEnabled(field, VALIDATIONS.ENABLED_MARKS, mark);\n","import * as React from 'react';\nimport constate from 'constate';\nimport { FieldExtensionSDK } from '@contentful/app-sdk';\n\ninterface SdkProviderProps {\n sdk: FieldExtensionSDK;\n}\n\nfunction useSdk({ sdk }: SdkProviderProps) {\n const sdkMemo = React.useMemo<FieldExtensionSDK>(() => sdk, []); // eslint-disable-line\n\n return sdkMemo;\n}\n\nexport const [SdkProvider, useSdkContext] = constate(useSdk);\n","import * as React from 'react';\nimport * as Slate from 'slate-react';\nimport { css, cx } from 'emotion';\nimport { Menu, Button } from '@contentful/f36-components';\nimport { ChevronDownIcon } from '@contentful/f36-icons';\nimport tokens from '@contentful/f36-tokens';\nimport { Editor, Transforms, Node } from 'slate';\nimport { BLOCKS } from '@contentful/rich-text-types';\nimport {\n PlatePlugin,\n getRenderElement,\n PlateEditor,\n getPlatePluginOptions,\n insertNodes,\n setNodes,\n toggleNodeType,\n} from '@udecode/plate';\nimport { CustomElement, CustomSlatePluginOptions } from '../../types';\nimport {\n getElementFromCurrentSelection,\n hasSelectionText,\n shouldUnwrapBlockquote,\n unwrapFromRoot,\n} from '../../helpers/editor';\nimport { isNodeTypeEnabled } from '../../helpers/validations';\nimport { useSdkContext } from '../../SdkProvider';\nimport { useContentfulEditor } from '../../ContentfulEditorProvider';\n\nconst styles = {\n dropdown: {\n root: css`\n font-weight: ${tokens.fontWeightDemiBold};\n `,\n [BLOCKS.PARAGRAPH]: css`\n font-size: ${tokens.fontSizeL};\n `,\n [BLOCKS.HEADING_1]: css`\n font-size: 1.625rem;\n `,\n [BLOCKS.HEADING_2]: css`\n font-size: 1.4375rem;\n `,\n [BLOCKS.HEADING_3]: css`\n font-size: 1.25rem;\n `,\n [BLOCKS.HEADING_4]: css`\n font-size: 1.125rem;\n `,\n [BLOCKS.HEADING_5]: css`\n font-size: 1rem;\n `,\n [BLOCKS.HEADING_6]: css`\n font-size: 0.875rem;\n `,\n },\n headings: {\n root: css`\n font-weight: ${tokens.fontWeightMedium};\n line-height: 1.3;\n margin: 0 0 ${tokens.spacingS};\n `,\n [BLOCKS.HEADING_1]: css`\n font-size: 1.875rem;\n `,\n [BLOCKS.HEADING_2]: css`\n font-size: 1.5625rem;\n `,\n [BLOCKS.HEADING_3]: css`\n font-size: 1.375rem;\n `,\n [BLOCKS.HEADING_4]: css`\n font-size: 1.25rem;\n `,\n [BLOCKS.HEADING_5]: css`\n font-size: 1.125rem;\n `,\n [BLOCKS.HEADING_6]: css`\n font-size: 1rem;\n `,\n },\n};\n\nexport function withHeadingEvents(editor: PlateEditor) {\n return (event: React.KeyboardEvent) => {\n if (!editor.selection) return;\n\n // Enter a new line on a heading element\n const headings: string[] = [\n BLOCKS.HEADING_1,\n BLOCKS.HEADING_2,\n BLOCKS.HEADING_3,\n BLOCKS.HEADING_4,\n BLOCKS.HEADING_5,\n BLOCKS.HEADING_6,\n ];\n const [currentFragment] = Editor.fragment(\n editor,\n editor.selection.focus.path\n ) as CustomElement[];\n const isEnter = event.keyCode === 13;\n const isCurrentFragmentAHeading = headings.includes(currentFragment.type);\n\n if (isEnter && isCurrentFragmentAHeading) {\n event.preventDefault();\n\n const text = { text: '' };\n const paragraph = { type: BLOCKS.PARAGRAPH, data: {}, children: [text] };\n const heading = { type: currentFragment.type, data: {}, children: [text] };\n\n if (hasSelectionText(editor)) {\n const currentOffset = editor.selection.focus.offset;\n const currentTextLength = Node.string(currentFragment).length;\n const cursorIsAtTheBeginning = currentOffset === 0;\n const cursorIsAtTheEnd = currentTextLength === currentOffset;\n\n if (cursorIsAtTheBeginning) {\n insertNodes(editor, paragraph, { at: editor.selection });\n } else if (cursorIsAtTheEnd) {\n insertNodes(editor, paragraph);\n } else {\n // Otherwise the cursor is in the middle\n Transforms.splitNodes(editor);\n setNodes(editor, paragraph);\n }\n } else {\n setNodes(editor, paragraph);\n insertNodes(editor, heading);\n }\n }\n\n // Toggle heading blocks when pressing cmd/ctrl+alt+1|2|3|4|5|6\n const headingKeyCodes = {\n 49: BLOCKS.HEADING_1,\n 50: BLOCKS.HEADING_2,\n 51: BLOCKS.HEADING_3,\n 52: BLOCKS.HEADING_4,\n 53: BLOCKS.HEADING_5,\n 54: BLOCKS.HEADING_6,\n };\n const isMod = event.ctrlKey || event.metaKey;\n const isAltOrOption = event.altKey;\n const headingKey = headingKeyCodes[event.keyCode];\n\n if (isMod && isAltOrOption && headingKey) {\n event.preventDefault();\n\n if (shouldUnwrapBlockquote(editor, headingKey)) {\n unwrapFromRoot(editor);\n }\n\n toggleNodeType(editor, { activeType: headingKey, inactiveType: BLOCKS.PARAGRAPH });\n }\n };\n}\n\nconst LABELS = {\n [BLOCKS.PARAGRAPH]: 'Normal text',\n [BLOCKS.HEADING_1]: 'Heading 1',\n [BLOCKS.HEADING_2]: 'Heading 2',\n [BLOCKS.HEADING_3]: 'Heading 3',\n [BLOCKS.HEADING_4]: 'Heading 4',\n [BLOCKS.HEADING_5]: 'Heading 5',\n [BLOCKS.HEADING_6]: 'Heading 6',\n};\n\ninterface ToolbarHeadingButtonProps {\n isDisabled?: boolean;\n}\n\nexport function ToolbarHeadingButton(props: ToolbarHeadingButtonProps) {\n const sdk = useSdkContext();\n const editor = useContentfulEditor();\n const [isOpen, setOpen] = React.useState(false);\n const [selected, setSelected] = React.useState<string>(BLOCKS.PARAGRAPH);\n\n React.useEffect(() => {\n if (!editor?.selection) return;\n\n const [element] = getElementFromCurrentSelection(editor);\n const type = (element as CustomElement).type;\n\n setSelected(LABELS[type] ? type : BLOCKS.PARAGRAPH);\n }, [editor?.operations, editor?.selection]); // eslint-disable-line\n\n const [nodeTypesByEnablement, someHeadingsEnabled] = React.useMemo(() => {\n const nodeTypesByEnablement = Object.fromEntries(\n Object.keys(LABELS).map((nodeType) => [nodeType, isNodeTypeEnabled(sdk.field, nodeType)])\n );\n const someHeadingsEnabled = Object.values(nodeTypesByEnablement).filter(Boolean).length > 0;\n return [nodeTypesByEnablement, someHeadingsEnabled];\n }, [sdk.field]);\n\n function handleOnSelectItem(type: BLOCKS): (event: React.MouseEvent<HTMLButtonElement>) => void {\n return (event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n\n if (!editor?.selection) return;\n\n setSelected(type);\n setOpen(false);\n\n if (shouldUnwrapBlockquote(editor, type)) {\n unwrapFromRoot(editor);\n }\n\n toggleNodeType(editor, { activeType: type, inactiveType: type });\n\n // TODO: Figure out why focus only works with timeout here.\n setTimeout(() => {\n Slate.ReactEditor.focus(editor);\n }, 0);\n };\n }\n\n if (!editor) return null;\n\n return (\n <Menu isOpen={isOpen} onClose={() => setOpen(false)}>\n <Menu.Trigger>\n <Button\n size=\"small\"\n testId=\"toolbar-heading-toggle\"\n variant=\"transparent\"\n endIcon={<ChevronDownIcon />}\n onClick={() => someHeadingsEnabled && setOpen(!isOpen)}>\n {LABELS[selected]}\n </Button>\n </Menu.Trigger>\n <Menu.List testId=\"dropdown-heading-list\">\n {' '}\n {Object.keys(LABELS)\n .map(\n (nodeType) =>\n nodeTypesByEnablement[nodeType] && (\n <Menu.Item\n key={nodeType}\n isInitiallyFocused={selected === nodeType}\n onClick={handleOnSelectItem(nodeType as BLOCKS)}\n testId={`dropdown-option-${nodeType}`}\n disabled={props.isDisabled}>\n <span className={cx(styles.dropdown.root, styles.dropdown[nodeType])}>\n {LABELS[nodeType]}\n </span>\n </Menu.Item>\n )\n )\n .filter(Boolean)}\n </Menu.List>\n </Menu>\n );\n}\n\nexport function createHeading(Tag, block: BLOCKS) {\n return function Heading(props: Slate.RenderElementProps) {\n return (\n <Tag {...props.attributes} className={cx(styles.headings.root, styles.headings[block])}>\n {props.children}\n </Tag>\n );\n };\n}\n\nexport const H1 = createHeading('h1', BLOCKS.HEADING_1);\nexport const H2 = createHeading('h2', BLOCKS.HEADING_2);\nexport const H3 = createHeading('h3', BLOCKS.HEADING_3);\nexport const H4 = createHeading('h4', BLOCKS.HEADING_4);\nexport const H5 = createHeading('h5', BLOCKS.HEADING_5);\nexport const H6 = createHeading('h6', BLOCKS.HEADING_6);\n\nexport function createHeadingPlugin(): PlatePlugin {\n const headings: string[] = [\n BLOCKS.HEADING_1,\n BLOCKS.HEADING_2,\n BLOCKS.HEADING_3,\n BLOCKS.HEADING_4,\n BLOCKS.HEADING_5,\n BLOCKS.HEADING_6,\n ];\n\n return {\n renderElement: getRenderElement(headings),\n pluginKeys: headings,\n onKeyDown: withHeadingEvents,\n deserialize: (editor) => {\n return {\n element: headings.map((headingType, index) => {\n const options = getPlatePluginOptions(editor, headingType);\n\n return {\n type: headingType,\n deserialize: (element) => {\n const isHeading = element.nodeName === `H${index + 1}`;\n\n if (!isHeading) return;\n\n return {\n type: headingType,\n };\n },\n ...options.deserialize,\n };\n }),\n };\n },\n };\n}\n\nexport const withHeadingOptions: CustomSlatePluginOptions = {\n [BLOCKS.HEADING_1]: {\n type: BLOCKS.HEADING_1,\n component: H1,\n },\n [BLOCKS.HEADING_2]: {\n type: BLOCKS.HEADING_2,\n component: H2,\n },\n [BLOCKS.HEADING_3]: {\n type: BLOCKS.HEADING_3,\n component: H3,\n },\n [BLOCKS.HEADING_4]: {\n type: BLOCKS.HEADING_4,\n component: H4,\n },\n [BLOCKS.HEADING_5]: {\n type: BLOCKS.HEADING_5,\n component: H5,\n },\n [BLOCKS.HEADING_6]: {\n type: BLOCKS.HEADING_6,\n component: H6,\n },\n};\n","import * as React from 'react';\nimport * as Slate from 'slate-react';\nimport { css } from 'emotion';\nimport tokens from '@contentful/f36-tokens';\nimport { QuoteIcon } from '@contentful/f36-icons';\nimport { ToolbarButton } from '../shared/ToolbarButton';\nimport { Transforms, Editor, Node, Element, Text } from 'slate';\nimport { BLOCKS } from '@contentful/rich-text-types';\nimport { PlatePlugin, PlateEditor, getRenderElement } from '@udecode/plate';\nimport { CustomElement } from '../../types';\nimport { CustomSlatePluginOptions } from 'types';\nimport {\n isBlockSelected,\n toggleBlock,\n hasSelectionText,\n getElementFromCurrentSelection,\n isNodeTypeSelected,\n} from '../../helpers/editor';\nimport { deserializeElement } from '../../helpers/deserializer';\nimport { useContentfulEditor } from '../../ContentfulEditorProvider';\n\nconst styles = {\n blockquote: css({\n margin: '0 0 1.3125rem',\n borderLeft: `6px solid ${tokens.gray200}`,\n paddingLeft: '0.875rem',\n fontStyle: 'normal',\n '& a': {\n color: 'inherit',\n },\n }),\n};\n\ninterface ToolbarQuoteButtonProps {\n isDisabled?: boolean;\n}\n\nconst createBlockQuote = (editor: PlateEditor) => {\n if (!editor.selection) return;\n\n toggleBlock(editor, BLOCKS.QUOTE);\n};\n\nexport function withQuoteEvents(editor: PlateEditor) {\n return (event: React.KeyboardEvent) => {\n if (!editor.selection) return;\n\n const [currentFragment] = Editor.fragment(\n editor,\n editor.selection.focus.path\n ) as CustomElement[];\n const isEnter = event.keyCode === 13;\n\n if (isEnter && currentFragment?.type === BLOCKS.QUOTE) {\n event.preventDefault();\n\n const text = { text: '' };\n const paragraph = { type: BLOCKS.PARAGRAPH, data: {}, children: [text] };\n\n if (hasSelectionText(editor)) {\n const currentOffset = editor.selection.focus.offset;\n const currentTextLength = Node.string(currentFragment).length;\n const cursorIsAtTheBeginning = currentOffset === 0;\n const cursorIsAtTheEnd = currentTextLength === currentOffset;\n\n if (cursorIsAtTheBeginning) {\n Transforms.insertNodes(editor, paragraph, { at: editor.selection });\n } else if (cursorIsAtTheEnd) {\n Transforms.insertNodes(editor, paragraph);\n } else {\n // Otherwise the cursor is in the middle\n Transforms.splitNodes(editor);\n Transforms.setNodes(editor, paragraph);\n }\n } else {\n Transforms.insertNodes(editor, paragraph);\n }\n }\n\n const isBackspace = event.keyCode === 8;\n const isMod = event.ctrlKey || event.metaKey;\n const isShift = event.shiftKey;\n const isOneKey = event.keyCode === 49;\n\n // shift + cmd/ctrl + 1 = shortcut to toggle blockquote\n if (isMod && isShift && isOneKey && !isNodeTypeSelected(editor, BLOCKS.TABLE)) {\n createBlockQuote(editor);\n }\n\n // On backspace, check if quote is empty. If it's empty, switch the current fragment to a paragraph\n if (isBackspace && currentFragment?.type === BLOCKS.QUOTE) {\n const quoteIsEmpty = (\n getElementFromCurrentSelection(editor)[0] as CustomElement\n ).children.every(\n (item) =>\n Element.isElement(item) &&\n item.children.every((item) => Text.isText(item) && item.text === '')\n );\n\n if (quoteIsEmpty) toggleBlock(editor, BLOCKS.PARAGRAPH);\n }\n };\n}\n\nexport function ToolbarQuoteButton(props: ToolbarQuoteButtonProps) {\n const editor = useContentfulEditor();\n\n function handleOnClick() {\n if (!editor) return;\n\n createBlockQuote(editor);\n Slate.ReactEditor.focus(editor);\n }\n\n if (!editor) return null;\n\n return (\n <ToolbarButton\n title=\"Blockquote\"\n onClick={handleOnClick}\n testId=\"quote-toolbar-button\"\n isDisabled={props.isDisabled}\n isActive={isBlockSelected(editor, BLOCKS.QUOTE)}>\n <QuoteIcon />\n </ToolbarButton>\n );\n}\n\nexport function Quote(props: Slate.RenderLeafProps) {\n return (\n <blockquote {...props.attributes} className={styles.blockquote}>\n {props.children}\n </blockquote>\n );\n}\n\nexport function createQuotePlugin(): PlatePlugin {\n return {\n pluginKeys: BLOCKS.QUOTE,\n renderElement: getRenderElement(BLOCKS.QUOTE),\n onKeyDown: withQuoteEvents,\n deserialize: deserializeElement(BLOCKS.QUOTE, [{ nodeNames: 'BLOCKQUOTE' }]),\n };\n}\n\nexport const withQuoteOptions: CustomSlatePluginOptions = {\n [BLOCKS.QUOTE]: {\n type: BLOCKS.QUOTE,\n component: Quote,\n },\n};\n","import * as React from 'react';\nimport * as Slate from 'slate-react';\nimport { Element, Text, Node, Transforms, Editor, NodeEntry, Path } from 'slate';\nimport { css } from 'emotion';\nimport {\n createListPlugin as createPlateListPlugin,\n withList,\n ELEMENT_LI,\n ELEMENT_UL,\n ELEMENT_OL,\n toggleList,\n ELEMENT_LIC,\n WithOverride,\n getParent,\n getAbove,\n PlateEditor,\n} from '@udecode/plate';\nimport { BLOCKS, INLINES, LIST_ITEM_BLOCKS, TopLevelBlockEnum } from '@contentful/rich-text-types';\nimport { ListBulletedIcon, ListNumberedIcon } from '@contentful/f36-icons';\n\nimport { ToolbarButton } from '../shared/ToolbarButton';\nimport {\n isBlockSelected,\n unwrapFromRoot,\n shouldUnwrapBlockquote,\n extractParagraphsAt,\n replaceNode,\n} from '../../helpers/editor';\nimport { isNodeTypeEnabled } from '../../helpers/validations';\nimport {\n CustomElement,\n CustomSlatePluginOptions,\n TextElement,\n TextOrCustomElement,\n} from '../../types';\nimport tokens from '@contentful/f36-tokens';\nimport { useSdkContext } from '../../SdkProvider';\nimport { useContentfulEditor } from '../../ContentfulEditorProvider';\nimport { getListInsertFragment } from './getListInsertFragment';\n\ninterface ToolbarListButtonProps {\n isDisabled?: boolean;\n}\n\nexport function ToolbarListButton(props: ToolbarListButtonProps) {\n const sdk = useSdkContext();\n const editor = useContentfulEditor();\n\n function handleClick(type: BLOCKS): () => void {\n return () => {\n if (!editor?.selection) return;\n\n if (shouldUnwrapBlockquote(editor, type)) {\n unwrapFromRoot(editor);\n }\n\n toggleList(editor, { type });\n\n Slate.ReactEditor.focus(editor);\n };\n }\n\n if (!editor) return null;\n\n return (\n <React.Fragment>\n {isNodeTypeEnabled(sdk.field, BLOCKS.UL_LIST) && (\n <ToolbarButton\n title=\"UL\"\n testId=\"ul-toolbar-button\"\n onClick={handleClick(BLOCKS.UL_LIST)}\n isActive={isBlockSelected(editor, BLOCKS.UL_LIST)}\n isDisabled={props.isDisabled}>\n <ListBulletedIcon />\n </ToolbarButton>\n )}\n {isNodeTypeEnabled(sdk.field, BLOCKS.OL_LIST) && (\n <ToolbarButton\n title=\"OL\"\n testId=\"ol-toolbar-button\"\n onClick={handleClick(BLOCKS.OL_LIST)}\n isActive={isBlockSelected(editor, BLOCKS.OL_LIST)}\n isDisabled={props.isDisabled}>\n <ListNumberedIcon />\n </ToolbarButton>\n )}\n </React.Fragment>\n );\n}\n\nconst listStyles = `\n padding: 0;\n margin: 0 0 1.25rem 1.25rem;\n div:first-child {\n margin: 0;\n line-height: ${tokens.lineHeightDefault};\n }\n`;\n\nconst styles = {\n [BLOCKS.UL_LIST]: css`\n ${listStyles}\n list-style-type: disc;\n ul {\n list-style-type: circle;\n ul {\n list-style-type: square;\n }\n }\n `,\n [BLOCKS.OL_LIST]: css`\n ${listStyles}\n list-style-type: decimal;\n ol {\n list-style-type: upper-alpha;\n ol {\n list-style-type: lower-roman;\n ol {\n list-style-type: lower-alpha;\n }\n }\n }\n `,\n [BLOCKS.LIST_ITEM]: css`\n margin: 0;\n list-style: inherit;\n ol,\n ul {\n margin: 0 0 0 ${tokens.spacingL};\n }\n `,\n};\n\nexport function createList(Tag, block: BLOCKS) {\n return function List(props: Slate.RenderElementProps) {\n return (\n <Tag {...props.attributes} className={styles[block]}>\n {props.children}\n </Tag>\n );\n };\n}\n\nexport const UL = createList('ul', BLOCKS.UL_LIST);\nexport const OL = createList('ol', BLOCKS.OL_LIST);\nexport const LI = createList('li', BLOCKS.LIST_ITEM);\n\nexport const withListOptions: CustomSlatePluginOptions = {\n // ELEMENT_LIC is a child of li, slatejs does ul > li > lic + ul\n [ELEMENT_LIC]: {\n type: BLOCKS.PARAGRAPH,\n },\n [ELEMENT_LI]: {\n type: BLOCKS.LIST_ITEM,\n component: LI,\n },\n [ELEMENT_UL]: {\n type: BLOCKS.UL_LIST,\n component: UL,\n },\n [ELEMENT_OL]: {\n type: BLOCKS.OL_LIST,\n component: OL,\n },\n};\n\nconst emptyNodeOfType = (type) => ({ type, children: [], data: {} });\n\nconst isList = (node: CustomElement) =>\n [BLOCKS.OL_LIST, BLOCKS.UL_LIST].includes(node.type as BLOCKS);\n\nconst isListItem = (node: CustomElement) => node.type === BLOCKS.LIST_ITEM;\n\nconst hasListAsDirectParent = (editor: Editor, path: Path) => {\n const [parentNode] = (getParent(editor, path) || []) as NodeEntry;\n return isList(parentNode as CustomElement);\n};\n\nconst isValidInsideListItem = (node: TextOrCustomElement) =>\n Text.isText(node as TextElement) ||\n (LIST_ITEM_BLOCKS as Array<TopLevelBlockEnum | INLINES>)\n .concat(Object.values(INLINES))\n .includes((node as CustomElement).type as TopLevelBlockEnum);\n\nconst replaceInvalidListItemWithText = (editor: PlateEditor, path: Path) => {\n const textFromEntry = extractParagraphsAt(editor, path);\n replaceNode(editor, path, textFromEntry);\n};\n\n/**\n * Ensures each list item follows the list schema.\n * Returns true if the list needed to have been normalized.\n */\nconst normalizeList = (editor: PlateEditor, path: Path): boolean => {\n for (const [child, childPath] of Node.children(editor, path)) {\n if (Element.isElement(child) && !isListItem(child)) {\n Transforms.wrapNodes(editor, emptyNodeOfType(BLOCKS.LIST_ITEM), { at: childPath });\n return true;\n }\n }\n return false;\n};\n\nconst getNearestListAncestor = (editor: PlateEditor, path: Path) => {\n return getAbove(editor, { at: path, mode: 'lowest', match: isList }) || [];\n};\n\n/**\n * Places orphaned list items in a list. If there's a list somewhere\n * in the node's ancestors, defaults to that list type, else places\n * the list item in an unordered list.\n */\nconst normalizeOrphanedListItem = (editor: PlateEditor, path: Path) => {\n const [parentList] = getNearestListAncestor(editor, path);\n const parentListType = parentList?.type;\n Transforms.wrapNodes(\n editor,\n { type: parentListType || BLOCKS.UL_LIST, children: [], data: {} },\n { at: path }\n );\n};\n\nconst withCustomList = (options): WithOverride => {\n const withDefaultOverrides = withList(options);\n\n return (editor) => {\n const { insertFragment } = editor;\n\n withDefaultOverrides(editor);\n\n // Reverts any overrides to insertFragment\n editor.insertFragment = insertFragment;\n\n // Use our custom getListInsertFragment\n editor.insertFragment = getListInsertFragment(editor);\n\n const { normalizeNode } = editor;\n editor.normalizeNode = (entry) => {\n const [node, path] = entry;\n\n if (isList(node as CustomElement)) {\n if (normalizeList(editor, path)) {\n return;\n }\n } else if (isListItem(node as CustomElement)) {\n if (!hasListAsDirectParent(editor, path)) {\n normalizeOrphanedListItem(editor, path);\n return;\n }\n\n const listItemChildren = Array.from(Node.children(editor, path));\n\n // Handle list items with no paragraph/text\n if (listItemChildren.length === 0) {\n Transforms.insertNodes(\n editor,\n [{ type: BLOCKS.PARAGRAPH, data: {}, children: [{ text: '' }] }],\n {\n at: path.concat([0]),\n }\n );\n return;\n }\n\n for (const [child, childPath] of listItemChildren) {\n if (Element.isElement(child) && !isValidInsideListItem(child)) {\n replaceInvalidListItemWithText(editor, childPath);\n return;\n }\n }\n }\n\n normalizeNode(entry);\n };\n\n return editor;\n };\n};\n\nexport const createListPlugin = () => {\n const options = {\n validLiChildrenTypes: LIST_ITEM_BLOCKS,\n };\n\n const plugin = createPlateListPlugin(options);\n\n plugin.withOverrides = withCustomList(options);\n\n return plugin;\n};\n","/**\n * A copy of Plate's list plugin with a few adjustments\n * to fix pasting text inside lists.\n */\nimport {\n findNode,\n getPlatePluginOptions,\n PlateEditor,\n PlatePluginOptions,\n TDescendant,\n ELEMENT_LI,\n ELEMENT_OL,\n ELEMENT_UL,\n} from '@udecode/plate';\nimport { Node, NodeEntry, Path, Transforms } from 'slate';\n\nexport const getListInsertFragment = (editor: PlateEditor) => {\n const { insertFragment } = editor;\n\n const li = getPlatePluginOptions(editor, ELEMENT_LI);\n const ul = getPlatePluginOptions(editor, ELEMENT_UL);\n const ol = getPlatePluginOptions(editor, ELEMENT_OL);\n\n const isListRoot = (node: TDescendant): boolean => [ul.type, ol.type].includes(node.type);\n\n const getFirstAncestorOfType = (\n root: TDescendant,\n entry: NodeEntry,\n { type }: PlatePluginOptions\n ): NodeEntry<TDescendant> => {\n let ancestor: Path = Path.parent(entry[1]);\n while ((Node.get(root, ancestor) as TDescendant).type !== type) {\n ancestor = Path.parent(ancestor);\n }\n\n return [Node.get(root, ancestor), ancestor];\n };\n\n /**\n * Removes the \"empty\" leading lis. Empty in this context means lis only with other lis as children.\n *\n * @returns If argument is not a list root, returns it, otherwise returns ul[] or li[].\n */\n const trimList = <T extends TDescendant>(listRoot: T): T[] => {\n if (!isListRoot(listRoot)) {\n return [listRoot];\n }\n\n const textEntries = Array.from(Node.texts(listRoot));\n\n const commonAncestorEntry = textEntries.reduce<NodeEntry<TDescendant>>(\n (commonAncestor, textEntry) =>\n Path.isAncestor(commonAncestor[1], textEntry[1])\n ? commonAncestor\n : Node.common(listRoot, textEntry[1], commonAncestor[1]),\n // any list item would do, we grab the first one\n getFirstAncestorOfType(listRoot, textEntries[0], li)\n );\n\n return isListRoot(commonAncestorEntry[0])\n ? commonAncestorEntry[0].children\n : [commonAncestorEntry[0]];\n };\n\n return (fragment: TDescendant[]) => {\n const liEntry = findNode(editor, {\n match: { type: li.type },\n mode: 'lowest',\n });\n\n if (liEntry) {\n const [, liPath] = liEntry;\n\n // FIXME: this is a temporarily workaround and needs a follow-up to properly\n // non-text elements\n const nodes = fragment.flatMap((node) => trimList(node));\n\n return Transforms.insertNodes(editor, nodes, {\n at: editor.selection || Path.next(liPath),\n select: true,\n });\n }\n\n const filtered: TDescendant[] = isListRoot(fragment[0])\n ? [{ text: '' }, ...fragment]\n : fragment;\n\n return insertFragment(filtered);\n };\n};\n","import * as React from 'react';\nimport * as Slate from 'slate-react';\nimport { css } from 'emotion';\nimport {\n getRenderLeaf,\n PlatePlugin,\n getToggleMarkOnKeyDown,\n isMarkActive,\n toggleMark,\n} from '@udecode/plate';\nimport { MARKS } from '@contentful/rich-text-types';\nimport { FormatBoldIcon } from '@contentful/f36-icons';\nimport { ToolbarButton } from '../shared/ToolbarButton';\nimport { CustomSlatePluginOptions } from 'types';\nimport { useContentfulEditor } from '../../ContentfulEditorProvider';\n\ninterface ToolbarBoldButtonProps {\n isDisabled?: boolean;\n}\n\nexport function ToolbarBoldButton(props: ToolbarBoldButtonProps) {\n const editor = useContentfulEditor();\n\n function handleClick() {\n if (!editor?.selection) return;\n\n toggleMark(editor, MARKS.BOLD);\n Slate.ReactEditor.focus(editor);\n }\n\n if (!editor) return null;\n\n return (\n <ToolbarButton\n title=\"Bold\"\n testId=\"bold-toolbar-button\"\n onClick={handleClick}\n isActive={isMarkActive(editor, MARKS.BOLD)}\n isDisabled={props.isDisabled}>\n <FormatBoldIcon />\n </ToolbarButton>\n );\n}\n\nconst styles = {\n bold: css({\n fontWeight: 600,\n }),\n};\n\nexport function Bold(props: Slate.RenderLeafProps) {\n return (\n <strong {...props.attributes} className={styles.bold}>\n {props.children}\n </strong>\n );\n}\n\nexport function createBoldPlugin(): PlatePlugin {\n return {\n pluginKeys: MARKS.BOLD,\n renderLeaf: getRenderLeaf(MARKS.BOLD),\n onKeyDown: getToggleMarkOnKeyDown(MARKS.BOLD),\n deserialize: () => {\n return {\n leaf: [\n {\n type: MARKS.BOLD,\n deserialize: (element) => {\n // We ignore it otherwise everything will be bold\n const isGoogleBoldWrapper =\n element.id.startsWith('docs-internal-guid') && element.nodeName === 'B';\n\n const isBold =\n ['600', '700', 'bold'].includes(element.style.fontWeight) ||\n ['STRONG', 'B'].includes(element.nodeName);\n\n if (isGoogleBoldWrapper || !isBold) return;\n\n return {\n [MARKS.BOLD]: true,\n };\n },\n },\n ],\n };\n },\n };\n}\n\nexport const withBoldOptions: CustomSlatePluginOptions = {\n [MARKS.BOLD]: {\n type: MARKS.BOLD,\n component: Bold,\n hotkey: ['mod+b'],\n },\n};\n","import * as React from 'react';\nimport * as Slate from 'slate-react';\nimport { css } from 'emotion';\nimport {\n PlatePlugin,\n getRenderLeaf,\n GetNodeDeserializerRule,\n getToggleMarkOnKeyDown,\n isMarkActive,\n toggleMark,\n} from '@udecode/plate';\nimport { MARKS } from '@contentful/rich-text-types';\nimport { CodeIcon } from '@contentful/f36-icons';\nimport { ToolbarButton } from '../shared/ToolbarButton';\nimport { CustomSlatePluginOptions } from 'types';\nimport { deserializeLeaf } from '../../helpers/deserializer';\nimport { useContentfulEditor } from '../../ContentfulEditorProvider';\n\ninterface ToolbarCodeButtonProps {\n isDisabled?: boolean;\n}\n\nexport function ToolbarCodeButton(props: ToolbarCodeButtonProps) {\n const editor = useContentfulEditor();\n\n function handleClick() {\n if (!editor?.selection) return;\n\n toggleMark(editor, MARKS.CODE);\n Slate.ReactEditor.focus(editor);\n }\n\n if (!editor) return null;\n\n return (\n <ToolbarButton\n title=\"Code\"\n testId=\"code-toolbar-button\"\n onClick={handleClick}\n isActive={isMarkActive(editor, MARKS.CODE)}\n isDisabled={props.isDisabled}>\n <CodeIcon />\n </ToolbarButton>\n );\n}\n\nconst styles = {\n code: css({\n fontFamily: 'monospace',\n fontSize: '.9em',\n }),\n};\n\nexport function Code(props: Slate.RenderLeafProps) {\n return (\n <code {...props.attributes} className={styles.code}>\n {props.children}\n </code>\n );\n}\n\nexport function createCodePlugin(): PlatePlugin {\n const deserializeRule: GetNodeDeserializerRule[] = [\n { nodeNames: ['CODE', 'PRE'] },\n { style: { fontFamily: 'monospace' } },\n ];\n\n return {\n pluginKeys: MARKS.CODE,\n renderLeaf: getRenderLeaf(MARKS.CODE),\n onKeyDown: getToggleMarkOnKeyDown(MARKS.CODE),\n deserialize: deserializeLeaf(MARKS.CODE, deserializeRule),\n };\n}\n\nexport const withCodeOptions: CustomSlatePluginOptions = {\n [MARKS.CODE]: {\n type: MARKS.CODE,\n component: Code,\n hotkey: ['mod+/'],\n },\n};\n","import * as React from 'react';\nimport * as Slate from 'slate-react';\nimport { css } from 'emotion';\nimport {\n PlatePlugin,\n getRenderLeaf,\n GetNodeDeserializerRule,\n getToggleMarkOnKeyDown,\n toggleMark,\n isMarkActive,\n} from '@udecode/plate';\nimport { MARKS } from '@contentful/rich-text-types';\nimport { FormatItalicIcon } from '@contentful/f36-icons';\nimport { ToolbarButton } from '../shared/ToolbarButton';\nimport { CustomSlatePluginOptions } from '../../types';\nimport { deserializeLeaf } from '../../helpers/deserializer';\nimport { useContentfulEditor } from '../../ContentfulEditorProvider';\n\ninterface ToolbarItalicButtonProps {\n isDisabled?: boolean;\n}\n\nexport function ToolbarItalicButton(props: ToolbarItalicButtonProps) {\n const editor = useContentfulEditor();\n\n function handleClick() {\n if (!editor?.selection) return;\n\n toggleMark(editor, MARKS.ITALIC);\n Slate.ReactEditor.focus(editor);\n }\n\n if (!editor) return null;\n\n return (\n <ToolbarButton\n title=\"Italic\"\n testId=\"italic-toolbar-button\"\n onClick={handleClick}\n isActive={isMarkActive(editor, MARKS.ITALIC)}\n isDisabled={props.isDisabled}>\n <FormatItalicIcon />\n </ToolbarButton>\n );\n}\n\nconst styles = {\n italic: css({\n fontStyle: 'italic',\n }),\n};\n\nexport function Italic(props: Slate.RenderLeafProps) {\n return (\n <em {...props.attributes} className={styles.italic}>\n {props.children}\n </em>\n );\n}\n\nexport function createItalicPlugin(): PlatePlugin {\n const deserializeRules: GetNodeDeserializerRule[] = [\n { nodeNames: ['I', 'EM'] },\n {\n style: {\n fontStyle: ['italic'],\n },\n },\n ];\n\n return {\n pluginKeys: MARKS.ITALIC,\n renderLeaf: getRenderLeaf(MARKS.ITALIC),\n onKeyDown: getToggleMarkOnKeyDown(MARKS.ITALIC),\n deserialize: deserializeLeaf(MARKS.ITALIC, deserializeRules),\n };\n}\n\nexport const withItalicOptions: CustomSlatePluginOptions = {\n [MARKS.ITALIC]: {\n type: MARKS.ITALIC,\n component: Italic,\n hotkey: ['mod+i'],\n },\n};\n","import * as React from 'react';\nimport * as Slate from 'slate-react';\nimport {\n PlatePlugin,\n getRenderLeaf,\n GetNodeDeserializerRule,\n getToggleMarkOnKeyDown,\n toggleMark,\n isMarkActive,\n} from '@udecode/plate';\nimport { MARKS } from '@contentful/rich-text-types';\nimport { FormatUnderlinedIcon } from '@contentful/f36-icons';\nimport { ToolbarButton } from '../shared/ToolbarButton';\nimport { CustomSlatePluginOptions } from 'types';\nimport { deserializeLeaf } from '../../helpers/deserializer';\nimport { useContentfulEditor } from '../../ContentfulEditorProvider';\n\ninterface ToolbarUnderlineButtonProps {\n isDisabled?: boolean;\n}\n\nexport function ToolbarUnderlineButton(props: ToolbarUnderlineButtonProps) {\n const editor = useContentfulEditor();\n\n function handleClick() {\n if (!editor?.selection) return;\n\n toggleMark(editor, MARKS.UNDERLINE);\n Slate.ReactEditor.focus(editor);\n }\n\n if (!editor) return null;\n\n return (\n <ToolbarButton\n title=\"Underline\"\n testId=\"underline-toolbar-button\"\n onClick={handleClick}\n isActive={isMarkActive(editor, MARKS.UNDERLINE)}\n isDisabled={props.isDisabled}>\n <FormatUnderlinedIcon />\n </ToolbarButton>\n );\n}\n\nexport function Underline(props: Slate.RenderLeafProps) {\n return <u {...props.attributes}>{props.children}</u>;\n}\n\nexport function createUnderlinePlugin(): PlatePlugin {\n const deserializeRules: GetNodeDeserializerRule[] = [\n { nodeNames: ['U'] },\n {\n style: {\n textDecoration: ['underline'],\n },\n },\n ];\n\n return {\n pluginKeys: MARKS.UNDERLINE,\n renderLeaf: getRenderLeaf(MARKS.UNDERLINE),\n onKeyDown: getToggleMarkOnKeyDown(MARKS.UNDERLINE),\n deserialize: deserializeLeaf(MARKS.UNDERLINE, deserializeRules),\n };\n}\n\nexport const withUnderlineOptions: CustomSlatePluginOptions = {\n [MARKS.UNDERLINE]: {\n type: MARKS.UNDERLINE,\n component: Underline,\n hotkey: ['mod+u'],\n },\n};\n","/**\n * Copyright (c) 2014-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nvar runtime = (function (exports) {\n \"use strict\";\n\n var Op = Object.prototype;\n var hasOwn = Op.hasOwnProperty;\n var undefined; // More compressible than void 0.\n var $Symbol = typeof Symbol === \"function\" ? Symbol : {};\n var iteratorSymbol = $Symbol.iterator || \"@@iterator\";\n var asyncIteratorSymbol = $Symbol.asyncIterator || \"@@asyncIterator\";\n var toStringTagSymbol = $Symbol.toStringTag || \"@@toStringTag\";\n\n function define(obj, key, value) {\n Object.defineProperty(obj, key, {\n value: value,\n enumerable: true,\n configurable: true,\n writable: true\n });\n return obj[key];\n }\n try {\n // IE 8 has a broken Object.defineProperty that only works on DOM objects.\n define({}, \"\");\n } catch (err) {\n define = function(obj, key, value) {\n return obj[key] = value;\n };\n }\n\n function wrap(innerFn, outerFn, self, tryLocsList) {\n // If outerFn provided and outerFn.prototype is a Generator, then outerFn.prototype instanceof Generator.\n var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator;\n var generator = Object.create(protoGenerator.prototype);\n var context = new Context(tryLocsList || []);\n\n // The ._invoke method unifies the implementations of the .next,\n // .throw, and .return methods.\n generator._invoke = makeInvokeMethod(innerFn, self, context);\n\n return generator;\n }\n exports.wrap = wrap;\n\n // Try/catch helper to minimize deoptimizations. Returns a completion\n // record like context.tryEntries[i].completion. This interface could\n // have been (and was previously) designed to take a closure to be\n // invoked without arguments, but in all the cases we care about we\n // already have an existing method we want to call, so there's no need\n // to create a new function object. We can even get away with assuming\n // the method takes exactly one argument, since that happens to be true\n // in every case, so we don't have to touch the arguments object. The\n // only additional allocation required is the completion record, which\n // has a stable shape and so hopefully should be cheap to allocate.\n function tryCatch(fn, obj, arg) {\n try {\n return { type: \"normal\", arg: fn.call(obj, arg) };\n } catch (err) {\n return { type: \"throw\", arg: err };\n }\n }\n\n var GenStateSuspendedStart = \"suspendedStart\";\n var GenStateSuspendedYield = \"suspendedYield\";\n var GenStateExecuting = \"executing\";\n var GenStateCompleted = \"completed\";\n\n // Returning this object from the innerFn has the same effect as\n // breaking out of the dispatch switch statement.\n var ContinueSentinel = {};\n\n // Dummy constructor functions that we use as the .constructor and\n // .constructor.prototype properties for functions that return Generator\n // objects. For full spec compliance, you may wish to configure your\n // minifier not to mangle the names of these two functions.\n function Generator() {}\n function GeneratorFunction() {}\n function GeneratorFunctionPrototype() {}\n\n // This is a polyfill for %IteratorPrototype% for environments that\n // don't natively support it.\n var IteratorPrototype = {};\n IteratorPrototype[iteratorSymbol] = function () {\n return this;\n };\n\n var getProto = Object.getPrototypeOf;\n var NativeIteratorPrototype = getProto && getProto(getProto(values([])));\n if (NativeIteratorPrototype &&\n NativeIteratorPrototype !== Op &&\n hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) {\n // This environment has a native %IteratorPrototype%; use it instead\n // of the polyfill.\n IteratorPrototype = NativeIteratorPrototype;\n }\n\n var Gp = GeneratorFunctionPrototype.prototype =\n Generator.prototype = Object.create(IteratorPrototype);\n GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype;\n GeneratorFunctionPrototype.constructor = GeneratorFunction;\n GeneratorFunction.displayName = define(\n GeneratorFunctionPrototype,\n toStringTagSymbol,\n \"GeneratorFunction\"\n );\n\n // Helper for defining the .next, .throw, and .return methods of the\n // Iterator interface in terms of a single ._invoke method.\n function defineIteratorMethods(prototype) {\n [\"next\", \"throw\", \"return\"].forEach(function(method) {\n define(prototype, method, function(arg) {\n return this._invoke(method, arg);\n });\n });\n }\n\n exports.isGeneratorFunction = function(genFun) {\n var ctor = typeof genFun === \"function\" && genFun.constructor;\n return ctor\n ? ctor === GeneratorFunction ||\n // For the native GeneratorFunction constructor, the best we can\n // do is to check its .name property.\n (ctor.displayName || ctor.name) === \"GeneratorFunction\"\n : false;\n };\n\n exports.mark = function(genFun) {\n if (Object.setPrototypeOf) {\n Object.setPrototypeOf(genFun, GeneratorFunctionPrototype);\n } else {\n genFun.__proto__ = GeneratorFunctionPrototype;\n define(genFun, toStringTagSymbol, \"GeneratorFunction\");\n }\n genFun.prototype = Object.create(Gp);\n return genFun;\n };\n\n // Within the body of any async function, `await x` is transformed to\n // `yield regeneratorRuntime.awrap(x)`, so that the runtime can test\n // `hasOwn.call(value, \"__await\")` to determine if the yielded value is\n // meant to be awaited.\n exports.awrap = function(arg) {\n return { __await: arg };\n };\n\n function AsyncIterator(generator, PromiseImpl) {\n function invoke(method, arg, resolve, reject) {\n var record = tryCatch(generator[method], generator, arg);\n if (record.type === \"throw\") {\n reject(record.arg);\n } else {\n var result = record.arg;\n var value = result.value;\n if (value &&\n typeof value === \"object\" &&\n hasOwn.call(value, \"__await\")) {\n return PromiseImpl.resolve(value.__await).then(function(value) {\n invoke(\"next\", value, resolve, reject);\n }, function(err) {\n invoke(\"throw\", err, resolve, reject);\n });\n }\n\n return PromiseImpl.resolve(value).then(function(unwrapped) {\n // When a yielded Promise is resolved, its final value becomes\n // the .value of the Promise<{value,done}> result for the\n // current iteration.\n result.value = unwrapped;\n resolve(result);\n }, function(error) {\n // If a rejected Promise was yielded, throw the rejection back\n // into the async generator function so it can be handled there.\n return invoke(\"throw\", error, resolve, reject);\n });\n }\n }\n\n var previousPromise;\n\n function enqueue(method, arg) {\n function callInvokeWithMethodAndArg() {\n return new PromiseImpl(function(resolve, reject) {\n invoke(method, arg, resolve, reject);\n });\n }\n\n return previousPromise =\n // If enqueue has been called before, then we want to wait until\n // all previous Promises have been resolved before calling invoke,\n // so that results are always delivered in the correct order. If\n // enqueue has not been called before, then it is important to\n // call invoke immediately, without waiting on a callback to fire,\n // so that the async generator function has the opportunity to do\n // any necessary setup in a predictable way. This predictability\n // is why the Promise constructor synchronously invokes its\n // executor callback, and why async functions synchronously\n // execute code before the first await. Since we implement simple\n // async functions in terms of async generators, it is especially\n // important to get this right, even though it requires care.\n previousPromise ? previousPromise.then(\n callInvokeWithMethodAndArg,\n // Avoid propagating failures to Promises returned by later\n // invocations of the iterator.\n callInvokeWithMethodAndArg\n ) : callInvokeWithMethodAndArg();\n }\n\n // Define the unified helper method that is used to implement .next,\n // .throw, and .return (see defineIteratorMethods).\n this._invoke = enqueue;\n }\n\n defineIteratorMethods(AsyncIterator.prototype);\n AsyncIterator.prototype[asyncIteratorSymbol] = function () {\n return this;\n };\n exports.AsyncIterator = AsyncIterator;\n\n // Note that simple async functions are implemented on top of\n // AsyncIterator objects; they just return a Promise for the value of\n // the final result produced by the iterator.\n exports.async = function(innerFn, outerFn, self, tryLocsList, PromiseImpl) {\n if (PromiseImpl === void 0) PromiseImpl = Promise;\n\n var iter = new AsyncIterator(\n wrap(innerFn, outerFn, self, tryLocsList),\n PromiseImpl\n );\n\n return exports.isGeneratorFunction(outerFn)\n ? iter // If outerFn is a generator, return the full iterator.\n : iter.next().then(function(result) {\n return result.done ? result.value : iter.next();\n });\n };\n\n function makeInvokeMethod(innerFn, self, context) {\n var state = GenStateSuspendedStart;\n\n return function invoke(method, arg) {\n if (state === GenStateExecuting) {\n throw new Error(\"Generator is already running\");\n }\n\n if (state === GenStateCompleted) {\n if (method === \"throw\") {\n throw arg;\n }\n\n // Be forgiving, per 25.3.3.3.3 of the spec:\n // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume\n return doneResult();\n }\n\n context.method = method;\n context.arg = arg;\n\n while (true) {\n var delegate = context.delegate;\n if (delegate) {\n var delegateResult = maybeInvokeDelegate(delegate, context);\n if (delegateResult) {\n if (delegateResult === ContinueSentinel) continue;\n return delegateResult;\n }\n }\n\n if (context.method === \"next\") {\n // Setting context._sent for legacy support of Babel's\n // function.sent implementation.\n context.sent = context._sent = context.arg;\n\n } else if (context.method === \"throw\") {\n if (state === GenStateSuspendedStart) {\n state = GenStateCompleted;\n throw context.arg;\n }\n\n context.dispatchException(context.arg);\n\n } else if (context.method === \"return\") {\n context.abrupt(\"return\", context.arg);\n }\n\n state = GenStateExecuting;\n\n var record = tryCatch(innerFn, self, context);\n if (record.type === \"normal\") {\n // If an exception is thrown from innerFn, we leave state ===\n // GenStateExecuting and loop back for another invocation.\n state = context.done\n ? GenStateCompleted\n : GenStateSuspendedYield;\n\n if (record.arg === ContinueSentinel) {\n continue;\n }\n\n return {\n value: record.arg,\n done: context.done\n };\n\n } else if (record.type === \"throw\") {\n state = GenStateCompleted;\n // Dispatch the exception by looping back around to the\n // context.dispatchException(context.arg) call above.\n context.method = \"throw\";\n context.arg = record.arg;\n }\n }\n };\n }\n\n // Call delegate.iterator[context.method](context.arg) and handle the\n // result, either by returning a { value, done } result from the\n // delegate iterator, or by modifying context.method and context.arg,\n // setting context.delegate to null, and returning the ContinueSentinel.\n function maybeInvokeDelegate(delegate, context) {\n var method = delegate.iterator[context.method];\n if (method === undefined) {\n // A .throw or .return when the delegate iterator has no .throw\n // method always terminates the yield* loop.\n context.delegate = null;\n\n if (context.method === \"throw\") {\n // Note: [\"return\"] must be used for ES3 parsing compatibility.\n if (delegate.iterator[\"return\"]) {\n // If the delegate iterator has a return method, give it a\n // chance to clean up.\n context.method = \"return\";\n context.arg = undefined;\n maybeInvokeDelegate(delegate, context);\n\n if (context.method === \"throw\") {\n // If maybeInvokeDelegate(context) changed context.method from\n // \"return\" to \"throw\", let that override the TypeError below.\n return ContinueSentinel;\n }\n }\n\n context.method = \"throw\";\n context.arg = new TypeError(\n \"The iterator does not provide a 'throw' method\");\n }\n\n return ContinueSentinel;\n }\n\n var record = tryCatch(method, delegate.iterator, context.arg);\n\n if (record.type === \"throw\") {\n context.method = \"throw\";\n context.arg = record.arg;\n context.delegate = null;\n return ContinueSentinel;\n }\n\n var info = record.arg;\n\n if (! info) {\n context.method = \"throw\";\n context.arg = new TypeError(\"iterator result is not an object\");\n context.delegate = null;\n return ContinueSentinel;\n }\n\n if (info.done) {\n // Assign the result of the finished delegate to the temporary\n // variable specified by delegate.resultName (see delegateYield).\n context[delegate.resultName] = info.value;\n\n // Resume execution at the desired location (see delegateYield).\n context.next = delegate.nextLoc;\n\n // If context.method was \"throw\" but the delegate handled the\n // exception, let the outer generator proceed normally. If\n // context.method was \"next\", forget context.arg since it has been\n // \"consumed\" by the delegate iterator. If context.method was\n // \"return\", allow the original .return call to continue in the\n // outer generator.\n if (context.method !== \"return\") {\n context.method = \"next\";\n context.arg = undefined;\n }\n\n } else {\n // Re-yield the result returned by the delegate method.\n return info;\n }\n\n // The delegate iterator is finished, so forget it and continue with\n // the outer generator.\n context.delegate = null;\n return ContinueSentinel;\n }\n\n // Define Generator.prototype.{next,throw,return} in terms of the\n // unified ._invoke helper method.\n defineIteratorMethods(Gp);\n\n define(Gp, toStringTagSymbol, \"Generator\");\n\n // A Generator should always return itself as the iterator object when the\n // @@iterator function is called on it. Some browsers' implementations of the\n // iterator prototype chain incorrectly implement this, causing the Generator\n // object to not be returned from this call. This ensures that doesn't happen.\n // See https://github.com/facebook/regenerator/issues/274 for more details.\n Gp[iteratorSymbol] = function() {\n return this;\n };\n\n Gp.toString = function() {\n return \"[object Generator]\";\n };\n\n function pushTryEntry(locs) {\n var entry = { tryLoc: locs[0] };\n\n if (1 in locs) {\n entry.catchLoc = locs[1];\n }\n\n if (2 in locs) {\n entry.finallyLoc = locs[2];\n entry.afterLoc = locs[3];\n }\n\n this.tryEntries.push(entry);\n }\n\n function resetTryEntry(entry) {\n var record = entry.completion || {};\n record.type = \"normal\";\n delete record.arg;\n entry.completion = record;\n }\n\n function Context(tryLocsList) {\n // The root entry object (effectively a try statement without a catch\n // or a finally block) gives us a place to store values thrown from\n // locations where there is no enclosing try statement.\n this.tryEntries = [{ tryLoc: \"root\" }];\n tryLocsList.forEach(pushTryEntry, this);\n this.reset(true);\n }\n\n exports.keys = function(object) {\n var keys = [];\n for (var key in object) {\n keys.push(key);\n }\n keys.reverse();\n\n // Rather than returning an object with a next method, we keep\n // things simple and return the next function itself.\n return function next() {\n while (keys.length) {\n var key = keys.pop();\n if (key in object) {\n next.value = key;\n next.done = false;\n return next;\n }\n }\n\n // To avoid creating an additional object, we just hang the .value\n // and .done properties off the next function object itself. This\n // also ensures that the minifier will not anonymize the function.\n next.done = true;\n return next;\n };\n };\n\n function values(iterable) {\n if (iterable) {\n var iteratorMethod = iterable[iteratorSymbol];\n if (iteratorMethod) {\n return iteratorMethod.call(iterable);\n }\n\n if (typeof iterable.next === \"function\") {\n return iterable;\n }\n\n if (!isNaN(iterable.length)) {\n var i = -1, next = function next() {\n while (++i < iterable.length) {\n if (hasOwn.call(iterable, i)) {\n next.value = iterable[i];\n next.done = false;\n return next;\n }\n }\n\n next.value = undefined;\n next.done = true;\n\n return next;\n };\n\n return next.next = next;\n }\n }\n\n // Return an iterator with no values.\n return { next: doneResult };\n }\n exports.values = values;\n\n function doneResult() {\n return { value: undefined, done: true };\n }\n\n Context.prototype = {\n constructor: Context,\n\n reset: function(skipTempReset) {\n this.prev = 0;\n this.next = 0;\n // Resetting context._sent for legacy support of Babel's\n // function.sent implementation.\n this.sent = this._sent = undefined;\n this.done = false;\n this.delegate = null;\n\n this.method = \"next\";\n this.arg = undefined;\n\n this.tryEntries.forEach(resetTryEntry);\n\n if (!skipTempReset) {\n for (var name in this) {\n // Not sure about the optimal order of these conditions:\n if (name.charAt(0) === \"t\" &&\n hasOwn.call(this, name) &&\n !isNaN(+name.slice(1))) {\n this[name] = undefined;\n }\n }\n }\n },\n\n stop: function() {\n this.done = true;\n\n var rootEntry = this.tryEntries[0];\n var rootRecord = rootEntry.completion;\n if (rootRecord.type === \"throw\") {\n throw rootRecord.arg;\n }\n\n return this.rval;\n },\n\n dispatchException: function(exception) {\n if (this.done) {\n throw exception;\n }\n\n var context = this;\n function handle(loc, caught) {\n record.type = \"throw\";\n record.arg = exception;\n context.next = loc;\n\n if (caught) {\n // If the dispatched exception was caught by a catch block,\n // then let that catch block handle the exception normally.\n context.method = \"next\";\n context.arg = undefined;\n }\n\n return !! caught;\n }\n\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n var record = entry.completion;\n\n if (entry.tryLoc === \"root\") {\n // Exception thrown outside of any try block that could handle\n // it, so set the completion value of the entire function to\n // throw the exception.\n return handle(\"end\");\n }\n\n if (entry.tryLoc <= this.prev) {\n var hasCatch = hasOwn.call(entry, \"catchLoc\");\n var hasFinally = hasOwn.call(entry, \"finallyLoc\");\n\n if (hasCatch && hasFinally) {\n if (this.prev < entry.catchLoc) {\n return handle(entry.catchLoc, true);\n } else if (this.prev < entry.finallyLoc) {\n return handle(entry.finallyLoc);\n }\n\n } else if (hasCatch) {\n if (this.prev < entry.catchLoc) {\n return handle(entry.catchLoc, true);\n }\n\n } else if (hasFinally) {\n if (this.prev < entry.finallyLoc) {\n return handle(entry.finallyLoc);\n }\n\n } else {\n throw new Error(\"try statement without catch or finally\");\n }\n }\n }\n },\n\n abrupt: function(type, arg) {\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n if (entry.tryLoc <= this.prev &&\n hasOwn.call(entry, \"finallyLoc\") &&\n this.prev < entry.finallyLoc) {\n var finallyEntry = entry;\n break;\n }\n }\n\n if (finallyEntry &&\n (type === \"break\" ||\n type === \"continue\") &&\n finallyEntry.tryLoc <= arg &&\n arg <= finallyEntry.finallyLoc) {\n // Ignore the finally entry if control is not jumping to a\n // location outside the try/catch block.\n finallyEntry = null;\n }\n\n var record = finallyEntry ? finallyEntry.completion : {};\n record.type = type;\n record.arg = arg;\n\n if (finallyEntry) {\n this.method = \"next\";\n this.next = finallyEntry.finallyLoc;\n return ContinueSentinel;\n }\n\n return this.complete(record);\n },\n\n complete: function(record, afterLoc) {\n if (record.type === \"throw\") {\n throw record.arg;\n }\n\n if (record.type === \"break\" ||\n record.type === \"continue\") {\n this.next = record.arg;\n } else if (record.type === \"return\") {\n this.rval = this.arg = record.arg;\n this.method = \"return\";\n this.next = \"end\";\n } else if (record.type === \"normal\" && afterLoc) {\n this.next = afterLoc;\n }\n\n return ContinueSentinel;\n },\n\n finish: function(finallyLoc) {\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n if (entry.finallyLoc === finallyLoc) {\n this.complete(entry.completion, entry.afterLoc);\n resetTryEntry(entry);\n return ContinueSentinel;\n }\n }\n },\n\n \"catch\": function(tryLoc) {\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n if (entry.tryLoc === tryLoc) {\n var record = entry.completion;\n if (record.type === \"throw\") {\n var thrown = record.arg;\n resetTryEntry(entry);\n }\n return thrown;\n }\n }\n\n // The context.catch method must only be called with a location\n // argument that corresponds to a known catch block.\n throw new Error(\"illegal catch attempt\");\n },\n\n delegateYield: function(iterable, resultName, nextLoc) {\n this.delegate = {\n iterator: values(iterable),\n resultName: resultName,\n nextLoc: nextLoc\n };\n\n if (this.method === \"next\") {\n // Deliberately forget the last sent value so that we don't\n // accidentally pass it on to the delegate.\n this.arg = undefined;\n }\n\n return ContinueSentinel;\n }\n };\n\n // Regardless of whether this script is executing as a CommonJS module\n // or not, return the runtime object so that we can declare the variable\n // regeneratorRuntime in the outer scope, which allows this module to be\n // injected easily by `bin/regenerator --include-runtime script.js`.\n return exports;\n\n}(\n // If this script is executing as a CommonJS module, use module.exports\n // as the regeneratorRuntime namespace. Otherwise create a new empty\n // object. Either way, the resulting object will be used to initialize\n // the regeneratorRuntime variable at the top of this file.\n typeof module === \"object\" ? module.exports : {}\n));\n\ntry {\n regeneratorRuntime = runtime;\n} catch (accidentalStrictMode) {\n // This module should not be running in strict mode, so the above\n // assignment should always work unless something is misconfigured. Just\n // in case runtime.js accidentally runs in strict mode, we can escape\n // strict mode using a global Function call. This could conceivably fail\n // if a Content Security Policy forbids using Function, but in that case\n // the proper solution is to fix the accidental strict mode problem. If\n // you've misconfigured your bundler to force strict mode and applied a\n // CSP to forbid Function, and you're not willing to fix either of those\n // problems, please detail your unique predicament in a GitHub issue.\n Function(\"r\", \"regeneratorRuntime = r\")(runtime);\n}\n","import * as React from 'react';\nimport {\n ContentEntityType as EntityType,\n ScheduledAction,\n} from '@contentful/field-editor-reference/dist/types';\nimport { entityHelpers, Entry, Asset, FieldExtensionSDK } from '@contentful/field-editor-shared';\nimport { getScheduleTooltipContent } from '@contentful/field-editor-reference';\nimport { truncate } from '../../helpers/truncate';\n\nfunction getEntityInfo({\n entityTitle,\n entityStatus,\n contentTypeName,\n}: {\n entityTitle: string;\n entityStatus: string;\n contentTypeName?: string;\n}) {\n const title = truncate(entityTitle, 60) || 'Untitled';\n\n return `${contentTypeName || 'Asset'} \"${title}\", ${entityStatus}`;\n}\n\ninterface EntryAssetTooltipProps {\n id: string;\n type: EntityType;\n sdk: FieldExtensionSDK;\n}\n\nexport function EntryAssetTooltip({ id, type, sdk }: EntryAssetTooltipProps) {\n const [entityTitle, setEntityTitle] = React.useState('');\n const [entityStatus, setEntityStatus] = React.useState('');\n const [jobs, setJobs] = React.useState<ScheduledAction[]>([]);\n const [isLoading, setIsLoading] = React.useState(true);\n const [hasError, setHasError] = React.useState(false);\n\n React.useEffect(() => {\n async function loadContent() {\n try {\n setIsLoading(true);\n setHasError(false);\n\n const actions = {\n Asset: {\n getEntity: sdk.space.getAsset,\n getEntityTitle: (args) => entityHelpers.getAssetTitle({ ...args, asset: args.entity }),\n },\n Entry: {\n getEntity: sdk.space.getEntry,\n getEntityTitle: (args) => entityHelpers.getEntryTitle({ ...args, entry: args.entity }),\n },\n };\n\n let contentType;\n const entity: Entry | Asset = await actions[type].getEntity(id);\n\n if (entity.sys.contentType) {\n const contentTypeId = entity.sys.contentType.sys.id;\n const contentTypes = sdk.space.getCachedContentTypes();\n contentType = contentTypes.find((ct) => ct.sys.id === contentTypeId);\n }\n\n const entityTitle: string = actions[type].getEntityTitle({\n entity,\n contentType,\n localeCode: sdk.field.locale,\n defaultLocaleCode: sdk.locales.default,\n entityType: type,\n });\n\n const jobs = await sdk.space.getEntityScheduledActions(type, id);\n const entityStatus = entityHelpers.getEntryStatus(entity.sys);\n\n setEntityTitle(entityTitle);\n setEntityStatus(entityStatus);\n setJobs(jobs);\n } catch (err) {\n console.log(err);\n setHasError(true);\n } finally {\n setIsLoading(false);\n }\n }\n\n loadContent();\n }, [id, type, sdk]);\n\n if (isLoading) {\n return <>{`Loading ${type.toLowerCase()}...`}</>;\n }\n\n if (hasError) {\n return <>{`${type} missing or inaccessible`}</>;\n }\n\n return (\n <>\n {getEntityInfo({ entityTitle, contentTypeName: type, entityStatus })}{' '}\n {jobs.length > 0 ? getScheduleTooltipContent({ job: jobs[0], jobsCount: jobs.length }) : ''}\n </>\n );\n}\n","export function truncate(str, length) {\n if (typeof str === 'string' && str.length > length) {\n return (\n str &&\n str\n .substr(0, length + 1) // +1 to look ahead and be replaced below.\n // Get rid of orphan letters but not one letter words (I, a, 2).\n // Try to not have “.” as last character to avoid awkward “....”.\n .replace(/(\\s+\\S(?=\\S)|\\s*)\\.?.$/, '…')\n );\n }\n\n return str;\n}\n","import * as React from 'react';\nimport { Entry, Asset } from '@contentful/field-editor-shared';\nimport { useEntities, ScheduledIconWithTooltip } from '@contentful/field-editor-reference';\nimport { ClockIcon } from '@contentful/f36-icons';\nimport { css } from 'emotion';\nimport tokens from '@contentful/f36-tokens';\n\nconst styles = {\n scheduleIcon: css({\n marginRight: tokens.spacing2Xs,\n }),\n};\n\ninterface EntityStatusIconProps {\n entity: Entry | Asset;\n entityType: 'Entry' | 'Asset';\n}\n\nexport function EntityStatusIcon({ entity, entityType }: EntityStatusIconProps) {\n const { loadEntityScheduledActions } = useEntities();\n\n return (\n <ScheduledIconWithTooltip\n getEntityScheduledActions={loadEntityScheduledActions}\n entityType={entityType}\n entityId={entity.sys.id}>\n <ClockIcon\n className={styles.scheduleIcon}\n size=\"small\"\n color=\"muted\"\n testId=\"schedule-icon\"\n />\n </ScheduledIconWithTooltip>\n );\n}\n","import * as React from 'react';\nimport { EntryCard, MenuItem } from '@contentful/f36-components';\nimport { useEntities, MissingEntityCard, AssetThumbnail } from '@contentful/field-editor-reference';\nimport { FieldExtensionSDK } from '@contentful/app-sdk';\nimport { entityHelpers, File, isValidImage } from '@contentful/field-editor-shared';\nimport { css } from 'emotion';\nimport { EntityStatusIcon } from './EntityStatusIcon';\n\nconst styles = {\n entryCard: css({ cursor: 'pointer' }),\n};\n\ninterface FetchingWrappedEntryCardProps {\n entryId: string;\n isDisabled: boolean;\n isSelected: boolean;\n locale: string;\n sdk: FieldExtensionSDK;\n onEdit?: () => void;\n onRemove?: () => void;\n}\n\ninterface EntryThumbnailProps {\n file: File;\n}\n\nfunction EntryThumbnail({ file }: EntryThumbnailProps) {\n if (!isValidImage(file)) return null;\n\n return <AssetThumbnail file={file as File} />;\n}\n\nexport function FetchingWrappedEntryCard(props: FetchingWrappedEntryCardProps) {\n const { getOrLoadEntry, entries } = useEntities();\n const [file, setFile] = React.useState<File | null>(null);\n const entry = entries[props.entryId];\n const contentType = React.useMemo(() => {\n if (!entry || entry === 'failed') {\n return undefined;\n }\n return props.sdk.space\n .getCachedContentTypes()\n .find((contentType) => contentType.sys.id === entry.sys.contentType.sys.id);\n }, [props.sdk, entry]);\n const defaultLocaleCode = props.sdk.locales.default;\n\n React.useEffect(() => {\n if (!entry || entry === 'failed') return;\n\n entityHelpers\n .getEntryImage(\n {\n entry,\n contentType,\n localeCode: props.locale,\n defaultLocaleCode,\n },\n props.sdk.space.getAsset\n )\n .then(setFile)\n .catch(() => setFile(null));\n }, [entry, contentType, props.locale, defaultLocaleCode, props.sdk, file]);\n\n React.useEffect(() => {\n getOrLoadEntry(props.entryId);\n }, [props.entryId]); // eslint-disable-line\n\n function renderDropdown() {\n if (!props.onEdit || !props.onRemove) return undefined;\n\n return [\n props.onEdit ? (\n <MenuItem\n key=\"edit\"\n testId=\"card-action-edit\"\n onClick={() => {\n props.onEdit && props.onEdit();\n }}>\n Edit\n </MenuItem>\n ) : null,\n props.onRemove ? (\n <MenuItem\n key=\"delete\"\n testId=\"card-action-remove\"\n onClick={() => {\n props.onRemove && props.onRemove();\n }}>\n Remove\n </MenuItem>\n ) : null,\n ].filter((item) => item);\n }\n\n if (entry === undefined) {\n return <EntryCard size=\"default\" isLoading={true} />;\n }\n\n if (entry === 'failed') {\n return (\n <MissingEntityCard\n entityType=\"Entry\"\n isDisabled={props.isDisabled}\n onRemove={props.onRemove}\n />\n );\n }\n\n const entryStatus = entry ? entityHelpers.getEntryStatus(entry.sys) : undefined;\n if (entryStatus === 'deleted') {\n return (\n <MissingEntityCard\n entityType=\"Entry\"\n isDisabled={props.isDisabled}\n onRemove={props.onRemove}\n />\n );\n }\n\n const title = entityHelpers.getEntryTitle({\n entry,\n contentType,\n localeCode: props.locale,\n defaultLocaleCode,\n defaultTitle: 'Untitled',\n });\n\n const description = entityHelpers.getEntityDescription({\n entity: entry,\n contentType,\n localeCode: props.locale,\n defaultLocaleCode,\n });\n\n return (\n <EntryCard\n contentType={contentType?.name}\n title={title}\n description={description}\n size=\"default\"\n isSelected={props.isSelected}\n status={entryStatus}\n className={styles.entryCard}\n thumbnailElement={file ? <EntryThumbnail file={file} /> : undefined}\n icon={<EntityStatusIcon entityType=\"Entry\" entity={entry} />}\n withDragHandle={false}\n actions={renderDropdown()}\n />\n );\n}\n","import * as React from 'react';\nimport { AssetCard, AssetType, Menu, Text } from '@contentful/f36-components';\nimport { useEntities, MissingEntityCard } from '@contentful/field-editor-reference';\n\nimport { FieldExtensionSDK } from '@contentful/app-sdk';\nimport { entityHelpers, File, shortenStorageUnit } from '@contentful/field-editor-shared';\nimport mimetype from '@contentful/mimetype';\nimport { css } from 'emotion';\nimport get from 'lodash/get';\nimport { EntityStatusIcon } from './EntityStatusIcon';\n\nconst styles = {\n assetCard: css({ cursor: 'pointer' }),\n cardDropdown: css({\n width: '300px',\n }),\n truncated: css({\n overflow: 'hidden',\n whiteSpace: 'nowrap',\n textOverflow: 'ellipsis',\n }),\n};\ninterface FetchingWrappedAssetCardProps {\n assetId: string;\n isDisabled: boolean;\n isSelected: boolean;\n locale: string;\n onEdit?: () => void;\n onRemove?: () => unknown;\n sdk: FieldExtensionSDK;\n}\n\nfunction downloadAsset(url: string) {\n window.open(url, '_blank', 'noopener,noreferrer');\n}\n\nexport function renderAssetInfo(props: { entityFile: File }) {\n const { entityFile } = props;\n const fileName = get(entityFile, 'fileName');\n const mimeType = get(entityFile, 'contentType');\n const fileSize = get(entityFile, 'details.size');\n const image = get(entityFile, 'details.image');\n return [\n <Menu.SectionTitle key=\"file-section\">File info</Menu.SectionTitle>,\n fileName && (\n <Menu.Item key=\"file-name\">\n <Text isTruncated>{fileName}</Text>\n </Menu.Item>\n ),\n mimeType && (\n <Menu.Item key=\"file-type\">\n <Text isTruncated>{mimeType}</Text>\n </Menu.Item>\n ),\n fileSize && <Menu.Item key=\"file-size\">{shortenStorageUnit(fileSize, 'B')}</Menu.Item>,\n image && <Menu.Item key=\"file-dimentions\">{`${image.width} × ${image.height}`}</Menu.Item>,\n ].filter((item) => item);\n}\n\nexport function renderActions(props: {\n onEdit?: () => void;\n onRemove?: () => void;\n isDisabled: boolean;\n entityFile?: File;\n}) {\n const { entityFile, isDisabled, onEdit, onRemove } = props;\n\n return [\n <Menu.SectionTitle key=\"section-title\">Actions</Menu.SectionTitle>,\n onEdit ? (\n <Menu.Item key=\"edit\" onClick={onEdit} testId=\"card-action-edit\">\n Edit\n </Menu.Item>\n ) : null,\n entityFile ? (\n <Menu.Item\n key=\"download\"\n onClick={() => {\n if (typeof entityFile.url === 'string') {\n downloadAsset(entityFile.url);\n }\n }}\n testId=\"card-action-download\">\n Download\n </Menu.Item>\n ) : null,\n onRemove ? (\n <Menu.Item key=\"remove\" disabled={isDisabled} onClick={onRemove} testId=\"card-action-remove\">\n Remove\n </Menu.Item>\n ) : null,\n ].filter((item) => item);\n}\n\nexport function FetchingWrappedAssetCard(props: FetchingWrappedAssetCardProps) {\n const { getOrLoadAsset, assets } = useEntities();\n const asset = assets[props.assetId];\n const defaultLocaleCode = props.sdk.locales.default;\n const entityFile: File | undefined = asset?.fields?.file\n ? asset.fields.file[props.locale] || asset.fields.file[defaultLocaleCode]\n : undefined;\n\n React.useEffect(() => {\n getOrLoadAsset(props.assetId);\n }, [props.assetId]); // eslint-disable-line\n\n function getAssetSrc() {\n if (!entityFile?.url) return '';\n\n return `${entityFile.url}?h=300`;\n }\n\n function getFileType(): AssetType {\n const groupToIconMap = {\n image: 'image',\n video: 'video',\n audio: 'audio',\n richtext: 'richtext',\n presentation: 'presentation',\n spreadsheet: 'spreadsheet',\n pdfdocument: 'pdf',\n archive: 'archive',\n plaintext: 'plaintext',\n code: 'code',\n markup: 'markup',\n };\n const archive = groupToIconMap['archive'] as AssetType;\n\n if (!entityFile) {\n return archive;\n }\n\n const groupName: keyof typeof groupToIconMap = mimetype.getGroupLabel({\n type: entityFile.contentType,\n fallbackFileName: entityFile.fileName,\n });\n\n return (groupToIconMap[groupName] as AssetType) || archive;\n }\n\n if (asset === undefined) {\n return <AssetCard size=\"small\" isLoading />;\n }\n\n if (asset === 'failed') {\n return (\n <MissingEntityCard\n entityType=\"Asset\"\n isDisabled={props.isDisabled}\n onRemove={props.onRemove}\n />\n );\n }\n\n const status = asset ? entityHelpers.getEntryStatus(asset.sys) : undefined;\n if (status === 'deleted') {\n return (\n <MissingEntityCard\n entityType=\"Asset\"\n asSquare={true}\n isDisabled={props.isDisabled}\n onRemove={props.onRemove}\n />\n );\n }\n\n const entityTitle = entityHelpers.getAssetTitle({\n asset,\n localeCode: props.locale,\n defaultLocaleCode,\n defaultTitle: 'Untitled',\n });\n\n return (\n <AssetCard\n title={entityTitle}\n isSelected={props.isSelected}\n size=\"small\"\n src={getAssetSrc()}\n type={getFileType()}\n status={status}\n icon={<EntityStatusIcon entityType=\"Asset\" entity={asset} />}\n className={styles.assetCard}\n actions={[\n renderActions({\n entityFile,\n isDisabled: props.isDisabled,\n onEdit: props.onEdit,\n onRemove: props.onRemove,\n }),\n entityFile ? renderAssetInfo({ entityFile }) : null,\n ].filter((item) => item)}\n />\n );\n}\n","/* eslint-disable you-dont-need-lodash-underscore/find */\nimport flow from 'lodash/flow';\nimport find from 'lodash/find';\nimport get from 'lodash/get';\n\n/**\n * Given a field object and a rich text node type, return a list of valid\n * content type IDs associated with the node type, based on that node type's\n * `linkContentType` validation.\n *\n * If there is no such validation or the validation is empty, return an empty\n * array.\n *\n * The navigation here is explained by the `nodes` validation having signature:\n * { nodes: { [nodeType]: validationObject[] } }\n *\n * We defensively navigate through this object because\n * 1) the field may not have a `validations` array,\n * 2) the `validations` array may be empty,\n * 3) the `validations` array may not have a `nodes` validation,\n * 4) the `nodes` validation may not validate the `nodeType`, and\n * 5) the `nodeType` validations may not have a `linkContentType` validation.\n *\n * Note that passing an empty array will result in all possible content types\n * being whitelisted.\n *\n * @param {object} field\n * @param {string} nodeType\n * @returns {string[]}\n */\nexport default function getLinkedContentTypeIdsForNodeType(field, nodeType): string[] {\n return flow(\n (v) => find(v, 'nodes'),\n (v) => get(v, ['nodes', nodeType]),\n (v) => find(v, 'linkContentType'),\n (v) => get(v, 'linkContentType', [])\n )(field.validations);\n}\n","import * as React from 'react';\nimport { INLINES } from '@contentful/rich-text-types';\nimport {\n TextLink,\n Button,\n FormControl,\n FormLabel,\n Select,\n TextInput,\n Form,\n ModalContent,\n ModalControls,\n} from '@contentful/f36-components';\nimport { ModalDialogLauncher, FieldExtensionSDK } from '@contentful/field-editor-shared';\nimport { PlateEditor } from '@udecode/plate';\nimport { Editor, Transforms } from 'slate';\nimport { ReactEditor } from 'slate-react';\nimport { HistoryEditor } from 'slate-history';\nimport { EntityProvider } from '@contentful/field-editor-reference';\nimport { Link } from '@contentful/field-editor-reference/dist/types';\nimport { css } from 'emotion';\nimport tokens from '@contentful/f36-tokens';\nimport { getNodeEntryFromSelection, insertLink, LINK_TYPES } from '../../helpers/editor';\nimport { FetchingWrappedEntryCard } from '../shared/FetchingWrappedEntryCard';\nimport { FetchingWrappedAssetCard } from '../shared/FetchingWrappedAssetCard';\nimport getLinkedContentTypeIdsForNodeType from '../../helpers/getLinkedContentTypeIdsForNodeType';\nimport { isNodeTypeEnabled } from '../../helpers/validations';\n\nconst styles = {\n removeSelectionLabel: css`\n margin-left: ${tokens.spacingS};\n `,\n};\n\ninterface HyperlinkModalProps {\n linkText?: string;\n linkType?: string;\n linkTarget?: string;\n linkEntity?: Link;\n onClose: (value: unknown) => void;\n sdk: FieldExtensionSDK;\n}\n\nconst SYS_LINK_TYPES = {\n [INLINES.ENTRY_HYPERLINK]: 'Entry',\n [INLINES.ASSET_HYPERLINK]: 'Asset',\n};\n\nconst LINK_TYPE_SELECTION_VALUES = {\n [INLINES.HYPERLINK]: 'URL',\n [INLINES.ENTRY_HYPERLINK]: 'Entry',\n [INLINES.ASSET_HYPERLINK]: 'Asset',\n};\n\nexport function HyperlinkModal(props: HyperlinkModalProps) {\n const enabledLinkTypes = LINK_TYPES.filter((nodeType) =>\n isNodeTypeEnabled(props.sdk.field, nodeType)\n );\n const [defaultLinkType] = enabledLinkTypes;\n const [linkText, setLinkText] = React.useState(props.linkText ?? '');\n const [linkType, setLinkType] = React.useState(props.linkType ?? defaultLinkType);\n const [linkTarget, setLinkTarget] = React.useState(props.linkTarget ?? '');\n const [linkEntity, setLinkEntity] = React.useState<Link | null>(props.linkEntity ?? null);\n\n function isLinkComplete() {\n const isRegularLink = linkType === INLINES.HYPERLINK;\n if (isRegularLink) {\n return !!(linkText && linkTarget);\n }\n\n const entityLinks: string[] = Object.keys(SYS_LINK_TYPES);\n const isEntityLink = entityLinks.includes(linkType);\n if (isEntityLink) {\n return !!(linkText && linkEntity);\n }\n\n return false;\n }\n\n function handleOnSubmit(event: React.MouseEvent<HTMLButtonElement>) {\n event.preventDefault();\n\n props.onClose({ linkText, linkType, linkTarget, linkEntity });\n }\n\n function entityToLink(entity): Link {\n const { id, type } = entity.sys;\n\n return { sys: { id, type: 'Link', linkType: type } };\n }\n\n async function selectEntry() {\n const options = {\n locale: props.sdk.field.locale,\n contentTypes: getLinkedContentTypeIdsForNodeType(props.sdk.field, INLINES.ENTRY_HYPERLINK),\n };\n const entry = await props.sdk.dialogs.selectSingleEntry(options);\n setLinkTarget('');\n setLinkEntity(entityToLink(entry));\n }\n\n async function selectAsset() {\n const options = {\n locale: props.sdk.field.locale,\n };\n const asset = await props.sdk.dialogs.selectSingleAsset(options);\n setLinkTarget('');\n setLinkEntity(entityToLink(asset));\n }\n\n function resetLinkEntity(event: React.MouseEvent) {\n event.preventDefault();\n\n setLinkEntity(null);\n }\n\n return (\n <EntityProvider sdk={props.sdk}>\n <React.Fragment>\n <ModalContent>\n <Form>\n {!props.linkType && (\n <FormControl id=\"link-text\" isRequired>\n <FormControl.Label>Link text</FormControl.Label>\n <TextInput\n testId=\"link-text-input\"\n name=\"link-text\"\n value={linkText}\n onChange={(event) => setLinkText(event.target.value)}\n />\n </FormControl>\n )}\n\n {enabledLinkTypes.length > 1 && (\n <FormControl id=\"link-type\">\n <FormControl.Label>Link type</FormControl.Label>\n <Select\n value={linkType}\n onChange={(event: React.ChangeEvent<HTMLSelectElement>) =>\n setLinkType(event.target.value)\n }\n testId=\"link-type-input\">\n {enabledLinkTypes.map((nodeType) => (\n <Select.Option key={nodeType} value={nodeType}>\n {LINK_TYPE_SELECTION_VALUES[nodeType]}\n </Select.Option>\n ))}\n </Select>\n </FormControl>\n )}\n\n {linkType === INLINES.HYPERLINK && (\n <FormControl id=\"linkTarget\" isRequired>\n <FormControl.Label>Link target</FormControl.Label>\n <TextInput\n name=\"linkTarget\"\n value={linkTarget}\n onChange={(event: React.ChangeEvent<HTMLInputElement>) => {\n setLinkEntity(null);\n setLinkTarget(event.target.value);\n }}\n testId=\"link-target-input\"\n />\n <FormControl.HelpText>\n A protocol may be required, e.g. https://\n </FormControl.HelpText>\n </FormControl>\n )}\n\n {linkType !== INLINES.HYPERLINK && (\n <div>\n <FormLabel isRequired htmlFor=\"\">\n Link target{' '}\n </FormLabel>\n\n {linkEntity && linkEntity.sys.linkType === SYS_LINK_TYPES[linkType] ? (\n <>\n <TextLink\n testId=\"entity-selection-link\"\n onClick={resetLinkEntity}\n className={styles.removeSelectionLabel}>\n Remove selection\n </TextLink>\n <div>\n {linkType === INLINES.ENTRY_HYPERLINK && (\n <FetchingWrappedEntryCard\n sdk={props.sdk}\n locale={props.sdk.field.locale}\n entryId={linkEntity.sys.id}\n isDisabled={true}\n isSelected={false}\n />\n )}\n {linkType === INLINES.ASSET_HYPERLINK && (\n <FetchingWrappedAssetCard\n sdk={props.sdk}\n locale={props.sdk.field.locale}\n assetId={linkEntity.sys.id}\n isDisabled={true}\n isSelected={false}\n />\n )}\n </div>\n </>\n ) : (\n <div>\n {linkType === INLINES.ENTRY_HYPERLINK && (\n <TextLink testId=\"entity-selection-link\" onClick={selectEntry}>\n Select entry\n </TextLink>\n )}\n {linkType === INLINES.ASSET_HYPERLINK && (\n <TextLink testId=\"entity-selection-link\" onClick={selectAsset}>\n Select asset\n </TextLink>\n )}\n </div>\n )}\n </div>\n )}\n </Form>\n </ModalContent>\n <ModalControls>\n <Button\n type=\"button\"\n onClick={() => props.onClose(null)}\n variant=\"secondary\"\n testId=\"cancel-cta\"\n size=\"small\">\n Cancel\n </Button>\n <Button\n type=\"submit\"\n variant=\"positive\"\n size=\"small\"\n isDisabled={!isLinkComplete()}\n onClick={handleOnSubmit}\n testId=\"confirm-cta\">\n {props.linkType ? 'Update' : 'Insert'}\n </Button>\n </ModalControls>\n </React.Fragment>\n </EntityProvider>\n );\n}\n\ninterface HyperLinkDialogData {\n linkText: string;\n linkType: INLINES.HYPERLINK | INLINES.ASSET_HYPERLINK | INLINES.ENTRY_HYPERLINK;\n linkTarget?: string;\n linkEntity?: Link;\n}\n\nexport async function addOrEditLink(\n editor: ReactEditor & HistoryEditor & PlateEditor,\n sdk: FieldExtensionSDK\n) {\n if (!editor.selection) return;\n\n let linkType;\n let linkText;\n let linkTarget;\n let linkEntity;\n\n const [node, path] = getNodeEntryFromSelection(editor, LINK_TYPES);\n if (node && path) {\n linkType = node.type;\n linkText = Editor.string(editor, path);\n linkTarget = (node.data as { uri: string }).uri || '';\n linkEntity = (node.data as { target: Link }).target;\n }\n\n const selectionBeforeBlur = { ...editor.selection };\n const currentLinkText = linkText || Editor.string(editor, editor.selection);\n\n const data = await ModalDialogLauncher.openDialog(\n {\n title: linkType ? 'Edit hyperlink' : 'Insert hyperlink',\n width: 'large',\n shouldCloseOnEscapePress: true,\n shouldCloseOnOverlayClick: true,\n allowHeightOverflow: true,\n },\n ({ onClose }) => {\n return (\n <HyperlinkModal\n linkTarget={linkTarget}\n linkText={currentLinkText}\n linkType={linkType}\n linkEntity={linkEntity}\n onClose={onClose}\n sdk={sdk}\n />\n );\n }\n );\n\n if (!data) return;\n\n const {\n linkText: text,\n linkTarget: url,\n linkType: type,\n linkEntity: target,\n } = data as HyperLinkDialogData;\n\n Transforms.select(editor, selectionBeforeBlur);\n\n insertLink(editor, { text, url, type, target, path });\n\n ReactEditor.focus(editor);\n}\n","import * as React from 'react';\nimport {\n PlatePlugin,\n getRenderElement,\n getPlatePluginTypes,\n getPlatePluginOptions,\n} from '@udecode/plate';\nimport { INLINES } from '@contentful/rich-text-types';\nimport { Tooltip, TextLink } from '@contentful/f36-components';\nimport { EntryAssetTooltip } from './EntryAssetTooltip';\nimport { LinkIcon } from '@contentful/f36-icons';\nimport { ToolbarButton } from '../shared/ToolbarButton';\nimport { css } from 'emotion';\nimport tokens from '@contentful/f36-tokens';\nimport { FieldExtensionSDK, Link, ContentEntityType as EntityType } from '@contentful/app-sdk';\nimport { CustomSlatePluginOptions, CustomRenderElementProps } from '../../types';\nimport { useSdkContext } from '../../SdkProvider';\nimport { addOrEditLink } from './HyperlinkModal';\nimport { isLinkActive, LINK_TYPES, unwrapLink } from '../../helpers/editor';\nimport { useContentfulEditor } from '../../ContentfulEditorProvider';\n\nconst styles = {\n hyperlinkWrapper: css({\n display: 'inline',\n position: 'static',\n a: {\n fontSize: 'inherit !important',\n },\n }),\n hyperlink: css({\n fontSize: 'inherit !important',\n display: 'inline !important',\n '&:hover': {\n fill: tokens.gray900,\n },\n '&:focus': {\n fill: tokens.gray900,\n },\n }),\n hyperlinkIEFallback: css({\n color: '#1683d0',\n textDecoration: 'underline',\n }),\n // TODO: use these styles once we can use the icon\n hyperlinkIcon: css({\n position: 'relative',\n top: '4px',\n height: '14px',\n margin: '0 -2px 0 -1px',\n webkitTransition: 'fill 100ms ease-in-out',\n transition: 'fill 100ms ease-in-out',\n '&:hover': {\n fill: tokens.gray900,\n },\n '&:focus': {\n fill: tokens.gray900,\n },\n }),\n};\n\nexport function createHyperlinkPlugin(sdk: FieldExtensionSDK): PlatePlugin {\n return {\n renderElement: getRenderElement(LINK_TYPES),\n pluginKeys: LINK_TYPES,\n inlineTypes: getPlatePluginTypes(LINK_TYPES),\n onKeyDown: buildHyperlinkEventHandler(sdk),\n deserialize: (editor) => {\n const hyperlinkOptions = getPlatePluginOptions(editor, INLINES.HYPERLINK);\n const entryHyperlinkOptions = getPlatePluginOptions(editor, INLINES.ENTRY_HYPERLINK);\n const assetHyperlinkOptions = getPlatePluginOptions(editor, INLINES.ASSET_HYPERLINK);\n\n const isAnchor = (element) =>\n element.nodeName === 'A' &&\n !!element.getAttribute('href') &&\n element.getAttribute('href') !== '#';\n const isEntryAnchor = (element) =>\n isAnchor(element) && element.getAttribute('data-link-type') === 'Entry';\n const isAssetAnchor = (element) =>\n isAnchor(element) && element.getAttribute('data-link-type') === 'Asset';\n\n return {\n element: [\n {\n type: INLINES.HYPERLINK,\n deserialize: (element) => {\n if (!isAnchor(element) || isEntryAnchor(element) || isAssetAnchor(element)) return;\n\n return {\n type: INLINES.HYPERLINK,\n data: {\n uri: element.getAttribute('href'),\n },\n };\n },\n ...hyperlinkOptions.deserialize,\n },\n {\n type: INLINES.ENTRY_HYPERLINK,\n deserialize: (element) => {\n if (!isEntryAnchor(element)) return;\n\n return {\n type: INLINES.ENTRY_HYPERLINK,\n data: {\n target: {\n sys: {\n id: element.getAttribute('data-link-id'),\n linkType: element.getAttribute('data-link-type'),\n type: 'Link',\n },\n },\n },\n };\n },\n ...entryHyperlinkOptions.deserialize,\n },\n {\n type: INLINES.ASSET_HYPERLINK,\n deserialize: (element) => {\n if (!isAssetAnchor(element)) return;\n\n return {\n type: INLINES.ASSET_HYPERLINK,\n data: {\n target: {\n sys: {\n id: element.getAttribute('data-link-id'),\n linkType: element.getAttribute('data-link-type'),\n type: 'Link',\n },\n },\n },\n };\n },\n ...assetHyperlinkOptions.deserialize,\n },\n ],\n };\n },\n };\n}\n\ntype K = 75;\ntype KEvent = React.KeyboardEvent & { keyCode: K };\ntype CtrlEvent = React.KeyboardEvent & { ctrlKey: true };\ntype MetaEvent = React.KeyboardEvent & { metaKey: true };\ntype ModEvent = CtrlEvent | MetaEvent;\ntype HyperlinkEvent = ModEvent & KEvent;\n\nconst isMod = (event: React.KeyboardEvent): event is ModEvent => event.ctrlKey || event.metaKey;\nconst isK = (event: React.KeyboardEvent): event is KEvent => event.keyCode === 75;\nconst wasHyperlinkEventTriggered = (event: React.KeyboardEvent): event is HyperlinkEvent =>\n isMod(event) && isK(event);\n\nexport function buildHyperlinkEventHandler(sdk) {\n return function withHyperlinkEvents(editor) {\n return function handleKeyDown(event: React.KeyboardEvent) {\n if (!editor.selection || !wasHyperlinkEventTriggered(event)) return;\n if (isLinkActive(editor)) {\n unwrapLink(editor);\n } else {\n addOrEditLink(editor, sdk);\n }\n };\n };\n}\n\ntype HyperlinkElementProps = CustomRenderElementProps<{\n uri?: string;\n target?: Link;\n}>;\n\nfunction UrlHyperlink(props: HyperlinkElementProps) {\n const editor = useContentfulEditor();\n const sdk: FieldExtensionSDK = useSdkContext();\n const { uri } = props.element.data;\n\n async function handleClick(event: React.MouseEvent<HTMLAnchorElement>) {\n event.preventDefault();\n event.stopPropagation();\n if (!editor) return;\n addOrEditLink(editor, sdk);\n }\n\n return (\n <Tooltip\n content={uri}\n targetWrapperClassName={styles.hyperlinkWrapper}\n placement=\"bottom\"\n maxWidth=\"auto\">\n <TextLink\n as=\"a\"\n href={uri}\n rel=\"noopener noreferrer\"\n onClick={handleClick}\n className={styles.hyperlink}>\n {props.children}\n </TextLink>\n </Tooltip>\n );\n}\n\nfunction EntityHyperlink(props: HyperlinkElementProps) {\n const editor = useContentfulEditor();\n const sdk: FieldExtensionSDK = useSdkContext();\n const { target } = props.element.data;\n\n if (!target) return null;\n\n async function handleClick(event: React.MouseEvent<HTMLButtonElement>) {\n event.preventDefault();\n event.stopPropagation();\n if (!editor) return;\n addOrEditLink(editor, sdk);\n }\n\n return (\n <Tooltip\n content={\n (\n <EntryAssetTooltip\n id={target.sys.id}\n type={target.sys.linkType as EntityType}\n sdk={sdk}\n />\n ) as unknown as string\n }\n targetWrapperClassName={styles.hyperlinkWrapper}\n placement=\"bottom\"\n maxWidth=\"auto\">\n <TextLink\n as=\"button\"\n onClick={handleClick}\n className={styles.hyperlink}\n data-link-type={target.sys.linkType}\n data-link-id={target.sys.id}>\n {props.children}\n </TextLink>\n </Tooltip>\n );\n}\n\ninterface ToolbarHyperlinkButtonProps {\n isDisabled: boolean | undefined;\n}\n\nexport function ToolbarHyperlinkButton(props: ToolbarHyperlinkButtonProps) {\n const editor = useContentfulEditor();\n const isActive = !!(editor && isLinkActive(editor));\n const sdk: FieldExtensionSDK = useSdkContext();\n\n async function handleClick() {\n if (!editor) return;\n\n if (isActive) {\n unwrapLink(editor);\n } else {\n addOrEditLink(editor, sdk);\n }\n }\n\n if (!editor) return null;\n\n return (\n <ToolbarButton\n title=\"Hyperlink\"\n testId=\"hyperlink-toolbar-button\"\n onClick={handleClick}\n isActive={isActive}\n isDisabled={props.isDisabled}>\n <LinkIcon />\n </ToolbarButton>\n );\n}\n\nexport const withHyperlinkOptions: CustomSlatePluginOptions = {\n [INLINES.HYPERLINK]: {\n type: INLINES.HYPERLINK,\n component: UrlHyperlink,\n },\n [INLINES.ENTRY_HYPERLINK]: {\n type: INLINES.ENTRY_HYPERLINK,\n component: EntityHyperlink,\n },\n [INLINES.ASSET_HYPERLINK]: {\n type: INLINES.ASSET_HYPERLINK,\n component: EntityHyperlink,\n },\n};\n","import { Transforms, Path, Editor, Ancestor } from 'slate';\nimport {\n PlateEditor,\n ELEMENT_TABLE,\n ELEMENT_TH,\n ELEMENT_TD,\n ELEMENT_TR,\n insertTable,\n getAbove,\n getChildren,\n isFirstChild,\n isAncestorEmpty,\n} from '@udecode/plate';\nimport { BLOCKS } from '@contentful/rich-text-types';\n\nimport {\n isBlockSelected,\n getNodeEntryFromSelection,\n getAncestorPathFromSelection,\n} from '../../helpers/editor';\nimport { CustomElement } from '../../types';\n\n/**\n * Sets the UI focus to the first cell of the selected table.\n *\n * This is necessary because udecode's plugin sets the focus to the\n * _last_ cell of the table after selection, which is weird.\n */\nfunction moveToFirstCellFromSelectedTable(editor) {\n const [, tablePath] = getNodeEntryFromSelection(editor, BLOCKS.TABLE);\n if (!tablePath) return;\n const firstTableCellPath = tablePath.concat([\n 0, // -> row\n 0, // -> cell\n 0, // -> paragraph\n 0, // -> text node\n ]);\n const anchor = { path: firstTableCellPath, offset: 0 };\n Transforms.setSelection(editor, { anchor, focus: anchor });\n}\n\nexport function insertTableAndFocusFirstCell(editor: PlateEditor): void {\n // FIXME: a table should only be allowed at root level. Currently this\n // code adds it at any level\n insertTable(editor, { header: true });\n moveToFirstCellFromSelectedTable(editor);\n replaceEmptyParagraphWithTable(editor);\n}\n\nexport function isTableActive(editor: PlateEditor) {\n const tableElements = [ELEMENT_TABLE, ELEMENT_TH, ELEMENT_TR, ELEMENT_TD];\n return tableElements.some((el) => isBlockSelected(editor, el));\n}\n\nexport function isTableHeaderEnabled(editor: PlateEditor) {\n const tableItem = getAbove(editor, {\n match: {\n type: BLOCKS.TABLE,\n },\n });\n\n if (!tableItem) {\n return false;\n }\n\n const firstRow = getChildren(tableItem)[0];\n\n if (!firstRow) {\n return false;\n }\n\n return getChildren(firstRow).every(([node]) => {\n return node.type === BLOCKS.TABLE_HEADER_CELL;\n });\n}\n\nexport function replaceEmptyParagraphWithTable(editor: PlateEditor) {\n const tablePath = getAncestorPathFromSelection(editor);\n if (!tablePath || isFirstChild(tablePath)) return;\n\n const previousPath = Path.previous(tablePath);\n if (!previousPath) return;\n\n const [nodes] = Editor.nodes(editor, {\n at: previousPath,\n match: (node) => (node as CustomElement).type === BLOCKS.PARAGRAPH,\n });\n if (!nodes) return;\n\n const [previousNode] = nodes;\n const isPreviousNodeTextEmpty = isAncestorEmpty(editor, previousNode as Ancestor);\n if (isPreviousNodeTextEmpty) {\n // Switch table with previous empty paragraph\n Transforms.moveNodes(editor, { at: tablePath, to: previousPath });\n // Remove previous paragraph that now is under the table\n Transforms.removeNodes(editor, { at: tablePath });\n }\n}\n","import * as React from 'react';\nimport constate from 'constate';\n\nexport type RichTextTrackingActionName =\n | 'insertTable'\n | 'insertTableRow'\n | 'insertTableColumn'\n | 'removeTable'\n | 'removeTableRow'\n | 'removeTableColumn'\n | 'paste';\n\nexport type RichTextTrackingActionHandler = (\n name: RichTextTrackingActionName,\n data: Record<string, unknown>\n) => unknown;\n\ninterface TrackingProviderProps {\n onAction: RichTextTrackingActionHandler;\n}\n\nexport interface TrackingProvider {\n onViewportAction: (\n actionName: RichTextTrackingActionName,\n data?: Record<string, unknown>\n ) => ReturnType<TrackingProviderProps['onAction']>;\n}\n\nfunction useTracking({ onAction }: TrackingProviderProps): TrackingProvider {\n const trackingMemo = React.useMemo<TrackingProvider>(\n () => ({\n onViewportAction: (actionName: RichTextTrackingActionName, data = {}) =>\n onAction(actionName, { origin: 'viewport-interaction', ...data }),\n }),\n [] // eslint-disable-line\n );\n\n return trackingMemo;\n}\n\nexport const [TrackingProvider, useTrackingContext] = constate(useTracking);\n","import { Transforms, Path, Editor } from 'slate';\nimport {\n getAbove,\n insertNodes,\n someNode,\n getPlatePluginType,\n PlateEditor,\n TElement,\n ELEMENT_TABLE,\n ELEMENT_TR,\n getEmptyRowNode,\n} from '@udecode/plate';\n\nconst addRow = (editor: PlateEditor, getNextRowPath: (currentRowPath: Path) => Path) => {\n if (\n someNode(editor, {\n match: { type: getPlatePluginType(editor, ELEMENT_TABLE) },\n })\n ) {\n const currentRowItem = getAbove(editor, {\n match: { type: getPlatePluginType(editor, ELEMENT_TR) },\n });\n\n if (currentRowItem) {\n const [currentRowElem, currentRowPath] = currentRowItem;\n const nextRowPath = getNextRowPath(currentRowPath);\n\n insertNodes<TElement>(\n editor,\n // @ts-expect-error\n getEmptyRowNode(editor, {\n header: false,\n colCount: currentRowElem.children.length,\n }),\n {\n at: nextRowPath,\n // Note: this selects the last cell of the new row\n select: true,\n }\n );\n\n // Select the first cell in the current row\n Transforms.select(editor, Editor.start(editor, nextRowPath));\n }\n }\n};\n\nexport const addRowBelow = (editor: PlateEditor) => {\n addRow(editor, (currentRowPath) => {\n return Path.next(currentRowPath);\n });\n};\n\nexport const addRowAbove = (editor: PlateEditor) => {\n addRow(editor, (currentRowPath) => {\n // The new row will be in in-place of the old row\n return currentRowPath;\n });\n};\n","import { Path } from 'slate';\nimport {\n getAbove,\n insertNodes,\n someNode,\n getPlatePluginType,\n PlateEditor,\n TElement,\n getEmptyCellNode,\n TablePluginOptions,\n ELEMENT_TABLE,\n ELEMENT_TD,\n ELEMENT_TH,\n} from '@udecode/plate';\n\nconst addColumn = (\n editor: PlateEditor,\n { header }: TablePluginOptions,\n getNextCellPath: (currentCellPath: Path) => Path\n) => {\n if (\n someNode(editor, {\n match: { type: getPlatePluginType(editor, ELEMENT_TABLE) },\n })\n ) {\n const currentCellItem = getAbove(editor, {\n match: {\n type: [getPlatePluginType(editor, ELEMENT_TD), getPlatePluginType(editor, ELEMENT_TH)],\n },\n });\n\n const currentTableItem = getAbove(editor, {\n match: { type: getPlatePluginType(editor, ELEMENT_TABLE) },\n });\n\n if (currentCellItem && currentTableItem) {\n const nextCellPath = getNextCellPath(currentCellItem[1]);\n const newCellPath = nextCellPath.slice();\n const replacePathPos = newCellPath.length - 2;\n\n currentTableItem[0].children.forEach((_, rowIdx) => {\n newCellPath[replacePathPos] = rowIdx;\n\n insertNodes<TElement>(\n editor,\n // @ts-expect-error\n getEmptyCellNode(editor, { header: header && rowIdx === 0 }),\n {\n at: newCellPath,\n // Select the first cell of the new column\n select: rowIdx === 0,\n }\n );\n });\n }\n }\n};\n\nexport const addColumnRight = (editor: PlateEditor, options: TablePluginOptions) => {\n addColumn(editor, options, (currentCellPath) => Path.next(currentCellPath));\n};\n\nexport const addColumnLeft = (editor: PlateEditor, options: TablePluginOptions) => {\n addColumn(editor, options, (currentCellPath) => currentCellPath);\n};\n","import React from 'react';\nimport { css } from 'emotion';\nimport * as Slate from 'slate-react';\nimport {\n PlateEditor,\n TablePluginOptions,\n deleteColumn,\n deleteRow,\n deleteTable,\n getAbove,\n} from '@udecode/plate';\nimport { IconButton, Menu } from '@contentful/f36-components';\nimport { ChevronDownIcon } from '@contentful/f36-icons';\nimport { BLOCKS } from '@contentful/rich-text-types';\n\nimport { isTableHeaderEnabled } from './helpers';\nimport { useContentfulEditor } from '../../ContentfulEditorProvider';\nimport { getNodeEntryFromSelection, getTableSize } from '../../helpers/editor';\nimport { RichTextTrackingActionName, useTrackingContext } from '../../TrackingProvider';\nimport { addRowAbove, addColumnLeft, addColumnRight, addRowBelow, setHeader } from './actions';\n\nexport const styles = {\n topRight: css({\n position: 'absolute',\n top: '6px',\n right: '5px',\n }),\n};\n\nconst getCurrentTableSize = (\n editor: PlateEditor\n): Record<'numRows' | 'numColumns', number> | null => {\n const [table] = getNodeEntryFromSelection(editor, BLOCKS.TABLE);\n return table ? getTableSize(table) : null;\n};\n\ntype TableAction = (editor: PlateEditor, options: TablePluginOptions) => void;\n\nexport const TableActions = () => {\n const editor = useContentfulEditor();\n const { onViewportAction } = useTrackingContext();\n const [isOpen, setOpen] = React.useState(false);\n const [isHeaderEnabled, setHeaderEnabled] = React.useState(false);\n\n const close = React.useCallback(() => {\n setOpen(false);\n\n if (!editor) return;\n\n // Makes sure we keep the editor in focus when clicking on/out\n // the dropdown menu\n Slate.ReactEditor.focus(editor);\n }, [editor]);\n\n React.useEffect(() => {\n setHeaderEnabled(Boolean(editor && isTableHeaderEnabled(editor)));\n }, [editor]);\n\n const canInsertRowAbove = React.useMemo(() => {\n if (!editor) {\n return false;\n }\n\n const headerCell = getAbove(editor, {\n match: {\n type: BLOCKS.TABLE_HEADER_CELL,\n },\n });\n\n return !headerCell;\n }, [editor]);\n\n const toggleHeader = React.useCallback(() => {\n close();\n\n if (!editor) {\n return;\n }\n\n const value = !isHeaderEnabled;\n\n setHeaderEnabled(value);\n setHeader(editor, value);\n }, [editor, close, isHeaderEnabled]);\n\n const action = React.useCallback(\n (cb: TableAction, type: 'insert' | 'remove', element: 'Table' | 'Row' | 'Column') => () => {\n if (!editor?.selection) return;\n close();\n\n const tableSize = getCurrentTableSize(editor);\n\n cb(editor, { header: isHeaderEnabled });\n\n // Tracking\n const actionName = `${type}Table${element === 'Table' ? '' : element}`;\n onViewportAction(actionName as RichTextTrackingActionName, { tableSize });\n },\n [editor, isHeaderEnabled, close, onViewportAction]\n );\n\n return (\n <Menu\n placement=\"left\"\n isOpen={isOpen}\n onOpen={() => {\n setOpen(true);\n }}\n onClose={close}>\n <Menu.Trigger>\n <IconButton\n size=\"small\"\n variant=\"transparent\"\n tabIndex={-1}\n className={styles.topRight}\n icon={<ChevronDownIcon />}\n aria-label=\"Open table menu\"\n testId=\"cf-table-actions-button\"\n />\n </Menu.Trigger>\n <Menu.List>\n <Menu.Item onClick={action(addRowAbove, 'insert', 'Row')} disabled={!canInsertRowAbove}>\n Add row above\n </Menu.Item>\n <Menu.Item onClick={action(addRowBelow, 'insert', 'Row')}>Add row below</Menu.Item>\n <Menu.Item onClick={action(addColumnLeft, 'insert', 'Column')}>Add column left</Menu.Item>\n <Menu.Item onClick={action(addColumnRight, 'insert', 'Column')}>Add column right</Menu.Item>\n <Menu.Divider />\n <Menu.Item onClick={toggleHeader}>\n {isHeaderEnabled ? 'Disable table header' : 'Enable table header'}\n </Menu.Item>\n <Menu.Divider />\n <Menu.Item onClick={action(deleteRow, 'remove', 'Row')}>Delete row</Menu.Item>\n <Menu.Item onClick={action(deleteColumn, 'remove', 'Column')}>Delete column</Menu.Item>\n <Menu.Item onClick={action(deleteTable, 'remove', 'Table')}>Delete table</Menu.Item>\n </Menu.List>\n </Menu>\n );\n};\n","import { PlateEditor, getAbove, setNodes, getChildren } from '@udecode/plate';\nimport { BLOCKS } from '@contentful/rich-text-types';\n\nexport const setHeader = (editor: PlateEditor, enable?: boolean) => {\n const tableItem = getAbove(editor, {\n match: { type: BLOCKS.TABLE },\n });\n\n if (!tableItem) {\n return;\n }\n\n const firstRow = getChildren(tableItem)[0];\n\n if (!firstRow) {\n return;\n }\n\n getChildren(firstRow).forEach(([, path]) => {\n setNodes(\n editor,\n {\n type: enable ? BLOCKS.TABLE_HEADER_CELL : BLOCKS.TABLE_CELL,\n },\n { at: path }\n );\n });\n};\n","import { NodeEntry, Element } from 'slate';\nimport { PlateEditor } from '@udecode/plate-core';\n\nimport { CustomElement } from '../types';\n\nexport type Normalizer = (editor: PlateEditor, entry: NodeEntry<CustomElement>) => true | undefined;\n\n/**\n * Injects a custom element normalization handler.\n *\n * Handlers must explicity return \"true\" to indicate a pass.\n * A pass is when a handler didn't encounter any normalization\n * paths (i.e. all nodes were valid)\n *\n * Important read:\n * https://docs.slatejs.org/concepts/11-normalizing#multi-pass-normalizing\n */\nexport const withNormalizer = (editor: PlateEditor, handler: Normalizer) => {\n const { normalizeNode } = editor;\n\n editor.normalizeNode = (entry) => {\n const [node] = entry;\n\n let passed = false;\n\n if (Element.isElement(node)) {\n passed = handler(editor, entry as NodeEntry<CustomElement>) === true;\n }\n\n if (passed) {\n normalizeNode(entry);\n }\n };\n};\n","import { PlateEditor } from '@udecode/plate';\nimport { Element, Node, Transforms } from 'slate';\nimport { BLOCKS, CONTAINERS } from '@contentful/rich-text-types';\n\nimport { CustomElement } from '../../types';\nimport { replaceNode, extractParagraphsAt } from '../../helpers/editor';\nimport { Normalizer, withNormalizer } from '../../helpers/normalizers';\n\nconst isTable = (node: CustomElement) => {\n return node.type === BLOCKS.TABLE;\n};\n\nconst isTableCell = (node: CustomElement) => {\n return node.type === BLOCKS.TABLE_CELL || node.type === BLOCKS.TABLE_HEADER_CELL;\n};\n\n/**\n * Normalizes TABLE_CELL & TABLE_HEADER_CELL nodes\n */\nconst normalizeTableCell: Normalizer = (editor, entry) => {\n const [node, path] = entry;\n\n if (!isTableCell(node)) {\n return true;\n }\n\n for (const [child, childPath] of Node.children(editor, path)) {\n if (!Element.isElement(child)) {\n continue;\n }\n\n const isValidTableCellItem = CONTAINERS[node.type].includes(child.type);\n\n if (!isValidTableCellItem) {\n const text = extractParagraphsAt(editor, childPath);\n replaceNode(editor, childPath, text);\n return;\n }\n }\n\n return true;\n};\n\n/**\n * Normalizes TABLE nodes\n */\nconst normalizeTable: Normalizer = (editor, entry) => {\n const [node, path] = entry;\n\n if (!isTable(node)) {\n return true;\n }\n\n // All direct children must be of type TABLE_ROW\n for (const [child, childPath] of Node.children(editor, path)) {\n if (!Element.isElement(child)) {\n continue;\n }\n\n const isValidTableChild = CONTAINERS[BLOCKS.TABLE].includes(child.type as BLOCKS);\n\n if (!isValidTableChild) {\n Transforms.removeNodes(editor, { at: childPath });\n return;\n }\n }\n\n return true;\n};\n\nexport const addTableNormalizers = (editor: PlateEditor) => {\n withNormalizer(editor, normalizeTable);\n withNormalizer(editor, normalizeTableCell);\n};\n","import { css } from 'emotion';\nimport * as React from 'react';\nimport * as Slate from 'slate-react';\nimport tokens from '@contentful/f36-tokens';\nimport { TableIcon } from '@contentful/f36-icons';\nimport { ToolbarButton } from '../shared/ToolbarButton';\nimport { BLOCKS, TableCell, TableHeaderCell } from '@contentful/rich-text-types';\nimport {\n createTablePlugin as createTablePluginFromUdecode,\n ELEMENT_TABLE,\n ELEMENT_TD,\n ELEMENT_TH,\n ELEMENT_TR,\n getTableOnKeyDown,\n PlateEditor,\n} from '@udecode/plate';\nimport { TableActions } from './TableActions';\nimport { useContentfulEditor } from '../../ContentfulEditorProvider';\nimport { CustomElement, CustomSlatePluginOptions } from '../../types';\nimport { insertTableAndFocusFirstCell, isTableActive } from './helpers';\nimport { TrackingProvider, useTrackingContext } from '../../TrackingProvider';\nimport { Transforms } from 'slate';\nimport {\n currentSelectionPrecedesTableCell,\n currentSelectionStartsTableCell,\n} from '../../helpers/editor';\nimport { addTableNormalizers } from './normalizers';\n\nconst styles = {\n [BLOCKS.TABLE]: css`\n margin-bottom: 1.5em;\n border-collapse: collapse;\n border-radius: 5px;\n border-style: hidden;\n box-shadow: 0 0 0 1px ${tokens.gray400};\n width: 100%;\n table-layout: fixed;\n overflow: hidden;\n `,\n [BLOCKS.TABLE_ROW]: css`\n border: 1px solid ${tokens.gray400};\n\n &:hover td {\n background-color: transparent !important;\n }\n `,\n [BLOCKS.TABLE_HEADER_CELL]: css`\n background-color: ${tokens.gray200};\n border: 1px solid ${tokens.gray400};\n padding: 10px 12px;\n font-weight: ${tokens.fontWeightMedium};\n text-align: left;\n min-width: 48px;\n position: relative;\n\n div:last-child {\n margin-bottom: 0;\n }\n `,\n [BLOCKS.TABLE_CELL]: css`\n border: 1px solid ${tokens.gray400};\n padding: 10px 12px;\n min-width: 48px;\n position: relative;\n\n div:last-child {\n margin-bottom: 0;\n }\n `,\n};\n\nexport const Table = (props: Slate.RenderElementProps) => (\n <table {...props.attributes} className={styles[BLOCKS.TABLE]}>\n <tbody>{props.children}</tbody>\n </table>\n);\n\nexport const TR = (props: Slate.RenderElementProps) => (\n <tr {...props.attributes} className={styles[BLOCKS.TABLE_ROW]}>\n {props.children}\n </tr>\n);\n\nexport const TH = (props: Slate.RenderElementProps) => {\n const isSelected = Slate.useSelected();\n\n return (\n <th\n {...props.attributes}\n // may include `colspan` and/or `rowspan`\n {...(props.element.data as TableHeaderCell['data'])}\n className={styles[BLOCKS.TABLE_HEADER_CELL]}>\n {isSelected && <TableActions />}\n {props.children}\n </th>\n );\n};\nexport const TD = (props: Slate.RenderElementProps) => {\n const isSelected = Slate.useSelected();\n\n return (\n <td\n {...props.attributes}\n // may include `colspan` and/or `rowspan`\n {...(props.element.data as TableCell['data'])}\n className={styles[BLOCKS.TABLE_CELL]}>\n {isSelected && <TableActions />}\n {props.children}\n </td>\n );\n};\n\nexport const withTableOptions: CustomSlatePluginOptions = {\n [ELEMENT_TABLE]: {\n type: BLOCKS.TABLE,\n component: Table,\n },\n [ELEMENT_TR]: {\n type: BLOCKS.TABLE_ROW,\n component: TR,\n },\n [ELEMENT_TH]: {\n type: BLOCKS.TABLE_HEADER_CELL,\n component: TH,\n },\n [ELEMENT_TD]: {\n type: BLOCKS.TABLE_CELL,\n component: TD,\n },\n};\n\nfunction addTableTrackingEvents(editor: PlateEditor, { onViewportAction }: TrackingProvider) {\n const { insertData } = editor;\n editor.insertData = (data: DataTransfer) => {\n const html = data.getData('text/html');\n\n if (html) {\n const { children: markupBefore } = editor;\n insertData(data);\n const { children: markupAfter } = editor;\n setTimeout(() => {\n if (hasTables(markupBefore)) return;\n if (hasTables(markupAfter)) {\n onViewportAction('paste', {\n tablePasted: true,\n hasHeadersOutsideFirstRow: hasHeadersOutsideFirstRow(markupAfter),\n });\n }\n }, 1);\n } else {\n insertData(data);\n }\n };\n}\n\nfunction hasTables(nodes: CustomElement[]) {\n return nodes.some(({ type }) => {\n return type === BLOCKS.TABLE;\n });\n}\n\nconst isTableHeaderCell = ({ type }) => type === BLOCKS.TABLE_HEADER_CELL;\n\nfunction hasHeadersOutsideFirstRow(nodes: CustomElement[]) {\n return nodes\n .filter(({ type }) => type === BLOCKS.TABLE)\n .flatMap(({ children }) => children.slice(1) as CustomElement[])\n .some(({ children }) => (children as CustomElement[]).some(isTableHeaderCell));\n}\n\nfunction createTableOnKeyDown() {\n return function withTableEvents(editor: PlateEditor) {\n const handleKeyDownFromPlateUdecode = getTableOnKeyDown()(editor);\n return function handleKeyDown(event: React.KeyboardEvent) {\n if (\n (event.key === 'Backspace' && currentSelectionStartsTableCell(editor)) ||\n (event.key === 'Delete' && currentSelectionPrecedesTableCell(editor))\n ) {\n // The default behavior here would be to delete the preceding or forthcoming\n // leaf node, in this case a cell or header cell. But we don't want to do that,\n // because it would leave us with a non-standard number of table cells.\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n handleKeyDownFromPlateUdecode(event);\n };\n };\n}\n\nexport const createTablePlugin = (tracking: TrackingProvider) => ({\n ...createTablePluginFromUdecode(),\n onKeyDown: createTableOnKeyDown(),\n withOverrides: (editor) => {\n addTableTrackingEvents(editor, tracking);\n addTableNormalizers(editor);\n\n const { insertFragment } = editor;\n\n editor.insertFragment = (fragments) => {\n // We need to make sure we have a new, empty and clean paragraph in order to paste tables as-is due to how Slate behaves\n // More info: https://github.com/ianstormtaylor/slate/pull/4489 and https://github.com/ianstormtaylor/slate/issues/4542\n const fragmentHasTable = fragments.some((fragment) => fragment.type === BLOCKS.TABLE);\n if (fragmentHasTable) {\n const emptyParagraph: CustomElement = {\n type: BLOCKS.PARAGRAPH,\n children: [{ text: '' }],\n data: {},\n isVoid: false,\n };\n Transforms.insertNodes(editor, emptyParagraph);\n }\n\n insertFragment(fragments);\n };\n\n return editor;\n },\n});\n\ninterface ToolbarTableButtonProps {\n isDisabled: boolean | undefined;\n}\n\nexport function ToolbarTableButton(props: ToolbarTableButtonProps) {\n const editor = useContentfulEditor();\n const { onViewportAction } = useTrackingContext();\n const isActive = editor && isTableActive(editor);\n\n async function handleClick() {\n if (!editor) return;\n\n onViewportAction('insertTable');\n insertTableAndFocusFirstCell(editor);\n Slate.ReactEditor.focus(editor);\n }\n\n if (!editor) return null;\n\n return (\n <ToolbarButton\n title=\"Table\"\n testId=\"table-toolbar-button\"\n onClick={handleClick}\n // TODO: active state looks off since the button will be disabled. Do we still need it?\n isActive={isActive}\n isDisabled={props.isDisabled}>\n <TableIcon />\n </ToolbarButton>\n );\n}\n","import * as React from 'react';\nimport { Button, Menu } from '@contentful/f36-components';\n\nimport { PlusIcon, ChevronDownIcon } from '@contentful/f36-icons';\n\ninterface EmbeddedEntityDropdownButtonProps {\n children: React.ReactNode;\n isDisabled: boolean | undefined;\n isOpen: boolean;\n onClose: () => void;\n onToggle: () => void;\n}\n\nexport function EmbeddedEntityDropdownButton({\n children,\n isDisabled,\n isOpen,\n onClose,\n onToggle,\n}: EmbeddedEntityDropdownButtonProps) {\n return (\n <Menu placement=\"bottom-end\" isOpen={isOpen} onClose={onClose} onOpen={onToggle}>\n <Menu.Trigger>\n <Button\n endIcon={<ChevronDownIcon />}\n testId=\"toolbar-entity-dropdown-toggle\"\n variant=\"secondary\"\n size=\"small\"\n startIcon={<PlusIcon />}\n isDisabled={isDisabled}>\n Embed\n </Button>\n </Menu.Trigger>\n <Menu.List className=\"toolbar-entity-dropdown-list\">{children}</Menu.List>\n </Menu>\n );\n}\n","// \"modern\" Edge was released at 79.x\nconst IS_EDGE_LEGACY =\n typeof navigator !== 'undefined' && /Edge?\\/(?:[0-6][0-9]|[0-7][0-8])/i.test(navigator.userAgent);\n\n// Native `beforeInput` events don't work well with react on Chrome 75\n// and older, Chrome 76+ can use `beforeInput` though.\nconst IS_CHROME_LEGACY =\n typeof navigator !== 'undefined' &&\n /Chrome?\\/(?:[0-7][0-5]|[0-6][0-9])/i.test(navigator.userAgent);\n\ntype CustomInputEvent = {\n getTargetRanges?: (() => StaticRange[]) | undefined;\n} & InputEvent;\n\n// COMPAT: Firefox/Edge Legacy don't support the `beforeinput` event\n// Chrome Legacy doesn't support `beforeinput` correctly\nexport const HAS_BEFORE_INPUT_SUPPORT =\n !IS_CHROME_LEGACY &&\n !IS_EDGE_LEGACY &&\n // globalThis is undefined in older browsers\n typeof globalThis !== 'undefined' &&\n globalThis.InputEvent &&\n typeof (globalThis.InputEvent.prototype as CustomInputEvent).getTargetRanges === 'function'; // The `getTargetRanges` property isn't recognized.\n","import React from 'react';\nimport { css } from 'emotion';\nimport { FetchingWrappedEntryCard } from '../shared/FetchingWrappedEntryCard';\nimport { FetchingWrappedAssetCard } from '../shared/FetchingWrappedAssetCard';\nimport { useSdkContext } from '../../SdkProvider';\nimport { CustomRenderElementProps } from '../../types';\nimport { ReactEditor, useSelected, useReadOnly } from 'slate-react';\nimport { Transforms } from 'slate';\nimport { useContentfulEditor } from '../../ContentfulEditorProvider';\nimport { HAS_BEFORE_INPUT_SUPPORT } from '../../helpers/environment';\n\nconst styles = {\n root: css({\n marginBottom: '1.25rem',\n }),\n};\n\ntype LinkedEntityBlockProps = CustomRenderElementProps<{\n target: {\n sys: {\n id: string;\n linkType: 'Entry' | 'Asset';\n type: 'Link';\n };\n };\n}>;\n\nexport function LinkedEntityBlock(props: LinkedEntityBlockProps) {\n const { attributes, children, element } = props;\n const isSelected = useSelected();\n const editor = useContentfulEditor();\n const sdk = useSdkContext();\n const isDisabled = useReadOnly();\n const { id: entityId, linkType: entityType } = element.data.target.sys;\n\n const handleEditClick = () => {\n const openEntity = entityType === 'Asset' ? sdk.navigator.openAsset : sdk.navigator.openEntry;\n return openEntity(entityId, { slideIn: true });\n };\n\n const handleRemoveClick = () => {\n if (!editor) return;\n const pathToElement = ReactEditor.findPath(editor, element);\n Transforms.removeNodes(editor, { at: pathToElement });\n };\n\n return (\n <div\n {...attributes}\n className={styles.root}\n data-entity-type={entityType}\n data-entity-id={entityId}\n // COMPAT: This makes copy & paste work for Firefox\n contentEditable={!HAS_BEFORE_INPUT_SUPPORT ? false : undefined}\n draggable={!HAS_BEFORE_INPUT_SUPPORT ? true : undefined}>\n <div\n // COMPAT: This makes copy & paste work for Chromium/Blink browsers and Safari\n contentEditable={HAS_BEFORE_INPUT_SUPPORT ? false : undefined}\n draggable={HAS_BEFORE_INPUT_SUPPORT ? true : undefined}>\n {entityType === 'Entry' && (\n <FetchingWrappedEntryCard\n sdk={sdk}\n entryId={entityId}\n locale={sdk.field.locale}\n isDisabled={isDisabled}\n isSelected={isSelected}\n onRemove={handleRemoveClick}\n onEdit={handleEditClick}\n />\n )}\n {entityType === 'Asset' && (\n <FetchingWrappedAssetCard\n sdk={sdk}\n assetId={entityId}\n locale={sdk.field.locale}\n isDisabled={isDisabled}\n isSelected={isSelected}\n onRemove={handleRemoveClick}\n onEdit={handleEditClick}\n />\n )}\n </div>\n {children}\n </div>\n );\n}\n","import getLinkedContentTypeIdsForNodeType from './getLinkedContentTypeIdsForNodeType';\n\n/**\n * Returns a config for the entity selector based on a given rich text field and a\n * rich text node type that the entity should be picked for. Takes the field\n * validations for the given node type into account.\n *\n * @param {object} field\n * @param {string} nodeType\n * @returns {object}\n */\nexport default function newEntitySelectorConfigFromRichTextField(field, nodeType) {\n return {\n entityType: getEntityTypeFromRichTextNode(nodeType),\n locale: field.locale || null, // Will fall back to default locale.\n contentTypes: getLinkedContentTypeIdsForNodeType(field, nodeType),\n };\n}\n\nfunction getEntityTypeFromRichTextNode(nodeType): 'Entry' | 'Asset' | never {\n const words = nodeType.split('-');\n if (words.indexOf('entry') !== -1) {\n return 'Entry';\n }\n if (words.indexOf('asset') !== -1) {\n return 'Asset';\n }\n throw new Error(`RichText node type \\`${nodeType}\\` has no associated \\`entityType\\``);\n}\n","import { getText } from '@udecode/plate';\nimport { Transforms } from 'slate';\nimport * as Slate from 'slate-react';\nimport newEntitySelectorConfigFromRichTextField from '../../helpers/newEntitySelectorConfigFromRichTextField';\n\nexport async function selectEntityAndInsert(nodeType, sdk, editor, logAction) {\n logAction('openCreateEmbedDialog', { nodeType });\n\n const { field, dialogs } = sdk;\n const baseConfig = newEntitySelectorConfigFromRichTextField(field, nodeType);\n const selectEntity =\n baseConfig.entityType === 'Asset' ? dialogs.selectSingleAsset : dialogs.selectSingleEntry;\n const config = { ...baseConfig, withCreate: true };\n try {\n const { selection } = editor;\n const entity = await selectEntity(config);\n if (!entity) {\n return;\n }\n Transforms.select(editor, selection);\n insertBlock(editor, nodeType, entity);\n logAction('insert', { nodeType });\n } catch (error) {\n if (error) {\n throw error;\n } else {\n logAction('cancelCreateEmbedDialog', { nodeType });\n }\n }\n}\n\nconst createNode = (nodeType, entity) => ({\n type: nodeType,\n data: {\n target: {\n sys: {\n id: entity.sys.id,\n type: 'Link',\n linkType: entity.sys.type,\n },\n },\n },\n children: [{ text: '' }],\n isVoid: true,\n});\n\n// TODO: DRY up copied code from HR\nexport function insertBlock(editor, nodeType, entity) {\n if (!editor?.selection) return;\n\n const linkedEntityBlock = createNode(nodeType, entity);\n\n const hasText = editor.selection && !!getText(editor, editor.selection.focus.path);\n\n if (hasText) {\n Transforms.insertNodes(editor, linkedEntityBlock);\n } else {\n Transforms.setNodes(editor, linkedEntityBlock);\n }\n\n Slate.ReactEditor.focus(editor);\n}\n","import React from 'react';\nimport { Flex, Icon, Button, Menu } from '@contentful/f36-components';\n\nimport { AssetIcon, EmbeddedEntryBlockIcon } from '@contentful/f36-icons';\nimport { selectEntityAndInsert } from './Util';\nimport noop from 'lodash/noop';\nimport { FieldExtensionSDK } from '@contentful/app-sdk';\nimport { useSdkContext } from '../../SdkProvider';\nimport { css } from 'emotion';\nimport { useContentfulEditor } from '../../ContentfulEditorProvider';\n\nexport const styles = {\n icon: css({\n marginRight: '10px',\n }),\n};\n\ninterface EmbeddedEntityBlockToolbarIconProps {\n isButton?: boolean;\n isDisabled: boolean;\n logAction?: () => void;\n nodeType: string;\n onClose: () => void;\n}\n\nexport function EmbeddedEntityBlockToolbarIcon({\n isButton,\n isDisabled,\n logAction,\n nodeType,\n onClose,\n}: EmbeddedEntityBlockToolbarIconProps) {\n const editor = useContentfulEditor();\n const sdk: FieldExtensionSDK = useSdkContext();\n\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n\n onClose();\n selectEntityAndInsert(nodeType, sdk, editor, logAction || noop);\n };\n\n const type = getEntityTypeFromNodeType(nodeType);\n const baseClass = `rich-text__${nodeType}`;\n return isButton ? (\n <Button\n isDisabled={isDisabled}\n className={`${baseClass}-button`}\n size=\"small\"\n onClick={handleClick}\n startIcon={type === 'Asset' ? <AssetIcon /> : <EmbeddedEntryBlockIcon />}\n variant=\"secondary\"\n testId={`toolbar-toggle-${nodeType}`}>\n {`Embed ${type.toLowerCase()}`}\n </Button>\n ) : (\n <Menu.Item\n disabled={isDisabled}\n className={`${baseClass}-list-item`}\n onClick={handleClick}\n testId={`toolbar-toggle-${nodeType}`}>\n <Flex alignItems=\"center\" flexDirection=\"row\">\n <Icon\n as={type === 'Asset' ? AssetIcon : EmbeddedEntryBlockIcon}\n className={`rich-text__embedded-entry-list-icon ${styles.icon}`}\n variant=\"secondary\"\n />\n <span>{type}</span>\n </Flex>\n </Menu.Item>\n );\n}\n\nfunction getEntityTypeFromNodeType(nodeType: string): string | never {\n const words = nodeType.toLowerCase().split('-');\n if (words.includes('entry')) {\n return 'Entry';\n }\n if (words.includes('asset')) {\n return 'Asset';\n }\n throw new Error(`Node type \\`${nodeType}\\` has no associated \\`entityType\\``);\n}\n","import { KeyboardEvent } from 'react';\nimport { BLOCKS } from '@contentful/rich-text-types';\nimport {\n getRenderElement,\n getPlatePluginTypes,\n PlatePlugin,\n getPlatePluginOptions,\n PlateEditor,\n} from '@udecode/plate';\nimport { Transforms } from 'slate';\nimport { getNodeEntryFromSelection } from '../../helpers/editor';\nimport { CustomSlatePluginOptions } from 'types';\nimport { LinkedEntityBlock } from './LinkedEntityBlock';\nimport { selectEntityAndInsert } from './Util';\nimport { FieldExtensionSDK } from '@contentful/app-sdk';\nimport noop from 'lodash/noop';\n\nexport { EmbeddedEntityBlockToolbarIcon as ToolbarIcon } from './ToolbarIcon';\n\nconst createEmbeddedEntityPlugin =\n (nodeType: BLOCKS.EMBEDDED_ENTRY | BLOCKS.EMBEDDED_ASSET) =>\n (sdk: FieldExtensionSDK): PlatePlugin => ({\n renderElement: getRenderElement(nodeType),\n pluginKeys: nodeType,\n onKeyDown: getWithEmbeddedEntityEvents(nodeType, sdk),\n voidTypes: getPlatePluginTypes(nodeType),\n deserialize: (editor) => {\n const options = getPlatePluginOptions(editor, nodeType);\n const entityTypes = {\n [BLOCKS.EMBEDDED_ENTRY]: 'Entry',\n [BLOCKS.EMBEDDED_ASSET]: 'Asset',\n };\n\n return {\n element: [\n {\n type: nodeType,\n deserialize: (element) => {\n const entityType = element.getAttribute('data-entity-type');\n const embeddedEntityId = element.getAttribute('data-entity-id');\n const isBlock = entityType === entityTypes[nodeType];\n\n if (!isBlock) return;\n\n return {\n type: nodeType,\n isVoid: true,\n data: {\n target: {\n sys: {\n id: embeddedEntityId,\n linkType: entityType,\n type: 'Link',\n },\n },\n },\n };\n },\n ...options.deserialize,\n },\n ],\n };\n },\n });\n\nexport const createEmbeddedEntryBlockPlugin = createEmbeddedEntityPlugin(BLOCKS.EMBEDDED_ENTRY);\nexport const createEmbeddedAssetBlockPlugin = createEmbeddedEntityPlugin(BLOCKS.EMBEDDED_ASSET);\n\nexport const withEmbeddedEntryBlockOptions: CustomSlatePluginOptions = {\n [BLOCKS.EMBEDDED_ENTRY]: {\n type: BLOCKS.EMBEDDED_ENTRY,\n component: LinkedEntityBlock,\n },\n};\nexport const withEmbeddedAssetBlockOptions: CustomSlatePluginOptions = {\n [BLOCKS.EMBEDDED_ASSET]: {\n type: BLOCKS.EMBEDDED_ASSET,\n component: LinkedEntityBlock,\n },\n};\n\ntype A = 65;\ntype E = 69;\ntype AEvent = KeyboardEvent & { keyCode: A };\ntype EEvent = KeyboardEvent & { keyCode: E };\ntype ShiftEvent = KeyboardEvent & { shiftKey: true };\ntype CtrlEvent = KeyboardEvent & { ctrlKey: true };\ntype MetaEvent = KeyboardEvent & { metaKey: true };\ntype ModEvent = CtrlEvent | MetaEvent;\ntype EmbeddedAssetEvent = ModEvent & ShiftEvent & AEvent;\ntype EmbeddedEntryEvent = ModEvent & ShiftEvent & EEvent;\n\nconst isA = (event: KeyboardEvent): event is AEvent => event.keyCode === 65;\nconst isE = (event: KeyboardEvent): event is EEvent => event.keyCode === 69;\nconst isMod = (event: KeyboardEvent): event is ModEvent => event.ctrlKey || event.metaKey;\nconst isShift = (event: KeyboardEvent): event is ShiftEvent => event.shiftKey;\nconst wasEmbeddedAssetEventTriggered = (event: KeyboardEvent): event is EmbeddedAssetEvent =>\n isMod(event) && isShift(event) && isA(event);\nconst wasEmbeddedEntryEventTriggered = (event: KeyboardEvent): event is EmbeddedEntryEvent =>\n isMod(event) && isShift(event) && isE(event);\n\nexport function getWithEmbeddedEntityEvents(\n nodeType: BLOCKS.EMBEDDED_ENTRY | BLOCKS.EMBEDDED_ASSET,\n sdk: FieldExtensionSDK\n) {\n return function withEmbeddedEntityEvents(editor: PlateEditor) {\n // TODO: Dry up copied code from HR\n return function handleEvent(event: KeyboardEvent) {\n if (!editor) return;\n\n const [, pathToSelectedElement] = getNodeEntryFromSelection(editor, nodeType);\n\n if (pathToSelectedElement) {\n const isDelete = event.key === 'Delete';\n const isBackspace = event.key === 'Backspace';\n\n if (isDelete || isBackspace) {\n event.preventDefault();\n Transforms.removeNodes(editor, { at: pathToSelectedElement });\n }\n } else if (\n (nodeType === BLOCKS.EMBEDDED_ENTRY && wasEmbeddedEntryEventTriggered(event)) ||\n (nodeType === BLOCKS.EMBEDDED_ASSET && wasEmbeddedAssetEventTriggered(event))\n ) {\n selectEntityAndInsert(nodeType, sdk, editor, noop);\n }\n };\n };\n}\n","import React from 'react';\nimport { css } from 'emotion';\nimport tokens from '@contentful/f36-tokens';\nimport { InlineEntryCard, MenuItem } from '@contentful/f36-components';\nimport { ClockIcon } from '@contentful/f36-icons';\nimport { entityHelpers, FieldExtensionSDK } from '@contentful/field-editor-shared';\nimport { useEntities, ScheduledIconWithTooltip } from '@contentful/field-editor-reference';\nimport { INLINES } from '@contentful/rich-text-types';\n\nconst { getEntryTitle, getEntryStatus } = entityHelpers;\n\nconst styles = {\n scheduledIcon: css({\n verticalAlign: 'text-bottom',\n marginRight: tokens.spacing2Xs,\n }),\n};\n\ninterface FetchingWrappedInlineEntryCardProps {\n entryId: string;\n sdk: FieldExtensionSDK;\n isSelected: boolean;\n isDisabled: boolean;\n onEdit: (event: React.MouseEvent<Element, MouseEvent>) => void;\n onRemove: (event: React.MouseEvent<Element, MouseEvent>) => void;\n}\n\nexport function FetchingWrappedInlineEntryCard(props: FetchingWrappedInlineEntryCardProps) {\n const { getOrLoadEntry, loadEntityScheduledActions, entries } = useEntities();\n const entry = React.useMemo(() => entries[props.entryId], [entries, props.entryId]);\n\n const allContentTypes = props.sdk.space.getCachedContentTypes();\n const contentType = React.useMemo(() => {\n if (!entry || entry === 'failed' || !allContentTypes) return undefined;\n\n return allContentTypes.find(\n (contentType) => contentType.sys.id === entry.sys.contentType.sys.id\n );\n }, [allContentTypes, entry]);\n\n const contentTypeName = contentType ? contentType.name : '';\n\n const title = React.useMemo(\n () =>\n getEntryTitle({\n entry,\n contentType,\n localeCode: props.sdk.field.locale,\n defaultLocaleCode: props.sdk.locales.default,\n defaultTitle: 'Untitled',\n }),\n [entry, contentType, props.sdk.field.locale, props.sdk.locales.default]\n );\n\n React.useEffect(() => {\n if (!props.entryId) return;\n getOrLoadEntry(props.entryId);\n // We don't include getOrLoadEntry below because it's part of the constate-derived\n // useEntities(), not props.\n // eslint-disable-next-line\n }, [props.entryId]);\n\n if (entry === 'failed') {\n return (\n <InlineEntryCard\n title=\"Entry missing or inaccessible\"\n testId={INLINES.EMBEDDED_ENTRY}\n isSelected={props.isSelected}\n />\n );\n }\n\n if (entry === undefined) {\n return <InlineEntryCard isLoading />;\n }\n\n const status = getEntryStatus(entry.sys);\n if (status === 'deleted') {\n return (\n <InlineEntryCard\n title=\"Entry missing or inaccessible\"\n testId={INLINES.EMBEDDED_ENTRY}\n isSelected={props.isSelected}\n actions={[\n <MenuItem key=\"remove\" onClick={props.onRemove} testId=\"card-action-remove\">\n Remove\n </MenuItem>,\n ]}\n />\n );\n }\n\n return (\n <InlineEntryCard\n testId={INLINES.EMBEDDED_ENTRY}\n isSelected={props.isSelected}\n title={\n (\n <>\n <span>\n {contentTypeName} {title}\n </span>\n <ScheduledIconWithTooltip\n getEntityScheduledActions={loadEntityScheduledActions}\n entityType=\"Entry\"\n entityId={entry.sys.id}>\n <ClockIcon className={styles.scheduledIcon} variant=\"muted\" testId=\"scheduled-icon\" />\n </ScheduledIconWithTooltip>\n </>\n ) as any\n }\n status={status}\n actions={[\n <MenuItem key=\"edit\" onClick={props.onEdit}>\n Edit\n </MenuItem>,\n <MenuItem\n key=\"remove\"\n onClick={props.onRemove}\n disabled={props.isDisabled}\n testId=\"card-action-remove\">\n Remove\n </MenuItem>,\n ]}\n />\n );\n}\n","import { INLINES } from '@contentful/rich-text-types';\n\nexport function createInlineEntryNode(id: string) {\n return {\n type: INLINES.EMBEDDED_ENTRY,\n children: [{ text: '' }],\n data: {\n target: {\n sys: {\n id,\n type: 'Link',\n linkType: 'Entry',\n },\n },\n },\n };\n}\n","import * as React from 'react';\nimport {\n PlatePlugin,\n getRenderElement,\n getPlatePluginTypes,\n getPlatePluginOptions,\n} from '@udecode/plate';\nimport { Transforms } from 'slate';\nimport { INLINES } from '@contentful/rich-text-types';\nimport { useSelected, ReactEditor, useReadOnly } from 'slate-react';\nimport { Button, Menu, Flex } from '@contentful/f36-components';\nimport { EmbeddedEntryInlineIcon } from '@contentful/f36-icons';\nimport { css } from 'emotion';\nimport { Link, FieldExtensionSDK } from '@contentful/app-sdk';\nimport { Entry } from '@contentful/field-editor-shared';\nimport { CustomSlatePluginOptions, CustomRenderElementProps } from '../../types';\nimport newEntitySelectorConfigFromRichTextField from '../../helpers/newEntitySelectorConfigFromRichTextField';\nimport { useSdkContext } from '../../SdkProvider';\nimport { FetchingWrappedInlineEntryCard } from './FetchingWrappedInlineEntryCard';\nimport { createInlineEntryNode } from './Util';\nimport { useContentfulEditor } from '../../ContentfulEditorProvider';\nimport { HAS_BEFORE_INPUT_SUPPORT } from '../../helpers/environment';\n\nconst styles = {\n icon: css({\n marginRight: '10px',\n }),\n\n root: css({\n margin: '0 1px',\n fontSize: 'inherit',\n span: {\n webkitUserSelect: 'none',\n mozUserSelect: 'none',\n msUserSelect: 'none',\n userSelect: 'none',\n },\n }),\n};\n\ntype EmbeddedEntityInlineProps = CustomRenderElementProps<{\n target: Link;\n}>;\n\nfunction EmbeddedEntityInline(props: EmbeddedEntityInlineProps) {\n const editor = useContentfulEditor();\n const sdk = useSdkContext();\n const isSelected = useSelected();\n const { id: entryId } = props.element.data.target.sys;\n const isDisabled = useReadOnly();\n\n function handleEditClick() {\n return sdk.navigator.openEntry(entryId, { slideIn: true });\n }\n\n function handleRemoveClick() {\n if (!editor) return;\n const pathToElement = ReactEditor.findPath(editor, props.element);\n Transforms.removeNodes(editor, { at: pathToElement });\n }\n\n return (\n <span\n {...props.attributes}\n className={styles.root}\n data-embedded-entity-inline-id={entryId}\n // COMPAT: This makes copy & paste work for Firefox\n contentEditable={!HAS_BEFORE_INPUT_SUPPORT ? false : undefined}\n draggable={!HAS_BEFORE_INPUT_SUPPORT ? true : undefined}>\n <span\n // COMPAT: This makes copy & paste work for Chromium/Blink browsers and Safari\n contentEditable={HAS_BEFORE_INPUT_SUPPORT ? false : undefined}\n draggable={HAS_BEFORE_INPUT_SUPPORT ? true : undefined}>\n <FetchingWrappedInlineEntryCard\n sdk={sdk}\n entryId={entryId}\n isSelected={isSelected}\n isDisabled={isDisabled}\n onRemove={handleRemoveClick}\n onEdit={handleEditClick}\n />\n </span>\n {props.children}\n </span>\n );\n}\n\ninterface ToolbarEmbeddedEntityInlineButtonProps {\n onClose: () => void;\n isDisabled: boolean;\n isButton?: boolean;\n}\n\nasync function selectEntityAndInsert(editor, sdk: FieldExtensionSDK) {\n const config = {\n ...newEntitySelectorConfigFromRichTextField(sdk.field, INLINES.EMBEDDED_ENTRY),\n withCreate: true,\n };\n const selection = editor.selection;\n\n const entry = await sdk.dialogs.selectSingleEntry<Entry>(config);\n ReactEditor.focus(editor); // Dialog steals focus from editor, return it.\n if (!entry) return;\n\n const inlineEntryNode = createInlineEntryNode(entry.sys.id);\n\n // Got to wait until focus is really back on the editor or setSelection() won't work.\n setTimeout(() => {\n Transforms.setSelection(editor, selection);\n Transforms.insertNodes(editor, inlineEntryNode);\n }, 0);\n}\n\nexport function ToolbarEmbeddedEntityInlineButton(props: ToolbarEmbeddedEntityInlineButtonProps) {\n const editor = useContentfulEditor();\n const sdk: FieldExtensionSDK = useSdkContext();\n\n async function handleClick(event) {\n event.preventDefault();\n\n if (!editor) return;\n\n props.onClose();\n\n await selectEntityAndInsert(editor, sdk);\n }\n\n return props.isButton ? (\n <Button\n isDisabled={props.isDisabled}\n className={`${INLINES.EMBEDDED_ENTRY}-button`}\n size=\"small\"\n onClick={handleClick}\n startIcon={<EmbeddedEntryInlineIcon />}\n variant=\"secondary\"\n testId={`toolbar-toggle-${INLINES.EMBEDDED_ENTRY}`}>\n Embed inline entry\n </Button>\n ) : (\n <Menu.Item\n disabled={props.isDisabled}\n className=\"rich-text__entry-link-block-button\"\n testId={`toolbar-toggle-${INLINES.EMBEDDED_ENTRY}`}\n onClick={handleClick}>\n <Flex alignItems=\"center\" flexDirection=\"row\">\n <EmbeddedEntryInlineIcon\n variant=\"secondary\"\n className={`rich-text__embedded-entry-list-icon ${styles.icon}`}\n />\n <span>Inline entry</span>\n </Flex>\n </Menu.Item>\n );\n}\n\nexport function createEmbeddedEntityInlinePlugin(sdk): PlatePlugin {\n return {\n renderElement: getRenderElement(INLINES.EMBEDDED_ENTRY),\n pluginKeys: INLINES.EMBEDDED_ENTRY,\n inlineTypes: getPlatePluginTypes(INLINES.EMBEDDED_ENTRY),\n voidTypes: getPlatePluginTypes(INLINES.EMBEDDED_ENTRY),\n onKeyDown: getWithEmbeddedEntryInlineEvents(sdk),\n deserialize: (editor) => {\n const options = getPlatePluginOptions(editor, INLINES.EMBEDDED_ENTRY);\n\n return {\n element: [\n {\n type: INLINES.EMBEDDED_ENTRY,\n deserialize: (element) => {\n const entryId = element.getAttribute('data-embedded-entity-inline-id');\n return entryId ? createInlineEntryNode(entryId) : undefined;\n },\n ...options.deserialize,\n },\n ],\n };\n },\n };\n}\n\nexport const withEmbeddedEntityInlineOptions: CustomSlatePluginOptions = {\n [INLINES.EMBEDDED_ENTRY]: {\n type: INLINES.EMBEDDED_ENTRY,\n component: EmbeddedEntityInline,\n },\n};\n\n// TODO: DRY up types from embedded entry block and elsewhere\ntype TWO = 50;\ntype TwoEvent = React.KeyboardEvent & { keyCode: TWO };\ntype ShiftEvent = React.KeyboardEvent & { shiftKey: true };\ntype CtrlEvent = React.KeyboardEvent & { ctrlKey: true };\ntype MetaEvent = React.KeyboardEvent & { metaKey: true };\ntype ModEvent = CtrlEvent | MetaEvent;\ntype EmbeddedEntryInlineEvent = ModEvent & ShiftEvent & TwoEvent;\n\nconst isTwo = (event: React.KeyboardEvent): event is TwoEvent => event.keyCode === 50;\nconst isMod = (event: React.KeyboardEvent): event is ModEvent => event.ctrlKey || event.metaKey;\nconst isShift = (event: React.KeyboardEvent): event is ShiftEvent => event.shiftKey;\nconst wasEmbeddedEntryInlineEventTriggered = (\n event: React.KeyboardEvent\n): event is EmbeddedEntryInlineEvent => isMod(event) && isShift(event) && isTwo(event);\n\nfunction getWithEmbeddedEntryInlineEvents(sdk) {\n return function withEmbeddedEntryInlineEvents(editor) {\n return function handleEvent(event) {\n if (!editor) return;\n\n if (wasEmbeddedEntryInlineEventTriggered(event)) {\n selectEntityAndInsert(editor, sdk);\n }\n };\n };\n}\n","import React, { useState } from 'react';\n\nimport { EmbeddedEntityDropdownButton } from '../plugins/EmbeddedEntity';\nimport { ToolbarIcon as EmbeddedEntityBlockToolbarIcon } from '../plugins/EmbeddedEntityBlock';\nimport { BLOCKS, INLINES } from '@contentful/rich-text-types';\nimport { isNodeTypeEnabled } from '../helpers/validations';\nimport { ToolbarEmbeddedEntityInlineButton } from '../plugins/EmbeddedEntityInline';\nimport { useSdkContext } from '../SdkProvider';\nimport { isLinkActive } from '../helpers/editor';\nimport { useContentfulEditor } from '../ContentfulEditorProvider';\n\nexport interface EmbedEntityWidgetProps {\n isDisabled?: boolean;\n canInsertBlocks?: boolean;\n}\n\nexport const EmbedEntityWidget = ({ isDisabled, canInsertBlocks }: EmbedEntityWidgetProps) => {\n const sdk = useSdkContext();\n const editor = useContentfulEditor();\n\n const [isEmbedDropdownOpen, setEmbedDropdownOpen] = useState(false);\n const onCloseEntityDropdown = () => setEmbedDropdownOpen(false);\n const onToggleEntityDropdown = () => setEmbedDropdownOpen(!isEmbedDropdownOpen);\n\n const [canAccessAssets, setCanAccessAssets] = useState(false);\n React.useEffect(() => {\n sdk.access.can('read', 'Asset').then(setCanAccessAssets);\n }, [sdk]);\n\n const inlineEntryEmbedEnabled = isNodeTypeEnabled(sdk.field, INLINES.EMBEDDED_ENTRY);\n const blockEntryEmbedEnabled =\n isNodeTypeEnabled(sdk.field, BLOCKS.EMBEDDED_ENTRY) && canInsertBlocks;\n const blockAssetEmbedEnabled =\n canAccessAssets && isNodeTypeEnabled(sdk.field, BLOCKS.EMBEDDED_ASSET) && canInsertBlocks;\n\n const numEnabledEmbeds = [\n inlineEntryEmbedEnabled,\n blockEntryEmbedEnabled,\n blockAssetEmbedEnabled,\n ].filter(Boolean).length;\n\n const shouldDisplayDropdown = numEnabledEmbeds > 1;\n\n // Avoids UI glitching when switching back and forth between\n // different layouts\n React.useEffect(() => {\n if (!shouldDisplayDropdown) {\n setEmbedDropdownOpen(false);\n }\n }, [shouldDisplayDropdown]);\n\n const actions = (\n <>\n {blockEntryEmbedEnabled && (\n <EmbeddedEntityBlockToolbarIcon\n isDisabled={!!isDisabled}\n nodeType={BLOCKS.EMBEDDED_ENTRY}\n onClose={onCloseEntityDropdown}\n isButton={!shouldDisplayDropdown}\n />\n )}\n {inlineEntryEmbedEnabled && (\n <ToolbarEmbeddedEntityInlineButton\n isDisabled={!!isDisabled || isLinkActive(editor)}\n onClose={onCloseEntityDropdown}\n isButton={!shouldDisplayDropdown}\n />\n )}\n {blockAssetEmbedEnabled && (\n <EmbeddedEntityBlockToolbarIcon\n isDisabled={!!isDisabled}\n nodeType={BLOCKS.EMBEDDED_ASSET}\n onClose={onCloseEntityDropdown}\n isButton={!shouldDisplayDropdown}\n />\n )}\n </>\n );\n\n if (!shouldDisplayDropdown) {\n return actions;\n }\n\n return (\n <EmbeddedEntityDropdownButton\n isDisabled={isDisabled}\n onClose={onCloseEntityDropdown}\n onToggle={onToggleEntityDropdown}\n isOpen={isEmbedDropdownOpen}>\n {actions}\n </EmbeddedEntityDropdownButton>\n );\n};\n","import React, { Fragment } from 'react';\nimport tokens from '@contentful/f36-tokens';\nimport { css } from 'emotion';\nimport { Flex } from '@contentful/f36-components';\nimport { ToolbarHrButton } from '../plugins/Hr';\nimport { ToolbarHeadingButton } from '../plugins/Heading';\nimport { ToolbarQuoteButton } from '../plugins/Quote';\nimport { ToolbarListButton } from '../plugins/List';\nimport { ToolbarBoldButton } from '../plugins/Bold';\nimport { ToolbarCodeButton } from '../plugins/Code';\nimport { ToolbarItalicButton } from '../plugins/Italic';\nimport { ToolbarUnderlineButton } from '../plugins/Underline';\nimport { ToolbarHyperlinkButton } from '../plugins/Hyperlink';\nimport { ToolbarTableButton } from '../plugins/Table';\nimport { BLOCKS, INLINES, MARKS } from '@contentful/rich-text-types';\nimport { isNodeTypeSelected } from '../helpers/editor';\nimport { isNodeTypeEnabled, isMarkEnabled } from '../helpers/validations';\nimport { useSdkContext } from '../SdkProvider';\nimport { FieldExtensionSDK } from '@contentful/app-sdk';\nimport { EmbedEntityWidget } from './EmbedEntityWidget';\nimport { useContentfulEditor } from '../ContentfulEditorProvider';\n\ntype ToolbarProps = {\n isDisabled?: boolean;\n};\n\nconst styles = {\n toolbar: css({\n border: `1px solid ${tokens.gray400}`,\n backgroundColor: tokens.gray100,\n padding: tokens.spacingXs,\n borderRadius: `${tokens.borderRadiusMedium} ${tokens.borderRadiusMedium} 0 0`,\n }),\n divider: css({\n display: 'inline-block',\n height: '21px',\n width: '1px',\n background: tokens.gray300,\n margin: `0 ${tokens.spacing2Xs}`,\n }),\n embedActionsWrapper: css({\n display: ['-webkit-box', '-ms-flexbox', 'flex'],\n webkitAlignSelf: 'flex-start',\n alignSelf: 'flex-start',\n msFlexItemAlign: 'start',\n marginLeft: 'auto',\n }),\n formattingOptionsWrapper: css({\n display: ['-webkit-box', '-ms-flexbox', 'flex'],\n msFlexAlign: 'center',\n webkitBoxAlign: 'center',\n alignItems: 'center',\n msFlexWrap: 'wrap',\n flexWrap: 'wrap',\n marginRight: '20px',\n }),\n};\n\nconst Toolbar = ({ isDisabled }: ToolbarProps) => {\n const sdk = useSdkContext();\n const editor = useContentfulEditor();\n const canInsertBlocks = !isNodeTypeSelected(editor, BLOCKS.TABLE);\n const validationInfo = React.useMemo(() => getValidationInfo(sdk.field), [sdk.field]);\n const isListSelected =\n isNodeTypeSelected(editor, BLOCKS.UL_LIST) || isNodeTypeSelected(editor, BLOCKS.OL_LIST);\n const isBlockquoteSelected = isNodeTypeSelected(editor, BLOCKS.QUOTE);\n const shouldDisableTables =\n isDisabled || !canInsertBlocks || isListSelected || isBlockquoteSelected;\n\n return (\n <Flex testId=\"toolbar\" className={styles.toolbar} alignItems=\"center\">\n <div className={styles.formattingOptionsWrapper}>\n <ToolbarHeadingButton isDisabled={isDisabled || !canInsertBlocks} />\n\n {validationInfo.isAnyMarkEnabled && <span className={styles.divider} />}\n\n {isMarkEnabled(sdk.field, MARKS.BOLD) && <ToolbarBoldButton isDisabled={isDisabled} />}\n {isMarkEnabled(sdk.field, MARKS.ITALIC) && <ToolbarItalicButton isDisabled={isDisabled} />}\n {isMarkEnabled(sdk.field, MARKS.UNDERLINE) && (\n <ToolbarUnderlineButton isDisabled={isDisabled} />\n )}\n {isMarkEnabled(sdk.field, MARKS.CODE) && <ToolbarCodeButton isDisabled={isDisabled} />}\n\n {validationInfo.isAnyHyperlinkEnabled && (\n <Fragment>\n <span className={styles.divider} />\n <ToolbarHyperlinkButton isDisabled={isDisabled} />\n </Fragment>\n )}\n\n {validationInfo.isAnyBlockFormattingEnabled && <span className={styles.divider} />}\n\n {isNodeTypeEnabled(sdk.field, BLOCKS.QUOTE) && (\n <ToolbarQuoteButton isDisabled={isDisabled || !canInsertBlocks} />\n )}\n <ToolbarListButton isDisabled={isDisabled || !canInsertBlocks} />\n {isNodeTypeEnabled(sdk.field, BLOCKS.HR) && (\n <ToolbarHrButton isDisabled={isDisabled || !canInsertBlocks} />\n )}\n {isNodeTypeEnabled(sdk.field, BLOCKS.TABLE) && (\n <ToolbarTableButton isDisabled={shouldDisableTables} />\n )}\n </div>\n <div className={styles.embedActionsWrapper}>\n <EmbedEntityWidget isDisabled={isDisabled} canInsertBlocks={canInsertBlocks} />\n </div>\n </Flex>\n );\n};\n\nfunction getValidationInfo(field: FieldExtensionSDK['field']): {\n isAnyMarkEnabled: boolean;\n isAnyHyperlinkEnabled: boolean;\n isAnyBlockFormattingEnabled: boolean;\n} {\n const someWithValidation = (vals, validation) => vals.some((val) => validation(field, val));\n\n const isAnyMarkEnabled = someWithValidation(Object.values(MARKS), isMarkEnabled);\n\n const isAnyHyperlinkEnabled = someWithValidation(\n [INLINES.HYPERLINK, INLINES.ASSET_HYPERLINK, INLINES.ENTRY_HYPERLINK],\n isNodeTypeEnabled\n );\n\n const isAnyBlockFormattingEnabled = someWithValidation(\n [BLOCKS.UL_LIST, BLOCKS.OL_LIST, BLOCKS.QUOTE, BLOCKS.HR],\n isNodeTypeEnabled\n );\n\n return {\n isAnyMarkEnabled,\n isAnyHyperlinkEnabled,\n isAnyBlockFormattingEnabled,\n };\n}\n\nexport default Toolbar;\n","import React, { ReactNode } from 'react';\nimport { css } from 'emotion';\n\nconst styles = {\n nativeSticky: css`\n position: -webkit-sticky;\n position: sticky;\n top: -1px;\n z-index: 2;\n `,\n};\n\ntype StickyToolbarProps = {\n isDisabled?: boolean;\n children: ReactNode;\n};\n\nconst StickyToolbarWrapper = ({ isDisabled, children }: StickyToolbarProps) => (\n <div className={isDisabled ? '' : styles.nativeSticky}>{children}</div>\n);\n\nexport default StickyToolbarWrapper;\n","import { BLOCKS, INLINES, VOID_BLOCKS, Text } from '@contentful/rich-text-types';\nimport { CustomElement, TextElement, TextOrCustomElement } from 'types';\nimport values from 'lodash/values'; // eslint-disable-line you-dont-need-lodash-underscore/values\n\ntype NodeType = BLOCKS | INLINES | Text['nodeType'];\n\nconst TEXT_PARENT_NODES: string[] = (VOID_BLOCKS as string[])\n .concat(values(INLINES) as string[])\n .concat(\n BLOCKS.PARAGRAPH,\n BLOCKS.HEADING_1,\n BLOCKS.HEADING_2,\n BLOCKS.HEADING_3,\n BLOCKS.HEADING_4,\n BLOCKS.HEADING_5,\n BLOCKS.HEADING_6\n );\n\nconst isTextElement = (node: TextOrCustomElement): node is TextElement => 'text' in node;\n\nconst wrapNode = (type: BLOCKS, node: TextOrCustomElement): CustomElement => ({\n type,\n data: {},\n children: [node],\n});\n\nfunction wrapOrphanedTextNode(parentNodeType: NodeType, node: TextElement): CustomElement {\n const paragraph = wrapNode(BLOCKS.PARAGRAPH, node);\n switch (parentNodeType) {\n case BLOCKS.OL_LIST:\n case BLOCKS.UL_LIST:\n return wrapNode(BLOCKS.LIST_ITEM, paragraph);\n case BLOCKS.TABLE_ROW:\n return wrapNode(BLOCKS.TABLE_CELL, paragraph);\n case BLOCKS.TABLE:\n return wrapNode(BLOCKS.TABLE_ROW, wrapNode(BLOCKS.TABLE_CELL, paragraph));\n default:\n return paragraph;\n }\n}\n\n/**\n * Ensures \"orphaned\" text node elements (those without a parent capable of\n * validly rendering a text child node) are wrapped with a suitable parent\n * element to prevent failures on the validation layer.\n *\n * It is commonplace for third party plugins (including udecode) to reconcile\n * deletion events by inserting such nodes into their schema. This\n * subprocedure is intended as a guard against such cases.\n */\nexport function sanitizeSlateDoc(\n nodes: TextOrCustomElement[] = [],\n parentNodeType: NodeType = BLOCKS.DOCUMENT\n): TextOrCustomElement[] {\n return nodes.map((node: TextOrCustomElement): TextOrCustomElement => {\n if (isTextElement(node)) {\n return TEXT_PARENT_NODES.includes(parentNodeType)\n ? node\n : wrapOrphanedTextNode(parentNodeType, node);\n }\n return {\n ...node,\n children: sanitizeSlateDoc(node.children, node.type as NodeType),\n };\n });\n}\n\n/**\n * Ensures incoming void nodes have a child leaf text element.\n */\nexport function sanitizeIncomingSlateDoc(nodes: TextOrCustomElement[] = []): TextOrCustomElement[] {\n return nodes.map((node: TextOrCustomElement): TextOrCustomElement => {\n if (isTextElement(node)) {\n return node;\n }\n if (node.isVoid && node.children?.length === 0) {\n return {\n ...node,\n children: [{ text: '', data: {} }],\n };\n }\n return {\n ...node,\n children: sanitizeIncomingSlateDoc(node.children),\n };\n });\n}\n","import { PlateEditor } from '@udecode/plate';\n\nexport type SanitizerTuple = [Document, PlateEditor];\n\ntype Predicate = (node: ChildNode) => boolean;\n\nexport const isHTMLElement = (node: ChildNode): node is HTMLElement =>\n node.nodeType === Node.ELEMENT_NODE;\n\nexport const removeChildNodes = (node: ChildNode, predicate: Predicate = Boolean) =>\n Array.from(node.childNodes)\n .filter(predicate)\n .forEach((table) => node.removeChild(table));\n\nexport const removeChildNodesUsingPredicate =\n (predicate: Predicate) =>\n (nodeList: NodeList): Node[] => {\n const nodes = Array.from(nodeList);\n while (nodes.length > 0) {\n const node = nodes.pop() as ChildNode;\n removeChildNodes(node, predicate);\n for (const childNode of Array.from(node.childNodes)) {\n nodes.push(childNode);\n }\n }\n return nodes;\n };\n","import { removeChildNodesUsingPredicate, SanitizerTuple } from './helpers';\n\nconst isComment = (node: ChildNode): node is Comment => node.nodeType === Node.COMMENT_NODE;\n\nconst removeCommentChildren = removeChildNodesUsingPredicate(isComment);\n\nexport const removeComments = ([doc, editor]: SanitizerTuple): SanitizerTuple => {\n removeCommentChildren(doc.childNodes);\n return [doc, editor];\n};\n","import { BLOCKS } from '@contentful/rich-text-types';\nimport { getNodeEntryFromSelection } from '../../../helpers/editor';\nimport { isHTMLElement, removeChildNodesUsingPredicate, SanitizerTuple } from './helpers';\n\nconst TAG_NAME_TABLE = 'TABLE';\nconst TAG_NAME_TABLE_CAPTION = 'CAPTION';\nconst DISALLOWED_TABLE_CHILD_ELEMENTS: Element['tagName'][] = [TAG_NAME_TABLE_CAPTION];\ntype DisallowedTableChildElement = HTMLTableCaptionElement;\n\nconst isTableElement = (node: ChildNode): node is HTMLTableElement =>\n isHTMLElement(node) && node.tagName === TAG_NAME_TABLE;\n\nconst isDisallowedTableChildElement = (node: ChildNode): node is DisallowedTableChildElement =>\n isHTMLElement(node) && DISALLOWED_TABLE_CHILD_ELEMENTS.includes(node.tagName);\n\nconst removeDisallowedTableChildElements = removeChildNodesUsingPredicate(\n isDisallowedTableChildElement\n);\n\nconst removeTableGrandchildren = (nodeList: NodeList) => {\n const nodes = Array.from(nodeList);\n while (nodes.length > 0) {\n const node = nodes.pop() as ChildNode;\n if (isTableElement(node)) {\n removeDisallowedTableChildElements(node.childNodes);\n continue;\n }\n for (const childNode of Array.from(node.childNodes)) {\n nodes.push(childNode);\n }\n }\n return nodes;\n};\n\nexport const sanitizeTables = ([doc, editor]: SanitizerTuple): SanitizerTuple => {\n const [node] = getNodeEntryFromSelection(editor, BLOCKS.TABLE);\n const isTableInCurrentSelection = !!node;\n if (isTableInCurrentSelection) {\n removeDisallowedTableChildElements(doc.childNodes);\n } else {\n removeTableGrandchildren(doc.childNodes);\n }\n return [doc, editor];\n};\n","import { PlatePlugin, PlateEditor } from '@udecode/plate';\nimport * as sanitizers from './sanitizers';\nimport flow from 'lodash/flow';\n\nconst MIME_TYPE_HTML = 'text/html';\n\n// TODO: Upgrade tslib so we can just flow(...sanitizers);\nconst sanitizeDocument = flow.apply(this, Object.values(sanitizers));\n\nconst sanitizeHtml = (html: string, editor: PlateEditor): string => {\n const doc = new DOMParser().parseFromString(html, MIME_TYPE_HTML);\n const [sanitizedDoc] = sanitizeDocument([doc, editor]);\n const sanitizedData = new XMLSerializer().serializeToString(sanitizedDoc);\n return sanitizedData;\n};\n\nconst htmlToDataTransfer = (html: string): DataTransfer => {\n const data = new DataTransfer();\n data.setData(MIME_TYPE_HTML, html);\n return data;\n};\n\nexport const createPastePlugin = (): PlatePlugin => ({\n withOverrides: (editor) => {\n const { insertData } = editor;\n editor.insertData = (data: DataTransfer) => {\n const html = data.getData(MIME_TYPE_HTML);\n if (html) {\n const sanitized = sanitizeHtml(html, editor);\n const newData = htmlToDataTransfer(sanitized);\n insertData(newData);\n } else {\n insertData(data);\n }\n };\n\n return editor;\n },\n});\n","import { isHTMLElement, removeChildNodes, SanitizerTuple } from './helpers';\n\n/**\n * Ensures the text selection from entity block elements is\n * not included in the paste buffer.\n */\nexport const sanitizeEntityBlocks = ([doc, editor]: SanitizerTuple): SanitizerTuple => {\n const nodes = Array.from(doc.childNodes);\n while (nodes.length > 0) {\n const node = nodes.pop() as ChildNode;\n if (isHTMLElement(node) && node.getAttribute('data-entity-type')) {\n removeChildNodes(node);\n continue;\n }\n for (const childNode of Array.from(node.childNodes)) {\n nodes.push(childNode);\n }\n }\n return [doc, editor];\n};\n","import * as React from 'react';\nimport { css } from 'emotion';\nimport {\n PlatePlugin,\n getRenderElement,\n PlateEditor,\n ELEMENT_PARAGRAPH,\n getToggleElementOnKeyDown,\n} from '@udecode/plate';\nimport { BLOCKS } from '@contentful/rich-text-types';\nimport tokens from '@contentful/f36-tokens';\nimport { Element, Node, Transforms } from 'slate';\nimport { RenderElementProps } from 'slate-react';\nimport { CustomSlatePluginOptions, CustomElement } from '../../types';\nimport { deserializeElement } from '../../helpers/deserializer';\n\nconst styles = {\n [BLOCKS.PARAGRAPH]: css`\n line-height: ${tokens.lineHeightDefault};\n margin-bottom: 1.5em;\n `,\n};\n\nexport function Paragraph(props: RenderElementProps) {\n return (\n <div {...props.attributes} className={styles[BLOCKS.PARAGRAPH]}>\n {props.children}\n </div>\n );\n}\n\nfunction isEmbed(element: HTMLElement) {\n return (\n element.hasAttribute('data-embedded-entity-inline-id') ||\n element.hasAttribute('data-entity-type')\n );\n}\n\nfunction isEmpty(element: HTMLElement) {\n return element.textContent === '';\n}\n\nexport function createParagraphPlugin(): PlatePlugin {\n const elementKeys: string[] = [ELEMENT_PARAGRAPH, BLOCKS.PARAGRAPH];\n\n const deserializer = deserializeElement(BLOCKS.PARAGRAPH, [\n {\n nodeNames: ['P', 'DIV'],\n },\n ]);\n\n return {\n renderElement: getRenderElement(elementKeys),\n pluginKeys: elementKeys,\n onKeyDown: getToggleElementOnKeyDown(BLOCKS.PARAGRAPH),\n deserialize: (editor: PlateEditor) => {\n const { element, ...rest } = deserializer(editor);\n return {\n ...rest,\n element: element?.map((deserializeNode) => ({\n ...deserializeNode,\n deserialize: (el: HTMLElement) => {\n if (isEmpty(el) || isEmbed(el)) {\n return;\n }\n return deserializeNode.deserialize(el);\n },\n })),\n };\n },\n withOverrides: (editor) => {\n const { normalizeNode } = editor;\n editor.normalizeNode = (entry) => {\n const [node, path] = entry;\n // If the element is a paragraph, ensure its children are valid.\n if (Element.isElement(node) && (node as CustomElement).type === BLOCKS.PARAGRAPH) {\n for (const [child, childPath] of Node.children(editor, path)) {\n if (Element.isElement(child) && !editor.isInline(child)) {\n Transforms.unwrapNodes(editor, {\n at: childPath,\n });\n return;\n }\n }\n }\n // Fall back to the original `normalizeNode` to enforce other constraints.\n normalizeNode(entry);\n };\n return editor;\n },\n };\n}\n\nexport const withParagraphOptions: CustomSlatePluginOptions = {\n [ELEMENT_PARAGRAPH]: {\n // We convert the default slate plugin `p` to Contentful `BLOCKS.PARAGRAPH`\n type: BLOCKS.PARAGRAPH,\n component: Paragraph,\n },\n [BLOCKS.PARAGRAPH]: {\n type: BLOCKS.PARAGRAPH,\n component: Paragraph,\n hotkey: ['mod+opt+0'],\n },\n};\n","import { FieldExtensionSDK } from '@contentful/app-sdk';\n\nimport { createPastePlugin } from './Paste';\nimport { createListPlugin, withListOptions } from './List';\nimport {\n createHistoryPlugin,\n createReactPlugin,\n createDeserializeAstPlugin,\n createDeserializeHTMLPlugin,\n} from '@udecode/plate';\nimport { createHrPlugin, withHrOptions } from './Hr';\nimport { withHeadingOptions, createHeadingPlugin } from './Heading';\nimport { createBoldPlugin, withBoldOptions } from './Bold';\nimport { withCodeOptions, createCodePlugin } from './Code';\nimport { withItalicOptions, createItalicPlugin } from './Italic';\nimport { createUnderlinePlugin, withUnderlineOptions } from './Underline';\nimport { createParagraphPlugin, withParagraphOptions } from './Paragraph';\nimport { createQuotePlugin, withQuoteOptions } from './Quote';\nimport { createNewLinePlugin } from './NewLine';\nimport { createInsertBeforeFirstVoidBlockPlugin } from './InsertBeforeFirstVoidBlock';\nimport { createTablePlugin, withTableOptions } from './Table';\nimport { createHyperlinkPlugin, withHyperlinkOptions } from './Hyperlink';\nimport {\n createEmbeddedAssetBlockPlugin,\n createEmbeddedEntryBlockPlugin,\n withEmbeddedAssetBlockOptions,\n withEmbeddedEntryBlockOptions,\n} from './EmbeddedEntityBlock';\nimport {\n createEmbeddedEntityInlinePlugin,\n withEmbeddedEntityInlineOptions,\n} from './EmbeddedEntityInline';\nimport { TrackingProvider } from '../TrackingProvider';\nimport { createTrailingParagraphPlugin } from './TrailingParagraph';\nimport { createDragAndDropPlugin } from './DragAndDrop';\nimport { createTextPlugin } from './Text';\n\nexport const getPlugins = (sdk: FieldExtensionSDK, tracking: TrackingProvider) => {\n const plugins = [\n // Core\n createReactPlugin(),\n createHistoryPlugin(),\n\n // Behavior\n createPastePlugin(),\n\n // Global shortcuts\n createNewLinePlugin(),\n createInsertBeforeFirstVoidBlockPlugin(),\n createDragAndDropPlugin(),\n\n // Block Elements\n createParagraphPlugin(),\n createListPlugin(),\n createHrPlugin(),\n createHeadingPlugin(),\n createQuotePlugin(),\n createTablePlugin(tracking),\n createEmbeddedEntryBlockPlugin(sdk),\n createEmbeddedAssetBlockPlugin(sdk),\n\n // Inline elements\n createHyperlinkPlugin(sdk),\n createEmbeddedEntityInlinePlugin(sdk),\n\n // Marks\n createBoldPlugin(),\n createCodePlugin(),\n createItalicPlugin(),\n createUnderlinePlugin(),\n\n // Other\n createTrailingParagraphPlugin(),\n createTextPlugin(),\n ];\n\n return plugins.concat([\n createDeserializeHTMLPlugin({ plugins }),\n createDeserializeAstPlugin({ plugins }),\n ] as any);\n};\n\nexport const pluginOptions = {\n // Block elements\n ...withParagraphOptions,\n ...withListOptions,\n ...withHrOptions,\n ...withHeadingOptions,\n ...withQuoteOptions,\n ...withTableOptions,\n ...withEmbeddedEntryBlockOptions,\n ...withEmbeddedAssetBlockOptions,\n\n // Inline elements\n ...withHyperlinkOptions,\n ...withEmbeddedEntityInlineOptions,\n\n // Marks\n ...withBoldOptions,\n ...withCodeOptions,\n ...withItalicOptions,\n ...withUnderlineOptions,\n};\n","import React, { useCallback, useState } from 'react';\nimport noop from 'lodash/noop';\nimport { toContentfulDocument, toSlatejsDocument } from '@contentful/contentful-slatejs-adapter';\nimport * as Contentful from '@contentful/rich-text-types';\nimport { EntityProvider } from '@contentful/field-editor-reference';\nimport { css, cx } from 'emotion';\nimport { styles } from './RichTextEditor.styles';\nimport schema from './constants/Schema';\nimport deepEquals from 'fast-deep-equal';\nimport Toolbar from './Toolbar';\nimport StickyToolbarWrapper from './Toolbar/StickyToolbarWrapper';\nimport { Plate } from '@udecode/plate';\nimport { SdkProvider } from './SdkProvider';\nimport {\n RichTextTrackingActionHandler,\n TrackingProvider,\n useTrackingContext,\n} from './TrackingProvider';\nimport { sanitizeIncomingSlateDoc, sanitizeSlateDoc } from './helpers/sanitizeSlateDoc';\nimport { TextOrCustomElement } from './types';\nimport { ContentfulEditorProvider, getContentfulEditorId } from './ContentfulEditorProvider';\nimport { FieldExtensionSDK } from '@contentful/app-sdk';\nimport { FieldConnector } from '@contentful/field-editor-shared';\nimport { getPlugins, pluginOptions } from './plugins';\n\ntype ConnectedProps = {\n sdk: FieldExtensionSDK;\n onAction?: RichTextTrackingActionHandler;\n minHeight?: string | number;\n value?: object;\n isDisabled?: boolean;\n onChange?: (doc: Contentful.Document) => unknown;\n isToolbarHidden?: boolean;\n actionsDisabled?: boolean;\n};\n\nexport const ConnectedRichTextEditor = (props: ConnectedProps) => {\n const tracking = useTrackingContext();\n\n const docFromAdapter = toSlatejsDocument({\n document: props.value || Contentful.EMPTY_DOCUMENT,\n schema,\n });\n\n const doc = sanitizeIncomingSlateDoc(docFromAdapter);\n\n const [value, setValue] = useState(doc);\n\n const classNames = cx(\n styles.editor,\n props.minHeight !== undefined ? css({ minHeight: props.minHeight }) : undefined,\n props.isDisabled ? styles.disabled : styles.enabled,\n props.isToolbarHidden && styles.hiddenToolbar\n );\n\n const plugins = React.useMemo(() => getPlugins(props.sdk, tracking), [props.sdk, tracking]);\n\n return (\n <div className={styles.root} data-test-id=\"rich-text-editor\">\n <Plate\n id={getContentfulEditorId(props.sdk)}\n initialValue={value}\n plugins={plugins}\n editableProps={{\n className: classNames,\n readOnly: props.isDisabled,\n }}\n onChange={(newValue) => {\n const slateDoc = sanitizeSlateDoc(newValue as TextOrCustomElement[]);\n setValue(slateDoc);\n const contentfulDoc = toContentfulDocument({ document: slateDoc, schema });\n props.onChange?.(contentfulDoc);\n }}\n // @ts-expect-error\n options={pluginOptions}>\n {!props.isToolbarHidden && (\n <StickyToolbarWrapper isDisabled={props.isDisabled}>\n <Toolbar isDisabled={props.isDisabled} />\n </StickyToolbarWrapper>\n )}\n </Plate>\n </div>\n );\n};\n\ntype Props = ConnectedProps & { isInitiallyDisabled: boolean };\n\nconst RichTextEditor = (props: Props) => {\n const { sdk, isInitiallyDisabled, onAction, ...otherProps } = props;\n const isEmptyValue = useCallback(\n (value) => !value || deepEquals(value, Contentful.EMPTY_DOCUMENT),\n []\n );\n return (\n <EntityProvider sdk={sdk}>\n <SdkProvider sdk={sdk}>\n <TrackingProvider onAction={onAction || noop}>\n <FieldConnector\n throttle={0}\n field={sdk.field}\n isInitiallyDisabled={isInitiallyDisabled}\n isEmptyValue={isEmptyValue}\n isEqualValues={deepEquals}>\n {({ lastRemoteValue, disabled, setValue, externalReset }) => (\n <ContentfulEditorProvider sdk={sdk}>\n <ConnectedRichTextEditor\n {...otherProps}\n key={`rich-text-editor-${externalReset}`}\n value={lastRemoteValue}\n sdk={sdk}\n onAction={onAction || noop}\n isDisabled={disabled}\n onChange={setValue}\n />\n </ContentfulEditorProvider>\n )}\n </FieldConnector>\n </TrackingProvider>\n </SdkProvider>\n </EntityProvider>\n );\n};\n\nexport default RichTextEditor;\n","import { Node as SlateNode, Transforms, Editor } from 'slate';\nimport { PlatePlugin, getNodes } from '@udecode/plate';\nimport { BLOCKS, CONTAINERS, INLINES } from '@contentful/rich-text-types';\n\nimport { CustomElement } from '../../types';\n\nexport function createDragAndDropPlugin(): PlatePlugin {\n // Elements that don't allow other elements to be dragged into them and which callback should be used\n const DND_BLOCKED_ELEMENTS = {\n [BLOCKS.QUOTE]: Transforms.liftNodes,\n };\n\n const DRAGGABLE_TYPES: string[] = [\n BLOCKS.EMBEDDED_ENTRY,\n BLOCKS.EMBEDDED_ASSET,\n INLINES.EMBEDDED_ENTRY,\n ];\n\n /**\n * HTML node names where dropping should be allowed\n * Usually for elements where `Transforms.removeNodes` is needed\n * TODO: looking up for html nodes is not the best solution and it won't scale but it works fine for our current cases/elements\n */\n const ON_DROP_ALLOWED_TYPES = {\n TABLE: [INLINES.EMBEDDED_ENTRY],\n };\n\n return {\n withOverrides: (editor) => {\n const { normalizeNode } = editor;\n\n editor.normalizeNode = (entry) => {\n const [node, path] = entry;\n\n Object.keys(DND_BLOCKED_ELEMENTS).forEach((blockedElementType) => {\n const nodeType = (node as CustomElement).type;\n\n if (SlateNode.isNode(node) && nodeType === blockedElementType) {\n for (const [child, childPath] of SlateNode.children(editor, path)) {\n const childType = (child as CustomElement).type;\n\n if (!CONTAINERS[blockedElementType]) return;\n if (!CONTAINERS[blockedElementType].includes(childType)) {\n const callback = DND_BLOCKED_ELEMENTS[blockedElementType];\n callback(editor, {\n at: childPath,\n match: (matchNode) =>\n SlateNode.isNode(matchNode) &&\n DRAGGABLE_TYPES.includes((matchNode as CustomElement).type),\n });\n\n return;\n }\n }\n }\n });\n\n normalizeNode(entry);\n };\n\n return editor;\n },\n\n // If true, the next handlers will be skipped.\n onDrop: (editor) => (event) => {\n const [draggingBlock] = Array.from(\n getNodes(editor, {\n match: (node) => Editor.isBlock(editor, node) && DRAGGABLE_TYPES.includes(node.type),\n })\n );\n if (!draggingBlock) return false;\n\n const [draggingNode] = draggingBlock;\n\n if (!event.nativeEvent.target) return false;\n\n // TODO: looking up for html nodes is not the best solution and it won't scale, we need to find a way to know the dropping target slate element\n return getParents(event.nativeEvent.target as Node).some((node) => {\n return ON_DROP_ALLOWED_TYPES[node.nodeName]\n ? !ON_DROP_ALLOWED_TYPES[node.nodeName]?.includes(draggingNode.type)\n : false;\n });\n },\n };\n}\n\nfunction getParents(el: Node): Node[] {\n const parents: Node[] = [];\n\n parents.push(el);\n while (el.parentNode) {\n parents.unshift(el.parentNode);\n el = el.parentNode;\n }\n\n return parents;\n}\n","import { KeyboardEvent } from 'react';\nimport { PlatePlugin, PlateEditor } from '@udecode/plate';\n\nexport function createNewLinePlugin(): PlatePlugin {\n return {\n onKeyDown: function (editor: PlateEditor) {\n return (event: KeyboardEvent) => {\n const isEnter = event.key === 'Enter';\n const isShift = event.shiftKey;\n\n if (isEnter && isShift) {\n event.preventDefault();\n editor.insertText('\\n');\n return true; // To prevent the next handler from running\n }\n\n return false; // something like next()\n };\n },\n };\n}\n","import { PlatePlugin, ExitBreakPluginOptions, createExitBreakPlugin } from '@udecode/plate';\nimport { isFirstChild } from '../../helpers/editor';\n\nexport function createInsertBeforeFirstVoidBlockPlugin(): PlatePlugin {\n const optionsExitBreakPlugin: ExitBreakPluginOptions = {\n rules: [\n {\n hotkey: 'enter',\n before: true,\n query: { filter: ([node, path]) => isFirstChild(path) && !!node.isVoid },\n },\n {\n hotkey: 'enter',\n query: { filter: ([node, path]) => !isFirstChild(path) && !!node.isVoid },\n },\n ],\n };\n\n return createExitBreakPlugin(optionsExitBreakPlugin);\n}\n","import { BLOCKS } from '@contentful/rich-text-types';\nimport { createTrailingBlockPlugin } from '@udecode/plate';\n\nexport const createTrailingParagraphPlugin = () => {\n return createTrailingBlockPlugin({\n type: BLOCKS.PARAGRAPH,\n level: 0,\n });\n};\n","import { Editor, Ancestor, Transforms } from 'slate';\nimport { PlatePlugin, isAncestorEmpty } from '@udecode/plate';\nimport { TEXT_CONTAINERS, BLOCKS } from '@contentful/rich-text-types';\nimport { CustomElement } from '../../types';\n\nexport function createTextPlugin(): PlatePlugin {\n return {\n withOverrides: (editor) => {\n const { deleteForward } = editor;\n\n // When pressing delete instead of backspace\n editor.deleteForward = (unit) => {\n const [nodes] = Editor.nodes(editor, {\n at: editor.selection?.focus.path,\n match: (node) => TEXT_CONTAINERS.includes((node as CustomElement).type as BLOCKS),\n });\n\n if (nodes) {\n const [paragraphOrHeading, path] = nodes;\n const isTextEmpty = isAncestorEmpty(editor, paragraphOrHeading as Ancestor);\n // We ignore paragraphs/headings that are children of ul, ol, blockquote, tables, etc\n const isRootLevel = path.length === 1;\n\n if (isTextEmpty && isRootLevel) {\n Transforms.removeNodes(editor, { at: path });\n } else {\n deleteForward(unit);\n }\n } else {\n deleteForward(unit);\n }\n };\n\n return editor;\n },\n };\n}\n","import React from 'react';\nimport { css } from 'emotion';\nimport PropTypes from 'prop-types';\nimport tokens from '@contentful/f36-tokens';\nimport { EntityProvider } from '@contentful/field-editor-reference';\nimport { FetchingWrappedEntryCard } from '../../plugins/shared/FetchingWrappedEntryCard';\nimport { FetchingWrappedAssetCard } from '../../plugins/shared/FetchingWrappedAssetCard';\n\nimport {\n TextLink,\n Button,\n FormControl,\n FormLabel,\n Select,\n TextInput,\n Form,\n ModalContent,\n ModalControls,\n} from '@contentful/f36-components';\n\nexport const LINK_TYPES = {\n URI: 'uri',\n ENTRY: 'Entry',\n ASSET: 'Asset',\n};\n\nfunction isFeaturingEntitySelector(entitySelectorConfigs = {}) {\n return !!entitySelectorConfigs.Entry || !!entitySelectorConfigs.Asset;\n}\n\nfunction entityToLink(entity) {\n const { id, type } = entity.sys;\n return { sys: { id, type: 'Link', linkType: type } };\n}\n\nexport class HyperlinkDialog extends React.Component {\n static propTypes = {\n sdk: PropTypes.object.isRequired,\n labels: PropTypes.shape({\n title: PropTypes.string,\n confirm: PropTypes.string,\n }),\n value: PropTypes.shape({\n text: PropTypes.string,\n uri: PropTypes.string,\n target: PropTypes.object,\n // Will be overwritten accordingly if `uri` or `target.sys.linkType` are set.\n type: PropTypes.oneOf(['uri', 'Entry', 'Asset']),\n }),\n entitySelectorConfigs: PropTypes.object,\n allowedHyperlinkTypes: PropTypes.arrayOf(\n PropTypes.oneOf([LINK_TYPES.ENTRY, LINK_TYPES.ASSET, LINK_TYPES.URI])\n ),\n hideText: PropTypes.bool,\n onClose: PropTypes.func.isRequired,\n };\n\n static defaultProps = {\n labels: {\n title: 'Insert link',\n confirm: 'Insert link',\n },\n value: {},\n hideText: false,\n entitySelectorConfigs: {},\n allowedHyperlinkTypes: [LINK_TYPES.ENTRY, LINK_TYPES.ASSET, LINK_TYPES.URI],\n };\n\n constructor(props) {\n super(props);\n\n const { text, type, uri, target } = props.value;\n const isEntityLink = Boolean(target);\n const entityLinks = {\n [LINK_TYPES.ENTRY]: null,\n [LINK_TYPES.ASSET]: null,\n };\n let linkType = type;\n\n if (isEntityLink) {\n linkType = target.sys.linkType;\n entityLinks[linkType] = target;\n } else if (props.allowedHyperlinkTypes.includes(LINK_TYPES.URI)) {\n linkType = LINK_TYPES.URI;\n } else {\n linkType = props.allowedHyperlinkTypes[0];\n }\n\n this.state = { text, uri, entityLinks, type: linkType };\n }\n\n setTargetEntity(type, entity) {\n this.setState((state) => ({\n entityLinks: {\n ...state.entityLinks,\n [type]: entity ? entityToLink(entity) : undefined,\n },\n }));\n }\n\n getValue() {\n const { text, type, uri } = this.state;\n const value = { type };\n if (text) {\n value.text = text;\n }\n if (type === LINK_TYPES.URI) {\n value.uri = uri;\n } else {\n value.target = this.state.entityLinks[type];\n }\n return value;\n }\n\n isLinkComplete() {\n const { text, type, uri, target } = this.getValue();\n const requiresText = !this.props.hideText;\n if (requiresText && !text) {\n return false;\n }\n return (type === LINK_TYPES.URI && uri) || target;\n }\n\n handleSubmit = (event) => {\n event.preventDefault();\n this.props.onClose(this.getValue());\n };\n\n selectEntry = async () => {\n const { locale, contentTypes } = this.props.entitySelectorConfigs.Entry;\n const entry = await this.props.sdk.dialogs.selectSingleEntry({ locale, contentTypes });\n this.setTargetEntity(LINK_TYPES.ENTRY, entry);\n };\n\n selectAsset = async () => {\n const { locale } = this.props.entitySelectorConfigs.Asset;\n const asset = await this.props.sdk.dialogs.selectSingleAsset({ locale });\n this.setTargetEntity(LINK_TYPES.ASSET, asset);\n };\n\n render() {\n const { labels } = this.props;\n return (\n <EntityProvider sdk={this.props.sdk}>\n <React.Fragment>\n <ModalContent>{this.renderFields()}</ModalContent>\n <ModalControls>\n <Button\n type=\"button\"\n onClick={() => this.props.onClose(null)}\n variant=\"secondary\"\n testId=\"cancel-cta\"\n size=\"small\">\n Cancel\n </Button>\n <Button\n type=\"submit\"\n variant=\"positive\"\n onClick={this.handleSubmit}\n isDisabled={!this.isLinkComplete()}\n testId=\"confirm-cta\"\n size=\"small\">\n {labels.confirm}\n </Button>\n </ModalControls>\n </React.Fragment>\n </EntityProvider>\n );\n }\n\n renderFields() {\n const { hideText, allowedHyperlinkTypes, entitySelectorConfigs } = this.props;\n const { uri, text, type } = this.state;\n const isUriInputAutoFocused = type === LINK_TYPES.URI && (hideText || !!text);\n\n return (\n <Form>\n {hideText ? null : (\n <FormControl id=\"link-text\" isRequired>\n <FormControl.Label>Link text</FormControl.Label>\n <TextInput\n testId=\"link-text-input\"\n name=\"link-text\"\n value={text || ''}\n onChange={(e) => this.setState({ text: e.target.value })}\n // eslint-disable-next-line jsx-a11y/no-autofocus\n autoFocus={!isUriInputAutoFocused}\n />\n </FormControl>\n )}\n {isFeaturingEntitySelector(entitySelectorConfigs) && (\n <FormControl id=\"link-type\" name=\"link-type\">\n <FormControl.Label>Link type</FormControl.Label>\n <Select\n value={type}\n onChange={(e) => this.setState({ type: e.target.value })}\n testId=\"link-type-select\">\n {/* Show the option if the link type is allowed or the current link is of type that is no longer valid */}\n {allowedHyperlinkTypes.includes(LINK_TYPES.URI) || type === LINK_TYPES.URI ? (\n <Select.Option value={LINK_TYPES.URI}>URL</Select.Option>\n ) : null}\n {allowedHyperlinkTypes.includes(LINK_TYPES.ENTRY) || type === LINK_TYPES.ENTRY ? (\n <Select.Option value={LINK_TYPES.ENTRY}>Entry</Select.Option>\n ) : null}\n {allowedHyperlinkTypes.includes(LINK_TYPES.ASSET) || type === LINK_TYPES.ASSET ? (\n <Select.Option value={LINK_TYPES.ASSET}>Asset</Select.Option>\n ) : null}\n </Select>\n </FormControl>\n )}\n {type === LINK_TYPES.URI ? (\n <FormControl id=\"link-uri\" isRequired>\n <FormControl.Label>Link target</FormControl.Label>\n <TextInput\n testId=\"link-target-input\"\n name=\"link-uri\"\n value={uri || ''}\n placeholder=\"https://\"\n onChange={(e) => this.setState({ uri: e.target.value })}\n // eslint-disable-next-line jsx-a11y/no-autofocus\n autoFocus={isUriInputAutoFocused}\n />\n <FormControl.HelpText>A protocol may be required, e.g. https://</FormControl.HelpText>\n </FormControl>\n ) : (\n this.renderEntityField()\n )}\n </Form>\n );\n }\n\n renderEntityField() {\n const { type, entityLinks } = this.state;\n const resetEntity = () => this.setTargetEntity(type, null);\n const entityLink = entityLinks[type];\n const isEntitySelectorVisible = !entityLink;\n return (\n <div>\n <FormLabel required htmlFor=\"\">\n Link target\n </FormLabel>\n {!isEntitySelectorVisible && (\n <TextLink\n as=\"button\"\n className={css({ marginLeft: tokens.spacingS })}\n onClick={resetEntity}>\n Remove selection\n </TextLink>\n )}\n {entityLink && (\n <div>\n {type === LINK_TYPES.ENTRY && (\n <FetchingWrappedEntryCard\n sdk={this.props.sdk}\n locale={this.props.entitySelectorConfigs.Entry.locale}\n entryId={entityLink.sys.id}\n isDisabled\n isSelected={false}\n />\n )}\n {type == LINK_TYPES.ASSET && (\n <FetchingWrappedAssetCard\n sdk={this.props.sdk}\n locale={this.props.entitySelectorConfigs.Asset.locale}\n assetId={entityLink.sys.id}\n isDisabled\n isSelected={false}\n />\n )}\n </div>\n )}\n {/* Keep all entity selectors in the DOM for super fast types switching ux.*/}\n {isEntitySelectorVisible && this.renderEntitySelector(type, isEntitySelectorVisible)}\n </div>\n );\n }\n\n renderEntitySelector(type) {\n return (\n <div className={css({ marginTop: tokens.spacingS })}>\n {type === LINK_TYPES.ENTRY && (\n <TextLink as=\"button\" onClick={this.selectEntry}>\n Select entry\n </TextLink>\n )}\n {type === LINK_TYPES.ASSET && (\n <TextLink as=\"button\" onClick={this.selectAsset}>\n Select asset\n </TextLink>\n )}\n </div>\n );\n }\n}\n\nexport const openHyperlinkDialog = (\n dialogs,\n { value, showTextInput, allowedHyperlinkTypes, entitySelectorConfigs }\n) => {\n const isNew = !(value.uri || value.target);\n const props = {\n labels: {\n title: isNew ? 'Insert hyperlink' : 'Edit hyperlink',\n confirm: isNew ? 'Insert' : 'Update',\n },\n value,\n hideText: !showTextInput,\n allowedHyperlinkTypes,\n entitySelectorConfigs,\n };\n\n return dialogs.openCurrent({\n title: props.labels.title,\n width: 'large',\n shouldCloseOnEscapePress: true,\n shouldCloseOnOverlayClick: true,\n allowHeightOverflow: true,\n parameters: {\n type: 'rich-text-hyperlink-dialog',\n ...props,\n },\n });\n};\n","import React from 'react';\nimport { DialogExtensionSDK } from '@contentful/app-sdk';\nimport { ModalDialogLauncher } from '@contentful/field-editor-shared';\nimport { HyperlinkDialog } from './HypelinkDialog/HyperlinkDialog';\n\nexport const openRichTextDialog = (sdk: DialogExtensionSDK) => (options) => {\n if (options.parameters?.type === 'rich-text-hyperlink-dialog') {\n return ModalDialogLauncher.openDialog(options, ({ onClose }) => {\n return <HyperlinkDialog {...options.parameters} onClose={onClose} sdk={sdk} />;\n });\n }\n return Promise.reject();\n};\n","import React from 'react';\nimport { DialogExtensionSDK } from '@contentful/app-sdk';\nimport { HyperlinkDialog } from './HypelinkDialog/HyperlinkDialog';\n\nexport const renderRichTextDialog = (sdk: DialogExtensionSDK) => {\n const parameters = sdk.parameters.invocation as Record<string, unknown>;\n if (parameters?.type === 'rich-text-hyperlink-dialog') {\n sdk.window.startAutoResizer();\n return <HyperlinkDialog {...sdk.parameters.invocation} onClose={sdk.close} sdk={sdk} />;\n }\n return <div />;\n};\n"],"names":["STYLE_EDITOR_BORDER","tokens","gray400","styles","root","css","position","editor","borderRadius","borderRadiusMedium","border","borderTop","padding","fontSize","spacingM","fontFamily","fontStackPrimary","minHeight","background","colorWhite","outline","whiteSpace","overflowWrap","webkitUserModify","a","span","cursor","margin","hiddenToolbar","enabled","disabled","gray100","inlines","Object","values","INLINES","map","type","document","nodes","types","TOP_LEVEL_BLOCKS","blocks","BLOCKS","PARAGRAPH","match","object","HEADING_1","HEADING_2","HEADING_3","HEADING_4","HEADING_5","HEADING_6","VOID_BLOCKS","reduce","nodeType","isVoid","QUOTE","CONTAINERS","min","normalize","error","code","unwrapBlockByKey","node","key","HYPERLINK","ENTRY_HYPERLINK","ASSET_HYPERLINK","EMBEDDED_ENTRY","button","height","width","marginLeft","spacing2Xs","marginRight","tooltip","zIndex","Number","zIndexTooltip","ToolbarButton","props","title","testId","isActive","children","isDisabled","React","Button","className","cx","startIcon","onClick","event","preventDefault","variant","size","Tooltip","placement","content","LINK_TYPES","LIST_TYPES","OL_LIST","UL_LIST","isBlockSelected","Array","from","Editor","Element","isElement","hasSelectionText","selection","focus","path","some","Text","isText","text","getNodeEntryFromSelection","nodeTypeOrTypes","nodeTypes","isArray","i","length","nodeEntry","slice","includes","isNodeTypeSelected","moveToTheNextLine","Transforms","move","distance","unit","toggleBlock","isList","isQuote","unwrapNodes","isEditor","split","setNodes","LIST_ITEM","wrapNodes","data","getElementFromCurrentSelection","at","flat","isFirstChild","insertLink","options","url","target","isLinkActive","unwrapLink","isCollapsed","Range","link","uri","insertText","select","insertNodes","collapse","edge","wrapLink","getAncestorPathFromSelection","Path","levels","find","level","shouldUnwrapBlockquote","isQuoteSelected","isValidType","HR","unwrapFromRoot","ancestorPath","replaceNode","replacement","removeNodes","extractParagraphsAt","TEXT_CONTAINERS","mode","deserializeLeaf","rules","pluginOptions","getPlatePluginOptions","leaf","getLeafDeserializer","deserialize","deserializeElement","element","getElementDeserializer","getContentfulEditorId","sdk","field","entry","getSys","id","locale","useContentfulEditorHook","editorId","usePlateEditorRef","constate","ContentfulEditorProvider","useContentfulEditor","container","spacingL","hr","gray300","hrSelected","colorPrimary","withHrEvents","isEnter","keyCode","pathToSelectedHr","ToolbarHrButton","getText","Slate","HorizontalRuleIcon","withHrOptions","component","isSelected","isFocused","attributes","contentEditable","undefined","DEFAULT_ENABLED_NODE_TYPES","DOCUMENT","isFormattingOptionEnabled","validationType","nodeTypeOrMark","enabledFormattings","flow","v","get","validations","getRichTextValidation","concat","isNodeTypeEnabled","isMarkEnabled","mark","useSdk","SdkProvider","useSdkContext","dropdown","fontWeightDemiBold","fontSizeL","headings","fontWeightMedium","spacingS","withHeadingEvents","currentFragment","fragment","isCurrentFragmentAHeading","paragraph","heading","currentOffset","offset","cursorIsAtTheEnd","Node","string","splitNodes","headingKey","ctrlKey","metaKey","altKey","toggleNodeType","activeType","inactiveType","LABELS","ToolbarHeadingButton","isOpen","setOpen","selected","setSelected","operations","nodeTypesByEnablement","fromEntries","keys","filter","Boolean","someHeadingsEnabled","Menu","onClose","Trigger","endIcon","ChevronDownIcon","List","Item","isInitiallyFocused","setTimeout","createHeading","Tag","block","H1","H2","H3","H4","H5","H6","withHeadingOptions","blockquote","borderLeft","gray200","paddingLeft","fontStyle","color","createBlockQuote","withQuoteEvents","isBackspace","shiftKey","TABLE","every","item","ToolbarQuoteButton","QuoteIcon","withQuoteOptions","ToolbarListButton","handleClick","toggleList","ListBulletedIcon","ListNumberedIcon","listStyles","lineHeightDefault","createList","UL","OL","LI","withListOptions","ELEMENT_LIC","ELEMENT_LI","ELEMENT_UL","ELEMENT_OL","isListItem","isValidInsideListItem","LIST_ITEM_BLOCKS","replaceInvalidListItemWithText","textFromEntry","withCustomList","withDefaultOverrides","withList","insertFragment","li","ul","ol","isListRoot","liEntry","findNode","liPath","flatMap","listRoot","textEntries","texts","commonAncestorEntry","commonAncestor","textEntry","isAncestor","common","ancestor","parent","getFirstAncestorOfType","trimList","next","filtered","getListInsertFragment","normalizeNode","child","childPath","normalizeList","getParent","hasListAsDirectParent","parentList","getAbove","getNearestListAncestor","normalizeOrphanedListItem","listItemChildren","ToolbarBoldButton","toggleMark","MARKS","BOLD","isMarkActive","FormatBoldIcon","bold","fontWeight","withBoldOptions","hotkey","ToolbarCodeButton","CODE","CodeIcon","withCodeOptions","ToolbarItalicButton","ITALIC","FormatItalicIcon","italic","withItalicOptions","ToolbarUnderlineButton","UNDERLINE","FormatUnderlinedIcon","withUnderlineOptions","runtime","exports","Op","prototype","hasOwn","hasOwnProperty","$Symbol","Symbol","iteratorSymbol","iterator","asyncIteratorSymbol","asyncIterator","toStringTagSymbol","toStringTag","define","obj","value","defineProperty","enumerable","configurable","writable","err","wrap","innerFn","outerFn","self","tryLocsList","generator","create","Generator","context","Context","_invoke","state","method","arg","Error","done","delegate","delegateResult","maybeInvokeDelegate","ContinueSentinel","sent","_sent","dispatchException","abrupt","record","tryCatch","makeInvokeMethod","fn","call","GeneratorFunction","GeneratorFunctionPrototype","IteratorPrototype","this","getProto","getPrototypeOf","NativeIteratorPrototype","Gp","defineIteratorMethods","forEach","AsyncIterator","PromiseImpl","previousPromise","callInvokeWithMethodAndArg","resolve","reject","invoke","result","__await","then","unwrapped","TypeError","info","resultName","nextLoc","pushTryEntry","locs","tryLoc","catchLoc","finallyLoc","afterLoc","tryEntries","push","resetTryEntry","completion","reset","iterable","iteratorMethod","isNaN","doneResult","constructor","displayName","isGeneratorFunction","genFun","ctor","name","setPrototypeOf","__proto__","awrap","async","Promise","iter","toString","reverse","pop","skipTempReset","prev","charAt","stop","rootRecord","rval","exception","handle","loc","caught","hasCatch","hasFinally","finallyEntry","complete","finish","thrown","delegateYield","module","regeneratorRuntime","accidentalStrictMode","Function","EntryAssetTooltip","entityTitle","setEntityTitle","entityStatus","setEntityStatus","jobs","setJobs","isLoading","setIsLoading","hasError","setHasError","actions","Asset","getEntity","space","getAsset","getEntityTitle","args","entityHelpers","getAssetTitle","asset","entity","Entry","getEntry","getEntryTitle","sys","contentType","contentTypeId","contentTypes","getCachedContentTypes","ct","localeCode","defaultLocaleCode","locales","entityType","getEntityScheduledActions","getEntryStatus","console","log","loadContent","toLowerCase","str","contentTypeName","substr","replace","getEntityInfo","getScheduleTooltipContent","job","jobsCount","scheduleIcon","EntityStatusIcon","useEntities","ScheduledIconWithTooltip","loadEntityScheduledActions","entityId","ClockIcon","entryCard","EntryThumbnail","file","isValidImage","AssetThumbnail","FetchingWrappedEntryCard","getOrLoadEntry","entries","setFile","entryId","getEntryImage","EntryCard","MissingEntityCard","onRemove","entryStatus","defaultTitle","description","getEntityDescription","status","thumbnailElement","icon","withDragHandle","onEdit","MenuItem","renderDropdown","assetCard","cardDropdown","truncated","overflow","textOverflow","renderAssetInfo","entityFile","fileName","mimeType","fileSize","image","SectionTitle","isTruncated","shortenStorageUnit","renderActions","window","open","FetchingWrappedAssetCard","getOrLoadAsset","assets","assetId","fields","AssetCard","asSquare","groupToIconMap","archive","src","video","audio","richtext","presentation","spreadsheet","pdfdocument","plaintext","markup","mimetype","getGroupLabel","fallbackFileName","getLinkedContentTypeIdsForNodeType","removeSelectionLabel","SYS_LINK_TYPES","LINK_TYPE_SELECTION_VALUES","HyperlinkModal","enabledLinkTypes","defaultLinkType","linkText","setLinkText","linkType","setLinkType","linkTarget","setLinkTarget","linkEntity","setLinkEntity","entityToLink","dialogs","selectSingleEntry","selectSingleAsset","EntityProvider","ModalContent","Form","FormControl","isRequired","Label","TextInput","onChange","Select","Option","HelpText","FormLabel","htmlFor","TextLink","ModalControls","addOrEditLink","selectionBeforeBlur","currentLinkText","ModalDialogLauncher","openDialog","shouldCloseOnEscapePress","shouldCloseOnOverlayClick","allowHeightOverflow","ReactEditor","hyperlinkWrapper","display","hyperlink","fill","gray900","hyperlinkIEFallback","textDecoration","hyperlinkIcon","top","webkitTransition","transition","createHyperlinkPlugin","renderElement","getRenderElement","pluginKeys","inlineTypes","getPlatePluginTypes","onKeyDown","buildHyperlinkEventHandler","hyperlinkOptions","entryHyperlinkOptions","assetHyperlinkOptions","isAnchor","nodeName","getAttribute","isEntryAnchor","isAssetAnchor","isMod","isK","wasHyperlinkEventTriggered","EntityHyperlink","stopPropagation","targetWrapperClassName","maxWidth","as","ToolbarHyperlinkButton","LinkIcon","withHyperlinkOptions","href","rel","insertTableAndFocusFirstCell","insertTable","header","tablePath","anchor","setSelection","moveToFirstCellFromSelectedTable","previousPath","previous","isAncestorEmpty","moveNodes","to","replaceEmptyParagraphWithTable","useTracking","onAction","onViewportAction","actionName","origin","TrackingProvider","useTrackingContext","addRow","getNextRowPath","someNode","getPlatePluginType","ELEMENT_TABLE","currentRowItem","ELEMENT_TR","currentRowElem","nextRowPath","getEmptyRowNode","colCount","start","addRowBelow","currentRowPath","addRowAbove","addColumn","getNextCellPath","currentCellItem","ELEMENT_TD","ELEMENT_TH","currentTableItem","newCellPath","replacePathPos","_","rowIdx","getEmptyCellNode","addColumnRight","currentCellPath","addColumnLeft","topRight","right","TableActions","useState","isHeaderEnabled","setHeaderEnabled","close","useCallback","useEffect","tableItem","firstRow","getChildren","TABLE_HEADER_CELL","isTableHeaderEnabled","canInsertRowAbove","useMemo","toggleHeader","enable","TABLE_CELL","setHeader","action","cb","tableSize","table","numRows","numColumns","_firstRow$children","getTableSize","getCurrentTableSize","onOpen","IconButton","tabIndex","Divider","deleteRow","deleteColumn","deleteTable","withNormalizer","handler","passed","normalizeTableCell","isTableCell","normalizeTable","TABLE_ROW","withTableOptions","hasTables","isTableHeaderCell","createTablePlugin","tracking","createTablePluginFromUdecode","handleKeyDownFromPlateUdecode","getTableOnKeyDown","currentSelectionStartsTableCell","nextNode","descendants","isCommon","getNextNode","TABLE_BLOCKS","_editor$selection2","isAtEndOfTextSelection","currentSelectionPrecedesTableCell","withOverrides","insertData","getData","markupBefore","markupAfter","tablePasted","hasHeadersOutsideFirstRow","addTableTrackingEvents","addTableNormalizers","fragments","ToolbarTableButton","el","isTableActive","TableIcon","EmbeddedEntityDropdownButton","onToggle","PlusIcon","IS_EDGE_LEGACY","navigator","test","userAgent","HAS_BEFORE_INPUT_SUPPORT","globalThis","InputEvent","getTargetRanges","marginBottom","LinkedEntityBlock","useSelected","useReadOnly","handleEditClick","openAsset","openEntry","slideIn","handleRemoveClick","pathToElement","findPath","draggable","newEntitySelectorConfigFromRichTextField","getEntityTypeFromRichTextNode","words","indexOf","selectEntityAndInsert","logAction","baseConfig","selectEntity","config","withCreate","insertBlock","linkedEntityBlock","createNode","EmbeddedEntityBlockToolbarIcon","isButton","noop","getEntityTypeFromNodeType","baseClass","AssetIcon","EmbeddedEntryBlockIcon","Flex","alignItems","flexDirection","Icon","createEmbeddedEntityPlugin","getWithEmbeddedEntityEvents","voidTypes","entityTypes","EMBEDDED_ASSET","embeddedEntityId","createEmbeddedEntryBlockPlugin","createEmbeddedAssetBlockPlugin","withEmbeddedEntryBlockOptions","withEmbeddedAssetBlockOptions","isShift","pathToSelectedElement","isE","wasEmbeddedEntryEventTriggered","isA","wasEmbeddedAssetEventTriggered","scheduledIcon","verticalAlign","FetchingWrappedInlineEntryCard","allContentTypes","InlineEntryCard","createInlineEntryNode","webkitUserSelect","mozUserSelect","msUserSelect","userSelect","inlineEntryNode","ToolbarEmbeddedEntityInlineButton","EmbeddedEntryInlineIcon","createEmbeddedEntityInlinePlugin","getWithEmbeddedEntryInlineEvents","withEmbeddedEntityInlineOptions","isTwo","wasEmbeddedEntryInlineEventTriggered","EmbedEntityWidget","canInsertBlocks","isEmbedDropdownOpen","setEmbedDropdownOpen","onCloseEntityDropdown","canAccessAssets","setCanAccessAssets","access","can","inlineEntryEmbedEnabled","blockEntryEmbedEnabled","blockAssetEmbedEnabled","shouldDisplayDropdown","toolbar","backgroundColor","spacingXs","divider","embedActionsWrapper","webkitAlignSelf","alignSelf","msFlexItemAlign","formattingOptionsWrapper","msFlexAlign","webkitBoxAlign","msFlexWrap","flexWrap","Toolbar","validationInfo","isAnyMarkEnabled","someWithValidation","vals","validation","val","isAnyHyperlinkEnabled","isAnyBlockFormattingEnabled","isListSelected","isBlockquoteSelected","shouldDisableTables","Fragment","nativeSticky","StickyToolbarWrapper","TEXT_PARENT_NODES","isTextElement","wrapNode","isHTMLElement","ELEMENT_NODE","removeChildNodes","predicate","childNodes","removeChild","removeChildNodesUsingPredicate","nodeList","removeCommentChildren","COMMENT_NODE","DISALLOWED_TABLE_CHILD_ELEMENTS","isTableElement","tagName","removeDisallowedTableChildElements","sanitizeDocument","apply","doc","removeTableGrandchildren","Paragraph","ELEMENT_PARAGRAPH","ConnectedRichTextEditor","sanitizeIncomingSlateDoc","toSlatejsDocument","Contentful","schema","setValue","classNames","isToolbarHidden","plugins","plugin","elementKeys","deserializer","DND_BLOCKED_ELEMENTS","DRAGGABLE_TYPES","ON_DROP_ALLOWED_TYPES","createReactPlugin","createHistoryPlugin","html","newData","DataTransfer","setData","htmlToDataTransfer","DOMParser","parseFromString","sanitizedDoc","XMLSerializer","serializeToString","sanitizeHtml","createExitBreakPlugin","before","query","liftNodes","blockedElementType","SlateNode","isNode","callback","matchNode","onDrop","draggingBlock","getNodes","isBlock","draggingNode","nativeEvent","parents","parentNode","unshift","getParents","_ON_DROP_ALLOWED_TYPE","nodeNames","getToggleElementOnKeyDown","deserializeNode","textContent","isEmpty","hasAttribute","isEmbed","isInline","validLiChildrenTypes","createPlateListPlugin","headingType","index","renderLeaf","getRenderLeaf","getToggleMarkOnKeyDown","isGoogleBoldWrapper","startsWith","isBold","style","createTrailingBlockPlugin","deleteForward","_editor$selection","createDeserializeHTMLPlugin","createDeserializeAstPlugin","getPlugins","Plate","initialValue","editableProps","readOnly","newValue","slateDoc","sanitizeSlateDoc","parentNodeType","wrapOrphanedTextNode","contentfulDoc","toContentfulDocument","HyperlinkDialog","handleSubmit","_this","getValue","selectEntry","entitySelectorConfigs","setTargetEntity","selectAsset","isEntityLink","entityLinks","allowedHyperlinkTypes","setState","isLinkComplete","hideText","render","labels","renderFields","_this2","confirm","isUriInputAutoFocused","e","_this3","autoFocus","isFeaturingEntitySelector","placeholder","renderEntityField","entityLink","isEntitySelectorVisible","required","_this4","renderEntitySelector","marginTop","Component","propTypes","PropTypes","shape","oneOf","arrayOf","bool","func","defaultProps","isInitiallyDisabled","otherProps","isEmptyValue","deepEquals","FieldConnector","throttle","isEqualValues","externalReset","lastRemoteValue","parameters","invocation","startAutoResizer"],"mappings":"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"}
1
+ {"version":3,"file":"field-editor-rich-text.cjs.production.min.js","sources":["../src/RichTextEditor.styles.ts","../src/constants/Schema.ts","../src/plugins/shared/ToolbarButton.tsx","../src/helpers/editor.ts","../src/helpers/deserializer.ts","../src/ContentfulEditorProvider.ts","../src/plugins/Hr/index.tsx","../src/helpers/validations.ts","../src/SdkProvider.tsx","../src/plugins/Heading/index.tsx","../src/plugins/Quote/index.tsx","../src/plugins/List/index.tsx","../src/plugins/List/getListInsertFragment.ts","../src/plugins/Bold/index.tsx","../src/plugins/Code/index.tsx","../src/plugins/Italic/index.tsx","../src/plugins/Underline/index.tsx","../../../node_modules/regenerator-runtime/runtime.js","../src/plugins/Hyperlink/EntryAssetTooltip.tsx","../src/helpers/truncate.ts","../src/plugins/shared/EntityStatusIcon.tsx","../src/plugins/shared/FetchingWrappedEntryCard.tsx","../src/plugins/shared/FetchingWrappedAssetCard.tsx","../src/helpers/getLinkedContentTypeIdsForNodeType.ts","../src/plugins/Hyperlink/HyperlinkModal.tsx","../src/plugins/Hyperlink/index.tsx","../src/plugins/Table/helpers.ts","../src/TrackingProvider.tsx","../src/plugins/Table/actions/addRow.ts","../src/plugins/Table/actions/addColumn.ts","../src/plugins/Table/TableActions.tsx","../src/plugins/Table/actions/setHeader.ts","../src/helpers/normalizers.ts","../src/plugins/Table/normalizers.ts","../src/plugins/Table/index.tsx","../src/plugins/EmbeddedEntity/index.tsx","../src/helpers/environment.ts","../src/plugins/EmbeddedEntityBlock/LinkedEntityBlock.tsx","../src/helpers/newEntitySelectorConfigFromRichTextField.ts","../src/plugins/EmbeddedEntityBlock/Util.ts","../src/plugins/EmbeddedEntityBlock/ToolbarIcon.tsx","../src/plugins/EmbeddedEntityBlock/index.tsx","../src/plugins/EmbeddedEntityInline/FetchingWrappedInlineEntryCard.tsx","../src/plugins/EmbeddedEntityInline/Util.ts","../src/plugins/EmbeddedEntityInline/index.tsx","../src/Toolbar/EmbedEntityWidget.tsx","../src/Toolbar/index.tsx","../src/Toolbar/StickyToolbarWrapper.tsx","../src/helpers/sanitizeSlateDoc.ts","../src/plugins/Paste/sanitizers/helpers.tsx","../src/plugins/Paste/sanitizers/removeComments.tsx","../src/plugins/Paste/sanitizers/sanitizeTables.tsx","../src/plugins/Paste/index.tsx","../src/plugins/Paste/sanitizers/sanitizeEntityBlocks.tsx","../src/plugins/Paragraph/index.tsx","../src/plugins/index.ts","../src/RichTextEditor.tsx","../src/plugins/DragAndDrop/index.tsx","../src/plugins/NewLine/index.tsx","../src/plugins/InsertBeforeFirstVoidBlock/index.tsx","../src/plugins/TrailingParagraph/index.ts","../src/plugins/Text/index.ts","../src/dialogs/HypelinkDialog/HyperlinkDialog.jsx","../src/dialogs/openRichTextDialog.tsx","../src/dialogs/renderRichTextDialog.tsx"],"sourcesContent":["import { css } from 'emotion';\nimport tokens from '@contentful/f36-tokens';\n\nconst STYLE_EDITOR_BORDER = `1px solid ${tokens.gray400}`;\n\nexport const styles = {\n root: css({\n position: 'relative',\n }),\n editor: css({\n borderRadius: `0 0 ${tokens.borderRadiusMedium} ${tokens.borderRadiusMedium}`,\n border: STYLE_EDITOR_BORDER,\n borderTop: 0,\n padding: '20px',\n fontSize: tokens.spacingM,\n fontFamily: tokens.fontStackPrimary,\n minHeight: '400px',\n background: tokens.colorWhite,\n outline: 'none',\n whiteSpace: 'pre-wrap',\n overflowWrap: 'break-word',\n webkitUserModify: 'read-write-plaintext-only',\n a: {\n span: {\n cursor: 'not-allowed',\n '&:hover': {\n cursor: 'not-allowed',\n },\n },\n },\n // We need to reset LIC style due to conflicts between PARAGRAPH styles\n 'ul > li > div': {\n margin: 0,\n },\n }),\n hiddenToolbar: css({\n borderTop: STYLE_EDITOR_BORDER,\n }),\n enabled: css({\n background: tokens.colorWhite,\n a: {\n span: {\n cursor: 'pointer',\n '&:hover': {\n cursor: 'pointer',\n },\n },\n },\n }),\n disabled: css({\n background: tokens.gray100,\n }),\n};\n","import {\n BLOCKS,\n INLINES,\n TOP_LEVEL_BLOCKS,\n VOID_BLOCKS,\n CONTAINERS,\n} from '@contentful/rich-text-types';\n\nconst inlines = Object.values(INLINES).map((type) => ({ type }));\n\nexport default {\n document: {\n nodes: [\n {\n types: TOP_LEVEL_BLOCKS.map((type) => ({ type })),\n },\n ],\n },\n\n blocks: {\n [BLOCKS.PARAGRAPH]: {\n nodes: [\n {\n match: [...inlines, { object: 'text' }],\n },\n ],\n },\n [BLOCKS.HEADING_1]: {\n nodes: [\n {\n match: [...inlines, { object: 'text' }],\n },\n ],\n },\n [BLOCKS.HEADING_2]: {\n nodes: [\n {\n match: [...inlines, { object: 'text' }],\n },\n ],\n },\n [BLOCKS.HEADING_3]: {\n nodes: [\n {\n match: [...inlines, { object: 'text' }],\n },\n ],\n },\n [BLOCKS.HEADING_4]: {\n nodes: [\n {\n match: [...inlines, { object: 'text' }],\n },\n ],\n },\n [BLOCKS.HEADING_5]: {\n nodes: [\n {\n match: [...inlines, { object: 'text' }],\n },\n ],\n },\n [BLOCKS.HEADING_6]: {\n nodes: [\n {\n match: [...inlines, { object: 'text' }],\n },\n ],\n },\n\n ...VOID_BLOCKS.reduce(\n (blocks, nodeType) => ({\n ...blocks,\n [nodeType]: { isVoid: true },\n }),\n {}\n ),\n\n // TODO: add list schema\n\n [BLOCKS.QUOTE]: {\n nodes: [\n {\n match: [CONTAINERS[BLOCKS.QUOTE].map((type) => ({ type }))],\n min: 1,\n },\n ],\n normalize: (editor, error) => {\n if (error.code === 'child_type_invalid') {\n return editor.unwrapBlockByKey(error.node.key, BLOCKS.QUOTE);\n }\n },\n },\n },\n\n inlines: {\n [INLINES.HYPERLINK]: {\n nodes: [\n {\n match: [{ object: 'text' }],\n },\n ],\n },\n [INLINES.ENTRY_HYPERLINK]: {\n nodes: [\n {\n match: [{ object: 'text' }],\n },\n ],\n },\n [INLINES.ASSET_HYPERLINK]: {\n nodes: [\n {\n match: [{ object: 'text' }],\n },\n ],\n },\n [INLINES.EMBEDDED_ENTRY]: {\n isVoid: true,\n },\n },\n};\n","import React from 'react';\nimport { css, cx } from 'emotion';\nimport { Button, Tooltip } from '@contentful/f36-components';\nimport tokens from '@contentful/f36-tokens';\n\nconst styles = {\n button: css({\n height: '30px',\n width: '30px',\n marginLeft: tokens.spacing2Xs,\n marginRight: tokens.spacing2Xs,\n }),\n\n tooltip: css({\n zIndex: Number(tokens.zIndexTooltip),\n }),\n};\n\ninterface ToolbarButtonProps {\n onClick: () => void;\n isActive?: boolean;\n isDisabled?: boolean;\n children: any;\n title: string;\n className?: string;\n testId?: string;\n}\n\nexport function ToolbarButton(props: ToolbarButtonProps) {\n const { title, testId, isActive, children, className, isDisabled = false } = props;\n const handleClick = (event) => {\n event.preventDefault();\n props.onClick();\n };\n\n const button = (\n <Button\n className={cx(styles.button, className)}\n isDisabled={isDisabled}\n startIcon={children}\n onClick={handleClick}\n testId={testId}\n variant={isActive ? 'secondary' : 'transparent'}\n size=\"small\"\n />\n );\n\n if (title) {\n return (\n <Tooltip className={styles.tooltip} placement=\"bottom\" content={title}>\n {button}\n </Tooltip>\n );\n }\n\n return button;\n}\n","import { PlateEditor } from '@udecode/plate-core';\nimport { getText } from '@udecode/plate-common';\nimport { Link } from '@contentful/field-editor-reference/dist/types';\nimport { Text, Editor, Element, Transforms, Path, Range, Node, Location } from 'slate';\nimport { BLOCKS, INLINES, TABLE_BLOCKS, TEXT_CONTAINERS } from '@contentful/rich-text-types';\n\nimport { CustomElement } from '../types';\n\nexport const LINK_TYPES: INLINES[] = [\n INLINES.HYPERLINK,\n INLINES.ENTRY_HYPERLINK,\n INLINES.ASSET_HYPERLINK,\n];\n\nconst LIST_TYPES: BLOCKS[] = [BLOCKS.OL_LIST, BLOCKS.UL_LIST];\n\nexport function isBlockSelected(editor, type: string): boolean {\n const [match] = Array.from(\n Editor.nodes(editor, {\n match: (node) => Element.isElement(node) && (node as CustomElement).type === type,\n })\n );\n return !!match;\n}\n\nexport function isVoid(editor, element): boolean {\n const { isVoid: originalIsVoid } = editor;\n\n return element.isVoid || originalIsVoid(element);\n}\n\nexport function hasSelectionText(editor) {\n return editor.selection\n ? Editor.node(editor, editor.selection.focus.path).some(\n (node) => Text.isText(node) && node.text !== ''\n )\n : false;\n}\n\ntype NodeEntry = [CustomElement, Path];\ntype NodeType = BLOCKS | INLINES;\nexport function getNodeEntryFromSelection(\n editor,\n nodeTypeOrTypes: NodeType | NodeType[]\n): NodeEntry | [] {\n if (!editor.selection) return [];\n const nodeTypes = Array.isArray(nodeTypeOrTypes) ? nodeTypeOrTypes : [nodeTypeOrTypes];\n const { path } = editor.selection.focus;\n for (let i = 0; i < path.length; i++) {\n const nodeEntry = Editor.node(editor, path.slice(0, i + 1)) as NodeEntry;\n if (nodeTypes.includes(nodeEntry[0].type as NodeType)) return nodeEntry;\n }\n return [];\n}\n\nexport function isNodeTypeSelected(editor, nodeType: BLOCKS | INLINES): boolean {\n if (!editor) return false;\n const [node] = getNodeEntryFromSelection(editor, nodeType);\n return !!node;\n}\n\nexport function moveToTheNextLine(editor) {\n Transforms.move(editor, { distance: 1, unit: 'line' });\n}\n\nexport function moveToThePreviousLine(editor) {\n Transforms.move(editor, { distance: 1, unit: 'line', reverse: true });\n}\n\nexport function toggleBlock(editor, type: string): void {\n const isActive = isBlockSelected(editor, type);\n const isList = LIST_TYPES.includes(type as BLOCKS);\n const isQuote = type === BLOCKS.QUOTE;\n\n Transforms.unwrapNodes(editor, {\n match: (node) => {\n if (Editor.isEditor(node) || !Element.isElement(node)) {\n return false;\n }\n\n // Lists\n if (isList && LIST_TYPES.includes((node as CustomElement).type as BLOCKS)) {\n return true;\n }\n\n // Quotes\n if (isQuote && (node as CustomElement).type === BLOCKS.QUOTE) {\n return true;\n }\n\n return false;\n },\n split: true,\n });\n const newProperties: Partial<CustomElement> = {\n type: isActive\n ? BLOCKS.PARAGRAPH\n : isList\n ? BLOCKS.LIST_ITEM\n : isQuote\n ? BLOCKS.PARAGRAPH\n : type,\n };\n Transforms.setNodes(editor, newProperties);\n\n if (!isActive && (isList || isQuote)) {\n const block = {\n type,\n data: {},\n children: [],\n };\n Transforms.wrapNodes(editor, block);\n }\n}\n\nexport function getElementFromCurrentSelection(editor) {\n if (!editor.selection) return [];\n\n return Array.from(\n Editor.nodes(editor, {\n at: editor.selection.focus,\n match: (node) => Element.isElement(node),\n })\n ).flat();\n}\n\nexport function isList(editor) {\n const element = getElementFromCurrentSelection(editor);\n\n return element.some(\n (element) =>\n Element.isElement(element) && LIST_TYPES.includes((element as CustomElement).type as BLOCKS)\n );\n}\n\nexport function getTableSize(\n table: CustomElement\n): Record<'numRows' | 'numColumns', number> | null {\n const numRows = table.children.length;\n if (!numRows) return null;\n const [firstRow] = table.children;\n const numColumns = (firstRow as CustomElement).children?.length;\n return { numRows, numColumns };\n}\n\nexport function isFirstChild(path: Path) {\n return path[path.length - 1] === 0;\n}\n\ninterface InsertLinkOptions {\n text: string;\n type: INLINES.HYPERLINK | INLINES.ENTRY_HYPERLINK | INLINES.ASSET_HYPERLINK;\n url?: string;\n target?: Link;\n path?: Path;\n}\n\nexport function insertLink(editor, options: InsertLinkOptions) {\n if (editor.selection) {\n wrapLink(editor, options);\n }\n}\n\nexport function isLinkActive(editor) {\n const [link] = Array.from(\n Editor.nodes(editor, {\n match: (node) =>\n !Editor.isEditor(node) &&\n Element.isElement(node) &&\n LINK_TYPES.includes((node as CustomElement).type as INLINES),\n })\n );\n return !!link;\n}\n\nexport function unwrapLink(editor) {\n Transforms.unwrapNodes(editor, {\n match: (node) =>\n !Editor.isEditor(node) &&\n Element.isElement(node) &&\n LINK_TYPES.includes((node as CustomElement).type as INLINES),\n });\n}\n\nexport function wrapLink(editor, { text, url, target, type, path }: InsertLinkOptions) {\n if (isLinkActive(editor) && !path) {\n unwrapLink(editor);\n }\n\n const { selection } = editor;\n const isCollapsed = selection && Range.isCollapsed(selection);\n const link = {\n type,\n data: {},\n children: isCollapsed ? [{ text }] : [],\n };\n\n if (url) {\n link.data = { uri: url };\n }\n\n if (target) {\n link.data = { target };\n }\n\n // TODO: always set the selection to the end of the inserted link\n if (path) {\n Transforms.setNodes(editor, link, { at: path });\n Transforms.insertText(editor, text, { at: path });\n Transforms.select(editor, path);\n } else if (isCollapsed) {\n Transforms.insertNodes(editor, link);\n } else {\n Transforms.wrapNodes(editor, link, { split: true });\n Transforms.delete(editor);\n Transforms.insertText(editor, text);\n Transforms.collapse(editor, { edge: 'end' });\n }\n}\n\nexport function getAncestorPathFromSelection(editor: PlateEditor) {\n if (!editor.selection) return undefined;\n\n return Path.levels(editor.selection.focus.path).find((level) => level.length === 1);\n}\n\nexport function shouldUnwrapBlockquote(editor: PlateEditor, type: BLOCKS) {\n const isQuoteSelected = isBlockSelected(editor, BLOCKS.QUOTE);\n const isValidType = [\n BLOCKS.HEADING_1,\n BLOCKS.HEADING_2,\n BLOCKS.HEADING_3,\n BLOCKS.HEADING_4,\n BLOCKS.HEADING_5,\n BLOCKS.HEADING_6,\n\n BLOCKS.OL_LIST,\n BLOCKS.UL_LIST,\n\n BLOCKS.HR,\n ].includes(type);\n\n return isQuoteSelected && isValidType;\n}\n\nexport function unwrapFromRoot(editor: PlateEditor) {\n const ancestorPath = getAncestorPathFromSelection(editor);\n Transforms.unwrapNodes(editor, { at: ancestorPath });\n}\n\nexport const isAtEndOfTextSelection = (editor: PlateEditor) =>\n editor.selection?.focus.offset === getText(editor, editor.selection?.focus.path).length;\n\nexport function currentSelectionStartsTableCell(editor: PlateEditor): boolean {\n const [tableCellNode, path] = getNodeEntryFromSelection(editor, [\n BLOCKS.TABLE_CELL,\n BLOCKS.TABLE_HEADER_CELL,\n ]);\n return !!tableCellNode && (!getText(editor, path) || editor.selection?.focus.offset === 0);\n}\n\n/**\n * This traversal strategy is unfortunately necessary because Slate doesn't\n * expose something like Node.next(editor).\n */\nexport function getNextNode(editor: PlateEditor): CustomElement | null {\n if (!editor.selection) {\n return null;\n }\n const descendants = Node.descendants(editor, { from: editor.selection.focus.path });\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const { done, value } = descendants.next();\n if (done) {\n return null;\n }\n const [node, path] = value as NodeEntry;\n if (Path.isCommon(path, editor.selection.focus.path)) {\n continue;\n }\n return node as CustomElement;\n }\n}\n\nexport function currentSelectionPrecedesTableCell(editor: PlateEditor): boolean {\n const nextNode = getNextNode(editor);\n return (\n !!nextNode && TABLE_BLOCKS.includes(nextNode.type as BLOCKS) && isAtEndOfTextSelection(editor)\n );\n}\n\nexport const replaceNode = (editor: Editor, path: Location, replacement: Node | Node[]) => {\n Transforms.removeNodes(editor, { at: path });\n Transforms.insertNodes(editor, replacement, { at: path });\n};\n\n/**\n * It filters out all paragraphs and headings from a path and convert them into paragraphs.\n */\nexport function extractParagraphsAt(editor: PlateEditor, path: Path): CustomElement[] {\n const paragraphs: CustomElement[] = Array.from(\n Editor.nodes<CustomElement>(editor, {\n at: path,\n match: (node) => TEXT_CONTAINERS.includes((node as CustomElement).type as BLOCKS),\n mode: 'all',\n })\n ).map(([node]) => ({\n ...node,\n type: BLOCKS.PARAGRAPH,\n }));\n\n return paragraphs;\n}\n","import {\n getPlatePluginOptions,\n PlateEditor,\n Deserialize,\n GetNodeDeserializerRule,\n} from '@udecode/plate-core';\nimport { getLeafDeserializer, getElementDeserializer } from '@udecode/plate-common';\n\nexport function deserializeLeaf(type: string, rules: GetNodeDeserializerRule[]): Deserialize {\n return function (editor: PlateEditor) {\n const pluginOptions = getPlatePluginOptions(editor, type);\n\n return {\n leaf: getLeafDeserializer({\n type,\n rules,\n ...pluginOptions.deserialize,\n }),\n };\n };\n}\n\nexport function deserializeElement(type: string, rules: GetNodeDeserializerRule[]): Deserialize {\n return function (editor: PlateEditor) {\n const pluginOptions = getPlatePluginOptions(editor, type);\n\n return {\n element: getElementDeserializer({\n type,\n rules,\n ...pluginOptions.deserialize,\n }),\n };\n };\n}\n","import constate from 'constate';\nimport { usePlateEditorRef } from '@udecode/plate-core';\nimport { FieldExtensionSDK } from '@contentful/app-sdk';\n\nexport function getContentfulEditorId(sdk: FieldExtensionSDK) {\n const { entry, field } = sdk;\n const entryId = entry.getSys().id;\n\n return `rich-text-editor-${entryId}-${field.id}-${field.locale}`;\n}\n\ninterface useContentfulEditorHookProps {\n sdk: FieldExtensionSDK;\n}\n\nfunction useContentfulEditorHook({ sdk }: useContentfulEditorHookProps) {\n const editorId = getContentfulEditorId(sdk);\n const editor = usePlateEditorRef(editorId);\n\n return editor;\n}\n\nexport const [ContentfulEditorProvider, useContentfulEditor] = constate(useContentfulEditorHook);\n","import * as React from 'react';\nimport * as Slate from 'slate-react';\nimport { css, cx } from 'emotion';\nimport tokens from '@contentful/f36-tokens';\nimport { HorizontalRuleIcon } from '@contentful/f36-icons';\nimport { ToolbarButton } from '../shared/ToolbarButton';\nimport { Transforms } from 'slate';\nimport { BLOCKS } from '@contentful/rich-text-types';\nimport {\n getPlatePluginTypes,\n getRenderElement,\n PlatePlugin,\n PlateEditor,\n} from '@udecode/plate-core';\nimport { getText, setNodes } from '@udecode/plate-common';\nimport {\n getNodeEntryFromSelection,\n isBlockSelected,\n moveToTheNextLine,\n shouldUnwrapBlockquote,\n unwrapFromRoot,\n} from '../../helpers/editor';\nimport { CustomSlatePluginOptions } from '../../types';\nimport { deserializeElement } from '../../helpers/deserializer';\nimport { useContentfulEditor } from '../../ContentfulEditorProvider';\n\nconst styles = {\n container: css`\n margin: 0 0 ${tokens.spacingL};\n `,\n hr: css`\n margin: 0;\n height: ${tokens.spacingM};\n background: transparent;\n position: relative;\n border: 0;\n user-select: none;\n &:hover {\n cursor: pointer;\n }\n &::after {\n content: '';\n position: absolute;\n width: 100%;\n height: 1px;\n background: ${tokens.gray300};\n top: 50%;\n }\n `,\n hrSelected: css`\n &::after {\n background: ${tokens.colorPrimary};\n -webkit-box-shadow: 0px 0px 5px ${tokens.colorPrimary};\n box-shadow: 0px 0px 5px ${tokens.colorPrimary};\n }\n `,\n};\n\ninterface ToolbarHrButtonProps {\n isDisabled?: boolean;\n}\n\nexport function withHrEvents(editor: PlateEditor) {\n return (event: React.KeyboardEvent) => {\n if (!editor) return;\n\n const isEnter = event.keyCode === 13;\n const [, pathToSelectedHr] = getNodeEntryFromSelection(editor, BLOCKS.HR);\n\n if (pathToSelectedHr) {\n if (shouldUnwrapBlockquote(editor, BLOCKS.HR)) {\n unwrapFromRoot(editor);\n }\n\n if (isEnter) {\n event.preventDefault();\n moveToTheNextLine(editor);\n } else if (event.key === 'Backspace') {\n event.preventDefault();\n Transforms.removeNodes(editor, { at: pathToSelectedHr });\n }\n }\n };\n}\n\nexport function ToolbarHrButton(props: ToolbarHrButtonProps) {\n const editor = useContentfulEditor();\n\n function handleOnClick() {\n if (!editor?.selection) return;\n\n if (shouldUnwrapBlockquote(editor, BLOCKS.HR)) {\n unwrapFromRoot(editor);\n }\n\n const hr = {\n type: BLOCKS.HR,\n data: {},\n children: [{ text: '' }],\n isVoid: true,\n };\n\n const hasText = !!getText(editor, editor.selection.focus.path);\n hasText ? Transforms.insertNodes(editor, hr) : setNodes(editor, hr);\n\n // Move focus to the next paragraph (added by TrailingParagraph plugin)\n moveToTheNextLine(editor);\n\n Slate.ReactEditor.focus(editor);\n }\n\n if (!editor) return null;\n\n return (\n <ToolbarButton\n title=\"HR\"\n isDisabled={props.isDisabled}\n onClick={handleOnClick}\n testId=\"hr-toolbar-button\"\n isActive={isBlockSelected(editor, BLOCKS.HR)}>\n <HorizontalRuleIcon />\n </ToolbarButton>\n );\n}\n\nexport function Hr(props: Slate.RenderLeafProps) {\n const isSelected = Slate.useSelected();\n const isFocused = Slate.useFocused();\n\n return (\n <div {...props.attributes} className={styles.container}>\n <div contentEditable={false}>\n <hr className={cx(styles.hr, isSelected && isFocused ? styles.hrSelected : undefined)} />\n </div>\n {props.children}\n </div>\n );\n}\n\nexport function createHrPlugin(): PlatePlugin {\n return {\n renderElement: getRenderElement(BLOCKS.HR),\n pluginKeys: BLOCKS.HR,\n onKeyDown: withHrEvents,\n voidTypes: getPlatePluginTypes(BLOCKS.HR),\n deserialize: deserializeElement(BLOCKS.HR, [\n {\n nodeNames: ['HR'],\n },\n ]),\n };\n}\n\nexport const withHrOptions: CustomSlatePluginOptions = {\n [BLOCKS.HR]: {\n type: BLOCKS.HR,\n component: Hr,\n },\n};\n","/* eslint-disable you-dont-need-lodash-underscore/find */\nimport find from 'lodash/find';\nimport flow from 'lodash/flow';\nimport get from 'lodash/get';\nimport { BLOCKS, INLINES, TOP_LEVEL_BLOCKS } from '@contentful/rich-text-types';\nimport { FieldExtensionSDK } from '@contentful/app-sdk';\n\n// TODO: Move these into separate package (maybe rich-text-types) and share with FE.\nexport const VALIDATIONS = {\n ENABLED_MARKS: 'enabledMarks',\n ENABLED_NODE_TYPES: 'enabledNodeTypes',\n};\nexport const DEFAULT_ENABLED_NODE_TYPES = [BLOCKS.DOCUMENT, BLOCKS.PARAGRAPH, 'text'];\n\nexport const VALIDATABLE_NODE_TYPES = ([] as Array<BLOCKS | INLINES>)\n .concat(TOP_LEVEL_BLOCKS)\n .filter((type) => type !== BLOCKS.PARAGRAPH)\n .concat(Object.values(INLINES));\n\n// TODO: Memoize\nconst getRichTextValidation = (field, validationType) =>\n flow(\n (v) => find(v, validationType),\n (v) => get(v, validationType)\n )(field.validations);\n\nconst isFormattingOptionEnabled = (field, validationType, nodeTypeOrMark) => {\n const enabledFormattings = getRichTextValidation(field, validationType);\n\n // TODO: In the future, validations will always be opt-in. In that case\n // we don't need this step.\n if (enabledFormattings === undefined) {\n return true;\n }\n\n return DEFAULT_ENABLED_NODE_TYPES.concat(enabledFormattings).includes(nodeTypeOrMark);\n};\n\nexport const isNodeTypeEnabled = (field: FieldExtensionSDK['field'], nodeType): boolean =>\n isFormattingOptionEnabled(field, VALIDATIONS.ENABLED_NODE_TYPES, nodeType);\n\nexport const isMarkEnabled = (field: FieldExtensionSDK['field'], mark) =>\n isFormattingOptionEnabled(field, VALIDATIONS.ENABLED_MARKS, mark);\n","import * as React from 'react';\nimport constate from 'constate';\nimport { FieldExtensionSDK } from '@contentful/app-sdk';\n\ninterface SdkProviderProps {\n sdk: FieldExtensionSDK;\n}\n\nfunction useSdk({ sdk }: SdkProviderProps) {\n const sdkMemo = React.useMemo<FieldExtensionSDK>(() => sdk, []); // eslint-disable-line\n\n return sdkMemo;\n}\n\nexport const [SdkProvider, useSdkContext] = constate(useSdk);\n","import * as React from 'react';\nimport * as Slate from 'slate-react';\nimport { css, cx } from 'emotion';\nimport { Menu, Button } from '@contentful/f36-components';\nimport { ChevronDownIcon } from '@contentful/f36-icons';\nimport tokens from '@contentful/f36-tokens';\nimport { Editor, Transforms, Node } from 'slate';\nimport { BLOCKS } from '@contentful/rich-text-types';\nimport {\n PlatePlugin,\n getRenderElement,\n PlateEditor,\n getPlatePluginOptions,\n} from '@udecode/plate-core';\nimport { insertNodes, setNodes, toggleNodeType } from '@udecode/plate-common';\nimport { CustomElement, CustomSlatePluginOptions } from '../../types';\nimport {\n getElementFromCurrentSelection,\n hasSelectionText,\n shouldUnwrapBlockquote,\n unwrapFromRoot,\n} from '../../helpers/editor';\nimport { isNodeTypeEnabled } from '../../helpers/validations';\nimport { useSdkContext } from '../../SdkProvider';\nimport { useContentfulEditor } from '../../ContentfulEditorProvider';\n\nconst styles = {\n dropdown: {\n root: css`\n font-weight: ${tokens.fontWeightDemiBold};\n `,\n [BLOCKS.PARAGRAPH]: css`\n font-size: ${tokens.fontSizeL};\n `,\n [BLOCKS.HEADING_1]: css`\n font-size: 1.625rem;\n `,\n [BLOCKS.HEADING_2]: css`\n font-size: 1.4375rem;\n `,\n [BLOCKS.HEADING_3]: css`\n font-size: 1.25rem;\n `,\n [BLOCKS.HEADING_4]: css`\n font-size: 1.125rem;\n `,\n [BLOCKS.HEADING_5]: css`\n font-size: 1rem;\n `,\n [BLOCKS.HEADING_6]: css`\n font-size: 0.875rem;\n `,\n },\n headings: {\n root: css`\n font-weight: ${tokens.fontWeightMedium};\n line-height: 1.3;\n margin: 0 0 ${tokens.spacingS};\n `,\n [BLOCKS.HEADING_1]: css`\n font-size: 1.875rem;\n `,\n [BLOCKS.HEADING_2]: css`\n font-size: 1.5625rem;\n `,\n [BLOCKS.HEADING_3]: css`\n font-size: 1.375rem;\n `,\n [BLOCKS.HEADING_4]: css`\n font-size: 1.25rem;\n `,\n [BLOCKS.HEADING_5]: css`\n font-size: 1.125rem;\n `,\n [BLOCKS.HEADING_6]: css`\n font-size: 1rem;\n `,\n },\n};\n\nexport function withHeadingEvents(editor: PlateEditor) {\n return (event: React.KeyboardEvent) => {\n if (!editor.selection) return;\n\n // Enter a new line on a heading element\n const headings: string[] = [\n BLOCKS.HEADING_1,\n BLOCKS.HEADING_2,\n BLOCKS.HEADING_3,\n BLOCKS.HEADING_4,\n BLOCKS.HEADING_5,\n BLOCKS.HEADING_6,\n ];\n const [currentFragment] = Editor.fragment(\n editor,\n editor.selection.focus.path\n ) as CustomElement[];\n const isEnter = event.keyCode === 13;\n const isCurrentFragmentAHeading = headings.includes(currentFragment.type);\n\n if (isEnter && isCurrentFragmentAHeading) {\n event.preventDefault();\n\n const text = { text: '' };\n const paragraph = { type: BLOCKS.PARAGRAPH, data: {}, children: [text] };\n const heading = { type: currentFragment.type, data: {}, children: [text] };\n\n if (hasSelectionText(editor)) {\n const currentOffset = editor.selection.focus.offset;\n const currentTextLength = Node.string(currentFragment).length;\n const cursorIsAtTheBeginning = currentOffset === 0;\n const cursorIsAtTheEnd = currentTextLength === currentOffset;\n\n if (cursorIsAtTheBeginning) {\n insertNodes(editor, paragraph, { at: editor.selection });\n } else if (cursorIsAtTheEnd) {\n insertNodes(editor, paragraph);\n } else {\n // Otherwise the cursor is in the middle\n Transforms.splitNodes(editor);\n setNodes(editor, paragraph);\n }\n } else {\n setNodes(editor, paragraph);\n insertNodes(editor, heading);\n }\n }\n\n // Toggle heading blocks when pressing cmd/ctrl+alt+1|2|3|4|5|6\n const headingKeyCodes = {\n 49: BLOCKS.HEADING_1,\n 50: BLOCKS.HEADING_2,\n 51: BLOCKS.HEADING_3,\n 52: BLOCKS.HEADING_4,\n 53: BLOCKS.HEADING_5,\n 54: BLOCKS.HEADING_6,\n };\n const isMod = event.ctrlKey || event.metaKey;\n const isAltOrOption = event.altKey;\n const headingKey = headingKeyCodes[event.keyCode];\n\n if (isMod && isAltOrOption && headingKey) {\n event.preventDefault();\n\n if (shouldUnwrapBlockquote(editor, headingKey)) {\n unwrapFromRoot(editor);\n }\n\n toggleNodeType(editor, { activeType: headingKey, inactiveType: BLOCKS.PARAGRAPH });\n }\n };\n}\n\nconst LABELS = {\n [BLOCKS.PARAGRAPH]: 'Normal text',\n [BLOCKS.HEADING_1]: 'Heading 1',\n [BLOCKS.HEADING_2]: 'Heading 2',\n [BLOCKS.HEADING_3]: 'Heading 3',\n [BLOCKS.HEADING_4]: 'Heading 4',\n [BLOCKS.HEADING_5]: 'Heading 5',\n [BLOCKS.HEADING_6]: 'Heading 6',\n};\n\ninterface ToolbarHeadingButtonProps {\n isDisabled?: boolean;\n}\n\nexport function ToolbarHeadingButton(props: ToolbarHeadingButtonProps) {\n const sdk = useSdkContext();\n const editor = useContentfulEditor();\n const [isOpen, setOpen] = React.useState(false);\n const [selected, setSelected] = React.useState<string>(BLOCKS.PARAGRAPH);\n\n React.useEffect(() => {\n if (!editor?.selection) return;\n\n const [element] = getElementFromCurrentSelection(editor);\n const type = (element as CustomElement).type;\n\n setSelected(LABELS[type] ? type : BLOCKS.PARAGRAPH);\n }, [editor?.operations, editor?.selection]); // eslint-disable-line\n\n const [nodeTypesByEnablement, someHeadingsEnabled] = React.useMemo(() => {\n const nodeTypesByEnablement = Object.fromEntries(\n Object.keys(LABELS).map((nodeType) => [nodeType, isNodeTypeEnabled(sdk.field, nodeType)])\n );\n const someHeadingsEnabled = Object.values(nodeTypesByEnablement).filter(Boolean).length > 0;\n return [nodeTypesByEnablement, someHeadingsEnabled];\n }, [sdk.field]);\n\n function handleOnSelectItem(type: BLOCKS): (event: React.MouseEvent<HTMLButtonElement>) => void {\n return (event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n\n if (!editor?.selection) return;\n\n setSelected(type);\n setOpen(false);\n\n if (shouldUnwrapBlockquote(editor, type)) {\n unwrapFromRoot(editor);\n }\n\n toggleNodeType(editor, { activeType: type, inactiveType: type });\n\n // TODO: Figure out why focus only works with timeout here.\n setTimeout(() => {\n Slate.ReactEditor.focus(editor);\n }, 0);\n };\n }\n\n if (!editor) return null;\n\n return (\n <Menu isOpen={isOpen} onClose={() => setOpen(false)}>\n <Menu.Trigger>\n <Button\n size=\"small\"\n testId=\"toolbar-heading-toggle\"\n variant=\"transparent\"\n endIcon={<ChevronDownIcon />}\n onClick={() => someHeadingsEnabled && setOpen(!isOpen)}>\n {LABELS[selected]}\n </Button>\n </Menu.Trigger>\n <Menu.List testId=\"dropdown-heading-list\">\n {' '}\n {Object.keys(LABELS)\n .map(\n (nodeType) =>\n nodeTypesByEnablement[nodeType] && (\n <Menu.Item\n key={nodeType}\n isInitiallyFocused={selected === nodeType}\n onClick={handleOnSelectItem(nodeType as BLOCKS)}\n testId={`dropdown-option-${nodeType}`}\n disabled={props.isDisabled}>\n <span className={cx(styles.dropdown.root, styles.dropdown[nodeType])}>\n {LABELS[nodeType]}\n </span>\n </Menu.Item>\n )\n )\n .filter(Boolean)}\n </Menu.List>\n </Menu>\n );\n}\n\nexport function createHeading(Tag, block: BLOCKS) {\n return function Heading(props: Slate.RenderElementProps) {\n return (\n <Tag {...props.attributes} className={cx(styles.headings.root, styles.headings[block])}>\n {props.children}\n </Tag>\n );\n };\n}\n\nexport const H1 = createHeading('h1', BLOCKS.HEADING_1);\nexport const H2 = createHeading('h2', BLOCKS.HEADING_2);\nexport const H3 = createHeading('h3', BLOCKS.HEADING_3);\nexport const H4 = createHeading('h4', BLOCKS.HEADING_4);\nexport const H5 = createHeading('h5', BLOCKS.HEADING_5);\nexport const H6 = createHeading('h6', BLOCKS.HEADING_6);\n\nexport function createHeadingPlugin(): PlatePlugin {\n const headings: string[] = [\n BLOCKS.HEADING_1,\n BLOCKS.HEADING_2,\n BLOCKS.HEADING_3,\n BLOCKS.HEADING_4,\n BLOCKS.HEADING_5,\n BLOCKS.HEADING_6,\n ];\n\n return {\n renderElement: getRenderElement(headings),\n pluginKeys: headings,\n onKeyDown: withHeadingEvents,\n deserialize: (editor) => {\n return {\n element: headings.map((headingType, index) => {\n const options = getPlatePluginOptions(editor, headingType);\n\n return {\n type: headingType,\n deserialize: (element) => {\n const isHeading = element.nodeName === `H${index + 1}`;\n\n if (!isHeading) return;\n\n return {\n type: headingType,\n };\n },\n ...options.deserialize,\n };\n }),\n };\n },\n };\n}\n\nexport const withHeadingOptions: CustomSlatePluginOptions = {\n [BLOCKS.HEADING_1]: {\n type: BLOCKS.HEADING_1,\n component: H1,\n },\n [BLOCKS.HEADING_2]: {\n type: BLOCKS.HEADING_2,\n component: H2,\n },\n [BLOCKS.HEADING_3]: {\n type: BLOCKS.HEADING_3,\n component: H3,\n },\n [BLOCKS.HEADING_4]: {\n type: BLOCKS.HEADING_4,\n component: H4,\n },\n [BLOCKS.HEADING_5]: {\n type: BLOCKS.HEADING_5,\n component: H5,\n },\n [BLOCKS.HEADING_6]: {\n type: BLOCKS.HEADING_6,\n component: H6,\n },\n};\n","import * as React from 'react';\nimport * as Slate from 'slate-react';\nimport { css } from 'emotion';\nimport tokens from '@contentful/f36-tokens';\nimport { QuoteIcon } from '@contentful/f36-icons';\nimport { ToolbarButton } from '../shared/ToolbarButton';\nimport { Transforms, Editor, Node, Element, Text } from 'slate';\nimport { BLOCKS } from '@contentful/rich-text-types';\nimport { PlatePlugin, PlateEditor, getRenderElement } from '@udecode/plate-core';\nimport { CustomElement } from '../../types';\nimport { CustomSlatePluginOptions } from 'types';\nimport {\n isBlockSelected,\n toggleBlock,\n hasSelectionText,\n getElementFromCurrentSelection,\n isNodeTypeSelected,\n} from '../../helpers/editor';\nimport { deserializeElement } from '../../helpers/deserializer';\nimport { useContentfulEditor } from '../../ContentfulEditorProvider';\n\nconst styles = {\n blockquote: css({\n margin: '0 0 1.3125rem',\n borderLeft: `6px solid ${tokens.gray200}`,\n paddingLeft: '0.875rem',\n fontStyle: 'normal',\n '& a': {\n color: 'inherit',\n },\n }),\n};\n\ninterface ToolbarQuoteButtonProps {\n isDisabled?: boolean;\n}\n\nconst createBlockQuote = (editor: PlateEditor) => {\n if (!editor.selection) return;\n\n toggleBlock(editor, BLOCKS.QUOTE);\n};\n\nexport function withQuoteEvents(editor: PlateEditor) {\n return (event: React.KeyboardEvent) => {\n if (!editor.selection) return;\n\n const [currentFragment] = Editor.fragment(\n editor,\n editor.selection.focus.path\n ) as CustomElement[];\n const isEnter = event.keyCode === 13;\n\n if (isEnter && currentFragment?.type === BLOCKS.QUOTE) {\n event.preventDefault();\n\n const text = { text: '' };\n const paragraph = { type: BLOCKS.PARAGRAPH, data: {}, children: [text] };\n\n if (hasSelectionText(editor)) {\n const currentOffset = editor.selection.focus.offset;\n const currentTextLength = Node.string(currentFragment).length;\n const cursorIsAtTheBeginning = currentOffset === 0;\n const cursorIsAtTheEnd = currentTextLength === currentOffset;\n\n if (cursorIsAtTheBeginning) {\n Transforms.insertNodes(editor, paragraph, { at: editor.selection });\n } else if (cursorIsAtTheEnd) {\n Transforms.insertNodes(editor, paragraph);\n } else {\n // Otherwise the cursor is in the middle\n Transforms.splitNodes(editor);\n Transforms.setNodes(editor, paragraph);\n }\n } else {\n Transforms.insertNodes(editor, paragraph);\n }\n }\n\n const isBackspace = event.keyCode === 8;\n const isMod = event.ctrlKey || event.metaKey;\n const isShift = event.shiftKey;\n const isOneKey = event.keyCode === 49;\n\n // shift + cmd/ctrl + 1 = shortcut to toggle blockquote\n if (isMod && isShift && isOneKey && !isNodeTypeSelected(editor, BLOCKS.TABLE)) {\n createBlockQuote(editor);\n }\n\n // On backspace, check if quote is empty. If it's empty, switch the current fragment to a paragraph\n if (isBackspace && currentFragment?.type === BLOCKS.QUOTE) {\n const quoteIsEmpty = (\n getElementFromCurrentSelection(editor)[0] as CustomElement\n ).children.every(\n (item) =>\n Element.isElement(item) &&\n item.children.every((item) => Text.isText(item) && item.text === '')\n );\n\n if (quoteIsEmpty) toggleBlock(editor, BLOCKS.PARAGRAPH);\n }\n };\n}\n\nexport function ToolbarQuoteButton(props: ToolbarQuoteButtonProps) {\n const editor = useContentfulEditor();\n\n function handleOnClick() {\n if (!editor) return;\n\n createBlockQuote(editor);\n Slate.ReactEditor.focus(editor);\n }\n\n if (!editor) return null;\n\n return (\n <ToolbarButton\n title=\"Blockquote\"\n onClick={handleOnClick}\n testId=\"quote-toolbar-button\"\n isDisabled={props.isDisabled}\n isActive={isBlockSelected(editor, BLOCKS.QUOTE)}>\n <QuoteIcon />\n </ToolbarButton>\n );\n}\n\nexport function Quote(props: Slate.RenderLeafProps) {\n return (\n <blockquote {...props.attributes} className={styles.blockquote}>\n {props.children}\n </blockquote>\n );\n}\n\nexport function createQuotePlugin(): PlatePlugin {\n return {\n pluginKeys: BLOCKS.QUOTE,\n renderElement: getRenderElement(BLOCKS.QUOTE),\n onKeyDown: withQuoteEvents,\n deserialize: deserializeElement(BLOCKS.QUOTE, [{ nodeNames: 'BLOCKQUOTE' }]),\n };\n}\n\nexport const withQuoteOptions: CustomSlatePluginOptions = {\n [BLOCKS.QUOTE]: {\n type: BLOCKS.QUOTE,\n component: Quote,\n },\n};\n","import * as React from 'react';\nimport * as Slate from 'slate-react';\nimport { Element, Text, Node, Transforms, Editor, NodeEntry, Path } from 'slate';\nimport { css } from 'emotion';\nimport { WithOverride, PlateEditor } from '@udecode/plate-core';\nimport { getParent, getAbove } from '@udecode/plate-common';\nimport {\n createListPlugin as createPlateListPlugin,\n withList,\n ELEMENT_LI,\n ELEMENT_UL,\n ELEMENT_OL,\n toggleList,\n ELEMENT_LIC,\n} from '@udecode/plate-list';\nimport { BLOCKS, INLINES, LIST_ITEM_BLOCKS, TopLevelBlockEnum } from '@contentful/rich-text-types';\nimport { ListBulletedIcon, ListNumberedIcon } from '@contentful/f36-icons';\n\nimport { ToolbarButton } from '../shared/ToolbarButton';\nimport {\n isBlockSelected,\n unwrapFromRoot,\n shouldUnwrapBlockquote,\n extractParagraphsAt,\n replaceNode,\n} from '../../helpers/editor';\nimport { isNodeTypeEnabled } from '../../helpers/validations';\nimport {\n CustomElement,\n CustomSlatePluginOptions,\n TextElement,\n TextOrCustomElement,\n} from '../../types';\nimport tokens from '@contentful/f36-tokens';\nimport { useSdkContext } from '../../SdkProvider';\nimport { useContentfulEditor } from '../../ContentfulEditorProvider';\nimport { getListInsertFragment } from './getListInsertFragment';\n\ninterface ToolbarListButtonProps {\n isDisabled?: boolean;\n}\n\nexport function ToolbarListButton(props: ToolbarListButtonProps) {\n const sdk = useSdkContext();\n const editor = useContentfulEditor();\n\n function handleClick(type: BLOCKS): () => void {\n return () => {\n if (!editor?.selection) return;\n\n if (shouldUnwrapBlockquote(editor, type)) {\n unwrapFromRoot(editor);\n }\n\n toggleList(editor, { type });\n\n Slate.ReactEditor.focus(editor);\n };\n }\n\n if (!editor) return null;\n\n return (\n <React.Fragment>\n {isNodeTypeEnabled(sdk.field, BLOCKS.UL_LIST) && (\n <ToolbarButton\n title=\"UL\"\n testId=\"ul-toolbar-button\"\n onClick={handleClick(BLOCKS.UL_LIST)}\n isActive={isBlockSelected(editor, BLOCKS.UL_LIST)}\n isDisabled={props.isDisabled}>\n <ListBulletedIcon />\n </ToolbarButton>\n )}\n {isNodeTypeEnabled(sdk.field, BLOCKS.OL_LIST) && (\n <ToolbarButton\n title=\"OL\"\n testId=\"ol-toolbar-button\"\n onClick={handleClick(BLOCKS.OL_LIST)}\n isActive={isBlockSelected(editor, BLOCKS.OL_LIST)}\n isDisabled={props.isDisabled}>\n <ListNumberedIcon />\n </ToolbarButton>\n )}\n </React.Fragment>\n );\n}\n\nconst listStyles = `\n padding: 0;\n margin: 0 0 1.25rem 1.25rem;\n div:first-child {\n margin: 0;\n line-height: ${tokens.lineHeightDefault};\n }\n`;\n\nconst styles = {\n [BLOCKS.UL_LIST]: css`\n ${listStyles}\n list-style-type: disc;\n ul {\n list-style-type: circle;\n ul {\n list-style-type: square;\n }\n }\n `,\n [BLOCKS.OL_LIST]: css`\n ${listStyles}\n list-style-type: decimal;\n ol {\n list-style-type: upper-alpha;\n ol {\n list-style-type: lower-roman;\n ol {\n list-style-type: lower-alpha;\n }\n }\n }\n `,\n [BLOCKS.LIST_ITEM]: css`\n margin: 0;\n list-style: inherit;\n ol,\n ul {\n margin: 0 0 0 ${tokens.spacingL};\n }\n `,\n};\n\nexport function createList(Tag, block: BLOCKS) {\n return function List(props: Slate.RenderElementProps) {\n return (\n <Tag {...props.attributes} className={styles[block]}>\n {props.children}\n </Tag>\n );\n };\n}\n\nexport const UL = createList('ul', BLOCKS.UL_LIST);\nexport const OL = createList('ol', BLOCKS.OL_LIST);\nexport const LI = createList('li', BLOCKS.LIST_ITEM);\n\nexport const withListOptions: CustomSlatePluginOptions = {\n // ELEMENT_LIC is a child of li, slatejs does ul > li > lic + ul\n [ELEMENT_LIC]: {\n type: BLOCKS.PARAGRAPH,\n },\n [ELEMENT_LI]: {\n type: BLOCKS.LIST_ITEM,\n component: LI,\n },\n [ELEMENT_UL]: {\n type: BLOCKS.UL_LIST,\n component: UL,\n },\n [ELEMENT_OL]: {\n type: BLOCKS.OL_LIST,\n component: OL,\n },\n};\n\nconst emptyNodeOfType = (type) => ({ type, children: [], data: {} });\n\nconst isList = (node: CustomElement) =>\n [BLOCKS.OL_LIST, BLOCKS.UL_LIST].includes(node.type as BLOCKS);\n\nconst isListItem = (node: CustomElement) => node.type === BLOCKS.LIST_ITEM;\n\nconst hasListAsDirectParent = (editor: Editor, path: Path) => {\n const [parentNode] = (getParent(editor, path) || []) as NodeEntry;\n return isList(parentNode as CustomElement);\n};\n\nconst isValidInsideListItem = (node: TextOrCustomElement) =>\n Text.isText(node as TextElement) ||\n (LIST_ITEM_BLOCKS as Array<TopLevelBlockEnum | INLINES>)\n .concat(Object.values(INLINES))\n .includes((node as CustomElement).type as TopLevelBlockEnum);\n\nconst replaceInvalidListItemWithText = (editor: PlateEditor, path: Path) => {\n const textFromEntry = extractParagraphsAt(editor, path);\n replaceNode(editor, path, textFromEntry);\n};\n\n/**\n * Ensures each list item follows the list schema.\n * Returns true if the list needed to have been normalized.\n */\nconst normalizeList = (editor: PlateEditor, path: Path): boolean => {\n for (const [child, childPath] of Node.children(editor, path)) {\n if (Element.isElement(child) && !isListItem(child)) {\n Transforms.wrapNodes(editor, emptyNodeOfType(BLOCKS.LIST_ITEM), { at: childPath });\n return true;\n }\n }\n return false;\n};\n\nconst getNearestListAncestor = (editor: PlateEditor, path: Path) => {\n return getAbove(editor, { at: path, mode: 'lowest', match: isList }) || [];\n};\n\n/**\n * Places orphaned list items in a list. If there's a list somewhere\n * in the node's ancestors, defaults to that list type, else places\n * the list item in an unordered list.\n */\nconst normalizeOrphanedListItem = (editor: PlateEditor, path: Path) => {\n const [parentList] = getNearestListAncestor(editor, path);\n const parentListType = parentList?.type;\n Transforms.wrapNodes(\n editor,\n { type: parentListType || BLOCKS.UL_LIST, children: [], data: {} },\n { at: path }\n );\n};\n\nconst withCustomList = (options): WithOverride => {\n const withDefaultOverrides = withList(options);\n\n return (editor) => {\n const { insertFragment } = editor;\n\n withDefaultOverrides(editor);\n\n // Reverts any overrides to insertFragment\n editor.insertFragment = insertFragment;\n\n // Use our custom getListInsertFragment\n editor.insertFragment = getListInsertFragment(editor);\n\n const { normalizeNode } = editor;\n editor.normalizeNode = (entry) => {\n const [node, path] = entry;\n\n if (isList(node as CustomElement)) {\n if (normalizeList(editor, path)) {\n return;\n }\n } else if (isListItem(node as CustomElement)) {\n if (!hasListAsDirectParent(editor, path)) {\n normalizeOrphanedListItem(editor, path);\n return;\n }\n\n const listItemChildren = Array.from(Node.children(editor, path));\n\n // Handle list items with no paragraph/text\n if (listItemChildren.length === 0) {\n Transforms.insertNodes(\n editor,\n [{ type: BLOCKS.PARAGRAPH, data: {}, children: [{ text: '' }] }],\n {\n at: path.concat([0]),\n }\n );\n return;\n }\n\n for (const [child, childPath] of listItemChildren) {\n if (Element.isElement(child) && !isValidInsideListItem(child)) {\n replaceInvalidListItemWithText(editor, childPath);\n return;\n }\n }\n }\n\n normalizeNode(entry);\n };\n\n return editor;\n };\n};\n\nexport const createListPlugin = () => {\n const options = {\n validLiChildrenTypes: LIST_ITEM_BLOCKS,\n };\n\n const plugin = createPlateListPlugin(options);\n\n plugin.withOverrides = withCustomList(options);\n\n return plugin;\n};\n","/**\n * A copy of Plate's list plugin with a few adjustments\n * to fix pasting text inside lists.\n */\nimport {\n getPlatePluginOptions,\n PlateEditor,\n PlatePluginOptions,\n TDescendant,\n} from '@udecode/plate-core';\nimport { findNode } from '@udecode/plate-common';\nimport { ELEMENT_LI, ELEMENT_OL, ELEMENT_UL } from '@udecode/plate-list';\nimport { Node, NodeEntry, Path, Transforms } from 'slate';\n\nexport const getListInsertFragment = (editor: PlateEditor) => {\n const { insertFragment } = editor;\n\n const li = getPlatePluginOptions(editor, ELEMENT_LI);\n const ul = getPlatePluginOptions(editor, ELEMENT_UL);\n const ol = getPlatePluginOptions(editor, ELEMENT_OL);\n\n const isListRoot = (node: TDescendant): boolean => [ul.type, ol.type].includes(node.type);\n\n const getFirstAncestorOfType = (\n root: TDescendant,\n entry: NodeEntry,\n { type }: PlatePluginOptions\n ): NodeEntry<TDescendant> => {\n let ancestor: Path = Path.parent(entry[1]);\n while ((Node.get(root, ancestor) as TDescendant).type !== type) {\n ancestor = Path.parent(ancestor);\n }\n\n return [Node.get(root, ancestor), ancestor];\n };\n\n /**\n * Removes the \"empty\" leading lis. Empty in this context means lis only with other lis as children.\n *\n * @returns If argument is not a list root, returns it, otherwise returns ul[] or li[].\n */\n const trimList = <T extends TDescendant>(listRoot: T): T[] => {\n if (!isListRoot(listRoot)) {\n return [listRoot];\n }\n\n const textEntries = Array.from(Node.texts(listRoot));\n\n const commonAncestorEntry = textEntries.reduce<NodeEntry<TDescendant>>(\n (commonAncestor, textEntry) =>\n Path.isAncestor(commonAncestor[1], textEntry[1])\n ? commonAncestor\n : Node.common(listRoot, textEntry[1], commonAncestor[1]),\n // any list item would do, we grab the first one\n getFirstAncestorOfType(listRoot, textEntries[0], li)\n );\n\n return isListRoot(commonAncestorEntry[0])\n ? commonAncestorEntry[0].children\n : [commonAncestorEntry[0]];\n };\n\n return (fragment: TDescendant[]) => {\n const liEntry = findNode(editor, {\n match: { type: li.type },\n mode: 'lowest',\n });\n\n if (liEntry) {\n const [, liPath] = liEntry;\n\n // FIXME: this is a temporarily workaround and needs a follow-up to properly\n // non-text elements\n const nodes = fragment.flatMap((node) => trimList(node));\n\n return Transforms.insertNodes(editor, nodes, {\n at: editor.selection || Path.next(liPath),\n select: true,\n });\n }\n\n const filtered: TDescendant[] = isListRoot(fragment[0])\n ? [{ text: '' }, ...fragment]\n : fragment;\n\n return insertFragment(filtered);\n };\n};\n","import * as React from 'react';\nimport * as Slate from 'slate-react';\nimport { css } from 'emotion';\nimport { getRenderLeaf, PlatePlugin } from '@udecode/plate-core';\nimport { getToggleMarkOnKeyDown, isMarkActive, toggleMark } from '@udecode/plate-common';\nimport { MARKS } from '@contentful/rich-text-types';\nimport { FormatBoldIcon } from '@contentful/f36-icons';\nimport { ToolbarButton } from '../shared/ToolbarButton';\nimport { CustomSlatePluginOptions } from 'types';\nimport { useContentfulEditor } from '../../ContentfulEditorProvider';\n\ninterface ToolbarBoldButtonProps {\n isDisabled?: boolean;\n}\n\nexport function ToolbarBoldButton(props: ToolbarBoldButtonProps) {\n const editor = useContentfulEditor();\n\n function handleClick() {\n if (!editor?.selection) return;\n\n toggleMark(editor, MARKS.BOLD);\n Slate.ReactEditor.focus(editor);\n }\n\n if (!editor) return null;\n\n return (\n <ToolbarButton\n title=\"Bold\"\n testId=\"bold-toolbar-button\"\n onClick={handleClick}\n isActive={isMarkActive(editor, MARKS.BOLD)}\n isDisabled={props.isDisabled}>\n <FormatBoldIcon />\n </ToolbarButton>\n );\n}\n\nconst styles = {\n bold: css({\n fontWeight: 600,\n }),\n};\n\nexport function Bold(props: Slate.RenderLeafProps) {\n return (\n <strong {...props.attributes} className={styles.bold}>\n {props.children}\n </strong>\n );\n}\n\nexport function createBoldPlugin(): PlatePlugin {\n return {\n pluginKeys: MARKS.BOLD,\n renderLeaf: getRenderLeaf(MARKS.BOLD),\n onKeyDown: getToggleMarkOnKeyDown(MARKS.BOLD),\n deserialize: () => {\n return {\n leaf: [\n {\n type: MARKS.BOLD,\n deserialize: (element) => {\n // We ignore it otherwise everything will be bold\n const isGoogleBoldWrapper =\n element.id.startsWith('docs-internal-guid') && element.nodeName === 'B';\n\n const isBold =\n ['600', '700', 'bold'].includes(element.style.fontWeight) ||\n ['STRONG', 'B'].includes(element.nodeName);\n\n if (isGoogleBoldWrapper || !isBold) return;\n\n return {\n [MARKS.BOLD]: true,\n };\n },\n },\n ],\n };\n },\n };\n}\n\nexport const withBoldOptions: CustomSlatePluginOptions = {\n [MARKS.BOLD]: {\n type: MARKS.BOLD,\n component: Bold,\n hotkey: ['mod+b'],\n },\n};\n","import * as React from 'react';\nimport * as Slate from 'slate-react';\nimport { css } from 'emotion';\nimport { PlatePlugin, getRenderLeaf, GetNodeDeserializerRule } from '@udecode/plate-core';\nimport { getToggleMarkOnKeyDown, isMarkActive, toggleMark } from '@udecode/plate-common';\nimport { MARKS } from '@contentful/rich-text-types';\nimport { CodeIcon } from '@contentful/f36-icons';\nimport { ToolbarButton } from '../shared/ToolbarButton';\nimport { CustomSlatePluginOptions } from 'types';\nimport { deserializeLeaf } from '../../helpers/deserializer';\nimport { useContentfulEditor } from '../../ContentfulEditorProvider';\n\ninterface ToolbarCodeButtonProps {\n isDisabled?: boolean;\n}\n\nexport function ToolbarCodeButton(props: ToolbarCodeButtonProps) {\n const editor = useContentfulEditor();\n\n function handleClick() {\n if (!editor?.selection) return;\n\n toggleMark(editor, MARKS.CODE);\n Slate.ReactEditor.focus(editor);\n }\n\n if (!editor) return null;\n\n return (\n <ToolbarButton\n title=\"Code\"\n testId=\"code-toolbar-button\"\n onClick={handleClick}\n isActive={isMarkActive(editor, MARKS.CODE)}\n isDisabled={props.isDisabled}>\n <CodeIcon />\n </ToolbarButton>\n );\n}\n\nconst styles = {\n code: css({\n fontFamily: 'monospace',\n fontSize: '.9em',\n }),\n};\n\nexport function Code(props: Slate.RenderLeafProps) {\n return (\n <code {...props.attributes} className={styles.code}>\n {props.children}\n </code>\n );\n}\n\nexport function createCodePlugin(): PlatePlugin {\n const deserializeRule: GetNodeDeserializerRule[] = [\n { nodeNames: ['CODE', 'PRE'] },\n { style: { fontFamily: 'monospace' } },\n ];\n\n return {\n pluginKeys: MARKS.CODE,\n renderLeaf: getRenderLeaf(MARKS.CODE),\n onKeyDown: getToggleMarkOnKeyDown(MARKS.CODE),\n deserialize: deserializeLeaf(MARKS.CODE, deserializeRule),\n };\n}\n\nexport const withCodeOptions: CustomSlatePluginOptions = {\n [MARKS.CODE]: {\n type: MARKS.CODE,\n component: Code,\n hotkey: ['mod+/'],\n },\n};\n","import * as React from 'react';\nimport * as Slate from 'slate-react';\nimport { css } from 'emotion';\nimport { PlatePlugin, getRenderLeaf, GetNodeDeserializerRule } from '@udecode/plate-core';\nimport { getToggleMarkOnKeyDown, toggleMark, isMarkActive } from '@udecode/plate-common';\nimport { MARKS } from '@contentful/rich-text-types';\nimport { FormatItalicIcon } from '@contentful/f36-icons';\nimport { ToolbarButton } from '../shared/ToolbarButton';\nimport { CustomSlatePluginOptions } from '../../types';\nimport { deserializeLeaf } from '../../helpers/deserializer';\nimport { useContentfulEditor } from '../../ContentfulEditorProvider';\n\ninterface ToolbarItalicButtonProps {\n isDisabled?: boolean;\n}\n\nexport function ToolbarItalicButton(props: ToolbarItalicButtonProps) {\n const editor = useContentfulEditor();\n\n function handleClick() {\n if (!editor?.selection) return;\n\n toggleMark(editor, MARKS.ITALIC);\n Slate.ReactEditor.focus(editor);\n }\n\n if (!editor) return null;\n\n return (\n <ToolbarButton\n title=\"Italic\"\n testId=\"italic-toolbar-button\"\n onClick={handleClick}\n isActive={isMarkActive(editor, MARKS.ITALIC)}\n isDisabled={props.isDisabled}>\n <FormatItalicIcon />\n </ToolbarButton>\n );\n}\n\nconst styles = {\n italic: css({\n fontStyle: 'italic',\n }),\n};\n\nexport function Italic(props: Slate.RenderLeafProps) {\n return (\n <em {...props.attributes} className={styles.italic}>\n {props.children}\n </em>\n );\n}\n\nexport function createItalicPlugin(): PlatePlugin {\n const deserializeRules: GetNodeDeserializerRule[] = [\n { nodeNames: ['I', 'EM'] },\n {\n style: {\n fontStyle: ['italic'],\n },\n },\n ];\n\n return {\n pluginKeys: MARKS.ITALIC,\n renderLeaf: getRenderLeaf(MARKS.ITALIC),\n onKeyDown: getToggleMarkOnKeyDown(MARKS.ITALIC),\n deserialize: deserializeLeaf(MARKS.ITALIC, deserializeRules),\n };\n}\n\nexport const withItalicOptions: CustomSlatePluginOptions = {\n [MARKS.ITALIC]: {\n type: MARKS.ITALIC,\n component: Italic,\n hotkey: ['mod+i'],\n },\n};\n","import * as React from 'react';\nimport * as Slate from 'slate-react';\nimport { PlatePlugin, getRenderLeaf, GetNodeDeserializerRule } from '@udecode/plate-core';\nimport { getToggleMarkOnKeyDown, toggleMark, isMarkActive } from '@udecode/plate-common';\nimport { MARKS } from '@contentful/rich-text-types';\nimport { FormatUnderlinedIcon } from '@contentful/f36-icons';\nimport { ToolbarButton } from '../shared/ToolbarButton';\nimport { CustomSlatePluginOptions } from 'types';\nimport { deserializeLeaf } from '../../helpers/deserializer';\nimport { useContentfulEditor } from '../../ContentfulEditorProvider';\n\ninterface ToolbarUnderlineButtonProps {\n isDisabled?: boolean;\n}\n\nexport function ToolbarUnderlineButton(props: ToolbarUnderlineButtonProps) {\n const editor = useContentfulEditor();\n\n function handleClick() {\n if (!editor?.selection) return;\n\n toggleMark(editor, MARKS.UNDERLINE);\n Slate.ReactEditor.focus(editor);\n }\n\n if (!editor) return null;\n\n return (\n <ToolbarButton\n title=\"Underline\"\n testId=\"underline-toolbar-button\"\n onClick={handleClick}\n isActive={isMarkActive(editor, MARKS.UNDERLINE)}\n isDisabled={props.isDisabled}>\n <FormatUnderlinedIcon />\n </ToolbarButton>\n );\n}\n\nexport function Underline(props: Slate.RenderLeafProps) {\n return <u {...props.attributes}>{props.children}</u>;\n}\n\nexport function createUnderlinePlugin(): PlatePlugin {\n const deserializeRules: GetNodeDeserializerRule[] = [\n { nodeNames: ['U'] },\n {\n style: {\n textDecoration: ['underline'],\n },\n },\n ];\n\n return {\n pluginKeys: MARKS.UNDERLINE,\n renderLeaf: getRenderLeaf(MARKS.UNDERLINE),\n onKeyDown: getToggleMarkOnKeyDown(MARKS.UNDERLINE),\n deserialize: deserializeLeaf(MARKS.UNDERLINE, deserializeRules),\n };\n}\n\nexport const withUnderlineOptions: CustomSlatePluginOptions = {\n [MARKS.UNDERLINE]: {\n type: MARKS.UNDERLINE,\n component: Underline,\n hotkey: ['mod+u'],\n },\n};\n","/**\n * Copyright (c) 2014-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nvar runtime = (function (exports) {\n \"use strict\";\n\n var Op = Object.prototype;\n var hasOwn = Op.hasOwnProperty;\n var undefined; // More compressible than void 0.\n var $Symbol = typeof Symbol === \"function\" ? Symbol : {};\n var iteratorSymbol = $Symbol.iterator || \"@@iterator\";\n var asyncIteratorSymbol = $Symbol.asyncIterator || \"@@asyncIterator\";\n var toStringTagSymbol = $Symbol.toStringTag || \"@@toStringTag\";\n\n function define(obj, key, value) {\n Object.defineProperty(obj, key, {\n value: value,\n enumerable: true,\n configurable: true,\n writable: true\n });\n return obj[key];\n }\n try {\n // IE 8 has a broken Object.defineProperty that only works on DOM objects.\n define({}, \"\");\n } catch (err) {\n define = function(obj, key, value) {\n return obj[key] = value;\n };\n }\n\n function wrap(innerFn, outerFn, self, tryLocsList) {\n // If outerFn provided and outerFn.prototype is a Generator, then outerFn.prototype instanceof Generator.\n var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator;\n var generator = Object.create(protoGenerator.prototype);\n var context = new Context(tryLocsList || []);\n\n // The ._invoke method unifies the implementations of the .next,\n // .throw, and .return methods.\n generator._invoke = makeInvokeMethod(innerFn, self, context);\n\n return generator;\n }\n exports.wrap = wrap;\n\n // Try/catch helper to minimize deoptimizations. Returns a completion\n // record like context.tryEntries[i].completion. This interface could\n // have been (and was previously) designed to take a closure to be\n // invoked without arguments, but in all the cases we care about we\n // already have an existing method we want to call, so there's no need\n // to create a new function object. We can even get away with assuming\n // the method takes exactly one argument, since that happens to be true\n // in every case, so we don't have to touch the arguments object. The\n // only additional allocation required is the completion record, which\n // has a stable shape and so hopefully should be cheap to allocate.\n function tryCatch(fn, obj, arg) {\n try {\n return { type: \"normal\", arg: fn.call(obj, arg) };\n } catch (err) {\n return { type: \"throw\", arg: err };\n }\n }\n\n var GenStateSuspendedStart = \"suspendedStart\";\n var GenStateSuspendedYield = \"suspendedYield\";\n var GenStateExecuting = \"executing\";\n var GenStateCompleted = \"completed\";\n\n // Returning this object from the innerFn has the same effect as\n // breaking out of the dispatch switch statement.\n var ContinueSentinel = {};\n\n // Dummy constructor functions that we use as the .constructor and\n // .constructor.prototype properties for functions that return Generator\n // objects. For full spec compliance, you may wish to configure your\n // minifier not to mangle the names of these two functions.\n function Generator() {}\n function GeneratorFunction() {}\n function GeneratorFunctionPrototype() {}\n\n // This is a polyfill for %IteratorPrototype% for environments that\n // don't natively support it.\n var IteratorPrototype = {};\n IteratorPrototype[iteratorSymbol] = function () {\n return this;\n };\n\n var getProto = Object.getPrototypeOf;\n var NativeIteratorPrototype = getProto && getProto(getProto(values([])));\n if (NativeIteratorPrototype &&\n NativeIteratorPrototype !== Op &&\n hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) {\n // This environment has a native %IteratorPrototype%; use it instead\n // of the polyfill.\n IteratorPrototype = NativeIteratorPrototype;\n }\n\n var Gp = GeneratorFunctionPrototype.prototype =\n Generator.prototype = Object.create(IteratorPrototype);\n GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype;\n GeneratorFunctionPrototype.constructor = GeneratorFunction;\n GeneratorFunction.displayName = define(\n GeneratorFunctionPrototype,\n toStringTagSymbol,\n \"GeneratorFunction\"\n );\n\n // Helper for defining the .next, .throw, and .return methods of the\n // Iterator interface in terms of a single ._invoke method.\n function defineIteratorMethods(prototype) {\n [\"next\", \"throw\", \"return\"].forEach(function(method) {\n define(prototype, method, function(arg) {\n return this._invoke(method, arg);\n });\n });\n }\n\n exports.isGeneratorFunction = function(genFun) {\n var ctor = typeof genFun === \"function\" && genFun.constructor;\n return ctor\n ? ctor === GeneratorFunction ||\n // For the native GeneratorFunction constructor, the best we can\n // do is to check its .name property.\n (ctor.displayName || ctor.name) === \"GeneratorFunction\"\n : false;\n };\n\n exports.mark = function(genFun) {\n if (Object.setPrototypeOf) {\n Object.setPrototypeOf(genFun, GeneratorFunctionPrototype);\n } else {\n genFun.__proto__ = GeneratorFunctionPrototype;\n define(genFun, toStringTagSymbol, \"GeneratorFunction\");\n }\n genFun.prototype = Object.create(Gp);\n return genFun;\n };\n\n // Within the body of any async function, `await x` is transformed to\n // `yield regeneratorRuntime.awrap(x)`, so that the runtime can test\n // `hasOwn.call(value, \"__await\")` to determine if the yielded value is\n // meant to be awaited.\n exports.awrap = function(arg) {\n return { __await: arg };\n };\n\n function AsyncIterator(generator, PromiseImpl) {\n function invoke(method, arg, resolve, reject) {\n var record = tryCatch(generator[method], generator, arg);\n if (record.type === \"throw\") {\n reject(record.arg);\n } else {\n var result = record.arg;\n var value = result.value;\n if (value &&\n typeof value === \"object\" &&\n hasOwn.call(value, \"__await\")) {\n return PromiseImpl.resolve(value.__await).then(function(value) {\n invoke(\"next\", value, resolve, reject);\n }, function(err) {\n invoke(\"throw\", err, resolve, reject);\n });\n }\n\n return PromiseImpl.resolve(value).then(function(unwrapped) {\n // When a yielded Promise is resolved, its final value becomes\n // the .value of the Promise<{value,done}> result for the\n // current iteration.\n result.value = unwrapped;\n resolve(result);\n }, function(error) {\n // If a rejected Promise was yielded, throw the rejection back\n // into the async generator function so it can be handled there.\n return invoke(\"throw\", error, resolve, reject);\n });\n }\n }\n\n var previousPromise;\n\n function enqueue(method, arg) {\n function callInvokeWithMethodAndArg() {\n return new PromiseImpl(function(resolve, reject) {\n invoke(method, arg, resolve, reject);\n });\n }\n\n return previousPromise =\n // If enqueue has been called before, then we want to wait until\n // all previous Promises have been resolved before calling invoke,\n // so that results are always delivered in the correct order. If\n // enqueue has not been called before, then it is important to\n // call invoke immediately, without waiting on a callback to fire,\n // so that the async generator function has the opportunity to do\n // any necessary setup in a predictable way. This predictability\n // is why the Promise constructor synchronously invokes its\n // executor callback, and why async functions synchronously\n // execute code before the first await. Since we implement simple\n // async functions in terms of async generators, it is especially\n // important to get this right, even though it requires care.\n previousPromise ? previousPromise.then(\n callInvokeWithMethodAndArg,\n // Avoid propagating failures to Promises returned by later\n // invocations of the iterator.\n callInvokeWithMethodAndArg\n ) : callInvokeWithMethodAndArg();\n }\n\n // Define the unified helper method that is used to implement .next,\n // .throw, and .return (see defineIteratorMethods).\n this._invoke = enqueue;\n }\n\n defineIteratorMethods(AsyncIterator.prototype);\n AsyncIterator.prototype[asyncIteratorSymbol] = function () {\n return this;\n };\n exports.AsyncIterator = AsyncIterator;\n\n // Note that simple async functions are implemented on top of\n // AsyncIterator objects; they just return a Promise for the value of\n // the final result produced by the iterator.\n exports.async = function(innerFn, outerFn, self, tryLocsList, PromiseImpl) {\n if (PromiseImpl === void 0) PromiseImpl = Promise;\n\n var iter = new AsyncIterator(\n wrap(innerFn, outerFn, self, tryLocsList),\n PromiseImpl\n );\n\n return exports.isGeneratorFunction(outerFn)\n ? iter // If outerFn is a generator, return the full iterator.\n : iter.next().then(function(result) {\n return result.done ? result.value : iter.next();\n });\n };\n\n function makeInvokeMethod(innerFn, self, context) {\n var state = GenStateSuspendedStart;\n\n return function invoke(method, arg) {\n if (state === GenStateExecuting) {\n throw new Error(\"Generator is already running\");\n }\n\n if (state === GenStateCompleted) {\n if (method === \"throw\") {\n throw arg;\n }\n\n // Be forgiving, per 25.3.3.3.3 of the spec:\n // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume\n return doneResult();\n }\n\n context.method = method;\n context.arg = arg;\n\n while (true) {\n var delegate = context.delegate;\n if (delegate) {\n var delegateResult = maybeInvokeDelegate(delegate, context);\n if (delegateResult) {\n if (delegateResult === ContinueSentinel) continue;\n return delegateResult;\n }\n }\n\n if (context.method === \"next\") {\n // Setting context._sent for legacy support of Babel's\n // function.sent implementation.\n context.sent = context._sent = context.arg;\n\n } else if (context.method === \"throw\") {\n if (state === GenStateSuspendedStart) {\n state = GenStateCompleted;\n throw context.arg;\n }\n\n context.dispatchException(context.arg);\n\n } else if (context.method === \"return\") {\n context.abrupt(\"return\", context.arg);\n }\n\n state = GenStateExecuting;\n\n var record = tryCatch(innerFn, self, context);\n if (record.type === \"normal\") {\n // If an exception is thrown from innerFn, we leave state ===\n // GenStateExecuting and loop back for another invocation.\n state = context.done\n ? GenStateCompleted\n : GenStateSuspendedYield;\n\n if (record.arg === ContinueSentinel) {\n continue;\n }\n\n return {\n value: record.arg,\n done: context.done\n };\n\n } else if (record.type === \"throw\") {\n state = GenStateCompleted;\n // Dispatch the exception by looping back around to the\n // context.dispatchException(context.arg) call above.\n context.method = \"throw\";\n context.arg = record.arg;\n }\n }\n };\n }\n\n // Call delegate.iterator[context.method](context.arg) and handle the\n // result, either by returning a { value, done } result from the\n // delegate iterator, or by modifying context.method and context.arg,\n // setting context.delegate to null, and returning the ContinueSentinel.\n function maybeInvokeDelegate(delegate, context) {\n var method = delegate.iterator[context.method];\n if (method === undefined) {\n // A .throw or .return when the delegate iterator has no .throw\n // method always terminates the yield* loop.\n context.delegate = null;\n\n if (context.method === \"throw\") {\n // Note: [\"return\"] must be used for ES3 parsing compatibility.\n if (delegate.iterator[\"return\"]) {\n // If the delegate iterator has a return method, give it a\n // chance to clean up.\n context.method = \"return\";\n context.arg = undefined;\n maybeInvokeDelegate(delegate, context);\n\n if (context.method === \"throw\") {\n // If maybeInvokeDelegate(context) changed context.method from\n // \"return\" to \"throw\", let that override the TypeError below.\n return ContinueSentinel;\n }\n }\n\n context.method = \"throw\";\n context.arg = new TypeError(\n \"The iterator does not provide a 'throw' method\");\n }\n\n return ContinueSentinel;\n }\n\n var record = tryCatch(method, delegate.iterator, context.arg);\n\n if (record.type === \"throw\") {\n context.method = \"throw\";\n context.arg = record.arg;\n context.delegate = null;\n return ContinueSentinel;\n }\n\n var info = record.arg;\n\n if (! info) {\n context.method = \"throw\";\n context.arg = new TypeError(\"iterator result is not an object\");\n context.delegate = null;\n return ContinueSentinel;\n }\n\n if (info.done) {\n // Assign the result of the finished delegate to the temporary\n // variable specified by delegate.resultName (see delegateYield).\n context[delegate.resultName] = info.value;\n\n // Resume execution at the desired location (see delegateYield).\n context.next = delegate.nextLoc;\n\n // If context.method was \"throw\" but the delegate handled the\n // exception, let the outer generator proceed normally. If\n // context.method was \"next\", forget context.arg since it has been\n // \"consumed\" by the delegate iterator. If context.method was\n // \"return\", allow the original .return call to continue in the\n // outer generator.\n if (context.method !== \"return\") {\n context.method = \"next\";\n context.arg = undefined;\n }\n\n } else {\n // Re-yield the result returned by the delegate method.\n return info;\n }\n\n // The delegate iterator is finished, so forget it and continue with\n // the outer generator.\n context.delegate = null;\n return ContinueSentinel;\n }\n\n // Define Generator.prototype.{next,throw,return} in terms of the\n // unified ._invoke helper method.\n defineIteratorMethods(Gp);\n\n define(Gp, toStringTagSymbol, \"Generator\");\n\n // A Generator should always return itself as the iterator object when the\n // @@iterator function is called on it. Some browsers' implementations of the\n // iterator prototype chain incorrectly implement this, causing the Generator\n // object to not be returned from this call. This ensures that doesn't happen.\n // See https://github.com/facebook/regenerator/issues/274 for more details.\n Gp[iteratorSymbol] = function() {\n return this;\n };\n\n Gp.toString = function() {\n return \"[object Generator]\";\n };\n\n function pushTryEntry(locs) {\n var entry = { tryLoc: locs[0] };\n\n if (1 in locs) {\n entry.catchLoc = locs[1];\n }\n\n if (2 in locs) {\n entry.finallyLoc = locs[2];\n entry.afterLoc = locs[3];\n }\n\n this.tryEntries.push(entry);\n }\n\n function resetTryEntry(entry) {\n var record = entry.completion || {};\n record.type = \"normal\";\n delete record.arg;\n entry.completion = record;\n }\n\n function Context(tryLocsList) {\n // The root entry object (effectively a try statement without a catch\n // or a finally block) gives us a place to store values thrown from\n // locations where there is no enclosing try statement.\n this.tryEntries = [{ tryLoc: \"root\" }];\n tryLocsList.forEach(pushTryEntry, this);\n this.reset(true);\n }\n\n exports.keys = function(object) {\n var keys = [];\n for (var key in object) {\n keys.push(key);\n }\n keys.reverse();\n\n // Rather than returning an object with a next method, we keep\n // things simple and return the next function itself.\n return function next() {\n while (keys.length) {\n var key = keys.pop();\n if (key in object) {\n next.value = key;\n next.done = false;\n return next;\n }\n }\n\n // To avoid creating an additional object, we just hang the .value\n // and .done properties off the next function object itself. This\n // also ensures that the minifier will not anonymize the function.\n next.done = true;\n return next;\n };\n };\n\n function values(iterable) {\n if (iterable) {\n var iteratorMethod = iterable[iteratorSymbol];\n if (iteratorMethod) {\n return iteratorMethod.call(iterable);\n }\n\n if (typeof iterable.next === \"function\") {\n return iterable;\n }\n\n if (!isNaN(iterable.length)) {\n var i = -1, next = function next() {\n while (++i < iterable.length) {\n if (hasOwn.call(iterable, i)) {\n next.value = iterable[i];\n next.done = false;\n return next;\n }\n }\n\n next.value = undefined;\n next.done = true;\n\n return next;\n };\n\n return next.next = next;\n }\n }\n\n // Return an iterator with no values.\n return { next: doneResult };\n }\n exports.values = values;\n\n function doneResult() {\n return { value: undefined, done: true };\n }\n\n Context.prototype = {\n constructor: Context,\n\n reset: function(skipTempReset) {\n this.prev = 0;\n this.next = 0;\n // Resetting context._sent for legacy support of Babel's\n // function.sent implementation.\n this.sent = this._sent = undefined;\n this.done = false;\n this.delegate = null;\n\n this.method = \"next\";\n this.arg = undefined;\n\n this.tryEntries.forEach(resetTryEntry);\n\n if (!skipTempReset) {\n for (var name in this) {\n // Not sure about the optimal order of these conditions:\n if (name.charAt(0) === \"t\" &&\n hasOwn.call(this, name) &&\n !isNaN(+name.slice(1))) {\n this[name] = undefined;\n }\n }\n }\n },\n\n stop: function() {\n this.done = true;\n\n var rootEntry = this.tryEntries[0];\n var rootRecord = rootEntry.completion;\n if (rootRecord.type === \"throw\") {\n throw rootRecord.arg;\n }\n\n return this.rval;\n },\n\n dispatchException: function(exception) {\n if (this.done) {\n throw exception;\n }\n\n var context = this;\n function handle(loc, caught) {\n record.type = \"throw\";\n record.arg = exception;\n context.next = loc;\n\n if (caught) {\n // If the dispatched exception was caught by a catch block,\n // then let that catch block handle the exception normally.\n context.method = \"next\";\n context.arg = undefined;\n }\n\n return !! caught;\n }\n\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n var record = entry.completion;\n\n if (entry.tryLoc === \"root\") {\n // Exception thrown outside of any try block that could handle\n // it, so set the completion value of the entire function to\n // throw the exception.\n return handle(\"end\");\n }\n\n if (entry.tryLoc <= this.prev) {\n var hasCatch = hasOwn.call(entry, \"catchLoc\");\n var hasFinally = hasOwn.call(entry, \"finallyLoc\");\n\n if (hasCatch && hasFinally) {\n if (this.prev < entry.catchLoc) {\n return handle(entry.catchLoc, true);\n } else if (this.prev < entry.finallyLoc) {\n return handle(entry.finallyLoc);\n }\n\n } else if (hasCatch) {\n if (this.prev < entry.catchLoc) {\n return handle(entry.catchLoc, true);\n }\n\n } else if (hasFinally) {\n if (this.prev < entry.finallyLoc) {\n return handle(entry.finallyLoc);\n }\n\n } else {\n throw new Error(\"try statement without catch or finally\");\n }\n }\n }\n },\n\n abrupt: function(type, arg) {\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n if (entry.tryLoc <= this.prev &&\n hasOwn.call(entry, \"finallyLoc\") &&\n this.prev < entry.finallyLoc) {\n var finallyEntry = entry;\n break;\n }\n }\n\n if (finallyEntry &&\n (type === \"break\" ||\n type === \"continue\") &&\n finallyEntry.tryLoc <= arg &&\n arg <= finallyEntry.finallyLoc) {\n // Ignore the finally entry if control is not jumping to a\n // location outside the try/catch block.\n finallyEntry = null;\n }\n\n var record = finallyEntry ? finallyEntry.completion : {};\n record.type = type;\n record.arg = arg;\n\n if (finallyEntry) {\n this.method = \"next\";\n this.next = finallyEntry.finallyLoc;\n return ContinueSentinel;\n }\n\n return this.complete(record);\n },\n\n complete: function(record, afterLoc) {\n if (record.type === \"throw\") {\n throw record.arg;\n }\n\n if (record.type === \"break\" ||\n record.type === \"continue\") {\n this.next = record.arg;\n } else if (record.type === \"return\") {\n this.rval = this.arg = record.arg;\n this.method = \"return\";\n this.next = \"end\";\n } else if (record.type === \"normal\" && afterLoc) {\n this.next = afterLoc;\n }\n\n return ContinueSentinel;\n },\n\n finish: function(finallyLoc) {\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n if (entry.finallyLoc === finallyLoc) {\n this.complete(entry.completion, entry.afterLoc);\n resetTryEntry(entry);\n return ContinueSentinel;\n }\n }\n },\n\n \"catch\": function(tryLoc) {\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n if (entry.tryLoc === tryLoc) {\n var record = entry.completion;\n if (record.type === \"throw\") {\n var thrown = record.arg;\n resetTryEntry(entry);\n }\n return thrown;\n }\n }\n\n // The context.catch method must only be called with a location\n // argument that corresponds to a known catch block.\n throw new Error(\"illegal catch attempt\");\n },\n\n delegateYield: function(iterable, resultName, nextLoc) {\n this.delegate = {\n iterator: values(iterable),\n resultName: resultName,\n nextLoc: nextLoc\n };\n\n if (this.method === \"next\") {\n // Deliberately forget the last sent value so that we don't\n // accidentally pass it on to the delegate.\n this.arg = undefined;\n }\n\n return ContinueSentinel;\n }\n };\n\n // Regardless of whether this script is executing as a CommonJS module\n // or not, return the runtime object so that we can declare the variable\n // regeneratorRuntime in the outer scope, which allows this module to be\n // injected easily by `bin/regenerator --include-runtime script.js`.\n return exports;\n\n}(\n // If this script is executing as a CommonJS module, use module.exports\n // as the regeneratorRuntime namespace. Otherwise create a new empty\n // object. Either way, the resulting object will be used to initialize\n // the regeneratorRuntime variable at the top of this file.\n typeof module === \"object\" ? module.exports : {}\n));\n\ntry {\n regeneratorRuntime = runtime;\n} catch (accidentalStrictMode) {\n // This module should not be running in strict mode, so the above\n // assignment should always work unless something is misconfigured. Just\n // in case runtime.js accidentally runs in strict mode, we can escape\n // strict mode using a global Function call. This could conceivably fail\n // if a Content Security Policy forbids using Function, but in that case\n // the proper solution is to fix the accidental strict mode problem. If\n // you've misconfigured your bundler to force strict mode and applied a\n // CSP to forbid Function, and you're not willing to fix either of those\n // problems, please detail your unique predicament in a GitHub issue.\n Function(\"r\", \"regeneratorRuntime = r\")(runtime);\n}\n","import * as React from 'react';\nimport {\n ContentEntityType as EntityType,\n ScheduledAction,\n} from '@contentful/field-editor-reference/dist/types';\nimport { entityHelpers, Entry, Asset, FieldExtensionSDK } from '@contentful/field-editor-shared';\nimport { getScheduleTooltipContent } from '@contentful/field-editor-reference';\nimport { truncate } from '../../helpers/truncate';\n\nfunction getEntityInfo({\n entityTitle,\n entityStatus,\n contentTypeName,\n}: {\n entityTitle: string;\n entityStatus: string;\n contentTypeName?: string;\n}) {\n const title = truncate(entityTitle, 60) || 'Untitled';\n\n return `${contentTypeName || 'Asset'} \"${title}\", ${entityStatus}`;\n}\n\ninterface EntryAssetTooltipProps {\n id: string;\n type: EntityType;\n sdk: FieldExtensionSDK;\n}\n\nexport function EntryAssetTooltip({ id, type, sdk }: EntryAssetTooltipProps) {\n const [entityTitle, setEntityTitle] = React.useState('');\n const [entityStatus, setEntityStatus] = React.useState('');\n const [jobs, setJobs] = React.useState<ScheduledAction[]>([]);\n const [isLoading, setIsLoading] = React.useState(true);\n const [hasError, setHasError] = React.useState(false);\n\n React.useEffect(() => {\n async function loadContent() {\n try {\n setIsLoading(true);\n setHasError(false);\n\n const actions = {\n Asset: {\n getEntity: sdk.space.getAsset,\n getEntityTitle: (args) => entityHelpers.getAssetTitle({ ...args, asset: args.entity }),\n },\n Entry: {\n getEntity: sdk.space.getEntry,\n getEntityTitle: (args) => entityHelpers.getEntryTitle({ ...args, entry: args.entity }),\n },\n };\n\n let contentType;\n const entity: Entry | Asset = await actions[type].getEntity(id);\n\n if (entity.sys.contentType) {\n const contentTypeId = entity.sys.contentType.sys.id;\n const contentTypes = sdk.space.getCachedContentTypes();\n contentType = contentTypes.find((ct) => ct.sys.id === contentTypeId);\n }\n\n const entityTitle: string = actions[type].getEntityTitle({\n entity,\n contentType,\n localeCode: sdk.field.locale,\n defaultLocaleCode: sdk.locales.default,\n entityType: type,\n });\n\n const jobs = await sdk.space.getEntityScheduledActions(type, id);\n const entityStatus = entityHelpers.getEntryStatus(entity.sys);\n\n setEntityTitle(entityTitle);\n setEntityStatus(entityStatus);\n setJobs(jobs);\n } catch (err) {\n console.log(err);\n setHasError(true);\n } finally {\n setIsLoading(false);\n }\n }\n\n loadContent();\n }, [id, type, sdk]);\n\n if (isLoading) {\n return <>{`Loading ${type.toLowerCase()}...`}</>;\n }\n\n if (hasError) {\n return <>{`${type} missing or inaccessible`}</>;\n }\n\n return (\n <>\n {getEntityInfo({ entityTitle, contentTypeName: type, entityStatus })}{' '}\n {jobs.length > 0 ? getScheduleTooltipContent({ job: jobs[0], jobsCount: jobs.length }) : ''}\n </>\n );\n}\n","export function truncate(str, length) {\n if (typeof str === 'string' && str.length > length) {\n return (\n str &&\n str\n .substr(0, length + 1) // +1 to look ahead and be replaced below.\n // Get rid of orphan letters but not one letter words (I, a, 2).\n // Try to not have “.” as last character to avoid awkward “....”.\n .replace(/(\\s+\\S(?=\\S)|\\s*)\\.?.$/, '…')\n );\n }\n\n return str;\n}\n","import * as React from 'react';\nimport { Entry, Asset } from '@contentful/field-editor-shared';\nimport { useEntities, ScheduledIconWithTooltip } from '@contentful/field-editor-reference';\nimport { ClockIcon } from '@contentful/f36-icons';\nimport { css } from 'emotion';\nimport tokens from '@contentful/f36-tokens';\n\nconst styles = {\n scheduleIcon: css({\n marginRight: tokens.spacing2Xs,\n }),\n};\n\ninterface EntityStatusIconProps {\n entity: Entry | Asset;\n entityType: 'Entry' | 'Asset';\n}\n\nexport function EntityStatusIcon({ entity, entityType }: EntityStatusIconProps) {\n const { loadEntityScheduledActions } = useEntities();\n\n return (\n <ScheduledIconWithTooltip\n getEntityScheduledActions={loadEntityScheduledActions}\n entityType={entityType}\n entityId={entity.sys.id}>\n <ClockIcon\n className={styles.scheduleIcon}\n size=\"small\"\n color=\"muted\"\n testId=\"schedule-icon\"\n />\n </ScheduledIconWithTooltip>\n );\n}\n","import * as React from 'react';\nimport { EntryCard, MenuItem } from '@contentful/f36-components';\nimport { useEntities, MissingEntityCard, AssetThumbnail } from '@contentful/field-editor-reference';\nimport { FieldExtensionSDK } from '@contentful/app-sdk';\nimport { entityHelpers, File, isValidImage } from '@contentful/field-editor-shared';\nimport { css } from 'emotion';\nimport { EntityStatusIcon } from './EntityStatusIcon';\n\nconst styles = {\n entryCard: css({ cursor: 'pointer' }),\n};\n\ninterface FetchingWrappedEntryCardProps {\n entryId: string;\n isDisabled: boolean;\n isSelected: boolean;\n locale: string;\n sdk: FieldExtensionSDK;\n onEdit?: () => void;\n onRemove?: () => void;\n}\n\ninterface EntryThumbnailProps {\n file: File;\n}\n\nfunction EntryThumbnail({ file }: EntryThumbnailProps) {\n if (!isValidImage(file)) return null;\n\n return <AssetThumbnail file={file as File} />;\n}\n\nexport function FetchingWrappedEntryCard(props: FetchingWrappedEntryCardProps) {\n const { getOrLoadEntry, entries, getOrLoadAsset } = useEntities();\n const [file, setFile] = React.useState<File | null>(null);\n const entry = entries[props.entryId];\n const contentType = React.useMemo(() => {\n if (!entry || entry === 'failed') {\n return undefined;\n }\n return props.sdk.space\n .getCachedContentTypes()\n .find((contentType) => contentType.sys.id === entry.sys.contentType.sys.id);\n }, [props.sdk, entry]);\n const defaultLocaleCode = props.sdk.locales.default;\n\n React.useEffect(() => {\n if (!entry || entry === 'failed') return;\n\n entityHelpers\n .getEntryImage(\n {\n entry,\n contentType,\n localeCode: props.locale,\n defaultLocaleCode,\n },\n getOrLoadAsset\n )\n .then(setFile)\n .catch(() => setFile(null));\n }, [entry, contentType, props.locale, defaultLocaleCode, props.sdk, file, getOrLoadAsset]);\n\n React.useEffect(() => {\n getOrLoadEntry(props.entryId);\n }, [props.entryId]); // eslint-disable-line\n\n function renderDropdown() {\n if (!props.onEdit || !props.onRemove) return undefined;\n\n return [\n props.onEdit ? (\n <MenuItem\n key=\"edit\"\n testId=\"card-action-edit\"\n onClick={() => {\n props.onEdit && props.onEdit();\n }}>\n Edit\n </MenuItem>\n ) : null,\n props.onRemove ? (\n <MenuItem\n key=\"delete\"\n testId=\"card-action-remove\"\n onClick={() => {\n props.onRemove && props.onRemove();\n }}>\n Remove\n </MenuItem>\n ) : null,\n ].filter((item) => item);\n }\n\n if (entry === undefined) {\n return <EntryCard size=\"default\" isLoading={true} />;\n }\n\n if (entry === 'failed') {\n return (\n <MissingEntityCard\n entityType=\"Entry\"\n isDisabled={props.isDisabled}\n onRemove={props.onRemove}\n />\n );\n }\n\n const entryStatus = entry ? entityHelpers.getEntryStatus(entry.sys) : undefined;\n if (entryStatus === 'deleted') {\n return (\n <MissingEntityCard\n entityType=\"Entry\"\n isDisabled={props.isDisabled}\n onRemove={props.onRemove}\n />\n );\n }\n\n const title = entityHelpers.getEntryTitle({\n entry,\n contentType,\n localeCode: props.locale,\n defaultLocaleCode,\n defaultTitle: 'Untitled',\n });\n\n const description = entityHelpers.getEntityDescription({\n entity: entry,\n contentType,\n localeCode: props.locale,\n defaultLocaleCode,\n });\n\n return (\n <EntryCard\n contentType={contentType?.name}\n title={title}\n description={description}\n size=\"default\"\n isSelected={props.isSelected}\n status={entryStatus}\n className={styles.entryCard}\n thumbnailElement={file ? <EntryThumbnail file={file} /> : undefined}\n icon={<EntityStatusIcon entityType=\"Entry\" entity={entry} />}\n withDragHandle={false}\n actions={renderDropdown()}\n />\n );\n}\n","import * as React from 'react';\nimport { AssetCard, AssetType, Menu, Text } from '@contentful/f36-components';\nimport { useEntities, MissingEntityCard } from '@contentful/field-editor-reference';\n\nimport { FieldExtensionSDK } from '@contentful/app-sdk';\nimport { entityHelpers, File, shortenStorageUnit } from '@contentful/field-editor-shared';\nimport mimetype from '@contentful/mimetype';\nimport { css } from 'emotion';\nimport get from 'lodash/get';\nimport { EntityStatusIcon } from './EntityStatusIcon';\n\nconst styles = {\n assetCard: css({ cursor: 'pointer' }),\n cardDropdown: css({\n width: '300px',\n }),\n truncated: css({\n overflow: 'hidden',\n whiteSpace: 'nowrap',\n textOverflow: 'ellipsis',\n }),\n};\ninterface FetchingWrappedAssetCardProps {\n assetId: string;\n isDisabled: boolean;\n isSelected: boolean;\n locale: string;\n onEdit?: () => void;\n onRemove?: () => unknown;\n sdk: FieldExtensionSDK;\n}\n\nfunction downloadAsset(url: string) {\n window.open(url, '_blank', 'noopener,noreferrer');\n}\n\nexport function renderAssetInfo(props: { entityFile: File }) {\n const { entityFile } = props;\n const fileName = get(entityFile, 'fileName');\n const mimeType = get(entityFile, 'contentType');\n const fileSize = get(entityFile, 'details.size');\n const image = get(entityFile, 'details.image');\n return [\n <Menu.SectionTitle key=\"file-section\">File info</Menu.SectionTitle>,\n fileName && (\n <Menu.Item key=\"file-name\">\n <Text isTruncated>{fileName}</Text>\n </Menu.Item>\n ),\n mimeType && (\n <Menu.Item key=\"file-type\">\n <Text isTruncated>{mimeType}</Text>\n </Menu.Item>\n ),\n fileSize && <Menu.Item key=\"file-size\">{shortenStorageUnit(fileSize, 'B')}</Menu.Item>,\n image && <Menu.Item key=\"file-dimentions\">{`${image.width} × ${image.height}`}</Menu.Item>,\n ].filter((item) => item);\n}\n\nexport function renderActions(props: {\n onEdit?: () => void;\n onRemove?: () => void;\n isDisabled: boolean;\n entityFile?: File;\n}) {\n const { entityFile, isDisabled, onEdit, onRemove } = props;\n\n return [\n <Menu.SectionTitle key=\"section-title\">Actions</Menu.SectionTitle>,\n onEdit ? (\n <Menu.Item key=\"edit\" onClick={onEdit} testId=\"card-action-edit\">\n Edit\n </Menu.Item>\n ) : null,\n entityFile ? (\n <Menu.Item\n key=\"download\"\n onClick={() => {\n if (typeof entityFile.url === 'string') {\n downloadAsset(entityFile.url);\n }\n }}\n testId=\"card-action-download\">\n Download\n </Menu.Item>\n ) : null,\n onRemove ? (\n <Menu.Item key=\"remove\" disabled={isDisabled} onClick={onRemove} testId=\"card-action-remove\">\n Remove\n </Menu.Item>\n ) : null,\n ].filter((item) => item);\n}\n\nexport function FetchingWrappedAssetCard(props: FetchingWrappedAssetCardProps) {\n const { getOrLoadAsset, assets } = useEntities();\n const asset = assets[props.assetId];\n const defaultLocaleCode = props.sdk.locales.default;\n const entityFile: File | undefined = asset?.fields?.file\n ? asset.fields.file[props.locale] || asset.fields.file[defaultLocaleCode]\n : undefined;\n\n React.useEffect(() => {\n getOrLoadAsset(props.assetId);\n }, [props.assetId]); // eslint-disable-line\n\n function getAssetSrc() {\n if (!entityFile?.url) return '';\n\n return `${entityFile.url}?h=300`;\n }\n\n function getFileType(): AssetType {\n const groupToIconMap = {\n image: 'image',\n video: 'video',\n audio: 'audio',\n richtext: 'richtext',\n presentation: 'presentation',\n spreadsheet: 'spreadsheet',\n pdfdocument: 'pdf',\n archive: 'archive',\n plaintext: 'plaintext',\n code: 'code',\n markup: 'markup',\n };\n const archive = groupToIconMap['archive'] as AssetType;\n\n if (!entityFile) {\n return archive;\n }\n\n const groupName: keyof typeof groupToIconMap = mimetype.getGroupLabel({\n type: entityFile.contentType,\n fallbackFileName: entityFile.fileName,\n });\n\n return (groupToIconMap[groupName] as AssetType) || archive;\n }\n\n if (asset === undefined) {\n return <AssetCard size=\"small\" isLoading />;\n }\n\n if (asset === 'failed') {\n return (\n <MissingEntityCard\n entityType=\"Asset\"\n isDisabled={props.isDisabled}\n onRemove={props.onRemove}\n />\n );\n }\n\n const status = asset ? entityHelpers.getEntryStatus(asset.sys) : undefined;\n if (status === 'deleted') {\n return (\n <MissingEntityCard\n entityType=\"Asset\"\n asSquare={true}\n isDisabled={props.isDisabled}\n onRemove={props.onRemove}\n />\n );\n }\n\n const entityTitle = entityHelpers.getAssetTitle({\n asset,\n localeCode: props.locale,\n defaultLocaleCode,\n defaultTitle: 'Untitled',\n });\n\n return (\n <AssetCard\n title={entityTitle}\n isSelected={props.isSelected}\n size=\"small\"\n src={getAssetSrc()}\n type={getFileType()}\n status={status}\n icon={<EntityStatusIcon entityType=\"Asset\" entity={asset} />}\n className={styles.assetCard}\n actions={[\n renderActions({\n entityFile,\n isDisabled: props.isDisabled,\n onEdit: props.onEdit,\n onRemove: props.onRemove,\n }),\n entityFile ? renderAssetInfo({ entityFile }) : null,\n ].filter((item) => item)}\n />\n );\n}\n","/* eslint-disable you-dont-need-lodash-underscore/find */\nimport flow from 'lodash/flow';\nimport find from 'lodash/find';\nimport get from 'lodash/get';\n\n/**\n * Given a field object and a rich text node type, return a list of valid\n * content type IDs associated with the node type, based on that node type's\n * `linkContentType` validation.\n *\n * If there is no such validation or the validation is empty, return an empty\n * array.\n *\n * The navigation here is explained by the `nodes` validation having signature:\n * { nodes: { [nodeType]: validationObject[] } }\n *\n * We defensively navigate through this object because\n * 1) the field may not have a `validations` array,\n * 2) the `validations` array may be empty,\n * 3) the `validations` array may not have a `nodes` validation,\n * 4) the `nodes` validation may not validate the `nodeType`, and\n * 5) the `nodeType` validations may not have a `linkContentType` validation.\n *\n * Note that passing an empty array will result in all possible content types\n * being whitelisted.\n *\n * @param {object} field\n * @param {string} nodeType\n * @returns {string[]}\n */\nexport default function getLinkedContentTypeIdsForNodeType(field, nodeType): string[] {\n return flow(\n (v) => find(v, 'nodes'),\n (v) => get(v, ['nodes', nodeType]),\n (v) => find(v, 'linkContentType'),\n (v) => get(v, 'linkContentType', [])\n )(field.validations);\n}\n","import * as React from 'react';\nimport { INLINES } from '@contentful/rich-text-types';\nimport {\n TextLink,\n Button,\n FormControl,\n FormLabel,\n Select,\n TextInput,\n Form,\n ModalContent,\n ModalControls,\n} from '@contentful/f36-components';\nimport { ModalDialogLauncher, FieldExtensionSDK } from '@contentful/field-editor-shared';\nimport { PlateEditor } from '@udecode/plate-core';\nimport { Editor, Transforms } from 'slate';\nimport { ReactEditor } from 'slate-react';\nimport { HistoryEditor } from 'slate-history';\nimport { EntityProvider } from '@contentful/field-editor-reference';\nimport { Link } from '@contentful/field-editor-reference/dist/types';\nimport { css } from 'emotion';\nimport tokens from '@contentful/f36-tokens';\nimport { getNodeEntryFromSelection, insertLink, LINK_TYPES } from '../../helpers/editor';\nimport { FetchingWrappedEntryCard } from '../shared/FetchingWrappedEntryCard';\nimport { FetchingWrappedAssetCard } from '../shared/FetchingWrappedAssetCard';\nimport getLinkedContentTypeIdsForNodeType from '../../helpers/getLinkedContentTypeIdsForNodeType';\nimport { isNodeTypeEnabled } from '../../helpers/validations';\n\nconst styles = {\n removeSelectionLabel: css`\n margin-left: ${tokens.spacingS};\n `,\n};\n\ninterface HyperlinkModalProps {\n linkText?: string;\n linkType?: string;\n linkTarget?: string;\n linkEntity?: Link;\n onClose: (value: unknown) => void;\n sdk: FieldExtensionSDK;\n}\n\nconst SYS_LINK_TYPES = {\n [INLINES.ENTRY_HYPERLINK]: 'Entry',\n [INLINES.ASSET_HYPERLINK]: 'Asset',\n};\n\nconst LINK_TYPE_SELECTION_VALUES = {\n [INLINES.HYPERLINK]: 'URL',\n [INLINES.ENTRY_HYPERLINK]: 'Entry',\n [INLINES.ASSET_HYPERLINK]: 'Asset',\n};\n\nexport function HyperlinkModal(props: HyperlinkModalProps) {\n const enabledLinkTypes = LINK_TYPES.filter((nodeType) =>\n isNodeTypeEnabled(props.sdk.field, nodeType)\n );\n const [defaultLinkType] = enabledLinkTypes;\n const [linkText, setLinkText] = React.useState(props.linkText ?? '');\n const [linkType, setLinkType] = React.useState(props.linkType ?? defaultLinkType);\n const [linkTarget, setLinkTarget] = React.useState(props.linkTarget ?? '');\n const [linkEntity, setLinkEntity] = React.useState<Link | null>(props.linkEntity ?? null);\n\n function isLinkComplete() {\n const isRegularLink = linkType === INLINES.HYPERLINK;\n if (isRegularLink) {\n return !!(linkText && linkTarget);\n }\n\n const entityLinks: string[] = Object.keys(SYS_LINK_TYPES);\n const isEntityLink = entityLinks.includes(linkType);\n if (isEntityLink) {\n return !!(linkText && linkEntity);\n }\n\n return false;\n }\n\n function handleOnSubmit(event: React.MouseEvent<HTMLButtonElement>) {\n event.preventDefault();\n\n props.onClose({ linkText, linkType, linkTarget, linkEntity });\n }\n\n function entityToLink(entity): Link {\n const { id, type } = entity.sys;\n\n return { sys: { id, type: 'Link', linkType: type } };\n }\n\n async function selectEntry() {\n const options = {\n locale: props.sdk.field.locale,\n contentTypes: getLinkedContentTypeIdsForNodeType(props.sdk.field, INLINES.ENTRY_HYPERLINK),\n };\n const entry = await props.sdk.dialogs.selectSingleEntry(options);\n setLinkTarget('');\n setLinkEntity(entityToLink(entry));\n }\n\n async function selectAsset() {\n const options = {\n locale: props.sdk.field.locale,\n };\n const asset = await props.sdk.dialogs.selectSingleAsset(options);\n setLinkTarget('');\n setLinkEntity(entityToLink(asset));\n }\n\n function resetLinkEntity(event: React.MouseEvent) {\n event.preventDefault();\n\n setLinkEntity(null);\n }\n\n return (\n <EntityProvider sdk={props.sdk}>\n <React.Fragment>\n <ModalContent>\n <Form>\n {!props.linkType && (\n <FormControl id=\"link-text\" isRequired>\n <FormControl.Label>Link text</FormControl.Label>\n <TextInput\n testId=\"link-text-input\"\n name=\"link-text\"\n value={linkText}\n onChange={(event) => setLinkText(event.target.value)}\n />\n </FormControl>\n )}\n\n {enabledLinkTypes.length > 1 && (\n <FormControl id=\"link-type\">\n <FormControl.Label>Link type</FormControl.Label>\n <Select\n value={linkType}\n onChange={(event: React.ChangeEvent<HTMLSelectElement>) =>\n setLinkType(event.target.value)\n }\n testId=\"link-type-input\">\n {enabledLinkTypes.map((nodeType) => (\n <Select.Option key={nodeType} value={nodeType}>\n {LINK_TYPE_SELECTION_VALUES[nodeType]}\n </Select.Option>\n ))}\n </Select>\n </FormControl>\n )}\n\n {linkType === INLINES.HYPERLINK && (\n <FormControl id=\"linkTarget\" isRequired>\n <FormControl.Label>Link target</FormControl.Label>\n <TextInput\n name=\"linkTarget\"\n value={linkTarget}\n onChange={(event: React.ChangeEvent<HTMLInputElement>) => {\n setLinkEntity(null);\n setLinkTarget(event.target.value);\n }}\n testId=\"link-target-input\"\n />\n <FormControl.HelpText>\n A protocol may be required, e.g. https://\n </FormControl.HelpText>\n </FormControl>\n )}\n\n {linkType !== INLINES.HYPERLINK && (\n <div>\n <FormLabel isRequired htmlFor=\"\">\n Link target{' '}\n </FormLabel>\n\n {linkEntity && linkEntity.sys.linkType === SYS_LINK_TYPES[linkType] ? (\n <>\n <TextLink\n testId=\"entity-selection-link\"\n onClick={resetLinkEntity}\n className={styles.removeSelectionLabel}>\n Remove selection\n </TextLink>\n <div>\n {linkType === INLINES.ENTRY_HYPERLINK && (\n <FetchingWrappedEntryCard\n sdk={props.sdk}\n locale={props.sdk.field.locale}\n entryId={linkEntity.sys.id}\n isDisabled={true}\n isSelected={false}\n />\n )}\n {linkType === INLINES.ASSET_HYPERLINK && (\n <FetchingWrappedAssetCard\n sdk={props.sdk}\n locale={props.sdk.field.locale}\n assetId={linkEntity.sys.id}\n isDisabled={true}\n isSelected={false}\n />\n )}\n </div>\n </>\n ) : (\n <div>\n {linkType === INLINES.ENTRY_HYPERLINK && (\n <TextLink testId=\"entity-selection-link\" onClick={selectEntry}>\n Select entry\n </TextLink>\n )}\n {linkType === INLINES.ASSET_HYPERLINK && (\n <TextLink testId=\"entity-selection-link\" onClick={selectAsset}>\n Select asset\n </TextLink>\n )}\n </div>\n )}\n </div>\n )}\n </Form>\n </ModalContent>\n <ModalControls>\n <Button\n type=\"button\"\n onClick={() => props.onClose(null)}\n variant=\"secondary\"\n testId=\"cancel-cta\"\n size=\"small\">\n Cancel\n </Button>\n <Button\n type=\"submit\"\n variant=\"positive\"\n size=\"small\"\n isDisabled={!isLinkComplete()}\n onClick={handleOnSubmit}\n testId=\"confirm-cta\">\n {props.linkType ? 'Update' : 'Insert'}\n </Button>\n </ModalControls>\n </React.Fragment>\n </EntityProvider>\n );\n}\n\ninterface HyperLinkDialogData {\n linkText: string;\n linkType: INLINES.HYPERLINK | INLINES.ASSET_HYPERLINK | INLINES.ENTRY_HYPERLINK;\n linkTarget?: string;\n linkEntity?: Link;\n}\n\nexport async function addOrEditLink(\n editor: ReactEditor & HistoryEditor & PlateEditor,\n sdk: FieldExtensionSDK\n) {\n if (!editor.selection) return;\n\n let linkType;\n let linkText;\n let linkTarget;\n let linkEntity;\n\n const [node, path] = getNodeEntryFromSelection(editor, LINK_TYPES);\n if (node && path) {\n linkType = node.type;\n linkText = Editor.string(editor, path);\n linkTarget = (node.data as { uri: string }).uri || '';\n linkEntity = (node.data as { target: Link }).target;\n }\n\n const selectionBeforeBlur = { ...editor.selection };\n const currentLinkText = linkText || Editor.string(editor, editor.selection);\n\n const data = await ModalDialogLauncher.openDialog(\n {\n title: linkType ? 'Edit hyperlink' : 'Insert hyperlink',\n width: 'large',\n shouldCloseOnEscapePress: true,\n shouldCloseOnOverlayClick: true,\n allowHeightOverflow: true,\n },\n ({ onClose }) => {\n return (\n <HyperlinkModal\n linkTarget={linkTarget}\n linkText={currentLinkText}\n linkType={linkType}\n linkEntity={linkEntity}\n onClose={onClose}\n sdk={sdk}\n />\n );\n }\n );\n\n if (!data) return;\n\n const {\n linkText: text,\n linkTarget: url,\n linkType: type,\n linkEntity: target,\n } = data as HyperLinkDialogData;\n\n Transforms.select(editor, selectionBeforeBlur);\n\n insertLink(editor, { text, url, type, target, path });\n\n ReactEditor.focus(editor);\n}\n","import * as React from 'react';\nimport {\n PlatePlugin,\n getRenderElement,\n getPlatePluginTypes,\n getPlatePluginOptions,\n} from '@udecode/plate-core';\nimport { INLINES } from '@contentful/rich-text-types';\nimport { Tooltip, TextLink } from '@contentful/f36-components';\nimport { EntryAssetTooltip } from './EntryAssetTooltip';\nimport { LinkIcon } from '@contentful/f36-icons';\nimport { ToolbarButton } from '../shared/ToolbarButton';\nimport { css } from 'emotion';\nimport tokens from '@contentful/f36-tokens';\nimport { FieldExtensionSDK, Link, ContentEntityType as EntityType } from '@contentful/app-sdk';\nimport { CustomSlatePluginOptions, CustomRenderElementProps } from '../../types';\nimport { useSdkContext } from '../../SdkProvider';\nimport { addOrEditLink } from './HyperlinkModal';\nimport { isLinkActive, LINK_TYPES, unwrapLink } from '../../helpers/editor';\nimport { useContentfulEditor } from '../../ContentfulEditorProvider';\n\nconst styles = {\n hyperlinkWrapper: css({\n display: 'inline',\n position: 'static',\n a: {\n fontSize: 'inherit !important',\n },\n }),\n hyperlink: css({\n fontSize: 'inherit !important',\n display: 'inline !important',\n '&:hover': {\n fill: tokens.gray900,\n },\n '&:focus': {\n fill: tokens.gray900,\n },\n }),\n hyperlinkIEFallback: css({\n color: '#1683d0',\n textDecoration: 'underline',\n }),\n // TODO: use these styles once we can use the icon\n hyperlinkIcon: css({\n position: 'relative',\n top: '4px',\n height: '14px',\n margin: '0 -2px 0 -1px',\n webkitTransition: 'fill 100ms ease-in-out',\n transition: 'fill 100ms ease-in-out',\n '&:hover': {\n fill: tokens.gray900,\n },\n '&:focus': {\n fill: tokens.gray900,\n },\n }),\n};\n\nexport function createHyperlinkPlugin(sdk: FieldExtensionSDK): PlatePlugin {\n return {\n renderElement: getRenderElement(LINK_TYPES),\n pluginKeys: LINK_TYPES,\n inlineTypes: getPlatePluginTypes(LINK_TYPES),\n onKeyDown: buildHyperlinkEventHandler(sdk),\n deserialize: (editor) => {\n const hyperlinkOptions = getPlatePluginOptions(editor, INLINES.HYPERLINK);\n const entryHyperlinkOptions = getPlatePluginOptions(editor, INLINES.ENTRY_HYPERLINK);\n const assetHyperlinkOptions = getPlatePluginOptions(editor, INLINES.ASSET_HYPERLINK);\n\n const isAnchor = (element) =>\n element.nodeName === 'A' &&\n !!element.getAttribute('href') &&\n element.getAttribute('href') !== '#';\n const isEntryAnchor = (element) =>\n isAnchor(element) && element.getAttribute('data-link-type') === 'Entry';\n const isAssetAnchor = (element) =>\n isAnchor(element) && element.getAttribute('data-link-type') === 'Asset';\n\n return {\n element: [\n {\n type: INLINES.HYPERLINK,\n deserialize: (element) => {\n if (!isAnchor(element) || isEntryAnchor(element) || isAssetAnchor(element)) return;\n\n return {\n type: INLINES.HYPERLINK,\n data: {\n uri: element.getAttribute('href'),\n },\n };\n },\n ...hyperlinkOptions.deserialize,\n },\n {\n type: INLINES.ENTRY_HYPERLINK,\n deserialize: (element) => {\n if (!isEntryAnchor(element)) return;\n\n return {\n type: INLINES.ENTRY_HYPERLINK,\n data: {\n target: {\n sys: {\n id: element.getAttribute('data-link-id'),\n linkType: element.getAttribute('data-link-type'),\n type: 'Link',\n },\n },\n },\n };\n },\n ...entryHyperlinkOptions.deserialize,\n },\n {\n type: INLINES.ASSET_HYPERLINK,\n deserialize: (element) => {\n if (!isAssetAnchor(element)) return;\n\n return {\n type: INLINES.ASSET_HYPERLINK,\n data: {\n target: {\n sys: {\n id: element.getAttribute('data-link-id'),\n linkType: element.getAttribute('data-link-type'),\n type: 'Link',\n },\n },\n },\n };\n },\n ...assetHyperlinkOptions.deserialize,\n },\n ],\n };\n },\n };\n}\n\ntype K = 75;\ntype KEvent = React.KeyboardEvent & { keyCode: K };\ntype CtrlEvent = React.KeyboardEvent & { ctrlKey: true };\ntype MetaEvent = React.KeyboardEvent & { metaKey: true };\ntype ModEvent = CtrlEvent | MetaEvent;\ntype HyperlinkEvent = ModEvent & KEvent;\n\nconst isMod = (event: React.KeyboardEvent): event is ModEvent => event.ctrlKey || event.metaKey;\nconst isK = (event: React.KeyboardEvent): event is KEvent => event.keyCode === 75;\nconst wasHyperlinkEventTriggered = (event: React.KeyboardEvent): event is HyperlinkEvent =>\n isMod(event) && isK(event);\n\nexport function buildHyperlinkEventHandler(sdk) {\n return function withHyperlinkEvents(editor) {\n return function handleKeyDown(event: React.KeyboardEvent) {\n if (!editor.selection || !wasHyperlinkEventTriggered(event)) return;\n if (isLinkActive(editor)) {\n unwrapLink(editor);\n } else {\n addOrEditLink(editor, sdk);\n }\n };\n };\n}\n\ntype HyperlinkElementProps = CustomRenderElementProps<{\n uri?: string;\n target?: Link;\n}>;\n\nfunction UrlHyperlink(props: HyperlinkElementProps) {\n const editor = useContentfulEditor();\n const sdk: FieldExtensionSDK = useSdkContext();\n const { uri } = props.element.data;\n\n async function handleClick(event: React.MouseEvent<HTMLAnchorElement>) {\n event.preventDefault();\n event.stopPropagation();\n if (!editor) return;\n addOrEditLink(editor, sdk);\n }\n\n return (\n <Tooltip\n content={uri}\n targetWrapperClassName={styles.hyperlinkWrapper}\n placement=\"bottom\"\n maxWidth=\"auto\">\n <TextLink\n as=\"a\"\n href={uri}\n rel=\"noopener noreferrer\"\n onClick={handleClick}\n className={styles.hyperlink}>\n {props.children}\n </TextLink>\n </Tooltip>\n );\n}\n\nfunction EntityHyperlink(props: HyperlinkElementProps) {\n const editor = useContentfulEditor();\n const sdk: FieldExtensionSDK = useSdkContext();\n const { target } = props.element.data;\n\n if (!target) return null;\n\n async function handleClick(event: React.MouseEvent<HTMLButtonElement>) {\n event.preventDefault();\n event.stopPropagation();\n if (!editor) return;\n addOrEditLink(editor, sdk);\n }\n\n return (\n <Tooltip\n content={\n (\n <EntryAssetTooltip\n id={target.sys.id}\n type={target.sys.linkType as EntityType}\n sdk={sdk}\n />\n ) as unknown as string\n }\n targetWrapperClassName={styles.hyperlinkWrapper}\n placement=\"bottom\"\n maxWidth=\"auto\">\n <TextLink\n as=\"button\"\n onClick={handleClick}\n className={styles.hyperlink}\n data-link-type={target.sys.linkType}\n data-link-id={target.sys.id}>\n {props.children}\n </TextLink>\n </Tooltip>\n );\n}\n\ninterface ToolbarHyperlinkButtonProps {\n isDisabled: boolean | undefined;\n}\n\nexport function ToolbarHyperlinkButton(props: ToolbarHyperlinkButtonProps) {\n const editor = useContentfulEditor();\n const isActive = !!(editor && isLinkActive(editor));\n const sdk: FieldExtensionSDK = useSdkContext();\n\n async function handleClick() {\n if (!editor) return;\n\n if (isActive) {\n unwrapLink(editor);\n } else {\n addOrEditLink(editor, sdk);\n }\n }\n\n if (!editor) return null;\n\n return (\n <ToolbarButton\n title=\"Hyperlink\"\n testId=\"hyperlink-toolbar-button\"\n onClick={handleClick}\n isActive={isActive}\n isDisabled={props.isDisabled}>\n <LinkIcon />\n </ToolbarButton>\n );\n}\n\nexport const withHyperlinkOptions: CustomSlatePluginOptions = {\n [INLINES.HYPERLINK]: {\n type: INLINES.HYPERLINK,\n component: UrlHyperlink,\n },\n [INLINES.ENTRY_HYPERLINK]: {\n type: INLINES.ENTRY_HYPERLINK,\n component: EntityHyperlink,\n },\n [INLINES.ASSET_HYPERLINK]: {\n type: INLINES.ASSET_HYPERLINK,\n component: EntityHyperlink,\n },\n};\n","import { Transforms, Path, Editor, Ancestor } from 'slate';\nimport { PlateEditor } from '@udecode/plate-core';\nimport {\n ELEMENT_TABLE,\n ELEMENT_TH,\n ELEMENT_TD,\n ELEMENT_TR,\n insertTable,\n} from '@udecode/plate-table';\nimport { getAbove, getChildren, isFirstChild, isAncestorEmpty } from '@udecode/plate-common';\nimport { BLOCKS } from '@contentful/rich-text-types';\n\nimport {\n isBlockSelected,\n getNodeEntryFromSelection,\n getAncestorPathFromSelection,\n} from '../../helpers/editor';\nimport { CustomElement } from '../../types';\n\n/**\n * Sets the UI focus to the first cell of the selected table.\n *\n * This is necessary because udecode's plugin sets the focus to the\n * _last_ cell of the table after selection, which is weird.\n */\nfunction moveToFirstCellFromSelectedTable(editor) {\n const [, tablePath] = getNodeEntryFromSelection(editor, BLOCKS.TABLE);\n if (!tablePath) return;\n const firstTableCellPath = tablePath.concat([\n 0, // -> row\n 0, // -> cell\n 0, // -> paragraph\n 0, // -> text node\n ]);\n const anchor = { path: firstTableCellPath, offset: 0 };\n Transforms.setSelection(editor, { anchor, focus: anchor });\n}\n\nexport function insertTableAndFocusFirstCell(editor: PlateEditor): void {\n // FIXME: a table should only be allowed at root level. Currently this\n // code adds it at any level\n insertTable(editor, { header: true });\n moveToFirstCellFromSelectedTable(editor);\n replaceEmptyParagraphWithTable(editor);\n}\n\nexport function isTableActive(editor: PlateEditor) {\n const tableElements = [ELEMENT_TABLE, ELEMENT_TH, ELEMENT_TR, ELEMENT_TD];\n return tableElements.some((el) => isBlockSelected(editor, el));\n}\n\nexport function isTableHeaderEnabled(editor: PlateEditor) {\n const tableItem = getAbove(editor, {\n match: {\n type: BLOCKS.TABLE,\n },\n });\n\n if (!tableItem) {\n return false;\n }\n\n const firstRow = getChildren(tableItem)[0];\n\n if (!firstRow) {\n return false;\n }\n\n return getChildren(firstRow).every(([node]) => {\n return node.type === BLOCKS.TABLE_HEADER_CELL;\n });\n}\n\nexport function replaceEmptyParagraphWithTable(editor: PlateEditor) {\n const tablePath = getAncestorPathFromSelection(editor);\n if (!tablePath || isFirstChild(tablePath)) return;\n\n const previousPath = Path.previous(tablePath);\n if (!previousPath) return;\n\n const [nodes] = Editor.nodes(editor, {\n at: previousPath,\n match: (node) => (node as CustomElement).type === BLOCKS.PARAGRAPH,\n });\n if (!nodes) return;\n\n const [previousNode] = nodes;\n const isPreviousNodeTextEmpty = isAncestorEmpty(editor, previousNode as Ancestor);\n if (isPreviousNodeTextEmpty) {\n // Switch table with previous empty paragraph\n Transforms.moveNodes(editor, { at: tablePath, to: previousPath });\n // Remove previous paragraph that now is under the table\n Transforms.removeNodes(editor, { at: tablePath });\n }\n}\n","import * as React from 'react';\nimport constate from 'constate';\n\nexport type RichTextTrackingActionName =\n | 'insertTable'\n | 'insertTableRow'\n | 'insertTableColumn'\n | 'removeTable'\n | 'removeTableRow'\n | 'removeTableColumn'\n | 'paste';\n\nexport type RichTextTrackingActionHandler = (\n name: RichTextTrackingActionName,\n data: Record<string, unknown>\n) => unknown;\n\ninterface TrackingProviderProps {\n onAction: RichTextTrackingActionHandler;\n}\n\nexport interface TrackingProvider {\n onViewportAction: (\n actionName: RichTextTrackingActionName,\n data?: Record<string, unknown>\n ) => ReturnType<TrackingProviderProps['onAction']>;\n}\n\nfunction useTracking({ onAction }: TrackingProviderProps): TrackingProvider {\n const trackingMemo = React.useMemo<TrackingProvider>(\n () => ({\n onViewportAction: (actionName: RichTextTrackingActionName, data = {}) =>\n onAction(actionName, { origin: 'viewport-interaction', ...data }),\n }),\n [] // eslint-disable-line\n );\n\n return trackingMemo;\n}\n\nexport const [TrackingProvider, useTrackingContext] = constate(useTracking);\n","import { Transforms, Path, Editor } from 'slate';\nimport { getPlatePluginType, PlateEditor, TElement } from '@udecode/plate-core';\nimport { ELEMENT_TABLE, ELEMENT_TR, getEmptyRowNode } from '@udecode/plate-table';\nimport { getAbove, insertNodes, someNode } from '@udecode/plate-common';\n\nconst addRow = (editor: PlateEditor, getNextRowPath: (currentRowPath: Path) => Path) => {\n if (\n someNode(editor, {\n match: { type: getPlatePluginType(editor, ELEMENT_TABLE) },\n })\n ) {\n const currentRowItem = getAbove(editor, {\n match: { type: getPlatePluginType(editor, ELEMENT_TR) },\n });\n\n if (currentRowItem) {\n const [currentRowElem, currentRowPath] = currentRowItem;\n const nextRowPath = getNextRowPath(currentRowPath);\n\n insertNodes<TElement>(\n editor,\n // @ts-expect-error\n getEmptyRowNode(editor, {\n header: false,\n colCount: currentRowElem.children.length,\n }),\n {\n at: nextRowPath,\n // Note: this selects the last cell of the new row\n select: true,\n }\n );\n\n // Select the first cell in the current row\n Transforms.select(editor, Editor.start(editor, nextRowPath));\n }\n }\n};\n\nexport const addRowBelow = (editor: PlateEditor) => {\n addRow(editor, (currentRowPath) => {\n return Path.next(currentRowPath);\n });\n};\n\nexport const addRowAbove = (editor: PlateEditor) => {\n addRow(editor, (currentRowPath) => {\n // The new row will be in in-place of the old row\n return currentRowPath;\n });\n};\n","import { Path } from 'slate';\nimport { getPlatePluginType, PlateEditor, TElement } from '@udecode/plate-core';\nimport { getAbove, insertNodes, someNode } from '@udecode/plate-common';\nimport {\n getEmptyCellNode,\n TablePluginOptions,\n ELEMENT_TABLE,\n ELEMENT_TD,\n ELEMENT_TH,\n} from '@udecode/plate-table';\n\nconst addColumn = (\n editor: PlateEditor,\n { header }: TablePluginOptions,\n getNextCellPath: (currentCellPath: Path) => Path\n) => {\n if (\n someNode(editor, {\n match: { type: getPlatePluginType(editor, ELEMENT_TABLE) },\n })\n ) {\n const currentCellItem = getAbove(editor, {\n match: {\n type: [getPlatePluginType(editor, ELEMENT_TD), getPlatePluginType(editor, ELEMENT_TH)],\n },\n });\n\n const currentTableItem = getAbove(editor, {\n match: { type: getPlatePluginType(editor, ELEMENT_TABLE) },\n });\n\n if (currentCellItem && currentTableItem) {\n const nextCellPath = getNextCellPath(currentCellItem[1]);\n const newCellPath = nextCellPath.slice();\n const replacePathPos = newCellPath.length - 2;\n\n currentTableItem[0].children.forEach((_, rowIdx) => {\n newCellPath[replacePathPos] = rowIdx;\n\n insertNodes<TElement>(\n editor,\n // @ts-expect-error\n getEmptyCellNode(editor, { header: header && rowIdx === 0 }),\n {\n at: newCellPath,\n // Select the first cell of the new column\n select: rowIdx === 0,\n }\n );\n });\n }\n }\n};\n\nexport const addColumnRight = (editor: PlateEditor, options: TablePluginOptions) => {\n addColumn(editor, options, (currentCellPath) => Path.next(currentCellPath));\n};\n\nexport const addColumnLeft = (editor: PlateEditor, options: TablePluginOptions) => {\n addColumn(editor, options, (currentCellPath) => currentCellPath);\n};\n","import React from 'react';\nimport { css } from 'emotion';\nimport * as Slate from 'slate-react';\nimport { PlateEditor } from '@udecode/plate-core';\nimport { getAbove } from '@udecode/plate-common';\nimport { TablePluginOptions, deleteColumn, deleteRow, deleteTable } from '@udecode/plate-table';\nimport { IconButton, Menu } from '@contentful/f36-components';\nimport { ChevronDownIcon } from '@contentful/f36-icons';\nimport { BLOCKS } from '@contentful/rich-text-types';\n\nimport { isTableHeaderEnabled } from './helpers';\nimport { useContentfulEditor } from '../../ContentfulEditorProvider';\nimport { getNodeEntryFromSelection, getTableSize } from '../../helpers/editor';\nimport { RichTextTrackingActionName, useTrackingContext } from '../../TrackingProvider';\nimport { addRowAbove, addColumnLeft, addColumnRight, addRowBelow, setHeader } from './actions';\n\nexport const styles = {\n topRight: css({\n position: 'absolute',\n top: '6px',\n right: '5px',\n }),\n};\n\nconst getCurrentTableSize = (\n editor: PlateEditor\n): Record<'numRows' | 'numColumns', number> | null => {\n const [table] = getNodeEntryFromSelection(editor, BLOCKS.TABLE);\n return table ? getTableSize(table) : null;\n};\n\ntype TableAction = (editor: PlateEditor, options: TablePluginOptions) => void;\n\nexport const TableActions = () => {\n const editor = useContentfulEditor();\n const { onViewportAction } = useTrackingContext();\n const [isOpen, setOpen] = React.useState(false);\n const [isHeaderEnabled, setHeaderEnabled] = React.useState(false);\n\n const close = React.useCallback(() => {\n setOpen(false);\n\n if (!editor) return;\n\n // Makes sure we keep the editor in focus when clicking on/out\n // the dropdown menu\n Slate.ReactEditor.focus(editor);\n }, [editor]);\n\n React.useEffect(() => {\n setHeaderEnabled(Boolean(editor && isTableHeaderEnabled(editor)));\n }, [editor]);\n\n const canInsertRowAbove = React.useMemo(() => {\n if (!editor) {\n return false;\n }\n\n const headerCell = getAbove(editor, {\n match: {\n type: BLOCKS.TABLE_HEADER_CELL,\n },\n });\n\n return !headerCell;\n }, [editor]);\n\n const toggleHeader = React.useCallback(() => {\n close();\n\n if (!editor) {\n return;\n }\n\n const value = !isHeaderEnabled;\n\n setHeaderEnabled(value);\n setHeader(editor, value);\n }, [editor, close, isHeaderEnabled]);\n\n const action = React.useCallback(\n (cb: TableAction, type: 'insert' | 'remove', element: 'Table' | 'Row' | 'Column') => () => {\n if (!editor?.selection) return;\n close();\n\n const tableSize = getCurrentTableSize(editor);\n\n cb(editor, { header: isHeaderEnabled });\n\n // Tracking\n const actionName = `${type}Table${element === 'Table' ? '' : element}`;\n onViewportAction(actionName as RichTextTrackingActionName, { tableSize });\n },\n [editor, isHeaderEnabled, close, onViewportAction]\n );\n\n return (\n <Menu\n placement=\"left\"\n isOpen={isOpen}\n onOpen={() => {\n setOpen(true);\n }}\n onClose={close}>\n <Menu.Trigger>\n <IconButton\n size=\"small\"\n variant=\"transparent\"\n tabIndex={-1}\n className={styles.topRight}\n icon={<ChevronDownIcon />}\n aria-label=\"Open table menu\"\n testId=\"cf-table-actions-button\"\n />\n </Menu.Trigger>\n <Menu.List>\n <Menu.Item onClick={action(addRowAbove, 'insert', 'Row')} disabled={!canInsertRowAbove}>\n Add row above\n </Menu.Item>\n <Menu.Item onClick={action(addRowBelow, 'insert', 'Row')}>Add row below</Menu.Item>\n <Menu.Item onClick={action(addColumnLeft, 'insert', 'Column')}>Add column left</Menu.Item>\n <Menu.Item onClick={action(addColumnRight, 'insert', 'Column')}>Add column right</Menu.Item>\n <Menu.Divider />\n <Menu.Item onClick={toggleHeader}>\n {isHeaderEnabled ? 'Disable table header' : 'Enable table header'}\n </Menu.Item>\n <Menu.Divider />\n <Menu.Item onClick={action(deleteRow, 'remove', 'Row')}>Delete row</Menu.Item>\n <Menu.Item onClick={action(deleteColumn, 'remove', 'Column')}>Delete column</Menu.Item>\n <Menu.Item onClick={action(deleteTable, 'remove', 'Table')}>Delete table</Menu.Item>\n </Menu.List>\n </Menu>\n );\n};\n","import { PlateEditor } from '@udecode/plate-core';\nimport { getAbove, setNodes, getChildren } from '@udecode/plate-common';\nimport { BLOCKS } from '@contentful/rich-text-types';\n\nexport const setHeader = (editor: PlateEditor, enable?: boolean) => {\n const tableItem = getAbove(editor, {\n match: { type: BLOCKS.TABLE },\n });\n\n if (!tableItem) {\n return;\n }\n\n const firstRow = getChildren(tableItem)[0];\n\n if (!firstRow) {\n return;\n }\n\n getChildren(firstRow).forEach(([, path]) => {\n setNodes(\n editor,\n {\n type: enable ? BLOCKS.TABLE_HEADER_CELL : BLOCKS.TABLE_CELL,\n },\n { at: path }\n );\n });\n};\n","import { NodeEntry, Element } from 'slate';\nimport { PlateEditor } from '@udecode/plate-core';\n\nimport { CustomElement } from '../types';\n\nexport type Normalizer = (editor: PlateEditor, entry: NodeEntry<CustomElement>) => true | undefined;\n\n/**\n * Injects a custom element normalization handler.\n *\n * Handlers must explicity return \"true\" to indicate a pass.\n * A pass is when a handler didn't encounter any normalization\n * paths (i.e. all nodes were valid)\n *\n * Important read:\n * https://docs.slatejs.org/concepts/11-normalizing#multi-pass-normalizing\n */\nexport const withNormalizer = (editor: PlateEditor, handler: Normalizer) => {\n const { normalizeNode } = editor;\n\n editor.normalizeNode = (entry) => {\n const [node] = entry;\n\n let passed = false;\n\n if (Element.isElement(node)) {\n passed = handler(editor, entry as NodeEntry<CustomElement>) === true;\n }\n\n if (passed) {\n normalizeNode(entry);\n }\n };\n};\n","import { PlateEditor } from '@udecode/plate-core';\nimport { Element, Node, Transforms } from 'slate';\nimport { BLOCKS, CONTAINERS } from '@contentful/rich-text-types';\n\nimport { CustomElement } from '../../types';\nimport { replaceNode, extractParagraphsAt } from '../../helpers/editor';\nimport { Normalizer, withNormalizer } from '../../helpers/normalizers';\n\nconst isTable = (node: CustomElement) => {\n return node.type === BLOCKS.TABLE;\n};\n\nconst isTableCell = (node: CustomElement) => {\n return node.type === BLOCKS.TABLE_CELL || node.type === BLOCKS.TABLE_HEADER_CELL;\n};\n\n/**\n * Normalizes TABLE_CELL & TABLE_HEADER_CELL nodes\n */\nconst normalizeTableCell: Normalizer = (editor, entry) => {\n const [node, path] = entry;\n\n if (!isTableCell(node)) {\n return true;\n }\n\n for (const [child, childPath] of Node.children(editor, path)) {\n if (!Element.isElement(child)) {\n continue;\n }\n\n const isValidTableCellItem = CONTAINERS[node.type].includes(child.type);\n\n if (!isValidTableCellItem) {\n const text = extractParagraphsAt(editor, childPath);\n replaceNode(editor, childPath, text);\n return;\n }\n }\n\n return true;\n};\n\n/**\n * Normalizes TABLE nodes\n */\nconst normalizeTable: Normalizer = (editor, entry) => {\n const [node, path] = entry;\n\n if (!isTable(node)) {\n return true;\n }\n\n // All direct children must be of type TABLE_ROW\n for (const [child, childPath] of Node.children(editor, path)) {\n if (!Element.isElement(child)) {\n continue;\n }\n\n const isValidTableChild = CONTAINERS[BLOCKS.TABLE].includes(child.type as BLOCKS);\n\n if (!isValidTableChild) {\n Transforms.removeNodes(editor, { at: childPath });\n return;\n }\n }\n\n return true;\n};\n\nexport const addTableNormalizers = (editor: PlateEditor) => {\n withNormalizer(editor, normalizeTable);\n withNormalizer(editor, normalizeTableCell);\n};\n","import { css } from 'emotion';\nimport * as React from 'react';\nimport * as Slate from 'slate-react';\nimport tokens from '@contentful/f36-tokens';\nimport { TableIcon } from '@contentful/f36-icons';\nimport { ToolbarButton } from '../shared/ToolbarButton';\nimport { BLOCKS, TableCell, TableHeaderCell } from '@contentful/rich-text-types';\nimport { PlateEditor } from '@udecode/plate-core';\nimport {\n createTablePlugin as createTablePluginFromUdecode,\n ELEMENT_TABLE,\n ELEMENT_TD,\n ELEMENT_TH,\n ELEMENT_TR,\n getTableOnKeyDown,\n} from '@udecode/plate-table';\nimport { TableActions } from './TableActions';\nimport { useContentfulEditor } from '../../ContentfulEditorProvider';\nimport { CustomElement, CustomSlatePluginOptions } from '../../types';\nimport { insertTableAndFocusFirstCell, isTableActive } from './helpers';\nimport { TrackingProvider, useTrackingContext } from '../../TrackingProvider';\nimport { Transforms } from 'slate';\nimport {\n currentSelectionPrecedesTableCell,\n currentSelectionStartsTableCell,\n} from '../../helpers/editor';\nimport { addTableNormalizers } from './normalizers';\n\nconst styles = {\n [BLOCKS.TABLE]: css`\n margin-bottom: 1.5em;\n border-collapse: collapse;\n border-radius: 5px;\n border-style: hidden;\n box-shadow: 0 0 0 1px ${tokens.gray400};\n width: 100%;\n table-layout: fixed;\n overflow: hidden;\n `,\n [BLOCKS.TABLE_ROW]: css`\n border: 1px solid ${tokens.gray400};\n\n &:hover td {\n background-color: transparent !important;\n }\n `,\n [BLOCKS.TABLE_HEADER_CELL]: css`\n background-color: ${tokens.gray200};\n border: 1px solid ${tokens.gray400};\n padding: 10px 12px;\n font-weight: ${tokens.fontWeightMedium};\n text-align: left;\n min-width: 48px;\n position: relative;\n\n div:last-child {\n margin-bottom: 0;\n }\n `,\n [BLOCKS.TABLE_CELL]: css`\n border: 1px solid ${tokens.gray400};\n padding: 10px 12px;\n min-width: 48px;\n position: relative;\n\n div:last-child {\n margin-bottom: 0;\n }\n `,\n};\n\nexport const Table = (props: Slate.RenderElementProps) => (\n <table {...props.attributes} className={styles[BLOCKS.TABLE]}>\n <tbody>{props.children}</tbody>\n </table>\n);\n\nexport const TR = (props: Slate.RenderElementProps) => (\n <tr {...props.attributes} className={styles[BLOCKS.TABLE_ROW]}>\n {props.children}\n </tr>\n);\n\nexport const TH = (props: Slate.RenderElementProps) => {\n const isSelected = Slate.useSelected();\n\n return (\n <th\n {...props.attributes}\n // may include `colspan` and/or `rowspan`\n {...(props.element.data as TableHeaderCell['data'])}\n className={styles[BLOCKS.TABLE_HEADER_CELL]}>\n {isSelected && <TableActions />}\n {props.children}\n </th>\n );\n};\nexport const TD = (props: Slate.RenderElementProps) => {\n const isSelected = Slate.useSelected();\n\n return (\n <td\n {...props.attributes}\n // may include `colspan` and/or `rowspan`\n {...(props.element.data as TableCell['data'])}\n className={styles[BLOCKS.TABLE_CELL]}>\n {isSelected && <TableActions />}\n {props.children}\n </td>\n );\n};\n\nexport const withTableOptions: CustomSlatePluginOptions = {\n [ELEMENT_TABLE]: {\n type: BLOCKS.TABLE,\n component: Table,\n },\n [ELEMENT_TR]: {\n type: BLOCKS.TABLE_ROW,\n component: TR,\n },\n [ELEMENT_TH]: {\n type: BLOCKS.TABLE_HEADER_CELL,\n component: TH,\n },\n [ELEMENT_TD]: {\n type: BLOCKS.TABLE_CELL,\n component: TD,\n },\n};\n\nfunction addTableTrackingEvents(editor: PlateEditor, { onViewportAction }: TrackingProvider) {\n const { insertData } = editor;\n editor.insertData = (data: DataTransfer) => {\n const html = data.getData('text/html');\n\n if (html) {\n const { children: markupBefore } = editor;\n insertData(data);\n const { children: markupAfter } = editor;\n setTimeout(() => {\n if (hasTables(markupBefore)) return;\n if (hasTables(markupAfter)) {\n onViewportAction('paste', {\n tablePasted: true,\n hasHeadersOutsideFirstRow: hasHeadersOutsideFirstRow(markupAfter),\n });\n }\n }, 1);\n } else {\n insertData(data);\n }\n };\n}\n\nfunction hasTables(nodes: CustomElement[]) {\n return nodes.some(({ type }) => {\n return type === BLOCKS.TABLE;\n });\n}\n\nconst isTableHeaderCell = ({ type }) => type === BLOCKS.TABLE_HEADER_CELL;\n\nfunction hasHeadersOutsideFirstRow(nodes: CustomElement[]) {\n return nodes\n .filter(({ type }) => type === BLOCKS.TABLE)\n .flatMap(({ children }) => children.slice(1) as CustomElement[])\n .some(({ children }) => (children as CustomElement[]).some(isTableHeaderCell));\n}\n\nfunction createTableOnKeyDown() {\n return function withTableEvents(editor: PlateEditor) {\n const handleKeyDownFromPlateUdecode = getTableOnKeyDown()(editor);\n return function handleKeyDown(event: React.KeyboardEvent) {\n if (\n (event.key === 'Backspace' && currentSelectionStartsTableCell(editor)) ||\n (event.key === 'Delete' && currentSelectionPrecedesTableCell(editor))\n ) {\n // The default behavior here would be to delete the preceding or forthcoming\n // leaf node, in this case a cell or header cell. But we don't want to do that,\n // because it would leave us with a non-standard number of table cells.\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n handleKeyDownFromPlateUdecode(event);\n };\n };\n}\n\nexport const createTablePlugin = (tracking: TrackingProvider) => ({\n ...createTablePluginFromUdecode(),\n onKeyDown: createTableOnKeyDown(),\n withOverrides: (editor) => {\n addTableTrackingEvents(editor, tracking);\n addTableNormalizers(editor);\n\n const { insertFragment } = editor;\n\n editor.insertFragment = (fragments) => {\n // We need to make sure we have a new, empty and clean paragraph in order to paste tables as-is due to how Slate behaves\n // More info: https://github.com/ianstormtaylor/slate/pull/4489 and https://github.com/ianstormtaylor/slate/issues/4542\n const fragmentHasTable = fragments.some((fragment) => fragment.type === BLOCKS.TABLE);\n if (fragmentHasTable) {\n const emptyParagraph: CustomElement = {\n type: BLOCKS.PARAGRAPH,\n children: [{ text: '' }],\n data: {},\n isVoid: false,\n };\n Transforms.insertNodes(editor, emptyParagraph);\n }\n\n insertFragment(fragments);\n };\n\n return editor;\n },\n});\n\ninterface ToolbarTableButtonProps {\n isDisabled: boolean | undefined;\n}\n\nexport function ToolbarTableButton(props: ToolbarTableButtonProps) {\n const editor = useContentfulEditor();\n const { onViewportAction } = useTrackingContext();\n const isActive = editor && isTableActive(editor);\n\n async function handleClick() {\n if (!editor) return;\n\n onViewportAction('insertTable');\n insertTableAndFocusFirstCell(editor);\n Slate.ReactEditor.focus(editor);\n }\n\n if (!editor) return null;\n\n return (\n <ToolbarButton\n title=\"Table\"\n testId=\"table-toolbar-button\"\n onClick={handleClick}\n // TODO: active state looks off since the button will be disabled. Do we still need it?\n isActive={isActive}\n isDisabled={props.isDisabled}>\n <TableIcon />\n </ToolbarButton>\n );\n}\n","import * as React from 'react';\nimport { Button, Menu } from '@contentful/f36-components';\n\nimport { PlusIcon, ChevronDownIcon } from '@contentful/f36-icons';\n\ninterface EmbeddedEntityDropdownButtonProps {\n children: React.ReactNode;\n isDisabled: boolean | undefined;\n isOpen: boolean;\n onClose: () => void;\n onToggle: () => void;\n}\n\nexport function EmbeddedEntityDropdownButton({\n children,\n isDisabled,\n isOpen,\n onClose,\n onToggle,\n}: EmbeddedEntityDropdownButtonProps) {\n return (\n <Menu placement=\"bottom-end\" isOpen={isOpen} onClose={onClose} onOpen={onToggle}>\n <Menu.Trigger>\n <Button\n endIcon={<ChevronDownIcon />}\n testId=\"toolbar-entity-dropdown-toggle\"\n variant=\"secondary\"\n size=\"small\"\n startIcon={<PlusIcon />}\n isDisabled={isDisabled}>\n Embed\n </Button>\n </Menu.Trigger>\n <Menu.List className=\"toolbar-entity-dropdown-list\">{children}</Menu.List>\n </Menu>\n );\n}\n","// \"modern\" Edge was released at 79.x\nconst IS_EDGE_LEGACY =\n typeof navigator !== 'undefined' && /Edge?\\/(?:[0-6][0-9]|[0-7][0-8])/i.test(navigator.userAgent);\n\n// Native `beforeInput` events don't work well with react on Chrome 75\n// and older, Chrome 76+ can use `beforeInput` though.\nconst IS_CHROME_LEGACY =\n typeof navigator !== 'undefined' &&\n /Chrome?\\/(?:[0-7][0-5]|[0-6][0-9])/i.test(navigator.userAgent);\n\ntype CustomInputEvent = {\n getTargetRanges?: (() => StaticRange[]) | undefined;\n} & InputEvent;\n\n// COMPAT: Firefox/Edge Legacy don't support the `beforeinput` event\n// Chrome Legacy doesn't support `beforeinput` correctly\nexport const HAS_BEFORE_INPUT_SUPPORT =\n !IS_CHROME_LEGACY &&\n !IS_EDGE_LEGACY &&\n // globalThis is undefined in older browsers\n typeof globalThis !== 'undefined' &&\n globalThis.InputEvent &&\n typeof (globalThis.InputEvent.prototype as CustomInputEvent).getTargetRanges === 'function'; // The `getTargetRanges` property isn't recognized.\n","import React from 'react';\nimport { css } from 'emotion';\nimport { FetchingWrappedEntryCard } from '../shared/FetchingWrappedEntryCard';\nimport { FetchingWrappedAssetCard } from '../shared/FetchingWrappedAssetCard';\nimport { useSdkContext } from '../../SdkProvider';\nimport { CustomRenderElementProps } from '../../types';\nimport { ReactEditor, useSelected, useReadOnly } from 'slate-react';\nimport { Transforms } from 'slate';\nimport { useContentfulEditor } from '../../ContentfulEditorProvider';\nimport { HAS_BEFORE_INPUT_SUPPORT } from '../../helpers/environment';\n\nconst styles = {\n root: css({\n marginBottom: '1.25rem',\n }),\n};\n\ntype LinkedEntityBlockProps = CustomRenderElementProps<{\n target: {\n sys: {\n id: string;\n linkType: 'Entry' | 'Asset';\n type: 'Link';\n };\n };\n}>;\n\nexport function LinkedEntityBlock(props: LinkedEntityBlockProps) {\n const { attributes, children, element } = props;\n const isSelected = useSelected();\n const editor = useContentfulEditor();\n const sdk = useSdkContext();\n const isDisabled = useReadOnly();\n const { id: entityId, linkType: entityType } = element.data.target.sys;\n\n const handleEditClick = () => {\n const openEntity = entityType === 'Asset' ? sdk.navigator.openAsset : sdk.navigator.openEntry;\n return openEntity(entityId, { slideIn: true });\n };\n\n const handleRemoveClick = () => {\n if (!editor) return;\n const pathToElement = ReactEditor.findPath(editor, element);\n Transforms.removeNodes(editor, { at: pathToElement });\n };\n\n return (\n <div\n {...attributes}\n className={styles.root}\n data-entity-type={entityType}\n data-entity-id={entityId}\n // COMPAT: This makes copy & paste work for Firefox\n contentEditable={!HAS_BEFORE_INPUT_SUPPORT ? false : undefined}\n draggable={!HAS_BEFORE_INPUT_SUPPORT ? true : undefined}>\n <div\n // COMPAT: This makes copy & paste work for Chromium/Blink browsers and Safari\n contentEditable={HAS_BEFORE_INPUT_SUPPORT ? false : undefined}\n draggable={HAS_BEFORE_INPUT_SUPPORT ? true : undefined}>\n {entityType === 'Entry' && (\n <FetchingWrappedEntryCard\n sdk={sdk}\n entryId={entityId}\n locale={sdk.field.locale}\n isDisabled={isDisabled}\n isSelected={isSelected}\n onRemove={handleRemoveClick}\n onEdit={handleEditClick}\n />\n )}\n {entityType === 'Asset' && (\n <FetchingWrappedAssetCard\n sdk={sdk}\n assetId={entityId}\n locale={sdk.field.locale}\n isDisabled={isDisabled}\n isSelected={isSelected}\n onRemove={handleRemoveClick}\n onEdit={handleEditClick}\n />\n )}\n </div>\n {children}\n </div>\n );\n}\n","import getLinkedContentTypeIdsForNodeType from './getLinkedContentTypeIdsForNodeType';\n\n/**\n * Returns a config for the entity selector based on a given rich text field and a\n * rich text node type that the entity should be picked for. Takes the field\n * validations for the given node type into account.\n *\n * @param {object} field\n * @param {string} nodeType\n * @returns {object}\n */\nexport default function newEntitySelectorConfigFromRichTextField(field, nodeType) {\n return {\n entityType: getEntityTypeFromRichTextNode(nodeType),\n locale: field.locale || null, // Will fall back to default locale.\n contentTypes: getLinkedContentTypeIdsForNodeType(field, nodeType),\n };\n}\n\nfunction getEntityTypeFromRichTextNode(nodeType): 'Entry' | 'Asset' | never {\n const words = nodeType.split('-');\n if (words.indexOf('entry') !== -1) {\n return 'Entry';\n }\n if (words.indexOf('asset') !== -1) {\n return 'Asset';\n }\n throw new Error(`RichText node type \\`${nodeType}\\` has no associated \\`entityType\\``);\n}\n","import { getText } from '@udecode/plate-common';\nimport { Transforms } from 'slate';\nimport * as Slate from 'slate-react';\nimport newEntitySelectorConfigFromRichTextField from '../../helpers/newEntitySelectorConfigFromRichTextField';\n\nexport async function selectEntityAndInsert(nodeType, sdk, editor, logAction) {\n logAction('openCreateEmbedDialog', { nodeType });\n\n const { field, dialogs } = sdk;\n const baseConfig = newEntitySelectorConfigFromRichTextField(field, nodeType);\n const selectEntity =\n baseConfig.entityType === 'Asset' ? dialogs.selectSingleAsset : dialogs.selectSingleEntry;\n const config = { ...baseConfig, withCreate: true };\n try {\n const { selection } = editor;\n const entity = await selectEntity(config);\n if (!entity) {\n return;\n }\n Transforms.select(editor, selection);\n insertBlock(editor, nodeType, entity);\n logAction('insert', { nodeType });\n } catch (error) {\n if (error) {\n throw error;\n } else {\n logAction('cancelCreateEmbedDialog', { nodeType });\n }\n }\n}\n\nconst createNode = (nodeType, entity) => ({\n type: nodeType,\n data: {\n target: {\n sys: {\n id: entity.sys.id,\n type: 'Link',\n linkType: entity.sys.type,\n },\n },\n },\n children: [{ text: '' }],\n isVoid: true,\n});\n\n// TODO: DRY up copied code from HR\nexport function insertBlock(editor, nodeType, entity) {\n if (!editor?.selection) return;\n\n const linkedEntityBlock = createNode(nodeType, entity);\n\n const hasText = editor.selection && !!getText(editor, editor.selection.focus.path);\n\n if (hasText) {\n Transforms.insertNodes(editor, linkedEntityBlock);\n } else {\n Transforms.setNodes(editor, linkedEntityBlock);\n }\n\n Slate.ReactEditor.focus(editor);\n}\n","import React from 'react';\nimport { Flex, Icon, Button, Menu } from '@contentful/f36-components';\n\nimport { AssetIcon, EmbeddedEntryBlockIcon } from '@contentful/f36-icons';\nimport { selectEntityAndInsert } from './Util';\nimport noop from 'lodash/noop';\nimport { FieldExtensionSDK } from '@contentful/app-sdk';\nimport { useSdkContext } from '../../SdkProvider';\nimport { css } from 'emotion';\nimport { useContentfulEditor } from '../../ContentfulEditorProvider';\n\nexport const styles = {\n icon: css({\n marginRight: '10px',\n }),\n};\n\ninterface EmbeddedEntityBlockToolbarIconProps {\n isButton?: boolean;\n isDisabled: boolean;\n logAction?: () => void;\n nodeType: string;\n onClose: () => void;\n}\n\nexport function EmbeddedEntityBlockToolbarIcon({\n isButton,\n isDisabled,\n logAction,\n nodeType,\n onClose,\n}: EmbeddedEntityBlockToolbarIconProps) {\n const editor = useContentfulEditor();\n const sdk: FieldExtensionSDK = useSdkContext();\n\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n\n onClose();\n selectEntityAndInsert(nodeType, sdk, editor, logAction || noop);\n };\n\n const type = getEntityTypeFromNodeType(nodeType);\n const baseClass = `rich-text__${nodeType}`;\n return isButton ? (\n <Button\n isDisabled={isDisabled}\n className={`${baseClass}-button`}\n size=\"small\"\n onClick={handleClick}\n startIcon={type === 'Asset' ? <AssetIcon /> : <EmbeddedEntryBlockIcon />}\n variant=\"secondary\"\n testId={`toolbar-toggle-${nodeType}`}>\n {`Embed ${type.toLowerCase()}`}\n </Button>\n ) : (\n <Menu.Item\n disabled={isDisabled}\n className={`${baseClass}-list-item`}\n onClick={handleClick}\n testId={`toolbar-toggle-${nodeType}`}>\n <Flex alignItems=\"center\" flexDirection=\"row\">\n <Icon\n as={type === 'Asset' ? AssetIcon : EmbeddedEntryBlockIcon}\n className={`rich-text__embedded-entry-list-icon ${styles.icon}`}\n variant=\"secondary\"\n />\n <span>{type}</span>\n </Flex>\n </Menu.Item>\n );\n}\n\nfunction getEntityTypeFromNodeType(nodeType: string): string | never {\n const words = nodeType.toLowerCase().split('-');\n if (words.includes('entry')) {\n return 'Entry';\n }\n if (words.includes('asset')) {\n return 'Asset';\n }\n throw new Error(`Node type \\`${nodeType}\\` has no associated \\`entityType\\``);\n}\n","import { KeyboardEvent } from 'react';\nimport { BLOCKS } from '@contentful/rich-text-types';\nimport {\n getRenderElement,\n getPlatePluginTypes,\n PlatePlugin,\n getPlatePluginOptions,\n PlateEditor,\n} from '@udecode/plate-core';\nimport { Transforms } from 'slate';\nimport { getNodeEntryFromSelection } from '../../helpers/editor';\nimport { CustomSlatePluginOptions } from 'types';\nimport { LinkedEntityBlock } from './LinkedEntityBlock';\nimport { selectEntityAndInsert } from './Util';\nimport { FieldExtensionSDK } from '@contentful/app-sdk';\nimport noop from 'lodash/noop';\n\nexport { EmbeddedEntityBlockToolbarIcon as ToolbarIcon } from './ToolbarIcon';\n\nconst createEmbeddedEntityPlugin =\n (nodeType: BLOCKS.EMBEDDED_ENTRY | BLOCKS.EMBEDDED_ASSET) =>\n (sdk: FieldExtensionSDK): PlatePlugin => ({\n renderElement: getRenderElement(nodeType),\n pluginKeys: nodeType,\n onKeyDown: getWithEmbeddedEntityEvents(nodeType, sdk),\n voidTypes: getPlatePluginTypes(nodeType),\n deserialize: (editor) => {\n const options = getPlatePluginOptions(editor, nodeType);\n const entityTypes = {\n [BLOCKS.EMBEDDED_ENTRY]: 'Entry',\n [BLOCKS.EMBEDDED_ASSET]: 'Asset',\n };\n\n return {\n element: [\n {\n type: nodeType,\n deserialize: (element) => {\n const entityType = element.getAttribute('data-entity-type');\n const embeddedEntityId = element.getAttribute('data-entity-id');\n const isBlock = entityType === entityTypes[nodeType];\n\n if (!isBlock) return;\n\n return {\n type: nodeType,\n isVoid: true,\n data: {\n target: {\n sys: {\n id: embeddedEntityId,\n linkType: entityType,\n type: 'Link',\n },\n },\n },\n };\n },\n ...options.deserialize,\n },\n ],\n };\n },\n });\n\nexport const createEmbeddedEntryBlockPlugin = createEmbeddedEntityPlugin(BLOCKS.EMBEDDED_ENTRY);\nexport const createEmbeddedAssetBlockPlugin = createEmbeddedEntityPlugin(BLOCKS.EMBEDDED_ASSET);\n\nexport const withEmbeddedEntryBlockOptions: CustomSlatePluginOptions = {\n [BLOCKS.EMBEDDED_ENTRY]: {\n type: BLOCKS.EMBEDDED_ENTRY,\n component: LinkedEntityBlock,\n },\n};\nexport const withEmbeddedAssetBlockOptions: CustomSlatePluginOptions = {\n [BLOCKS.EMBEDDED_ASSET]: {\n type: BLOCKS.EMBEDDED_ASSET,\n component: LinkedEntityBlock,\n },\n};\n\ntype A = 65;\ntype E = 69;\ntype AEvent = KeyboardEvent & { keyCode: A };\ntype EEvent = KeyboardEvent & { keyCode: E };\ntype ShiftEvent = KeyboardEvent & { shiftKey: true };\ntype CtrlEvent = KeyboardEvent & { ctrlKey: true };\ntype MetaEvent = KeyboardEvent & { metaKey: true };\ntype ModEvent = CtrlEvent | MetaEvent;\ntype EmbeddedAssetEvent = ModEvent & ShiftEvent & AEvent;\ntype EmbeddedEntryEvent = ModEvent & ShiftEvent & EEvent;\n\nconst isA = (event: KeyboardEvent): event is AEvent => event.keyCode === 65;\nconst isE = (event: KeyboardEvent): event is EEvent => event.keyCode === 69;\nconst isMod = (event: KeyboardEvent): event is ModEvent => event.ctrlKey || event.metaKey;\nconst isShift = (event: KeyboardEvent): event is ShiftEvent => event.shiftKey;\nconst wasEmbeddedAssetEventTriggered = (event: KeyboardEvent): event is EmbeddedAssetEvent =>\n isMod(event) && isShift(event) && isA(event);\nconst wasEmbeddedEntryEventTriggered = (event: KeyboardEvent): event is EmbeddedEntryEvent =>\n isMod(event) && isShift(event) && isE(event);\n\nexport function getWithEmbeddedEntityEvents(\n nodeType: BLOCKS.EMBEDDED_ENTRY | BLOCKS.EMBEDDED_ASSET,\n sdk: FieldExtensionSDK\n) {\n return function withEmbeddedEntityEvents(editor: PlateEditor) {\n // TODO: Dry up copied code from HR\n return function handleEvent(event: KeyboardEvent) {\n if (!editor) return;\n\n const [, pathToSelectedElement] = getNodeEntryFromSelection(editor, nodeType);\n\n if (pathToSelectedElement) {\n const isDelete = event.key === 'Delete';\n const isBackspace = event.key === 'Backspace';\n\n if (isDelete || isBackspace) {\n event.preventDefault();\n Transforms.removeNodes(editor, { at: pathToSelectedElement });\n }\n } else if (\n (nodeType === BLOCKS.EMBEDDED_ENTRY && wasEmbeddedEntryEventTriggered(event)) ||\n (nodeType === BLOCKS.EMBEDDED_ASSET && wasEmbeddedAssetEventTriggered(event))\n ) {\n selectEntityAndInsert(nodeType, sdk, editor, noop);\n }\n };\n };\n}\n","import React from 'react';\nimport { css } from 'emotion';\nimport tokens from '@contentful/f36-tokens';\nimport { InlineEntryCard, MenuItem } from '@contentful/f36-components';\nimport { ClockIcon } from '@contentful/f36-icons';\nimport { entityHelpers, FieldExtensionSDK } from '@contentful/field-editor-shared';\nimport { useEntities, ScheduledIconWithTooltip } from '@contentful/field-editor-reference';\nimport { INLINES } from '@contentful/rich-text-types';\n\nconst { getEntryTitle, getEntryStatus } = entityHelpers;\n\nconst styles = {\n scheduledIcon: css({\n verticalAlign: 'text-bottom',\n marginRight: tokens.spacing2Xs,\n }),\n};\n\ninterface FetchingWrappedInlineEntryCardProps {\n entryId: string;\n sdk: FieldExtensionSDK;\n isSelected: boolean;\n isDisabled: boolean;\n onEdit: (event: React.MouseEvent<Element, MouseEvent>) => void;\n onRemove: (event: React.MouseEvent<Element, MouseEvent>) => void;\n}\n\nexport function FetchingWrappedInlineEntryCard(props: FetchingWrappedInlineEntryCardProps) {\n const { getOrLoadEntry, loadEntityScheduledActions, entries } = useEntities();\n const entry = React.useMemo(() => entries[props.entryId], [entries, props.entryId]);\n\n const allContentTypes = props.sdk.space.getCachedContentTypes();\n const contentType = React.useMemo(() => {\n if (!entry || entry === 'failed' || !allContentTypes) return undefined;\n\n return allContentTypes.find(\n (contentType) => contentType.sys.id === entry.sys.contentType.sys.id\n );\n }, [allContentTypes, entry]);\n\n const contentTypeName = contentType ? contentType.name : '';\n\n const title = React.useMemo(\n () =>\n getEntryTitle({\n entry,\n contentType,\n localeCode: props.sdk.field.locale,\n defaultLocaleCode: props.sdk.locales.default,\n defaultTitle: 'Untitled',\n }),\n [entry, contentType, props.sdk.field.locale, props.sdk.locales.default]\n );\n\n React.useEffect(() => {\n if (!props.entryId) return;\n getOrLoadEntry(props.entryId);\n // We don't include getOrLoadEntry below because it's part of the constate-derived\n // useEntities(), not props.\n // eslint-disable-next-line\n }, [props.entryId]);\n\n if (entry === 'failed') {\n return (\n <InlineEntryCard\n title=\"Entry missing or inaccessible\"\n testId={INLINES.EMBEDDED_ENTRY}\n isSelected={props.isSelected}\n />\n );\n }\n\n if (entry === undefined) {\n return <InlineEntryCard isLoading />;\n }\n\n const status = getEntryStatus(entry.sys);\n if (status === 'deleted') {\n return (\n <InlineEntryCard\n title=\"Entry missing or inaccessible\"\n testId={INLINES.EMBEDDED_ENTRY}\n isSelected={props.isSelected}\n actions={[\n <MenuItem key=\"remove\" onClick={props.onRemove} testId=\"card-action-remove\">\n Remove\n </MenuItem>,\n ]}\n />\n );\n }\n\n return (\n <InlineEntryCard\n testId={INLINES.EMBEDDED_ENTRY}\n isSelected={props.isSelected}\n title={\n (\n <>\n <span>\n {contentTypeName} {title}\n </span>\n <ScheduledIconWithTooltip\n getEntityScheduledActions={loadEntityScheduledActions}\n entityType=\"Entry\"\n entityId={entry.sys.id}>\n <ClockIcon className={styles.scheduledIcon} variant=\"muted\" testId=\"scheduled-icon\" />\n </ScheduledIconWithTooltip>\n </>\n ) as any\n }\n status={status}\n actions={[\n <MenuItem key=\"edit\" onClick={props.onEdit}>\n Edit\n </MenuItem>,\n <MenuItem\n key=\"remove\"\n onClick={props.onRemove}\n disabled={props.isDisabled}\n testId=\"card-action-remove\">\n Remove\n </MenuItem>,\n ]}\n />\n );\n}\n","import { INLINES } from '@contentful/rich-text-types';\n\nexport function createInlineEntryNode(id: string) {\n return {\n type: INLINES.EMBEDDED_ENTRY,\n children: [{ text: '' }],\n data: {\n target: {\n sys: {\n id,\n type: 'Link',\n linkType: 'Entry',\n },\n },\n },\n };\n}\n","import * as React from 'react';\nimport {\n PlatePlugin,\n getRenderElement,\n getPlatePluginTypes,\n getPlatePluginOptions,\n} from '@udecode/plate-core';\nimport { Transforms } from 'slate';\nimport { INLINES } from '@contentful/rich-text-types';\nimport { useSelected, ReactEditor, useReadOnly } from 'slate-react';\nimport { Button, Menu, Flex } from '@contentful/f36-components';\nimport { EmbeddedEntryInlineIcon } from '@contentful/f36-icons';\nimport { css } from 'emotion';\nimport { Link, FieldExtensionSDK } from '@contentful/app-sdk';\nimport { Entry } from '@contentful/field-editor-shared';\nimport { CustomSlatePluginOptions, CustomRenderElementProps } from '../../types';\nimport newEntitySelectorConfigFromRichTextField from '../../helpers/newEntitySelectorConfigFromRichTextField';\nimport { useSdkContext } from '../../SdkProvider';\nimport { FetchingWrappedInlineEntryCard } from './FetchingWrappedInlineEntryCard';\nimport { createInlineEntryNode } from './Util';\nimport { useContentfulEditor } from '../../ContentfulEditorProvider';\nimport { HAS_BEFORE_INPUT_SUPPORT } from '../../helpers/environment';\n\nconst styles = {\n icon: css({\n marginRight: '10px',\n }),\n\n root: css({\n margin: '0 1px',\n fontSize: 'inherit',\n span: {\n webkitUserSelect: 'none',\n mozUserSelect: 'none',\n msUserSelect: 'none',\n userSelect: 'none',\n },\n }),\n};\n\ntype EmbeddedEntityInlineProps = CustomRenderElementProps<{\n target: Link;\n}>;\n\nfunction EmbeddedEntityInline(props: EmbeddedEntityInlineProps) {\n const editor = useContentfulEditor();\n const sdk = useSdkContext();\n const isSelected = useSelected();\n const { id: entryId } = props.element.data.target.sys;\n const isDisabled = useReadOnly();\n\n function handleEditClick() {\n return sdk.navigator.openEntry(entryId, { slideIn: true });\n }\n\n function handleRemoveClick() {\n if (!editor) return;\n const pathToElement = ReactEditor.findPath(editor, props.element);\n Transforms.removeNodes(editor, { at: pathToElement });\n }\n\n return (\n <span\n {...props.attributes}\n className={styles.root}\n data-embedded-entity-inline-id={entryId}\n // COMPAT: This makes copy & paste work for Firefox\n contentEditable={!HAS_BEFORE_INPUT_SUPPORT ? false : undefined}\n draggable={!HAS_BEFORE_INPUT_SUPPORT ? true : undefined}>\n <span\n // COMPAT: This makes copy & paste work for Chromium/Blink browsers and Safari\n contentEditable={HAS_BEFORE_INPUT_SUPPORT ? false : undefined}\n draggable={HAS_BEFORE_INPUT_SUPPORT ? true : undefined}>\n <FetchingWrappedInlineEntryCard\n sdk={sdk}\n entryId={entryId}\n isSelected={isSelected}\n isDisabled={isDisabled}\n onRemove={handleRemoveClick}\n onEdit={handleEditClick}\n />\n </span>\n {props.children}\n </span>\n );\n}\n\ninterface ToolbarEmbeddedEntityInlineButtonProps {\n onClose: () => void;\n isDisabled: boolean;\n isButton?: boolean;\n}\n\nasync function selectEntityAndInsert(editor, sdk: FieldExtensionSDK) {\n const config = {\n ...newEntitySelectorConfigFromRichTextField(sdk.field, INLINES.EMBEDDED_ENTRY),\n withCreate: true,\n };\n const selection = editor.selection;\n\n const entry = await sdk.dialogs.selectSingleEntry<Entry>(config);\n ReactEditor.focus(editor); // Dialog steals focus from editor, return it.\n if (!entry) return;\n\n const inlineEntryNode = createInlineEntryNode(entry.sys.id);\n\n // Got to wait until focus is really back on the editor or setSelection() won't work.\n setTimeout(() => {\n Transforms.setSelection(editor, selection);\n Transforms.insertNodes(editor, inlineEntryNode);\n }, 0);\n}\n\nexport function ToolbarEmbeddedEntityInlineButton(props: ToolbarEmbeddedEntityInlineButtonProps) {\n const editor = useContentfulEditor();\n const sdk: FieldExtensionSDK = useSdkContext();\n\n async function handleClick(event) {\n event.preventDefault();\n\n if (!editor) return;\n\n props.onClose();\n\n await selectEntityAndInsert(editor, sdk);\n }\n\n return props.isButton ? (\n <Button\n isDisabled={props.isDisabled}\n className={`${INLINES.EMBEDDED_ENTRY}-button`}\n size=\"small\"\n onClick={handleClick}\n startIcon={<EmbeddedEntryInlineIcon />}\n variant=\"secondary\"\n testId={`toolbar-toggle-${INLINES.EMBEDDED_ENTRY}`}>\n Embed inline entry\n </Button>\n ) : (\n <Menu.Item\n disabled={props.isDisabled}\n className=\"rich-text__entry-link-block-button\"\n testId={`toolbar-toggle-${INLINES.EMBEDDED_ENTRY}`}\n onClick={handleClick}>\n <Flex alignItems=\"center\" flexDirection=\"row\">\n <EmbeddedEntryInlineIcon\n variant=\"secondary\"\n className={`rich-text__embedded-entry-list-icon ${styles.icon}`}\n />\n <span>Inline entry</span>\n </Flex>\n </Menu.Item>\n );\n}\n\nexport function createEmbeddedEntityInlinePlugin(sdk): PlatePlugin {\n return {\n renderElement: getRenderElement(INLINES.EMBEDDED_ENTRY),\n pluginKeys: INLINES.EMBEDDED_ENTRY,\n inlineTypes: getPlatePluginTypes(INLINES.EMBEDDED_ENTRY),\n voidTypes: getPlatePluginTypes(INLINES.EMBEDDED_ENTRY),\n onKeyDown: getWithEmbeddedEntryInlineEvents(sdk),\n deserialize: (editor) => {\n const options = getPlatePluginOptions(editor, INLINES.EMBEDDED_ENTRY);\n\n return {\n element: [\n {\n type: INLINES.EMBEDDED_ENTRY,\n deserialize: (element) => {\n const entryId = element.getAttribute('data-embedded-entity-inline-id');\n return entryId ? createInlineEntryNode(entryId) : undefined;\n },\n ...options.deserialize,\n },\n ],\n };\n },\n };\n}\n\nexport const withEmbeddedEntityInlineOptions: CustomSlatePluginOptions = {\n [INLINES.EMBEDDED_ENTRY]: {\n type: INLINES.EMBEDDED_ENTRY,\n component: EmbeddedEntityInline,\n },\n};\n\n// TODO: DRY up types from embedded entry block and elsewhere\ntype TWO = 50;\ntype TwoEvent = React.KeyboardEvent & { keyCode: TWO };\ntype ShiftEvent = React.KeyboardEvent & { shiftKey: true };\ntype CtrlEvent = React.KeyboardEvent & { ctrlKey: true };\ntype MetaEvent = React.KeyboardEvent & { metaKey: true };\ntype ModEvent = CtrlEvent | MetaEvent;\ntype EmbeddedEntryInlineEvent = ModEvent & ShiftEvent & TwoEvent;\n\nconst isTwo = (event: React.KeyboardEvent): event is TwoEvent => event.keyCode === 50;\nconst isMod = (event: React.KeyboardEvent): event is ModEvent => event.ctrlKey || event.metaKey;\nconst isShift = (event: React.KeyboardEvent): event is ShiftEvent => event.shiftKey;\nconst wasEmbeddedEntryInlineEventTriggered = (\n event: React.KeyboardEvent\n): event is EmbeddedEntryInlineEvent => isMod(event) && isShift(event) && isTwo(event);\n\nfunction getWithEmbeddedEntryInlineEvents(sdk) {\n return function withEmbeddedEntryInlineEvents(editor) {\n return function handleEvent(event) {\n if (!editor) return;\n\n if (wasEmbeddedEntryInlineEventTriggered(event)) {\n selectEntityAndInsert(editor, sdk);\n }\n };\n };\n}\n","import React, { useState } from 'react';\n\nimport { EmbeddedEntityDropdownButton } from '../plugins/EmbeddedEntity';\nimport { ToolbarIcon as EmbeddedEntityBlockToolbarIcon } from '../plugins/EmbeddedEntityBlock';\nimport { BLOCKS, INLINES } from '@contentful/rich-text-types';\nimport { isNodeTypeEnabled } from '../helpers/validations';\nimport { ToolbarEmbeddedEntityInlineButton } from '../plugins/EmbeddedEntityInline';\nimport { useSdkContext } from '../SdkProvider';\nimport { isLinkActive } from '../helpers/editor';\nimport { useContentfulEditor } from '../ContentfulEditorProvider';\n\nexport interface EmbedEntityWidgetProps {\n isDisabled?: boolean;\n canInsertBlocks?: boolean;\n}\n\nexport const EmbedEntityWidget = ({ isDisabled, canInsertBlocks }: EmbedEntityWidgetProps) => {\n const sdk = useSdkContext();\n const editor = useContentfulEditor();\n\n const [isEmbedDropdownOpen, setEmbedDropdownOpen] = useState(false);\n const onCloseEntityDropdown = () => setEmbedDropdownOpen(false);\n const onToggleEntityDropdown = () => setEmbedDropdownOpen(!isEmbedDropdownOpen);\n\n const [canAccessAssets, setCanAccessAssets] = useState(false);\n React.useEffect(() => {\n sdk.access.can('read', 'Asset').then(setCanAccessAssets);\n }, [sdk]);\n\n const inlineEntryEmbedEnabled = isNodeTypeEnabled(sdk.field, INLINES.EMBEDDED_ENTRY);\n const blockEntryEmbedEnabled =\n isNodeTypeEnabled(sdk.field, BLOCKS.EMBEDDED_ENTRY) && canInsertBlocks;\n const blockAssetEmbedEnabled =\n canAccessAssets && isNodeTypeEnabled(sdk.field, BLOCKS.EMBEDDED_ASSET) && canInsertBlocks;\n\n const numEnabledEmbeds = [\n inlineEntryEmbedEnabled,\n blockEntryEmbedEnabled,\n blockAssetEmbedEnabled,\n ].filter(Boolean).length;\n\n const shouldDisplayDropdown = numEnabledEmbeds > 1;\n\n // Avoids UI glitching when switching back and forth between\n // different layouts\n React.useEffect(() => {\n if (!shouldDisplayDropdown) {\n setEmbedDropdownOpen(false);\n }\n }, [shouldDisplayDropdown]);\n\n const actions = (\n <>\n {blockEntryEmbedEnabled && (\n <EmbeddedEntityBlockToolbarIcon\n isDisabled={!!isDisabled}\n nodeType={BLOCKS.EMBEDDED_ENTRY}\n onClose={onCloseEntityDropdown}\n isButton={!shouldDisplayDropdown}\n />\n )}\n {inlineEntryEmbedEnabled && (\n <ToolbarEmbeddedEntityInlineButton\n isDisabled={!!isDisabled || isLinkActive(editor)}\n onClose={onCloseEntityDropdown}\n isButton={!shouldDisplayDropdown}\n />\n )}\n {blockAssetEmbedEnabled && (\n <EmbeddedEntityBlockToolbarIcon\n isDisabled={!!isDisabled}\n nodeType={BLOCKS.EMBEDDED_ASSET}\n onClose={onCloseEntityDropdown}\n isButton={!shouldDisplayDropdown}\n />\n )}\n </>\n );\n\n if (!shouldDisplayDropdown) {\n return actions;\n }\n\n return (\n <EmbeddedEntityDropdownButton\n isDisabled={isDisabled}\n onClose={onCloseEntityDropdown}\n onToggle={onToggleEntityDropdown}\n isOpen={isEmbedDropdownOpen}>\n {actions}\n </EmbeddedEntityDropdownButton>\n );\n};\n","import React, { Fragment } from 'react';\nimport tokens from '@contentful/f36-tokens';\nimport { css } from 'emotion';\nimport { Flex } from '@contentful/f36-components';\nimport { ToolbarHrButton } from '../plugins/Hr';\nimport { ToolbarHeadingButton } from '../plugins/Heading';\nimport { ToolbarQuoteButton } from '../plugins/Quote';\nimport { ToolbarListButton } from '../plugins/List';\nimport { ToolbarBoldButton } from '../plugins/Bold';\nimport { ToolbarCodeButton } from '../plugins/Code';\nimport { ToolbarItalicButton } from '../plugins/Italic';\nimport { ToolbarUnderlineButton } from '../plugins/Underline';\nimport { ToolbarHyperlinkButton } from '../plugins/Hyperlink';\nimport { ToolbarTableButton } from '../plugins/Table';\nimport { BLOCKS, INLINES, MARKS } from '@contentful/rich-text-types';\nimport { isNodeTypeSelected } from '../helpers/editor';\nimport { isNodeTypeEnabled, isMarkEnabled } from '../helpers/validations';\nimport { useSdkContext } from '../SdkProvider';\nimport { FieldExtensionSDK } from '@contentful/app-sdk';\nimport { EmbedEntityWidget } from './EmbedEntityWidget';\nimport { useContentfulEditor } from '../ContentfulEditorProvider';\n\ntype ToolbarProps = {\n isDisabled?: boolean;\n};\n\nconst styles = {\n toolbar: css({\n border: `1px solid ${tokens.gray400}`,\n backgroundColor: tokens.gray100,\n padding: tokens.spacingXs,\n borderRadius: `${tokens.borderRadiusMedium} ${tokens.borderRadiusMedium} 0 0`,\n }),\n divider: css({\n display: 'inline-block',\n height: '21px',\n width: '1px',\n background: tokens.gray300,\n margin: `0 ${tokens.spacing2Xs}`,\n }),\n embedActionsWrapper: css({\n display: ['-webkit-box', '-ms-flexbox', 'flex'],\n webkitAlignSelf: 'flex-start',\n alignSelf: 'flex-start',\n msFlexItemAlign: 'start',\n marginLeft: 'auto',\n }),\n formattingOptionsWrapper: css({\n display: ['-webkit-box', '-ms-flexbox', 'flex'],\n msFlexAlign: 'center',\n webkitBoxAlign: 'center',\n alignItems: 'center',\n msFlexWrap: 'wrap',\n flexWrap: 'wrap',\n marginRight: '20px',\n }),\n};\n\nconst Toolbar = ({ isDisabled }: ToolbarProps) => {\n const sdk = useSdkContext();\n const editor = useContentfulEditor();\n const canInsertBlocks = !isNodeTypeSelected(editor, BLOCKS.TABLE);\n const validationInfo = React.useMemo(() => getValidationInfo(sdk.field), [sdk.field]);\n const isListSelected =\n isNodeTypeSelected(editor, BLOCKS.UL_LIST) || isNodeTypeSelected(editor, BLOCKS.OL_LIST);\n const isBlockquoteSelected = isNodeTypeSelected(editor, BLOCKS.QUOTE);\n const shouldDisableTables =\n isDisabled || !canInsertBlocks || isListSelected || isBlockquoteSelected;\n\n return (\n <Flex testId=\"toolbar\" className={styles.toolbar} alignItems=\"center\">\n <div className={styles.formattingOptionsWrapper}>\n <ToolbarHeadingButton isDisabled={isDisabled || !canInsertBlocks} />\n\n {validationInfo.isAnyMarkEnabled && <span className={styles.divider} />}\n\n {isMarkEnabled(sdk.field, MARKS.BOLD) && <ToolbarBoldButton isDisabled={isDisabled} />}\n {isMarkEnabled(sdk.field, MARKS.ITALIC) && <ToolbarItalicButton isDisabled={isDisabled} />}\n {isMarkEnabled(sdk.field, MARKS.UNDERLINE) && (\n <ToolbarUnderlineButton isDisabled={isDisabled} />\n )}\n {isMarkEnabled(sdk.field, MARKS.CODE) && <ToolbarCodeButton isDisabled={isDisabled} />}\n\n {validationInfo.isAnyHyperlinkEnabled && (\n <Fragment>\n <span className={styles.divider} />\n <ToolbarHyperlinkButton isDisabled={isDisabled} />\n </Fragment>\n )}\n\n {validationInfo.isAnyBlockFormattingEnabled && <span className={styles.divider} />}\n\n {isNodeTypeEnabled(sdk.field, BLOCKS.QUOTE) && (\n <ToolbarQuoteButton isDisabled={isDisabled || !canInsertBlocks} />\n )}\n <ToolbarListButton isDisabled={isDisabled || !canInsertBlocks} />\n {isNodeTypeEnabled(sdk.field, BLOCKS.HR) && (\n <ToolbarHrButton isDisabled={isDisabled || !canInsertBlocks} />\n )}\n {isNodeTypeEnabled(sdk.field, BLOCKS.TABLE) && (\n <ToolbarTableButton isDisabled={shouldDisableTables} />\n )}\n </div>\n <div className={styles.embedActionsWrapper}>\n <EmbedEntityWidget isDisabled={isDisabled} canInsertBlocks={canInsertBlocks} />\n </div>\n </Flex>\n );\n};\n\nfunction getValidationInfo(field: FieldExtensionSDK['field']): {\n isAnyMarkEnabled: boolean;\n isAnyHyperlinkEnabled: boolean;\n isAnyBlockFormattingEnabled: boolean;\n} {\n const someWithValidation = (vals, validation) => vals.some((val) => validation(field, val));\n\n const isAnyMarkEnabled = someWithValidation(Object.values(MARKS), isMarkEnabled);\n\n const isAnyHyperlinkEnabled = someWithValidation(\n [INLINES.HYPERLINK, INLINES.ASSET_HYPERLINK, INLINES.ENTRY_HYPERLINK],\n isNodeTypeEnabled\n );\n\n const isAnyBlockFormattingEnabled = someWithValidation(\n [BLOCKS.UL_LIST, BLOCKS.OL_LIST, BLOCKS.QUOTE, BLOCKS.HR],\n isNodeTypeEnabled\n );\n\n return {\n isAnyMarkEnabled,\n isAnyHyperlinkEnabled,\n isAnyBlockFormattingEnabled,\n };\n}\n\nexport default Toolbar;\n","import React, { ReactNode } from 'react';\nimport { css } from 'emotion';\n\nconst styles = {\n nativeSticky: css`\n position: -webkit-sticky;\n position: sticky;\n top: -1px;\n z-index: 2;\n `,\n};\n\ntype StickyToolbarProps = {\n isDisabled?: boolean;\n children: ReactNode;\n};\n\nconst StickyToolbarWrapper = ({ isDisabled, children }: StickyToolbarProps) => (\n <div className={isDisabled ? '' : styles.nativeSticky}>{children}</div>\n);\n\nexport default StickyToolbarWrapper;\n","import { BLOCKS, INLINES, VOID_BLOCKS, Text } from '@contentful/rich-text-types';\nimport { CustomElement, TextElement, TextOrCustomElement } from 'types';\nimport values from 'lodash/values'; // eslint-disable-line you-dont-need-lodash-underscore/values\n\ntype NodeType = BLOCKS | INLINES | Text['nodeType'];\n\nconst TEXT_PARENT_NODES: string[] = (VOID_BLOCKS as string[])\n .concat(values(INLINES) as string[])\n .concat(\n BLOCKS.PARAGRAPH,\n BLOCKS.HEADING_1,\n BLOCKS.HEADING_2,\n BLOCKS.HEADING_3,\n BLOCKS.HEADING_4,\n BLOCKS.HEADING_5,\n BLOCKS.HEADING_6\n );\n\nconst isTextElement = (node: TextOrCustomElement): node is TextElement => 'text' in node;\n\nconst wrapNode = (type: BLOCKS, node: TextOrCustomElement): CustomElement => ({\n type,\n data: {},\n children: [node],\n});\n\nfunction wrapOrphanedTextNode(parentNodeType: NodeType, node: TextElement): CustomElement {\n const paragraph = wrapNode(BLOCKS.PARAGRAPH, node);\n switch (parentNodeType) {\n case BLOCKS.OL_LIST:\n case BLOCKS.UL_LIST:\n return wrapNode(BLOCKS.LIST_ITEM, paragraph);\n case BLOCKS.TABLE_ROW:\n return wrapNode(BLOCKS.TABLE_CELL, paragraph);\n case BLOCKS.TABLE:\n return wrapNode(BLOCKS.TABLE_ROW, wrapNode(BLOCKS.TABLE_CELL, paragraph));\n default:\n return paragraph;\n }\n}\n\n/**\n * Ensures \"orphaned\" text node elements (those without a parent capable of\n * validly rendering a text child node) are wrapped with a suitable parent\n * element to prevent failures on the validation layer.\n *\n * It is commonplace for third party plugins (including udecode) to reconcile\n * deletion events by inserting such nodes into their schema. This\n * subprocedure is intended as a guard against such cases.\n */\nexport function sanitizeSlateDoc(\n nodes: TextOrCustomElement[] = [],\n parentNodeType: NodeType = BLOCKS.DOCUMENT\n): TextOrCustomElement[] {\n return nodes.map((node: TextOrCustomElement): TextOrCustomElement => {\n if (isTextElement(node)) {\n return TEXT_PARENT_NODES.includes(parentNodeType)\n ? node\n : wrapOrphanedTextNode(parentNodeType, node);\n }\n return {\n ...node,\n children: sanitizeSlateDoc(node.children, node.type as NodeType),\n };\n });\n}\n\n/**\n * Ensures incoming void nodes have a child leaf text element.\n */\nexport function sanitizeIncomingSlateDoc(nodes: TextOrCustomElement[] = []): TextOrCustomElement[] {\n return nodes.map((node: TextOrCustomElement): TextOrCustomElement => {\n if (isTextElement(node)) {\n return node;\n }\n if (node.isVoid && node.children?.length === 0) {\n return {\n ...node,\n children: [{ text: '', data: {} }],\n };\n }\n return {\n ...node,\n children: sanitizeIncomingSlateDoc(node.children),\n };\n });\n}\n","import { PlateEditor } from '@udecode/plate-core';\n\nexport type SanitizerTuple = [Document, PlateEditor];\n\ntype Predicate = (node: ChildNode) => boolean;\n\nexport const isHTMLElement = (node: ChildNode): node is HTMLElement =>\n node.nodeType === Node.ELEMENT_NODE;\n\nexport const removeChildNodes = (node: ChildNode, predicate: Predicate = Boolean) =>\n Array.from(node.childNodes)\n .filter(predicate)\n .forEach((table) => node.removeChild(table));\n\nexport const removeChildNodesUsingPredicate =\n (predicate: Predicate) =>\n (nodeList: NodeList): Node[] => {\n const nodes = Array.from(nodeList);\n while (nodes.length > 0) {\n const node = nodes.pop() as ChildNode;\n removeChildNodes(node, predicate);\n for (const childNode of Array.from(node.childNodes)) {\n nodes.push(childNode);\n }\n }\n return nodes;\n };\n","import { removeChildNodesUsingPredicate, SanitizerTuple } from './helpers';\n\nconst isComment = (node: ChildNode): node is Comment => node.nodeType === Node.COMMENT_NODE;\n\nconst removeCommentChildren = removeChildNodesUsingPredicate(isComment);\n\nexport const removeComments = ([doc, editor]: SanitizerTuple): SanitizerTuple => {\n removeCommentChildren(doc.childNodes);\n return [doc, editor];\n};\n","import { BLOCKS } from '@contentful/rich-text-types';\nimport { getNodeEntryFromSelection } from '../../../helpers/editor';\nimport { isHTMLElement, removeChildNodesUsingPredicate, SanitizerTuple } from './helpers';\n\nconst TAG_NAME_TABLE = 'TABLE';\nconst TAG_NAME_TABLE_CAPTION = 'CAPTION';\nconst DISALLOWED_TABLE_CHILD_ELEMENTS: Element['tagName'][] = [TAG_NAME_TABLE_CAPTION];\ntype DisallowedTableChildElement = HTMLTableCaptionElement;\n\nconst isTableElement = (node: ChildNode): node is HTMLTableElement =>\n isHTMLElement(node) && node.tagName === TAG_NAME_TABLE;\n\nconst isDisallowedTableChildElement = (node: ChildNode): node is DisallowedTableChildElement =>\n isHTMLElement(node) && DISALLOWED_TABLE_CHILD_ELEMENTS.includes(node.tagName);\n\nconst removeDisallowedTableChildElements = removeChildNodesUsingPredicate(\n isDisallowedTableChildElement\n);\n\nconst removeTableGrandchildren = (nodeList: NodeList) => {\n const nodes = Array.from(nodeList);\n while (nodes.length > 0) {\n const node = nodes.pop() as ChildNode;\n if (isTableElement(node)) {\n removeDisallowedTableChildElements(node.childNodes);\n continue;\n }\n for (const childNode of Array.from(node.childNodes)) {\n nodes.push(childNode);\n }\n }\n return nodes;\n};\n\nexport const sanitizeTables = ([doc, editor]: SanitizerTuple): SanitizerTuple => {\n const [node] = getNodeEntryFromSelection(editor, BLOCKS.TABLE);\n const isTableInCurrentSelection = !!node;\n if (isTableInCurrentSelection) {\n removeDisallowedTableChildElements(doc.childNodes);\n } else {\n removeTableGrandchildren(doc.childNodes);\n }\n return [doc, editor];\n};\n","import { PlatePlugin, PlateEditor } from '@udecode/plate-core';\nimport * as sanitizers from './sanitizers';\nimport flow from 'lodash/flow';\n\nconst MIME_TYPE_HTML = 'text/html';\n\n// TODO: Upgrade tslib so we can just flow(...sanitizers);\nconst sanitizeDocument = flow.apply(this, Object.values(sanitizers));\n\nconst sanitizeHtml = (html: string, editor: PlateEditor): string => {\n const doc = new DOMParser().parseFromString(html, MIME_TYPE_HTML);\n const [sanitizedDoc] = sanitizeDocument([doc, editor]);\n const sanitizedData = new XMLSerializer().serializeToString(sanitizedDoc);\n return sanitizedData;\n};\n\nconst htmlToDataTransfer = (html: string): DataTransfer => {\n const data = new DataTransfer();\n data.setData(MIME_TYPE_HTML, html);\n return data;\n};\n\nexport const createPastePlugin = (): PlatePlugin => ({\n withOverrides: (editor) => {\n const { insertData } = editor;\n editor.insertData = (data: DataTransfer) => {\n const html = data.getData(MIME_TYPE_HTML);\n if (html) {\n const sanitized = sanitizeHtml(html, editor);\n const newData = htmlToDataTransfer(sanitized);\n insertData(newData);\n } else {\n insertData(data);\n }\n };\n\n return editor;\n },\n});\n","import { isHTMLElement, removeChildNodes, SanitizerTuple } from './helpers';\n\n/**\n * Ensures the text selection from entity block elements is\n * not included in the paste buffer.\n */\nexport const sanitizeEntityBlocks = ([doc, editor]: SanitizerTuple): SanitizerTuple => {\n const nodes = Array.from(doc.childNodes);\n while (nodes.length > 0) {\n const node = nodes.pop() as ChildNode;\n if (isHTMLElement(node) && node.getAttribute('data-entity-type')) {\n removeChildNodes(node);\n continue;\n }\n for (const childNode of Array.from(node.childNodes)) {\n nodes.push(childNode);\n }\n }\n return [doc, editor];\n};\n","import * as React from 'react';\nimport { css } from 'emotion';\nimport { PlatePlugin, getRenderElement, PlateEditor } from '@udecode/plate-core';\nimport { ELEMENT_PARAGRAPH } from '@udecode/plate-paragraph';\nimport { getToggleElementOnKeyDown } from '@udecode/plate-common';\nimport { BLOCKS } from '@contentful/rich-text-types';\nimport tokens from '@contentful/f36-tokens';\nimport { Element, Node, Transforms } from 'slate';\nimport { RenderElementProps } from 'slate-react';\nimport { CustomSlatePluginOptions, CustomElement } from '../../types';\nimport { deserializeElement } from '../../helpers/deserializer';\n\nconst styles = {\n [BLOCKS.PARAGRAPH]: css`\n line-height: ${tokens.lineHeightDefault};\n margin-bottom: 1.5em;\n `,\n};\n\nexport function Paragraph(props: RenderElementProps) {\n return (\n <div {...props.attributes} className={styles[BLOCKS.PARAGRAPH]}>\n {props.children}\n </div>\n );\n}\n\nfunction isEmbed(element: HTMLElement) {\n return (\n element.hasAttribute('data-embedded-entity-inline-id') ||\n element.hasAttribute('data-entity-type')\n );\n}\n\nfunction isEmpty(element: HTMLElement) {\n return element.textContent === '';\n}\n\nexport function createParagraphPlugin(): PlatePlugin {\n const elementKeys: string[] = [ELEMENT_PARAGRAPH, BLOCKS.PARAGRAPH];\n\n const deserializer = deserializeElement(BLOCKS.PARAGRAPH, [\n {\n nodeNames: ['P', 'DIV'],\n },\n ]);\n\n return {\n renderElement: getRenderElement(elementKeys),\n pluginKeys: elementKeys,\n onKeyDown: getToggleElementOnKeyDown(BLOCKS.PARAGRAPH),\n deserialize: (editor: PlateEditor) => {\n const { element, ...rest } = deserializer(editor);\n return {\n ...rest,\n element: element?.map((deserializeNode) => ({\n ...deserializeNode,\n deserialize: (el: HTMLElement) => {\n if (isEmpty(el) || isEmbed(el)) {\n return;\n }\n return deserializeNode.deserialize(el);\n },\n })),\n };\n },\n withOverrides: (editor) => {\n const { normalizeNode } = editor;\n editor.normalizeNode = (entry) => {\n const [node, path] = entry;\n // If the element is a paragraph, ensure its children are valid.\n if (Element.isElement(node) && (node as CustomElement).type === BLOCKS.PARAGRAPH) {\n for (const [child, childPath] of Node.children(editor, path)) {\n if (Element.isElement(child) && !editor.isInline(child)) {\n Transforms.unwrapNodes(editor, {\n at: childPath,\n });\n return;\n }\n }\n }\n // Fall back to the original `normalizeNode` to enforce other constraints.\n normalizeNode(entry);\n };\n return editor;\n },\n };\n}\n\nexport const withParagraphOptions: CustomSlatePluginOptions = {\n [ELEMENT_PARAGRAPH]: {\n // We convert the default slate plugin `p` to Contentful `BLOCKS.PARAGRAPH`\n type: BLOCKS.PARAGRAPH,\n component: Paragraph,\n },\n [BLOCKS.PARAGRAPH]: {\n type: BLOCKS.PARAGRAPH,\n component: Paragraph,\n hotkey: ['mod+opt+0'],\n },\n};\n","import { FieldExtensionSDK } from '@contentful/app-sdk';\n\nimport { createPastePlugin } from './Paste';\nimport { createListPlugin, withListOptions } from './List';\nimport { createHistoryPlugin, createReactPlugin } from '@udecode/plate-core';\nimport { createDeserializeHTMLPlugin } from '@udecode/plate-html-serializer';\nimport { createDeserializeAstPlugin } from '@udecode/plate-ast-serializer';\nimport { createHrPlugin, withHrOptions } from './Hr';\nimport { withHeadingOptions, createHeadingPlugin } from './Heading';\nimport { createBoldPlugin, withBoldOptions } from './Bold';\nimport { withCodeOptions, createCodePlugin } from './Code';\nimport { withItalicOptions, createItalicPlugin } from './Italic';\nimport { createUnderlinePlugin, withUnderlineOptions } from './Underline';\nimport { createParagraphPlugin, withParagraphOptions } from './Paragraph';\nimport { createQuotePlugin, withQuoteOptions } from './Quote';\nimport { createNewLinePlugin } from './NewLine';\nimport { createInsertBeforeFirstVoidBlockPlugin } from './InsertBeforeFirstVoidBlock';\nimport { createTablePlugin, withTableOptions } from './Table';\nimport { createHyperlinkPlugin, withHyperlinkOptions } from './Hyperlink';\nimport {\n createEmbeddedAssetBlockPlugin,\n createEmbeddedEntryBlockPlugin,\n withEmbeddedAssetBlockOptions,\n withEmbeddedEntryBlockOptions,\n} from './EmbeddedEntityBlock';\nimport {\n createEmbeddedEntityInlinePlugin,\n withEmbeddedEntityInlineOptions,\n} from './EmbeddedEntityInline';\nimport { TrackingProvider } from '../TrackingProvider';\nimport { createTrailingParagraphPlugin } from './TrailingParagraph';\nimport { createDragAndDropPlugin } from './DragAndDrop';\nimport { createTextPlugin } from './Text';\n\nexport const getPlugins = (sdk: FieldExtensionSDK, tracking: TrackingProvider) => {\n const plugins = [\n // Core\n createReactPlugin(),\n createHistoryPlugin(),\n\n // Behavior\n createPastePlugin(),\n\n // Global shortcuts\n createNewLinePlugin(),\n createInsertBeforeFirstVoidBlockPlugin(),\n createDragAndDropPlugin(),\n\n // Block Elements\n createParagraphPlugin(),\n createListPlugin(),\n createHrPlugin(),\n createHeadingPlugin(),\n createQuotePlugin(),\n createTablePlugin(tracking),\n createEmbeddedEntryBlockPlugin(sdk),\n createEmbeddedAssetBlockPlugin(sdk),\n\n // Inline elements\n createHyperlinkPlugin(sdk),\n createEmbeddedEntityInlinePlugin(sdk),\n\n // Marks\n createBoldPlugin(),\n createCodePlugin(),\n createItalicPlugin(),\n createUnderlinePlugin(),\n\n // Other\n createTrailingParagraphPlugin(),\n createTextPlugin(),\n ];\n\n return plugins.concat([\n createDeserializeHTMLPlugin({ plugins }),\n createDeserializeAstPlugin({ plugins }),\n ] as any);\n};\n\nexport const pluginOptions = {\n // Block elements\n ...withParagraphOptions,\n ...withListOptions,\n ...withHrOptions,\n ...withHeadingOptions,\n ...withQuoteOptions,\n ...withTableOptions,\n ...withEmbeddedEntryBlockOptions,\n ...withEmbeddedAssetBlockOptions,\n\n // Inline elements\n ...withHyperlinkOptions,\n ...withEmbeddedEntityInlineOptions,\n\n // Marks\n ...withBoldOptions,\n ...withCodeOptions,\n ...withItalicOptions,\n ...withUnderlineOptions,\n};\n","import React, { useCallback, useState } from 'react';\nimport noop from 'lodash/noop';\nimport { toContentfulDocument, toSlatejsDocument } from '@contentful/contentful-slatejs-adapter';\nimport * as Contentful from '@contentful/rich-text-types';\nimport { EntityProvider } from '@contentful/field-editor-reference';\nimport { css, cx } from 'emotion';\nimport { styles } from './RichTextEditor.styles';\nimport schema from './constants/Schema';\nimport deepEquals from 'fast-deep-equal';\nimport Toolbar from './Toolbar';\nimport StickyToolbarWrapper from './Toolbar/StickyToolbarWrapper';\nimport { Plate } from '@udecode/plate-core';\nimport { SdkProvider } from './SdkProvider';\nimport {\n RichTextTrackingActionHandler,\n TrackingProvider,\n useTrackingContext,\n} from './TrackingProvider';\nimport { sanitizeIncomingSlateDoc, sanitizeSlateDoc } from './helpers/sanitizeSlateDoc';\nimport { TextOrCustomElement } from './types';\nimport { ContentfulEditorProvider, getContentfulEditorId } from './ContentfulEditorProvider';\nimport { FieldExtensionSDK } from '@contentful/app-sdk';\nimport { FieldConnector } from '@contentful/field-editor-shared';\nimport { getPlugins, pluginOptions } from './plugins';\n\ntype ConnectedProps = {\n sdk: FieldExtensionSDK;\n onAction?: RichTextTrackingActionHandler;\n minHeight?: string | number;\n value?: object;\n isDisabled?: boolean;\n onChange?: (doc: Contentful.Document) => unknown;\n isToolbarHidden?: boolean;\n actionsDisabled?: boolean;\n};\n\nexport const ConnectedRichTextEditor = (props: ConnectedProps) => {\n const tracking = useTrackingContext();\n\n const docFromAdapter = toSlatejsDocument({\n document: props.value || Contentful.EMPTY_DOCUMENT,\n schema,\n });\n\n const doc = sanitizeIncomingSlateDoc(docFromAdapter);\n\n const [value, setValue] = useState(doc);\n\n const classNames = cx(\n styles.editor,\n props.minHeight !== undefined ? css({ minHeight: props.minHeight }) : undefined,\n props.isDisabled ? styles.disabled : styles.enabled,\n props.isToolbarHidden && styles.hiddenToolbar\n );\n\n const plugins = React.useMemo(() => getPlugins(props.sdk, tracking), [props.sdk, tracking]);\n\n return (\n <div className={styles.root} data-test-id=\"rich-text-editor\">\n <Plate\n id={getContentfulEditorId(props.sdk)}\n initialValue={value}\n plugins={plugins}\n editableProps={{\n className: classNames,\n readOnly: props.isDisabled,\n }}\n onChange={(newValue) => {\n const slateDoc = sanitizeSlateDoc(newValue as TextOrCustomElement[]);\n setValue(slateDoc);\n const contentfulDoc = toContentfulDocument({ document: slateDoc, schema });\n props.onChange?.(contentfulDoc);\n }}\n // @ts-expect-error\n options={pluginOptions}>\n {!props.isToolbarHidden && (\n <StickyToolbarWrapper isDisabled={props.isDisabled}>\n <Toolbar isDisabled={props.isDisabled} />\n </StickyToolbarWrapper>\n )}\n </Plate>\n </div>\n );\n};\n\ntype Props = ConnectedProps & { isInitiallyDisabled: boolean };\n\nconst RichTextEditor = (props: Props) => {\n const { sdk, isInitiallyDisabled, onAction, ...otherProps } = props;\n const isEmptyValue = useCallback(\n (value) => !value || deepEquals(value, Contentful.EMPTY_DOCUMENT),\n []\n );\n return (\n <EntityProvider sdk={sdk}>\n <SdkProvider sdk={sdk}>\n <TrackingProvider onAction={onAction || noop}>\n <FieldConnector\n throttle={0}\n field={sdk.field}\n isInitiallyDisabled={isInitiallyDisabled}\n isEmptyValue={isEmptyValue}\n isEqualValues={deepEquals}>\n {({ lastRemoteValue, disabled, setValue, externalReset }) => (\n <ContentfulEditorProvider sdk={sdk}>\n <ConnectedRichTextEditor\n {...otherProps}\n key={`rich-text-editor-${externalReset}`}\n value={lastRemoteValue}\n sdk={sdk}\n onAction={onAction || noop}\n isDisabled={disabled}\n onChange={setValue}\n />\n </ContentfulEditorProvider>\n )}\n </FieldConnector>\n </TrackingProvider>\n </SdkProvider>\n </EntityProvider>\n );\n};\n\nexport default RichTextEditor;\n","import { Node as SlateNode, Transforms } from 'slate';\nimport { PlatePlugin } from '@udecode/plate-core';\nimport { getNodes } from '@udecode/plate-common';\nimport { BLOCKS, CONTAINERS, INLINES } from '@contentful/rich-text-types';\n\nimport { CustomElement } from '../../types';\n\nexport function createDragAndDropPlugin(): PlatePlugin {\n // Elements that don't allow other elements to be dragged into them and which callback should be used\n const DND_BLOCKED_ELEMENTS = {\n [BLOCKS.QUOTE]: Transforms.liftNodes,\n };\n\n const DRAGGABLE_TYPES: string[] = [\n BLOCKS.EMBEDDED_ENTRY,\n BLOCKS.EMBEDDED_ASSET,\n INLINES.EMBEDDED_ENTRY,\n ];\n\n /**\n * HTML node names where dropping should be allowed\n * Usually for elements where `Transforms.removeNodes` is needed\n * TODO: looking up for html nodes is not the best solution and it won't scale but it works fine for our current cases/elements\n */\n const ON_DROP_ALLOWED_TYPES = {\n TABLE: [INLINES.EMBEDDED_ENTRY],\n };\n\n return {\n withOverrides: (editor) => {\n const { normalizeNode } = editor;\n\n editor.normalizeNode = (entry) => {\n const [node, path] = entry;\n\n Object.keys(DND_BLOCKED_ELEMENTS).forEach((blockedElementType) => {\n const nodeType = (node as CustomElement).type;\n\n if (SlateNode.isNode(node) && nodeType === blockedElementType) {\n for (const [child, childPath] of SlateNode.children(editor, path)) {\n const childType = (child as CustomElement).type;\n\n if (!CONTAINERS[blockedElementType]) return;\n if (!CONTAINERS[blockedElementType].includes(childType)) {\n const callback = DND_BLOCKED_ELEMENTS[blockedElementType];\n callback(editor, {\n at: childPath,\n match: (matchNode) =>\n SlateNode.isNode(matchNode) &&\n DRAGGABLE_TYPES.includes((matchNode as CustomElement).type),\n });\n\n return;\n }\n }\n }\n });\n\n normalizeNode(entry);\n };\n\n return editor;\n },\n\n // If true, the next handlers will be skipped.\n onDrop: (editor) => (event) => {\n const [draggingBlock] = Array.from(\n getNodes(editor, {\n match: (node) => DRAGGABLE_TYPES.includes(node?.type),\n })\n );\n if (!draggingBlock) return false;\n\n const [draggingNode] = draggingBlock;\n\n if (!event.nativeEvent.target) return false;\n\n // TODO: looking up for html nodes is not the best solution and it won't scale, we need to find a way to know the dropping target slate element\n const dropDisallowed = getParents(event.nativeEvent.target as Node).some((node) => {\n return ON_DROP_ALLOWED_TYPES[node.nodeName]\n ? !ON_DROP_ALLOWED_TYPES[node.nodeName]?.includes(draggingNode.type)\n : false;\n });\n\n if (!dropDisallowed) {\n // Move the drop event to a new undo batch mitigating the bug where undo not only moves it back,\n // but also undoes a previous action: https://github.com/ianstormtaylor/slate/issues/4694\n editor.history.undos.push([]);\n }\n\n return dropDisallowed;\n },\n };\n}\n\nfunction getParents(el: Node): Node[] {\n const parents: Node[] = [];\n\n parents.push(el);\n while (el.parentNode) {\n parents.unshift(el.parentNode);\n el = el.parentNode;\n }\n\n return parents;\n}\n","import { KeyboardEvent } from 'react';\nimport { PlatePlugin, PlateEditor } from '@udecode/plate-core';\n\nexport function createNewLinePlugin(): PlatePlugin {\n return {\n onKeyDown: function (editor: PlateEditor) {\n return (event: KeyboardEvent) => {\n const isEnter = event.key === 'Enter';\n const isShift = event.shiftKey;\n\n if (isEnter && isShift) {\n event.preventDefault();\n editor.insertText('\\n');\n return true; // To prevent the next handler from running\n }\n\n return false; // something like next()\n };\n },\n };\n}\n","import { PlatePlugin } from '@udecode/plate-core';\nimport { ExitBreakPluginOptions, createExitBreakPlugin } from '@udecode/plate-break';\nimport { isFirstChild } from '../../helpers/editor';\n\nexport function createInsertBeforeFirstVoidBlockPlugin(): PlatePlugin {\n const optionsExitBreakPlugin: ExitBreakPluginOptions = {\n rules: [\n {\n hotkey: 'enter',\n before: true,\n query: { filter: ([node, path]) => isFirstChild(path) && !!node.isVoid },\n },\n {\n hotkey: 'enter',\n query: { filter: ([node, path]) => !isFirstChild(path) && !!node.isVoid },\n },\n ],\n };\n\n return createExitBreakPlugin(optionsExitBreakPlugin);\n}\n","import { BLOCKS } from '@contentful/rich-text-types';\nimport { createTrailingBlockPlugin } from '@udecode/plate-trailing-block';\n\nexport const createTrailingParagraphPlugin = () => {\n return createTrailingBlockPlugin({\n type: BLOCKS.PARAGRAPH,\n level: 0,\n });\n};\n","import { Editor, Ancestor, Transforms } from 'slate';\nimport { PlatePlugin } from '@udecode/plate-core';\nimport { isAncestorEmpty } from '@udecode/plate-common';\nimport { TEXT_CONTAINERS, BLOCKS } from '@contentful/rich-text-types';\nimport { CustomElement } from '../../types';\n\nexport function createTextPlugin(): PlatePlugin {\n return {\n withOverrides: (editor) => {\n const { deleteForward } = editor;\n\n // When pressing delete instead of backspace\n editor.deleteForward = (unit) => {\n const [nodes] = Editor.nodes(editor, {\n at: editor.selection?.focus.path,\n match: (node) => TEXT_CONTAINERS.includes((node as CustomElement).type as BLOCKS),\n });\n\n if (nodes) {\n const [paragraphOrHeading, path] = nodes;\n const isTextEmpty = isAncestorEmpty(editor, paragraphOrHeading as Ancestor);\n // We ignore paragraphs/headings that are children of ul, ol, blockquote, tables, etc\n const isRootLevel = path.length === 1;\n\n if (isTextEmpty && isRootLevel) {\n Transforms.removeNodes(editor, { at: path });\n } else {\n deleteForward(unit);\n }\n } else {\n deleteForward(unit);\n }\n };\n\n return editor;\n },\n };\n}\n","import React from 'react';\nimport { css } from 'emotion';\nimport PropTypes from 'prop-types';\nimport tokens from '@contentful/f36-tokens';\nimport { EntityProvider } from '@contentful/field-editor-reference';\nimport { FetchingWrappedEntryCard } from '../../plugins/shared/FetchingWrappedEntryCard';\nimport { FetchingWrappedAssetCard } from '../../plugins/shared/FetchingWrappedAssetCard';\n\nimport {\n TextLink,\n Button,\n FormControl,\n FormLabel,\n Select,\n TextInput,\n Form,\n ModalContent,\n ModalControls,\n} from '@contentful/f36-components';\n\nexport const LINK_TYPES = {\n URI: 'uri',\n ENTRY: 'Entry',\n ASSET: 'Asset',\n};\n\nfunction isFeaturingEntitySelector(entitySelectorConfigs = {}) {\n return !!entitySelectorConfigs.Entry || !!entitySelectorConfigs.Asset;\n}\n\nfunction entityToLink(entity) {\n const { id, type } = entity.sys;\n return { sys: { id, type: 'Link', linkType: type } };\n}\n\nexport class HyperlinkDialog extends React.Component {\n static propTypes = {\n sdk: PropTypes.object.isRequired,\n labels: PropTypes.shape({\n title: PropTypes.string,\n confirm: PropTypes.string,\n }),\n value: PropTypes.shape({\n text: PropTypes.string,\n uri: PropTypes.string,\n target: PropTypes.object,\n // Will be overwritten accordingly if `uri` or `target.sys.linkType` are set.\n type: PropTypes.oneOf(['uri', 'Entry', 'Asset']),\n }),\n entitySelectorConfigs: PropTypes.object,\n allowedHyperlinkTypes: PropTypes.arrayOf(\n PropTypes.oneOf([LINK_TYPES.ENTRY, LINK_TYPES.ASSET, LINK_TYPES.URI])\n ),\n hideText: PropTypes.bool,\n onClose: PropTypes.func.isRequired,\n };\n\n static defaultProps = {\n labels: {\n title: 'Insert link',\n confirm: 'Insert link',\n },\n value: {},\n hideText: false,\n entitySelectorConfigs: {},\n allowedHyperlinkTypes: [LINK_TYPES.ENTRY, LINK_TYPES.ASSET, LINK_TYPES.URI],\n };\n\n constructor(props) {\n super(props);\n\n const { text, type, uri, target } = props.value;\n const isEntityLink = Boolean(target);\n const entityLinks = {\n [LINK_TYPES.ENTRY]: null,\n [LINK_TYPES.ASSET]: null,\n };\n let linkType = type;\n\n if (isEntityLink) {\n linkType = target.sys.linkType;\n entityLinks[linkType] = target;\n } else if (props.allowedHyperlinkTypes.includes(LINK_TYPES.URI)) {\n linkType = LINK_TYPES.URI;\n } else {\n linkType = props.allowedHyperlinkTypes[0];\n }\n\n this.state = { text, uri, entityLinks, type: linkType };\n }\n\n setTargetEntity(type, entity) {\n this.setState((state) => ({\n entityLinks: {\n ...state.entityLinks,\n [type]: entity ? entityToLink(entity) : undefined,\n },\n }));\n }\n\n getValue() {\n const { text, type, uri } = this.state;\n const value = { type };\n if (text) {\n value.text = text;\n }\n if (type === LINK_TYPES.URI) {\n value.uri = uri;\n } else {\n value.target = this.state.entityLinks[type];\n }\n return value;\n }\n\n isLinkComplete() {\n const { text, type, uri, target } = this.getValue();\n const requiresText = !this.props.hideText;\n if (requiresText && !text) {\n return false;\n }\n return (type === LINK_TYPES.URI && uri) || target;\n }\n\n handleSubmit = (event) => {\n event.preventDefault();\n this.props.onClose(this.getValue());\n };\n\n selectEntry = async () => {\n const { locale, contentTypes } = this.props.entitySelectorConfigs.Entry;\n const entry = await this.props.sdk.dialogs.selectSingleEntry({ locale, contentTypes });\n this.setTargetEntity(LINK_TYPES.ENTRY, entry);\n };\n\n selectAsset = async () => {\n const { locale } = this.props.entitySelectorConfigs.Asset;\n const asset = await this.props.sdk.dialogs.selectSingleAsset({ locale });\n this.setTargetEntity(LINK_TYPES.ASSET, asset);\n };\n\n render() {\n const { labels } = this.props;\n return (\n <EntityProvider sdk={this.props.sdk}>\n <React.Fragment>\n <ModalContent>{this.renderFields()}</ModalContent>\n <ModalControls>\n <Button\n type=\"button\"\n onClick={() => this.props.onClose(null)}\n variant=\"secondary\"\n testId=\"cancel-cta\"\n size=\"small\">\n Cancel\n </Button>\n <Button\n type=\"submit\"\n variant=\"positive\"\n onClick={this.handleSubmit}\n isDisabled={!this.isLinkComplete()}\n testId=\"confirm-cta\"\n size=\"small\">\n {labels.confirm}\n </Button>\n </ModalControls>\n </React.Fragment>\n </EntityProvider>\n );\n }\n\n renderFields() {\n const { hideText, allowedHyperlinkTypes, entitySelectorConfigs } = this.props;\n const { uri, text, type } = this.state;\n const isUriInputAutoFocused = type === LINK_TYPES.URI && (hideText || !!text);\n\n return (\n <Form>\n {hideText ? null : (\n <FormControl id=\"link-text\" isRequired>\n <FormControl.Label>Link text</FormControl.Label>\n <TextInput\n testId=\"link-text-input\"\n name=\"link-text\"\n value={text || ''}\n onChange={(e) => this.setState({ text: e.target.value })}\n // eslint-disable-next-line jsx-a11y/no-autofocus\n autoFocus={!isUriInputAutoFocused}\n />\n </FormControl>\n )}\n {isFeaturingEntitySelector(entitySelectorConfigs) && (\n <FormControl id=\"link-type\" name=\"link-type\">\n <FormControl.Label>Link type</FormControl.Label>\n <Select\n value={type}\n onChange={(e) => this.setState({ type: e.target.value })}\n testId=\"link-type-select\">\n {/* Show the option if the link type is allowed or the current link is of type that is no longer valid */}\n {allowedHyperlinkTypes.includes(LINK_TYPES.URI) || type === LINK_TYPES.URI ? (\n <Select.Option value={LINK_TYPES.URI}>URL</Select.Option>\n ) : null}\n {allowedHyperlinkTypes.includes(LINK_TYPES.ENTRY) || type === LINK_TYPES.ENTRY ? (\n <Select.Option value={LINK_TYPES.ENTRY}>Entry</Select.Option>\n ) : null}\n {allowedHyperlinkTypes.includes(LINK_TYPES.ASSET) || type === LINK_TYPES.ASSET ? (\n <Select.Option value={LINK_TYPES.ASSET}>Asset</Select.Option>\n ) : null}\n </Select>\n </FormControl>\n )}\n {type === LINK_TYPES.URI ? (\n <FormControl id=\"link-uri\" isRequired>\n <FormControl.Label>Link target</FormControl.Label>\n <TextInput\n testId=\"link-target-input\"\n name=\"link-uri\"\n value={uri || ''}\n placeholder=\"https://\"\n onChange={(e) => this.setState({ uri: e.target.value })}\n // eslint-disable-next-line jsx-a11y/no-autofocus\n autoFocus={isUriInputAutoFocused}\n />\n <FormControl.HelpText>A protocol may be required, e.g. https://</FormControl.HelpText>\n </FormControl>\n ) : (\n this.renderEntityField()\n )}\n </Form>\n );\n }\n\n renderEntityField() {\n const { type, entityLinks } = this.state;\n const resetEntity = () => this.setTargetEntity(type, null);\n const entityLink = entityLinks[type];\n const isEntitySelectorVisible = !entityLink;\n return (\n <div>\n <FormLabel required htmlFor=\"\">\n Link target\n </FormLabel>\n {!isEntitySelectorVisible && (\n <TextLink\n as=\"button\"\n className={css({ marginLeft: tokens.spacingS })}\n onClick={resetEntity}>\n Remove selection\n </TextLink>\n )}\n {entityLink && (\n <div>\n {type === LINK_TYPES.ENTRY && (\n <FetchingWrappedEntryCard\n sdk={this.props.sdk}\n locale={this.props.entitySelectorConfigs.Entry.locale}\n entryId={entityLink.sys.id}\n isDisabled\n isSelected={false}\n />\n )}\n {type == LINK_TYPES.ASSET && (\n <FetchingWrappedAssetCard\n sdk={this.props.sdk}\n locale={this.props.entitySelectorConfigs.Asset.locale}\n assetId={entityLink.sys.id}\n isDisabled\n isSelected={false}\n />\n )}\n </div>\n )}\n {/* Keep all entity selectors in the DOM for super fast types switching ux.*/}\n {isEntitySelectorVisible && this.renderEntitySelector(type, isEntitySelectorVisible)}\n </div>\n );\n }\n\n renderEntitySelector(type) {\n return (\n <div className={css({ marginTop: tokens.spacingS })}>\n {type === LINK_TYPES.ENTRY && (\n <TextLink as=\"button\" onClick={this.selectEntry}>\n Select entry\n </TextLink>\n )}\n {type === LINK_TYPES.ASSET && (\n <TextLink as=\"button\" onClick={this.selectAsset}>\n Select asset\n </TextLink>\n )}\n </div>\n );\n }\n}\n\nexport const openHyperlinkDialog = (\n dialogs,\n { value, showTextInput, allowedHyperlinkTypes, entitySelectorConfigs }\n) => {\n const isNew = !(value.uri || value.target);\n const props = {\n labels: {\n title: isNew ? 'Insert hyperlink' : 'Edit hyperlink',\n confirm: isNew ? 'Insert' : 'Update',\n },\n value,\n hideText: !showTextInput,\n allowedHyperlinkTypes,\n entitySelectorConfigs,\n };\n\n return dialogs.openCurrent({\n title: props.labels.title,\n width: 'large',\n shouldCloseOnEscapePress: true,\n shouldCloseOnOverlayClick: true,\n allowHeightOverflow: true,\n parameters: {\n type: 'rich-text-hyperlink-dialog',\n ...props,\n },\n });\n};\n","import React from 'react';\nimport { DialogExtensionSDK } from '@contentful/app-sdk';\nimport { ModalDialogLauncher } from '@contentful/field-editor-shared';\nimport { HyperlinkDialog } from './HypelinkDialog/HyperlinkDialog';\n\nexport const openRichTextDialog = (sdk: DialogExtensionSDK) => (options) => {\n if (options.parameters?.type === 'rich-text-hyperlink-dialog') {\n return ModalDialogLauncher.openDialog(options, ({ onClose }) => {\n return <HyperlinkDialog {...options.parameters} onClose={onClose} sdk={sdk} />;\n });\n }\n return Promise.reject();\n};\n","import React from 'react';\nimport { DialogExtensionSDK } from '@contentful/app-sdk';\nimport { HyperlinkDialog } from './HypelinkDialog/HyperlinkDialog';\n\nexport const renderRichTextDialog = (sdk: DialogExtensionSDK) => {\n const parameters = sdk.parameters.invocation as Record<string, unknown>;\n if (parameters?.type === 'rich-text-hyperlink-dialog') {\n sdk.window.startAutoResizer();\n return <HyperlinkDialog {...sdk.parameters.invocation} onClose={sdk.close} sdk={sdk} />;\n }\n return <div />;\n};\n"],"names":["STYLE_EDITOR_BORDER","tokens","gray400","styles","root","css","position","editor","borderRadius","borderRadiusMedium","border","borderTop","padding","fontSize","spacingM","fontFamily","fontStackPrimary","minHeight","background","colorWhite","outline","whiteSpace","overflowWrap","webkitUserModify","a","span","cursor","margin","hiddenToolbar","enabled","disabled","gray100","inlines","Object","values","INLINES","map","type","document","nodes","types","TOP_LEVEL_BLOCKS","blocks","BLOCKS","PARAGRAPH","match","object","HEADING_1","HEADING_2","HEADING_3","HEADING_4","HEADING_5","HEADING_6","VOID_BLOCKS","reduce","nodeType","isVoid","QUOTE","CONTAINERS","min","normalize","error","code","unwrapBlockByKey","node","key","HYPERLINK","ENTRY_HYPERLINK","ASSET_HYPERLINK","EMBEDDED_ENTRY","button","height","width","marginLeft","spacing2Xs","marginRight","tooltip","zIndex","Number","zIndexTooltip","ToolbarButton","props","title","testId","isActive","children","isDisabled","React","Button","className","cx","startIcon","onClick","event","preventDefault","variant","size","Tooltip","placement","content","LINK_TYPES","LIST_TYPES","OL_LIST","UL_LIST","isBlockSelected","Array","from","Editor","Element","isElement","hasSelectionText","selection","focus","path","some","Text","isText","text","getNodeEntryFromSelection","nodeTypeOrTypes","nodeTypes","isArray","i","length","nodeEntry","slice","includes","isNodeTypeSelected","moveToTheNextLine","Transforms","move","distance","unit","toggleBlock","isList","isQuote","unwrapNodes","isEditor","split","setNodes","LIST_ITEM","wrapNodes","data","getElementFromCurrentSelection","at","flat","isFirstChild","insertLink","options","url","target","isLinkActive","unwrapLink","isCollapsed","Range","link","uri","insertText","select","insertNodes","collapse","edge","wrapLink","getAncestorPathFromSelection","Path","levels","find","level","shouldUnwrapBlockquote","isQuoteSelected","isValidType","HR","unwrapFromRoot","ancestorPath","replaceNode","replacement","removeNodes","extractParagraphsAt","TEXT_CONTAINERS","mode","deserializeLeaf","rules","pluginOptions","getPlatePluginOptions","leaf","getLeafDeserializer","deserialize","deserializeElement","element","getElementDeserializer","getContentfulEditorId","sdk","field","entry","getSys","id","locale","useContentfulEditorHook","editorId","usePlateEditorRef","constate","ContentfulEditorProvider","useContentfulEditor","container","spacingL","hr","gray300","hrSelected","colorPrimary","withHrEvents","isEnter","keyCode","pathToSelectedHr","ToolbarHrButton","getText","Slate","HorizontalRuleIcon","withHrOptions","component","isSelected","isFocused","attributes","contentEditable","undefined","DEFAULT_ENABLED_NODE_TYPES","DOCUMENT","isFormattingOptionEnabled","validationType","nodeTypeOrMark","enabledFormattings","flow","v","get","validations","getRichTextValidation","concat","isNodeTypeEnabled","isMarkEnabled","mark","useSdk","SdkProvider","useSdkContext","dropdown","fontWeightDemiBold","fontSizeL","headings","fontWeightMedium","spacingS","withHeadingEvents","currentFragment","fragment","isCurrentFragmentAHeading","paragraph","heading","currentOffset","offset","cursorIsAtTheEnd","Node","string","splitNodes","headingKey","ctrlKey","metaKey","altKey","toggleNodeType","activeType","inactiveType","LABELS","ToolbarHeadingButton","isOpen","setOpen","selected","setSelected","operations","nodeTypesByEnablement","fromEntries","keys","filter","Boolean","someHeadingsEnabled","Menu","onClose","Trigger","endIcon","ChevronDownIcon","List","Item","isInitiallyFocused","setTimeout","createHeading","Tag","block","H1","H2","H3","H4","H5","H6","withHeadingOptions","blockquote","borderLeft","gray200","paddingLeft","fontStyle","color","createBlockQuote","withQuoteEvents","isBackspace","shiftKey","TABLE","every","item","ToolbarQuoteButton","QuoteIcon","withQuoteOptions","ToolbarListButton","handleClick","toggleList","ListBulletedIcon","ListNumberedIcon","listStyles","lineHeightDefault","createList","UL","OL","LI","withListOptions","ELEMENT_LIC","ELEMENT_LI","ELEMENT_UL","ELEMENT_OL","isListItem","isValidInsideListItem","LIST_ITEM_BLOCKS","replaceInvalidListItemWithText","textFromEntry","withCustomList","withDefaultOverrides","withList","insertFragment","li","ul","ol","isListRoot","liEntry","findNode","liPath","flatMap","listRoot","textEntries","texts","commonAncestorEntry","commonAncestor","textEntry","isAncestor","common","ancestor","parent","getFirstAncestorOfType","trimList","next","filtered","getListInsertFragment","normalizeNode","child","childPath","normalizeList","getParent","hasListAsDirectParent","parentList","getAbove","getNearestListAncestor","normalizeOrphanedListItem","listItemChildren","ToolbarBoldButton","toggleMark","MARKS","BOLD","isMarkActive","FormatBoldIcon","bold","fontWeight","withBoldOptions","hotkey","ToolbarCodeButton","CODE","CodeIcon","withCodeOptions","ToolbarItalicButton","ITALIC","FormatItalicIcon","italic","withItalicOptions","ToolbarUnderlineButton","UNDERLINE","FormatUnderlinedIcon","withUnderlineOptions","runtime","exports","Op","prototype","hasOwn","hasOwnProperty","$Symbol","Symbol","iteratorSymbol","iterator","asyncIteratorSymbol","asyncIterator","toStringTagSymbol","toStringTag","define","obj","value","defineProperty","enumerable","configurable","writable","err","wrap","innerFn","outerFn","self","tryLocsList","generator","create","Generator","context","Context","_invoke","state","method","arg","Error","done","delegate","delegateResult","maybeInvokeDelegate","ContinueSentinel","sent","_sent","dispatchException","abrupt","record","tryCatch","makeInvokeMethod","fn","call","GeneratorFunction","GeneratorFunctionPrototype","IteratorPrototype","this","getProto","getPrototypeOf","NativeIteratorPrototype","Gp","defineIteratorMethods","forEach","AsyncIterator","PromiseImpl","previousPromise","callInvokeWithMethodAndArg","resolve","reject","invoke","result","__await","then","unwrapped","TypeError","info","resultName","nextLoc","pushTryEntry","locs","tryLoc","catchLoc","finallyLoc","afterLoc","tryEntries","push","resetTryEntry","completion","reset","iterable","iteratorMethod","isNaN","doneResult","constructor","displayName","isGeneratorFunction","genFun","ctor","name","setPrototypeOf","__proto__","awrap","async","Promise","iter","toString","reverse","pop","skipTempReset","prev","charAt","stop","rootRecord","rval","exception","handle","loc","caught","hasCatch","hasFinally","finallyEntry","complete","finish","thrown","delegateYield","module","regeneratorRuntime","accidentalStrictMode","Function","EntryAssetTooltip","entityTitle","setEntityTitle","entityStatus","setEntityStatus","jobs","setJobs","isLoading","setIsLoading","hasError","setHasError","actions","Asset","getEntity","space","getAsset","getEntityTitle","args","entityHelpers","getAssetTitle","asset","entity","Entry","getEntry","getEntryTitle","sys","contentType","contentTypeId","contentTypes","getCachedContentTypes","ct","localeCode","defaultLocaleCode","locales","entityType","getEntityScheduledActions","getEntryStatus","console","log","loadContent","toLowerCase","str","contentTypeName","substr","replace","getEntityInfo","getScheduleTooltipContent","job","jobsCount","scheduleIcon","EntityStatusIcon","useEntities","ScheduledIconWithTooltip","loadEntityScheduledActions","entityId","ClockIcon","entryCard","EntryThumbnail","file","isValidImage","AssetThumbnail","FetchingWrappedEntryCard","getOrLoadEntry","entries","getOrLoadAsset","setFile","entryId","getEntryImage","EntryCard","MissingEntityCard","onRemove","entryStatus","defaultTitle","description","getEntityDescription","status","thumbnailElement","icon","withDragHandle","onEdit","MenuItem","renderDropdown","assetCard","cardDropdown","truncated","overflow","textOverflow","renderAssetInfo","entityFile","fileName","mimeType","fileSize","image","SectionTitle","isTruncated","shortenStorageUnit","renderActions","window","open","FetchingWrappedAssetCard","assets","assetId","fields","AssetCard","asSquare","groupToIconMap","archive","src","video","audio","richtext","presentation","spreadsheet","pdfdocument","plaintext","markup","mimetype","getGroupLabel","fallbackFileName","getLinkedContentTypeIdsForNodeType","removeSelectionLabel","SYS_LINK_TYPES","LINK_TYPE_SELECTION_VALUES","HyperlinkModal","enabledLinkTypes","defaultLinkType","linkText","setLinkText","linkType","setLinkType","linkTarget","setLinkTarget","linkEntity","setLinkEntity","entityToLink","dialogs","selectSingleEntry","selectSingleAsset","EntityProvider","ModalContent","Form","FormControl","isRequired","Label","TextInput","onChange","Select","Option","HelpText","FormLabel","htmlFor","TextLink","ModalControls","addOrEditLink","selectionBeforeBlur","currentLinkText","ModalDialogLauncher","openDialog","shouldCloseOnEscapePress","shouldCloseOnOverlayClick","allowHeightOverflow","ReactEditor","hyperlinkWrapper","display","hyperlink","fill","gray900","hyperlinkIEFallback","textDecoration","hyperlinkIcon","top","webkitTransition","transition","createHyperlinkPlugin","renderElement","getRenderElement","pluginKeys","inlineTypes","getPlatePluginTypes","onKeyDown","buildHyperlinkEventHandler","hyperlinkOptions","entryHyperlinkOptions","assetHyperlinkOptions","isAnchor","nodeName","getAttribute","isEntryAnchor","isAssetAnchor","isMod","isK","wasHyperlinkEventTriggered","EntityHyperlink","stopPropagation","targetWrapperClassName","maxWidth","as","ToolbarHyperlinkButton","LinkIcon","withHyperlinkOptions","href","rel","insertTableAndFocusFirstCell","insertTable","header","tablePath","anchor","setSelection","moveToFirstCellFromSelectedTable","previousPath","previous","isAncestorEmpty","moveNodes","to","replaceEmptyParagraphWithTable","useTracking","onAction","onViewportAction","actionName","origin","TrackingProvider","useTrackingContext","addRow","getNextRowPath","someNode","getPlatePluginType","ELEMENT_TABLE","currentRowItem","ELEMENT_TR","currentRowElem","nextRowPath","getEmptyRowNode","colCount","start","addRowBelow","currentRowPath","addRowAbove","addColumn","getNextCellPath","currentCellItem","ELEMENT_TD","ELEMENT_TH","currentTableItem","newCellPath","replacePathPos","_","rowIdx","getEmptyCellNode","addColumnRight","currentCellPath","addColumnLeft","topRight","right","TableActions","useState","isHeaderEnabled","setHeaderEnabled","close","useCallback","useEffect","tableItem","firstRow","getChildren","TABLE_HEADER_CELL","isTableHeaderEnabled","canInsertRowAbove","useMemo","toggleHeader","enable","TABLE_CELL","setHeader","action","cb","tableSize","table","numRows","numColumns","_firstRow$children","getTableSize","getCurrentTableSize","onOpen","IconButton","tabIndex","Divider","deleteRow","deleteColumn","deleteTable","withNormalizer","handler","passed","normalizeTableCell","isTableCell","normalizeTable","TABLE_ROW","withTableOptions","hasTables","isTableHeaderCell","createTablePlugin","tracking","createTablePluginFromUdecode","handleKeyDownFromPlateUdecode","getTableOnKeyDown","currentSelectionStartsTableCell","nextNode","descendants","isCommon","getNextNode","TABLE_BLOCKS","_editor$selection2","isAtEndOfTextSelection","currentSelectionPrecedesTableCell","withOverrides","insertData","getData","markupBefore","markupAfter","tablePasted","hasHeadersOutsideFirstRow","addTableTrackingEvents","addTableNormalizers","fragments","ToolbarTableButton","el","isTableActive","TableIcon","EmbeddedEntityDropdownButton","onToggle","PlusIcon","IS_EDGE_LEGACY","navigator","test","userAgent","HAS_BEFORE_INPUT_SUPPORT","globalThis","InputEvent","getTargetRanges","marginBottom","LinkedEntityBlock","useSelected","useReadOnly","handleEditClick","openAsset","openEntry","slideIn","handleRemoveClick","pathToElement","findPath","draggable","newEntitySelectorConfigFromRichTextField","getEntityTypeFromRichTextNode","words","indexOf","selectEntityAndInsert","logAction","baseConfig","selectEntity","config","withCreate","insertBlock","linkedEntityBlock","createNode","EmbeddedEntityBlockToolbarIcon","isButton","noop","getEntityTypeFromNodeType","baseClass","AssetIcon","EmbeddedEntryBlockIcon","Flex","alignItems","flexDirection","Icon","createEmbeddedEntityPlugin","getWithEmbeddedEntityEvents","voidTypes","entityTypes","EMBEDDED_ASSET","embeddedEntityId","createEmbeddedEntryBlockPlugin","createEmbeddedAssetBlockPlugin","withEmbeddedEntryBlockOptions","withEmbeddedAssetBlockOptions","isShift","pathToSelectedElement","isE","wasEmbeddedEntryEventTriggered","isA","wasEmbeddedAssetEventTriggered","scheduledIcon","verticalAlign","FetchingWrappedInlineEntryCard","allContentTypes","InlineEntryCard","createInlineEntryNode","webkitUserSelect","mozUserSelect","msUserSelect","userSelect","inlineEntryNode","ToolbarEmbeddedEntityInlineButton","EmbeddedEntryInlineIcon","createEmbeddedEntityInlinePlugin","getWithEmbeddedEntryInlineEvents","withEmbeddedEntityInlineOptions","isTwo","wasEmbeddedEntryInlineEventTriggered","EmbedEntityWidget","canInsertBlocks","isEmbedDropdownOpen","setEmbedDropdownOpen","onCloseEntityDropdown","canAccessAssets","setCanAccessAssets","access","can","inlineEntryEmbedEnabled","blockEntryEmbedEnabled","blockAssetEmbedEnabled","shouldDisplayDropdown","toolbar","backgroundColor","spacingXs","divider","embedActionsWrapper","webkitAlignSelf","alignSelf","msFlexItemAlign","formattingOptionsWrapper","msFlexAlign","webkitBoxAlign","msFlexWrap","flexWrap","Toolbar","validationInfo","isAnyMarkEnabled","someWithValidation","vals","validation","val","isAnyHyperlinkEnabled","isAnyBlockFormattingEnabled","isListSelected","isBlockquoteSelected","shouldDisableTables","Fragment","nativeSticky","StickyToolbarWrapper","TEXT_PARENT_NODES","isTextElement","wrapNode","isHTMLElement","ELEMENT_NODE","removeChildNodes","predicate","childNodes","removeChild","removeChildNodesUsingPredicate","nodeList","removeCommentChildren","COMMENT_NODE","DISALLOWED_TABLE_CHILD_ELEMENTS","isTableElement","tagName","removeDisallowedTableChildElements","sanitizeDocument","apply","doc","removeTableGrandchildren","Paragraph","ELEMENT_PARAGRAPH","ConnectedRichTextEditor","sanitizeIncomingSlateDoc","toSlatejsDocument","Contentful","schema","setValue","classNames","isToolbarHidden","plugins","plugin","elementKeys","deserializer","DND_BLOCKED_ELEMENTS","DRAGGABLE_TYPES","ON_DROP_ALLOWED_TYPES","createReactPlugin","createHistoryPlugin","html","newData","DataTransfer","setData","htmlToDataTransfer","DOMParser","parseFromString","sanitizedDoc","XMLSerializer","serializeToString","sanitizeHtml","createExitBreakPlugin","before","query","liftNodes","blockedElementType","SlateNode","isNode","callback","matchNode","onDrop","draggingBlock","getNodes","draggingNode","nativeEvent","dropDisallowed","parents","parentNode","unshift","getParents","_ON_DROP_ALLOWED_TYPE","history","undos","nodeNames","getToggleElementOnKeyDown","deserializeNode","textContent","isEmpty","hasAttribute","isEmbed","isInline","validLiChildrenTypes","createPlateListPlugin","headingType","index","renderLeaf","getRenderLeaf","getToggleMarkOnKeyDown","isGoogleBoldWrapper","startsWith","isBold","style","createTrailingBlockPlugin","deleteForward","_editor$selection","createDeserializeHTMLPlugin","createDeserializeAstPlugin","getPlugins","Plate","initialValue","editableProps","readOnly","newValue","slateDoc","sanitizeSlateDoc","parentNodeType","wrapOrphanedTextNode","contentfulDoc","toContentfulDocument","HyperlinkDialog","handleSubmit","_this","getValue","selectEntry","entitySelectorConfigs","setTargetEntity","selectAsset","isEntityLink","entityLinks","allowedHyperlinkTypes","setState","isLinkComplete","hideText","render","labels","renderFields","_this2","confirm","isUriInputAutoFocused","e","_this3","autoFocus","isFeaturingEntitySelector","placeholder","renderEntityField","entityLink","isEntitySelectorVisible","required","_this4","renderEntitySelector","marginTop","Component","propTypes","PropTypes","shape","oneOf","arrayOf","bool","func","defaultProps","isInitiallyDisabled","otherProps","isEmptyValue","deepEquals","FieldConnector","throttle","isEqualValues","externalReset","lastRemoteValue","parameters","invocation","startAutoResizer"],"mappings":"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"}