@strapi/content-manager 5.58.0 → 5.59.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/components/ConfigurationForm/Fields.js +4 -3
- package/dist/admin/components/ConfigurationForm/Fields.js.map +1 -1
- package/dist/admin/components/ConfigurationForm/Fields.mjs +4 -3
- package/dist/admin/components/ConfigurationForm/Fields.mjs.map +1 -1
- package/dist/admin/components/RelativeTime.js +2 -1
- package/dist/admin/components/RelativeTime.js.map +1 -1
- package/dist/admin/components/RelativeTime.mjs +2 -1
- package/dist/admin/components/RelativeTime.mjs.map +1 -1
- package/dist/admin/content-manager.js.map +1 -1
- package/dist/admin/content-manager.mjs.map +1 -1
- package/dist/admin/history/components/VersionContent.js +8 -8
- package/dist/admin/history/components/VersionContent.js.map +1 -1
- package/dist/admin/history/components/VersionContent.mjs +8 -8
- package/dist/admin/history/components/VersionContent.mjs.map +1 -1
- package/dist/admin/hooks/useDocumentActions.js.map +1 -1
- package/dist/admin/hooks/useDocumentActions.mjs.map +1 -1
- package/dist/admin/hooks/useDocumentLayout.js.map +1 -1
- package/dist/admin/hooks/useDocumentLayout.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksEditor.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksEditor.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Component/Input.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Component/Input.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Component/NonRepeatable.js +2 -2
- package/dist/admin/pages/EditView/components/FormInputs/Component/NonRepeatable.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Component/NonRepeatable.mjs +2 -2
- package/dist/admin/pages/EditView/components/FormInputs/Component/NonRepeatable.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Component/Repeatable.js +7 -6
- package/dist/admin/pages/EditView/components/FormInputs/Component/Repeatable.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Component/Repeatable.mjs +7 -6
- package/dist/admin/pages/EditView/components/FormInputs/Component/Repeatable.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.js +2 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.mjs +2 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/ComponentPicker.js +2 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/ComponentPicker.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/ComponentPicker.mjs +2 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/ComponentPicker.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.js +4 -3
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.mjs +4 -3
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/Field.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/Field.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.js +4 -4
- package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.mjs +4 -4
- package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/UID.js +2 -1
- package/dist/admin/pages/EditView/components/FormInputs/UID.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/UID.mjs +2 -1
- package/dist/admin/pages/EditView/components/FormInputs/UID.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/Editor.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/Editor.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormLayout.js +4 -4
- package/dist/admin/pages/EditView/components/FormLayout.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormLayout.mjs +4 -4
- package/dist/admin/pages/EditView/components/FormLayout.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/Panels.js.map +1 -1
- package/dist/admin/pages/EditView/components/Panels.mjs.map +1 -1
- package/dist/admin/pages/EditView/utils/data.js +3 -3
- package/dist/admin/pages/EditView/utils/data.js.map +1 -1
- package/dist/admin/pages/EditView/utils/data.mjs +3 -3
- package/dist/admin/pages/EditView/utils/data.mjs.map +1 -1
- package/dist/admin/pages/ListConfiguration/components/Settings.js +3 -3
- package/dist/admin/pages/ListConfiguration/components/Settings.js.map +1 -1
- package/dist/admin/pages/ListConfiguration/components/Settings.mjs +3 -3
- package/dist/admin/pages/ListConfiguration/components/Settings.mjs.map +1 -1
- package/dist/admin/pages/ListConfiguration/components/SortDisplayedFields.js +2 -2
- package/dist/admin/pages/ListConfiguration/components/SortDisplayedFields.js.map +1 -1
- package/dist/admin/pages/ListConfiguration/components/SortDisplayedFields.mjs +2 -2
- package/dist/admin/pages/ListConfiguration/components/SortDisplayedFields.mjs.map +1 -1
- package/dist/admin/pages/ListView/ListViewPage.js +73 -13
- package/dist/admin/pages/ListView/ListViewPage.js.map +1 -1
- package/dist/admin/pages/ListView/ListViewPage.mjs +74 -14
- package/dist/admin/pages/ListView/ListViewPage.mjs.map +1 -1
- package/dist/admin/pages/ListView/components/AutoCloneFailureModal.js +1 -1
- package/dist/admin/pages/ListView/components/AutoCloneFailureModal.js.map +1 -1
- package/dist/admin/pages/ListView/components/AutoCloneFailureModal.mjs +1 -1
- package/dist/admin/pages/ListView/components/AutoCloneFailureModal.mjs.map +1 -1
- package/dist/admin/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.js.map +1 -1
- package/dist/admin/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.mjs.map +1 -1
- package/dist/admin/pages/ListView/components/BulkActions/PublishAction.js +4 -1
- package/dist/admin/pages/ListView/components/BulkActions/PublishAction.js.map +1 -1
- package/dist/admin/pages/ListView/components/BulkActions/PublishAction.mjs +4 -1
- package/dist/admin/pages/ListView/components/BulkActions/PublishAction.mjs.map +1 -1
- package/dist/admin/pages/ListView/components/Filters.js +12 -10
- package/dist/admin/pages/ListView/components/Filters.js.map +1 -1
- package/dist/admin/pages/ListView/components/Filters.mjs +12 -10
- package/dist/admin/pages/ListView/components/Filters.mjs.map +1 -1
- package/dist/admin/pages/ListView/components/TableCells/Relations.js.map +1 -1
- package/dist/admin/pages/ListView/components/TableCells/Relations.mjs.map +1 -1
- package/dist/admin/pages/ListView/components/ViewSettingsMenu.js +2 -1
- package/dist/admin/pages/ListView/components/ViewSettingsMenu.js.map +1 -1
- package/dist/admin/pages/ListView/components/ViewSettingsMenu.mjs +2 -1
- package/dist/admin/pages/ListView/components/ViewSettingsMenu.mjs.map +1 -1
- package/dist/admin/pages/ListView/utils/applyAttributeRenames.js +68 -0
- package/dist/admin/pages/ListView/utils/applyAttributeRenames.js.map +1 -0
- package/dist/admin/pages/ListView/utils/applyAttributeRenames.mjs +64 -0
- package/dist/admin/pages/ListView/utils/applyAttributeRenames.mjs.map +1 -0
- package/dist/admin/preview/components/PreviewHeader.js +3 -1
- package/dist/admin/preview/components/PreviewHeader.js.map +1 -1
- package/dist/admin/preview/components/PreviewHeader.mjs +3 -1
- package/dist/admin/preview/components/PreviewHeader.mjs.map +1 -1
- package/dist/admin/services/relations.js +2 -2
- package/dist/admin/services/relations.js.map +1 -1
- package/dist/admin/services/relations.mjs +2 -2
- package/dist/admin/services/relations.mjs.map +1 -1
- package/dist/admin/src/components/ConfigurationForm/Fields.d.ts +1 -1
- package/dist/admin/src/pages/ListView/utils/applyAttributeRenames.d.ts +12 -0
- package/dist/admin/translations/eu.json.js +3 -3
- package/dist/admin/translations/eu.json.mjs +3 -3
- package/dist/admin/translations/gu.json.js +4 -4
- package/dist/admin/translations/gu.json.mjs +4 -4
- package/dist/admin/translations/hi.json.js +9 -9
- package/dist/admin/translations/hi.json.mjs +9 -9
- package/dist/admin/translations/ml.json.js +6 -6
- package/dist/admin/translations/ml.json.mjs +6 -6
- package/dist/admin/translations/sa.json.js +10 -10
- package/dist/admin/translations/sa.json.mjs +10 -10
- package/dist/server/homepage/services/homepage.js.map +1 -1
- package/dist/server/homepage/services/homepage.mjs.map +1 -1
- package/dist/server/preview/services/preview-config.js.map +1 -1
- package/dist/server/preview/services/preview-config.mjs.map +1 -1
- package/dist/server/register.js +6 -0
- package/dist/server/register.js.map +1 -1
- package/dist/server/register.mjs +6 -0
- package/dist/server/register.mjs.map +1 -1
- package/dist/server/services/components.js.map +1 -1
- package/dist/server/services/components.mjs.map +1 -1
- package/dist/server/services/configuration/rename-fields.js +68 -0
- package/dist/server/services/configuration/rename-fields.js.map +1 -0
- package/dist/server/services/configuration/rename-fields.mjs +66 -0
- package/dist/server/services/configuration/rename-fields.mjs.map +1 -0
- package/dist/server/services/utils/configuration/attribute-renames.js +164 -0
- package/dist/server/services/utils/configuration/attribute-renames.js.map +1 -0
- package/dist/server/services/utils/configuration/attribute-renames.mjs +161 -0
- package/dist/server/services/utils/configuration/attribute-renames.mjs.map +1 -0
- package/dist/server/services/utils/configuration/attributes.js +12 -12
- package/dist/server/services/utils/configuration/attributes.js.map +1 -1
- package/dist/server/services/utils/configuration/attributes.mjs +12 -12
- package/dist/server/services/utils/configuration/attributes.mjs.map +1 -1
- package/dist/server/src/homepage/services/homepage.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +2 -0
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/preview/services/index.d.ts.map +1 -1
- package/dist/server/src/preview/services/preview-config.d.ts.map +1 -1
- package/dist/server/src/register.d.ts.map +1 -1
- package/dist/server/src/services/components.d.ts +2 -0
- package/dist/server/src/services/components.d.ts.map +1 -1
- package/dist/server/src/services/configuration/rename-fields.d.ts +15 -0
- package/dist/server/src/services/configuration/rename-fields.d.ts.map +1 -0
- package/dist/server/src/services/index.d.ts +2 -0
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/utils/configuration/attribute-renames.d.ts +57 -0
- package/dist/server/src/services/utils/configuration/attribute-renames.d.ts.map +1 -0
- package/dist/shared/contracts/content-types.d.ts +5 -0
- package/dist/shared/contracts/content-types.d.ts.map +1 -1
- package/package.json +6 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BlocksEditor.js","sources":["../../../../../../../admin/src/pages/EditView/components/FormInputs/BlocksInput/BlocksEditor.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n createContext,\n useStrapiApp,\n type FieldValue,\n useIsMobile,\n} from '@strapi/admin/strapi-admin';\nimport { IconButton, Divider, VisuallyHidden } from '@strapi/design-system';\nimport { Expand } from '@strapi/icons';\nimport { flushSync } from 'react-dom';\nimport { MessageDescriptor, useIntl } from 'react-intl';\nimport { Editor, type Descendant, createEditor, Transforms, Element, Node } from 'slate';\nimport { withHistory } from 'slate-history';\nimport { type RenderElementProps, Slate, withReact, ReactEditor, useSlate } from 'slate-react';\nimport { styled, type CSSProperties } from 'styled-components';\n\nimport { ContentManagerPlugin } from '../../../../../content-manager';\nimport { getTranslation } from '../../../../../utils/translations';\n\nimport { BlocksContent, type BlocksContentProps } from './BlocksContent';\nimport { BlocksToolbar } from './BlocksToolbar';\nimport { EditorLayout } from './EditorLayout';\nimport { type ModifiersStore, modifiers } from './Modifiers';\nimport { withStrapiSchema } from './plugins/withStrapiSchema';\nimport { isNonNullable } from './utils/types';\n\nimport type { Schema } from '@strapi/types';\n\n/* -------------------------------------------------------------------------------------------------\n * BlocksEditorProvider\n * -----------------------------------------------------------------------------------------------*/\n\ninterface CustomNode extends Omit<Schema.Attribute.BlocksNode, 'type'> {\n type: Schema.Attribute.BlocksNode['type'] | string;\n level?: number;\n format?: string;\n}\n\ninterface BaseBlock {\n renderElement: (props: RenderElementProps) => React.JSX.Element;\n /** Function to check if a given node is of this type of block */\n matchNode: (node: Schema.Attribute.BlocksNode | CustomNode) => boolean;\n handleConvert?: (editor: Editor) => void | (() => React.JSX.Element);\n handleEnterKey?: (editor: Editor) => void;\n handleBackspaceKey?: (editor: Editor, event: React.KeyboardEvent<HTMLElement>) => void;\n handleTab?: (editor: Editor) => void;\n handleShiftTab?: (editor: Editor) => void;\n snippets?: string[];\n /** Adjust the vertical positioning of the drag-to-reorder grip icon */\n dragHandleTopMargin?: CSSProperties['marginTop'];\n /** A Slate plugin: function that will wrap the editor creation */\n plugin?: (editor: Editor) => Editor;\n /**\n * Function that checks if an element should be draggable\n * @default () => true */\n isDraggable?: (element: Element) => boolean;\n}\n\nexport interface NonSelectorBlock extends BaseBlock {\n isInBlocksSelector?: false;\n}\n\nexport interface SelectorBlock extends BaseBlock {\n isInBlocksSelector: true;\n icon?: React.ComponentType;\n label: MessageDescriptor;\n}\n\ntype NonSelectorBlockKey = 'list-item' | 'link';\n\nconst selectorBlockKeys = [\n 'paragraph',\n 'heading-one',\n 'heading-two',\n 'heading-three',\n 'heading-four',\n 'heading-five',\n 'heading-six',\n 'list-ordered',\n 'list-unordered',\n 'image',\n 'quote',\n 'code',\n] as const;\n\ntype SelectorBlockKey = (typeof selectorBlockKeys)[number];\n\nconst isSelectorBlockKey = (key: unknown): key is SelectorBlockKey => {\n return typeof key === 'string' && selectorBlockKeys.includes(key as SelectorBlockKey);\n};\n\ntype BlocksStore = {\n [K in SelectorBlockKey]: SelectorBlock;\n} & {\n [K in NonSelectorBlockKey]: NonSelectorBlock;\n};\n\ntype RichTextBlocksStore = Partial<BlocksStore> & Record<string, SelectorBlock | NonSelectorBlock>;\n\ninterface BlocksEditorContextValue {\n blocks: RichTextBlocksStore;\n modifiers: ModifiersStore;\n disabled: boolean;\n name: string;\n setLiveText: (text: string) => void;\n isExpandedMode: boolean;\n /** Push debounced Slate → form sync immediately (e.g. on Editable blur before Save). */\n flushPendingFormSync: () => void;\n}\n\nconst [BlocksEditorProvider, usePartialBlocksEditorContext] =\n createContext<BlocksEditorContextValue>('BlocksEditor');\n\nfunction useBlocksEditorContext(consumerName: string): BlocksEditorContextValue & {\n editor: Editor;\n} {\n const context = usePartialBlocksEditorContext(consumerName, (state) => state);\n const editor = useSlate();\n\n return {\n ...context,\n editor,\n };\n}\n\n/* -------------------------------------------------------------------------------------------------\n * BlocksEditor\n * -----------------------------------------------------------------------------------------------*/\n\nconst EditorDivider = styled(Divider)`\n background: ${({ theme }) => theme.colors.neutral200};\n`;\n\n/**\n * Forces an update of the Slate editor when the value prop changes from outside of Slate.\n * The root cause is that Slate is not a controlled component: https://github.com/ianstormtaylor/slate/issues/4612\n * Why not use JSON.stringify(value) as the key?\n * Because it would force a rerender of the entire editor every time the user types a character.\n * Why not use the entity id as the key, since it's unique for each locale?\n * Because it would not solve the problem when using the \"fill in from other locale\" feature\n */\nfunction useResetKey(\n editor: Editor,\n value?: Schema.Attribute.BlocksValue\n): {\n key: number;\n incrementSlateUpdatesCount: () => void;\n} {\n // Keep track how many times Slate detected a change from a user interaction in the editor\n const slateUpdatesCount = React.useRef(0);\n // Keep track of how many times the value prop was updated, whether from within editor or from outside\n const valueUpdatesCount = React.useRef(0);\n // Use a key to force a rerender of the Slate editor when needed\n const [key, setKey] = React.useState(0);\n\n React.useEffect(() => {\n valueUpdatesCount.current += 1;\n\n // If the 2 refs are not equal, it means the value was updated from outside\n if (valueUpdatesCount.current !== slateUpdatesCount.current) {\n // Bring the 2 refs back in sync\n slateUpdatesCount.current = valueUpdatesCount.current;\n\n // The update may just be an echo of the editor's own content coming back through the form\n // (e.g. the debounced sync, or a re-render while document queries settle). Remounting in\n // that case is pointless and destructive: it wipes pending input and the DOM under the\n // user's caret. Only force a remount when the content is actually different.\n const externalState = value?.length ? normalizeBlocksState(editor, value) : null;\n const editorState = normalizeBlocksState(editor, editor.children);\n if (JSON.stringify(externalState) === JSON.stringify(editorState)) {\n return;\n }\n\n // The remount reuses the same editor instance, so a selection pointing into the old\n // content would survive it and crash slate-react's toDOMPoint when the new content is\n // shorter. Drop the selection before swapping the children.\n if (editor.selection) {\n Transforms.deselect(editor);\n }\n\n // Change the key to force a rerender of the Slate editor,\n // which will pick up the new value through its initialValue prop\n setKey((previousKey) => previousKey + 1);\n }\n }, [editor, value]);\n\n const incrementSlateUpdatesCount = React.useCallback(() => {\n slateUpdatesCount.current += 1;\n }, []);\n\n return { key, incrementSlateUpdatesCount };\n}\n\nconst pipe =\n (...fns: ((baseEditor: Editor) => Editor)[]) =>\n (value: Editor) =>\n fns.reduce<Editor>((prev, fn) => fn(prev), value);\n\n/**\n * Normalize the blocks state to null if the editor state is considered empty,\n * otherwise return the state\n */\nconst normalizeBlocksState = (\n editor: Editor,\n value: Schema.Attribute.BlocksValue | Descendant[]\n): Schema.Attribute.BlocksValue | Descendant[] | null => {\n const isEmpty =\n value.length === 1 && Editor.isEmpty(editor, value[0] as Schema.Attribute.BlocksNode);\n\n return isEmpty ? null : value;\n};\n\ninterface BlocksEditorProps\n extends Pick<FieldValue<Schema.Attribute.BlocksValue>, 'onChange' | 'value' | 'error'>,\n BlocksContentProps {\n disabled?: boolean;\n name: string;\n /** When true, sync form state on every keystroke (Live Preview popover). */\n livePreviewSync?: boolean;\n /** Index of the block that was double-clicked in the live preview. When provided,\n * the editor positions the Slate cursor at that block on mount instead of using autoFocus. */\n blockIndex?: number | null;\n}\n\nconst BlocksEditor = React.forwardRef<{ focus: () => void }, BlocksEditorProps>(\n (\n {\n disabled = false,\n name,\n onChange,\n value,\n error,\n livePreviewSync = false,\n blockIndex,\n ...contentProps\n },\n forwardedRef\n ) => {\n const { formatMessage } = useIntl();\n const isMobile = useIsMobile();\n\n const blocks = useStrapiApp(\n 'BlocksEditor',\n (state) =>\n (\n state.plugins['content-manager']?.apis as\n | ContentManagerPlugin['config']['apis']\n | undefined\n )?.getRichTextBlocks() ?? ({} as RichTextBlocksStore)\n );\n\n const blockRegisteredPlugins = Object.values(blocks)\n .map((block) => block.plugin)\n .filter(isNonNullable);\n\n const [editor] = React.useState(() =>\n pipe(withHistory, withStrapiSchema, withReact, ...blockRegisteredPlugins)(createEditor())\n );\n const [liveText, setLiveText] = React.useState('');\n const ariaDescriptionId = React.useId();\n const [isExpandedMode, handleToggleExpand] = React.useReducer((prev) => !prev, false);\n\n /**\n * Editable is not able to hold the ref, https://github.com/ianstormtaylor/slate/issues/4082\n * so with \"useImperativeHandle\" we can use ReactEditor methods to expose to the parent above\n * also not passing forwarded ref here, gives console warning.\n */\n React.useImperativeHandle(\n forwardedRef,\n () => ({\n focus() {\n ReactEditor.focus(editor);\n },\n }),\n [editor]\n );\n\n const { key, incrementSlateUpdatesCount } = useResetKey(editor, value);\n\n const debounceTimeout = React.useRef<NodeJS.Timeout | null>(null);\n\n const flushPendingFormSync = React.useCallback(() => {\n if (!debounceTimeout.current) {\n return;\n }\n clearTimeout(debounceTimeout.current);\n debounceTimeout.current = null;\n // Counter was already bumped when the AST changed; only push form state here.\n // Ensure Strapi Form state updates before the next event (e.g. Save click) reads values.\n flushSync(() => {\n onChange(\n name,\n normalizeBlocksState(editor, editor.children) as Schema.Attribute.BlocksValue\n );\n });\n }, [editor, name, onChange]);\n\n const handleSlateChange = React.useCallback(\n (state: Descendant[]) => {\n const isAstChange = editor.operations.some((op) => op.type !== 'set_selection');\n\n if (isAstChange) {\n /**\n * Slate handles the state of the editor internally. We just need to keep Strapi's form\n * state in sync with it in order to make sure that things like the \"modified\" state\n * isn't broken. Updating the whole state on every change is very expensive however,\n * so we debounce calls to onChange to mitigate input lag.\n *\n * Bump the reset-key counter immediately (not inside the debounce). Otherwise any\n * value-prop identity change during the 300ms window — e.g. clicking the blocks\n * toolbar — looks like an external update with stale empty form state and remounts\n * the editor, wiping the pending input (blocks e2e flake).\n */\n incrementSlateUpdatesCount();\n if (livePreviewSync) {\n onChange(name, normalizeBlocksState(editor, state) as Schema.Attribute.BlocksValue);\n return;\n }\n\n if (debounceTimeout.current) {\n clearTimeout(debounceTimeout.current);\n }\n\n debounceTimeout.current = setTimeout(() => {\n // Normalize the state (empty editor becomes null)\n onChange(name, normalizeBlocksState(editor, state) as Schema.Attribute.BlocksValue);\n debounceTimeout.current = null;\n }, 300);\n }\n },\n [editor, incrementSlateUpdatesCount, livePreviewSync, name, onChange]\n );\n\n // Clean up the timeout on unmount\n React.useEffect(() => {\n return () => {\n if (debounceTimeout.current) {\n clearTimeout(debounceTimeout.current);\n }\n };\n }, []);\n\n // When opened from a live-preview double-click, position the cursor at the clicked block\n React.useEffect(() => {\n if (blockIndex == null) return;\n\n const targetIndex = Math.min(blockIndex, editor.children.length - 1);\n\n try {\n Transforms.select(editor, Editor.start(editor, [targetIndex]));\n } catch {\n // Slate tree not yet ready; skip cursor positioning and scroll\n return;\n }\n try {\n ReactEditor.focus(editor);\n } catch {\n // non-fatal — editor DOM not yet committed\n }\n\n // Defer scroll past the re-render triggered by Transforms.select above.\n // Slate's handleScrollSelectionIntoView runs as a layout effect during\n // that re-render; our rAF fires after it, letting us override the position.\n const raf = requestAnimationFrame(() => {\n try {\n const blockNode = Node.get(editor, [targetIndex]);\n const domEl = ReactEditor.toDOMNode(editor, blockNode as Element);\n // Walk to BlocksContent's scroll container via the Slate editor root,\n // bypassing scrollIntoView which can target overflow:hidden ancestors.\n const editorDomEl = domEl.closest('[data-slate-editor]');\n const scrollContainer = editorDomEl?.parentElement as HTMLElement | null;\n if (scrollContainer) {\n const blockRect = domEl.getBoundingClientRect();\n const containerRect = scrollContainer.getBoundingClientRect();\n // 24px = BlocksContent paddingTop={6} (design-system 4px scale)\n scrollContainer.scrollTop =\n blockRect.top - containerRect.top + scrollContainer.scrollTop - 24;\n } else {\n domEl.scrollIntoView({ block: 'start' });\n }\n } catch {\n // scroll errors are non-fatal; the cursor is already positioned\n }\n });\n\n return () => cancelAnimationFrame(raf);\n // `key` is included so that if useResetKey remounts the Slate editor (clearing\n // editor.selection to null), this effect re-runs and restores the cursor position.\n }, [blockIndex, editor, key]);\n\n // Ensure the editor is in sync after discard\n React.useEffect(() => {\n // Never deselect while the editor is actively focused (typing / editing),\n if (ReactEditor.isFocused(editor)) {\n return;\n }\n\n // Normalize empty states for comparison to avoid losing focus on the editor when content is deleted\n const normalizedValue = value?.length ? value : null;\n const normalizedEditorState = normalizeBlocksState(editor, editor.children);\n\n // Compare the field value with the editor state to check for a stale selection\n if (\n normalizedValue &&\n normalizedEditorState &&\n JSON.stringify(normalizedEditorState) !== JSON.stringify(normalizedValue)\n ) {\n // When there is a diff, unset selection to avoid an invalid state\n Transforms.deselect(editor);\n }\n }, [editor, value]);\n\n return (\n <>\n <VisuallyHidden id={ariaDescriptionId}>\n {formatMessage({\n id: getTranslation('components.Blocks.dnd.instruction'),\n defaultMessage: `To reorder blocks, press Command or Control along with Shift and the Up or Down arrow keys`,\n })}\n </VisuallyHidden>\n <VisuallyHidden aria-live=\"assertive\">{liveText}</VisuallyHidden>\n <Slate\n editor={editor}\n initialValue={\n value?.length ? value : [{ type: 'paragraph', children: [{ type: 'text', text: '' }] }]\n }\n onChange={handleSlateChange}\n key={key}\n >\n <BlocksEditorProvider\n blocks={blocks}\n modifiers={modifiers}\n disabled={disabled}\n name={name}\n setLiveText={setLiveText}\n isExpandedMode={isExpandedMode}\n flushPendingFormSync={flushPendingFormSync}\n >\n <EditorLayout\n error={error}\n disabled={disabled}\n onToggleExpand={handleToggleExpand}\n ariaDescriptionId={ariaDescriptionId}\n livePreviewSync={livePreviewSync}\n >\n <BlocksToolbar />\n <EditorDivider width=\"100%\" />\n <BlocksContent {...contentProps} />\n {!isExpandedMode && !isMobile && (\n <IconButton\n position=\"absolute\"\n bottom=\"1.2rem\"\n right=\"1.2rem\"\n shadow=\"filterShadow\"\n label={formatMessage({\n id: getTranslation('components.Blocks.expand'),\n defaultMessage: 'Expand',\n })}\n onClick={handleToggleExpand}\n >\n <Expand />\n </IconButton>\n )}\n </EditorLayout>\n </BlocksEditorProvider>\n </Slate>\n </>\n );\n }\n);\n\nexport {\n type BlocksStore,\n type RichTextBlocksStore,\n type SelectorBlockKey,\n BlocksEditor,\n BlocksEditorProvider,\n useBlocksEditorContext,\n isSelectorBlockKey,\n normalizeBlocksState,\n};\n"],"names":["BlocksEditorProvider","usePartialBlocksEditorContext","createContext","useBlocksEditorContext","consumerName","context","state","editor","useSlate","EditorDivider","styled","Divider","theme","colors","neutral200","useResetKey","value","slateUpdatesCount","React","useRef","valueUpdatesCount","key","setKey","useState","useEffect","current","externalState","length","normalizeBlocksState","editorState","children","JSON","stringify","selection","Transforms","deselect","previousKey","incrementSlateUpdatesCount","useCallback","pipe","fns","reduce","prev","fn","isEmpty","Editor","BlocksEditor","forwardRef","disabled","name","onChange","error","livePreviewSync","blockIndex","contentProps","forwardedRef","formatMessage","useIntl","isMobile","useIsMobile","blocks","useStrapiApp","plugins","apis","getRichTextBlocks","blockRegisteredPlugins","Object","values","map","block","plugin","filter","isNonNullable","withHistory","withStrapiSchema","withReact","createEditor","liveText","setLiveText","ariaDescriptionId","useId","isExpandedMode","handleToggleExpand","useReducer","useImperativeHandle","focus","ReactEditor","debounceTimeout","flushPendingFormSync","clearTimeout","flushSync","handleSlateChange","isAstChange","operations","some","op","type","setTimeout","targetIndex","Math","min","select","start","raf","requestAnimationFrame","blockNode","Node","get","domEl","toDOMNode","editorDomEl","closest","scrollContainer","parentElement","blockRect","getBoundingClientRect","containerRect","scrollTop","top","scrollIntoView","cancelAnimationFrame","isFocused","normalizedValue","normalizedEditorState","_jsxs","_Fragment","_jsx","VisuallyHidden","id","getTranslation","defaultMessage","aria-live","Slate","initialValue","text","modifiers","EditorLayout","onToggleExpand","BlocksToolbar","width","BlocksContent","IconButton","position","bottom","right","shadow","label","onClick","Expand"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BlocksEditor.js","sources":["../../../../../../../admin/src/pages/EditView/components/FormInputs/BlocksInput/BlocksEditor.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n createContext,\n useStrapiApp,\n type FieldValue,\n useIsMobile,\n} from '@strapi/admin/strapi-admin';\nimport { IconButton, Divider, VisuallyHidden } from '@strapi/design-system';\nimport { Expand } from '@strapi/icons';\nimport { flushSync } from 'react-dom';\nimport { MessageDescriptor, useIntl } from 'react-intl';\nimport { Editor, type Descendant, createEditor, Transforms, Element, Node } from 'slate';\nimport { withHistory } from 'slate-history';\nimport { type RenderElementProps, Slate, withReact, ReactEditor, useSlate } from 'slate-react';\nimport { styled, type CSSProperties } from 'styled-components';\n\nimport { ContentManagerPlugin } from '../../../../../content-manager';\nimport { getTranslation } from '../../../../../utils/translations';\n\nimport { BlocksContent, type BlocksContentProps } from './BlocksContent';\nimport { BlocksToolbar } from './BlocksToolbar';\nimport { EditorLayout } from './EditorLayout';\nimport { type ModifiersStore, modifiers } from './Modifiers';\nimport { withStrapiSchema } from './plugins/withStrapiSchema';\nimport { isNonNullable } from './utils/types';\n\nimport type { Schema } from '@strapi/types';\n\n/* -------------------------------------------------------------------------------------------------\n * BlocksEditorProvider\n * -----------------------------------------------------------------------------------------------*/\n\ninterface CustomNode extends Omit<Schema.Attribute.BlocksNode, 'type'> {\n type: Schema.Attribute.BlocksNode['type'] | string;\n level?: number;\n format?: string;\n}\n\ninterface BaseBlock {\n renderElement: (props: RenderElementProps) => React.JSX.Element;\n /** Function to check if a given node is of this type of block */\n matchNode: (node: Schema.Attribute.BlocksNode | CustomNode) => boolean;\n handleConvert?: (editor: Editor) => void | (() => React.JSX.Element);\n handleEnterKey?: (editor: Editor) => void;\n handleBackspaceKey?: (editor: Editor, event: React.KeyboardEvent<HTMLElement>) => void;\n handleTab?: (editor: Editor) => void;\n handleShiftTab?: (editor: Editor) => void;\n snippets?: string[];\n /** Adjust the vertical positioning of the drag-to-reorder grip icon */\n dragHandleTopMargin?: CSSProperties['marginTop'];\n /** A Slate plugin: function that will wrap the editor creation */\n plugin?: (editor: Editor) => Editor;\n /**\n * Function that checks if an element should be draggable\n * @default () => true */\n isDraggable?: (element: Element) => boolean;\n}\n\nexport interface NonSelectorBlock extends BaseBlock {\n isInBlocksSelector?: false;\n}\n\nexport interface SelectorBlock extends BaseBlock {\n isInBlocksSelector: true;\n icon?: React.ComponentType;\n label: MessageDescriptor;\n}\n\ntype NonSelectorBlockKey = 'list-item' | 'link';\n\nconst selectorBlockKeys = [\n 'paragraph',\n 'heading-one',\n 'heading-two',\n 'heading-three',\n 'heading-four',\n 'heading-five',\n 'heading-six',\n 'list-ordered',\n 'list-unordered',\n 'image',\n 'quote',\n 'code',\n] as const;\n\ntype SelectorBlockKey = (typeof selectorBlockKeys)[number];\n\nconst isSelectorBlockKey = (key: unknown): key is SelectorBlockKey => {\n return typeof key === 'string' && selectorBlockKeys.includes(key as SelectorBlockKey);\n};\n\ntype BlocksStore = {\n [K in SelectorBlockKey]: SelectorBlock;\n} & {\n [K in NonSelectorBlockKey]: NonSelectorBlock;\n};\n\ntype RichTextBlocksStore = Partial<BlocksStore> & Record<string, SelectorBlock | NonSelectorBlock>;\n\ninterface BlocksEditorContextValue {\n blocks: RichTextBlocksStore;\n modifiers: ModifiersStore;\n disabled: boolean;\n name: string;\n setLiveText: (text: string) => void;\n isExpandedMode: boolean;\n /** Push debounced Slate → form sync immediately (e.g. on Editable blur before Save). */\n flushPendingFormSync: () => void;\n}\n\nconst [BlocksEditorProvider, usePartialBlocksEditorContext] =\n createContext<BlocksEditorContextValue>('BlocksEditor');\n\nfunction useBlocksEditorContext(consumerName: string): BlocksEditorContextValue & {\n editor: Editor;\n} {\n const context = usePartialBlocksEditorContext(consumerName, (state) => state);\n const editor = useSlate();\n\n return {\n ...context,\n editor,\n };\n}\n\n/* -------------------------------------------------------------------------------------------------\n * BlocksEditor\n * -----------------------------------------------------------------------------------------------*/\n\nconst EditorDivider = styled(Divider)`\n background: ${({ theme }) => theme.colors.neutral200};\n`;\n\n/**\n * Forces an update of the Slate editor when the value prop changes from outside of Slate.\n * The root cause is that Slate is not a controlled component: https://github.com/ianstormtaylor/slate/issues/4612\n * Why not use JSON.stringify(value) as the key?\n * Because it would force a rerender of the entire editor every time the user types a character.\n * Why not use the entity id as the key, since it's unique for each locale?\n * Because it would not solve the problem when using the \"fill in from other locale\" feature\n */\nfunction useResetKey(\n editor: Editor,\n value?: Schema.Attribute.BlocksValue\n): {\n key: number;\n incrementSlateUpdatesCount: () => void;\n} {\n // Keep track how many times Slate detected a change from a user interaction in the editor\n const slateUpdatesCount = React.useRef(0);\n // Keep track of how many times the value prop was updated, whether from within editor or from outside\n const valueUpdatesCount = React.useRef(0);\n // Use a key to force a rerender of the Slate editor when needed\n const [key, setKey] = React.useState(0);\n\n React.useEffect(() => {\n valueUpdatesCount.current += 1;\n\n // If the 2 refs are not equal, it means the value was updated from outside\n if (valueUpdatesCount.current !== slateUpdatesCount.current) {\n // Bring the 2 refs back in sync\n slateUpdatesCount.current = valueUpdatesCount.current;\n\n // The update may just be an echo of the editor's own content coming back through the form\n // (e.g. the debounced sync, or a re-render while document queries settle). Remounting in\n // that case is pointless and destructive: it wipes pending input and the DOM under the\n // user's caret. Only force a remount when the content is actually different.\n const externalState = value?.length ? normalizeBlocksState(editor, value) : null;\n const editorState = normalizeBlocksState(editor, editor.children);\n if (JSON.stringify(externalState) === JSON.stringify(editorState)) {\n return;\n }\n\n // The remount reuses the same editor instance, so a selection pointing into the old\n // content would survive it and crash slate-react's toDOMPoint when the new content is\n // shorter. Drop the selection before swapping the children.\n if (editor.selection) {\n Transforms.deselect(editor);\n }\n\n // Change the key to force a rerender of the Slate editor,\n // which will pick up the new value through its initialValue prop\n setKey((previousKey) => previousKey + 1);\n }\n }, [editor, value]);\n\n const incrementSlateUpdatesCount = React.useCallback(() => {\n slateUpdatesCount.current += 1;\n }, []);\n\n return { key, incrementSlateUpdatesCount };\n}\n\nconst pipe =\n (...fns: ((baseEditor: Editor) => Editor)[]) =>\n (value: Editor) =>\n fns.reduce<Editor>((prev, fn) => fn(prev), value);\n\n/**\n * Normalize the blocks state to null if the editor state is considered empty,\n * otherwise return the state\n */\nconst normalizeBlocksState = (\n editor: Editor,\n value: Schema.Attribute.BlocksValue | Descendant[]\n): Schema.Attribute.BlocksValue | Descendant[] | null => {\n const isEmpty =\n value.length === 1 && Editor.isEmpty(editor, value[0] as Schema.Attribute.BlocksNode);\n\n return isEmpty ? null : value;\n};\n\ninterface BlocksEditorProps\n extends\n Pick<FieldValue<Schema.Attribute.BlocksValue>, 'onChange' | 'value' | 'error'>,\n BlocksContentProps {\n disabled?: boolean;\n name: string;\n /** When true, sync form state on every keystroke (Live Preview popover). */\n livePreviewSync?: boolean;\n /** Index of the block that was double-clicked in the live preview. When provided,\n * the editor positions the Slate cursor at that block on mount instead of using autoFocus. */\n blockIndex?: number | null;\n}\n\nconst BlocksEditor = React.forwardRef<{ focus: () => void }, BlocksEditorProps>(\n (\n {\n disabled = false,\n name,\n onChange,\n value,\n error,\n livePreviewSync = false,\n blockIndex,\n ...contentProps\n },\n forwardedRef\n ) => {\n const { formatMessage } = useIntl();\n const isMobile = useIsMobile();\n\n const blocks = useStrapiApp(\n 'BlocksEditor',\n (state) =>\n (\n state.plugins['content-manager']?.apis as\n ContentManagerPlugin['config']['apis'] | undefined\n )?.getRichTextBlocks() ?? ({} as RichTextBlocksStore)\n );\n\n const blockRegisteredPlugins = Object.values(blocks)\n .map((block) => block.plugin)\n .filter(isNonNullable);\n\n const [editor] = React.useState(() =>\n pipe(withHistory, withStrapiSchema, withReact, ...blockRegisteredPlugins)(createEditor())\n );\n const [liveText, setLiveText] = React.useState('');\n const ariaDescriptionId = React.useId();\n const [isExpandedMode, handleToggleExpand] = React.useReducer((prev) => !prev, false);\n\n /**\n * Editable is not able to hold the ref, https://github.com/ianstormtaylor/slate/issues/4082\n * so with \"useImperativeHandle\" we can use ReactEditor methods to expose to the parent above\n * also not passing forwarded ref here, gives console warning.\n */\n React.useImperativeHandle(\n forwardedRef,\n () => ({\n focus() {\n ReactEditor.focus(editor);\n },\n }),\n [editor]\n );\n\n const { key, incrementSlateUpdatesCount } = useResetKey(editor, value);\n\n const debounceTimeout = React.useRef<NodeJS.Timeout | null>(null);\n\n const flushPendingFormSync = React.useCallback(() => {\n if (!debounceTimeout.current) {\n return;\n }\n clearTimeout(debounceTimeout.current);\n debounceTimeout.current = null;\n // Counter was already bumped when the AST changed; only push form state here.\n // Ensure Strapi Form state updates before the next event (e.g. Save click) reads values.\n flushSync(() => {\n onChange(\n name,\n normalizeBlocksState(editor, editor.children) as Schema.Attribute.BlocksValue\n );\n });\n }, [editor, name, onChange]);\n\n const handleSlateChange = React.useCallback(\n (state: Descendant[]) => {\n const isAstChange = editor.operations.some((op) => op.type !== 'set_selection');\n\n if (isAstChange) {\n /**\n * Slate handles the state of the editor internally. We just need to keep Strapi's form\n * state in sync with it in order to make sure that things like the \"modified\" state\n * isn't broken. Updating the whole state on every change is very expensive however,\n * so we debounce calls to onChange to mitigate input lag.\n *\n * Bump the reset-key counter immediately (not inside the debounce). Otherwise any\n * value-prop identity change during the 300ms window — e.g. clicking the blocks\n * toolbar — looks like an external update with stale empty form state and remounts\n * the editor, wiping the pending input (blocks e2e flake).\n */\n incrementSlateUpdatesCount();\n if (livePreviewSync) {\n onChange(name, normalizeBlocksState(editor, state) as Schema.Attribute.BlocksValue);\n return;\n }\n\n if (debounceTimeout.current) {\n clearTimeout(debounceTimeout.current);\n }\n\n debounceTimeout.current = setTimeout(() => {\n // Normalize the state (empty editor becomes null)\n onChange(name, normalizeBlocksState(editor, state) as Schema.Attribute.BlocksValue);\n debounceTimeout.current = null;\n }, 300);\n }\n },\n [editor, incrementSlateUpdatesCount, livePreviewSync, name, onChange]\n );\n\n // Clean up the timeout on unmount\n React.useEffect(() => {\n return () => {\n if (debounceTimeout.current) {\n clearTimeout(debounceTimeout.current);\n }\n };\n }, []);\n\n // When opened from a live-preview double-click, position the cursor at the clicked block\n React.useEffect(() => {\n if (blockIndex == null) return;\n\n const targetIndex = Math.min(blockIndex, editor.children.length - 1);\n\n try {\n Transforms.select(editor, Editor.start(editor, [targetIndex]));\n } catch {\n // Slate tree not yet ready; skip cursor positioning and scroll\n return;\n }\n try {\n ReactEditor.focus(editor);\n } catch {\n // non-fatal — editor DOM not yet committed\n }\n\n // Defer scroll past the re-render triggered by Transforms.select above.\n // Slate's handleScrollSelectionIntoView runs as a layout effect during\n // that re-render; our rAF fires after it, letting us override the position.\n const raf = requestAnimationFrame(() => {\n try {\n const blockNode = Node.get(editor, [targetIndex]);\n const domEl = ReactEditor.toDOMNode(editor, blockNode as Element);\n // Walk to BlocksContent's scroll container via the Slate editor root,\n // bypassing scrollIntoView which can target overflow:hidden ancestors.\n const editorDomEl = domEl.closest('[data-slate-editor]');\n const scrollContainer = editorDomEl?.parentElement as HTMLElement | null;\n if (scrollContainer) {\n const blockRect = domEl.getBoundingClientRect();\n const containerRect = scrollContainer.getBoundingClientRect();\n // 24px = BlocksContent paddingTop={6} (design-system 4px scale)\n scrollContainer.scrollTop =\n blockRect.top - containerRect.top + scrollContainer.scrollTop - 24;\n } else {\n domEl.scrollIntoView({ block: 'start' });\n }\n } catch {\n // scroll errors are non-fatal; the cursor is already positioned\n }\n });\n\n return () => cancelAnimationFrame(raf);\n // `key` is included so that if useResetKey remounts the Slate editor (clearing\n // editor.selection to null), this effect re-runs and restores the cursor position.\n }, [blockIndex, editor, key]);\n\n // Ensure the editor is in sync after discard\n React.useEffect(() => {\n // Never deselect while the editor is actively focused (typing / editing),\n if (ReactEditor.isFocused(editor)) {\n return;\n }\n\n // Normalize empty states for comparison to avoid losing focus on the editor when content is deleted\n const normalizedValue = value?.length ? value : null;\n const normalizedEditorState = normalizeBlocksState(editor, editor.children);\n\n // Compare the field value with the editor state to check for a stale selection\n if (\n normalizedValue &&\n normalizedEditorState &&\n JSON.stringify(normalizedEditorState) !== JSON.stringify(normalizedValue)\n ) {\n // When there is a diff, unset selection to avoid an invalid state\n Transforms.deselect(editor);\n }\n }, [editor, value]);\n\n return (\n <>\n <VisuallyHidden id={ariaDescriptionId}>\n {formatMessage({\n id: getTranslation('components.Blocks.dnd.instruction'),\n defaultMessage: `To reorder blocks, press Command or Control along with Shift and the Up or Down arrow keys`,\n })}\n </VisuallyHidden>\n <VisuallyHidden aria-live=\"assertive\">{liveText}</VisuallyHidden>\n <Slate\n editor={editor}\n initialValue={\n value?.length ? value : [{ type: 'paragraph', children: [{ type: 'text', text: '' }] }]\n }\n onChange={handleSlateChange}\n key={key}\n >\n <BlocksEditorProvider\n blocks={blocks}\n modifiers={modifiers}\n disabled={disabled}\n name={name}\n setLiveText={setLiveText}\n isExpandedMode={isExpandedMode}\n flushPendingFormSync={flushPendingFormSync}\n >\n <EditorLayout\n error={error}\n disabled={disabled}\n onToggleExpand={handleToggleExpand}\n ariaDescriptionId={ariaDescriptionId}\n livePreviewSync={livePreviewSync}\n >\n <BlocksToolbar />\n <EditorDivider width=\"100%\" />\n <BlocksContent {...contentProps} />\n {!isExpandedMode && !isMobile && (\n <IconButton\n position=\"absolute\"\n bottom=\"1.2rem\"\n right=\"1.2rem\"\n shadow=\"filterShadow\"\n label={formatMessage({\n id: getTranslation('components.Blocks.expand'),\n defaultMessage: 'Expand',\n })}\n onClick={handleToggleExpand}\n >\n <Expand />\n </IconButton>\n )}\n </EditorLayout>\n </BlocksEditorProvider>\n </Slate>\n </>\n );\n }\n);\n\nexport {\n type BlocksStore,\n type RichTextBlocksStore,\n type SelectorBlockKey,\n BlocksEditor,\n BlocksEditorProvider,\n useBlocksEditorContext,\n isSelectorBlockKey,\n normalizeBlocksState,\n};\n"],"names":["BlocksEditorProvider","usePartialBlocksEditorContext","createContext","useBlocksEditorContext","consumerName","context","state","editor","useSlate","EditorDivider","styled","Divider","theme","colors","neutral200","useResetKey","value","slateUpdatesCount","React","useRef","valueUpdatesCount","key","setKey","useState","useEffect","current","externalState","length","normalizeBlocksState","editorState","children","JSON","stringify","selection","Transforms","deselect","previousKey","incrementSlateUpdatesCount","useCallback","pipe","fns","reduce","prev","fn","isEmpty","Editor","BlocksEditor","forwardRef","disabled","name","onChange","error","livePreviewSync","blockIndex","contentProps","forwardedRef","formatMessage","useIntl","isMobile","useIsMobile","blocks","useStrapiApp","plugins","apis","getRichTextBlocks","blockRegisteredPlugins","Object","values","map","block","plugin","filter","isNonNullable","withHistory","withStrapiSchema","withReact","createEditor","liveText","setLiveText","ariaDescriptionId","useId","isExpandedMode","handleToggleExpand","useReducer","useImperativeHandle","focus","ReactEditor","debounceTimeout","flushPendingFormSync","clearTimeout","flushSync","handleSlateChange","isAstChange","operations","some","op","type","setTimeout","targetIndex","Math","min","select","start","raf","requestAnimationFrame","blockNode","Node","get","domEl","toDOMNode","editorDomEl","closest","scrollContainer","parentElement","blockRect","getBoundingClientRect","containerRect","scrollTop","top","scrollIntoView","cancelAnimationFrame","isFocused","normalizedValue","normalizedEditorState","_jsxs","_Fragment","_jsx","VisuallyHidden","id","getTranslation","defaultMessage","aria-live","Slate","initialValue","text","modifiers","EditorLayout","onToggleExpand","BlocksToolbar","width","BlocksContent","IconButton","position","bottom","right","shadow","label","onClick","Expand"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+GA,MAAM,CAACA,oBAAAA,EAAsBC,6BAAAA,CAA8B,GACzDC,yBAAAA,CAAwC,cAAA;AAE1C,SAASC,uBAAuBC,YAAoB,EAAA;AAGlD,IAAA,MAAMC,OAAAA,GAAUJ,6BAAAA,CAA8BG,YAAAA,EAAc,CAACE,KAAAA,GAAUA,KAAAA,CAAAA;AACvE,IAAA,MAAMC,MAAAA,GAASC,mBAAAA,EAAAA;IAEf,OAAO;AACL,QAAA,GAAGH,OAAO;AACVE,QAAAA;AACF,KAAA;AACF;AAEA;;AAEkG,qGAElG,MAAME,aAAAA,GAAgBC,uBAAAA,CAAOC,oBAAAA,CAAQ;cACvB,EAAE,CAAC,EAAEC,KAAK,EAAE,GAAKA,KAAAA,CAAMC,MAAM,CAACC,UAAU,CAAC;AACvD,CAAC;AAED;;;;;;;AAOC,IACD,SAASC,WAAAA,CACPR,MAAc,EACdS,KAAoC,EAAA;;IAMpC,MAAMC,iBAAAA,GAAoBC,gBAAAA,CAAMC,MAAM,CAAC,CAAA,CAAA;;IAEvC,MAAMC,iBAAAA,GAAoBF,gBAAAA,CAAMC,MAAM,CAAC,CAAA,CAAA;;AAEvC,IAAA,MAAM,CAACE,GAAAA,EAAKC,MAAAA,CAAO,GAAGJ,gBAAAA,CAAMK,QAAQ,CAAC,CAAA,CAAA;AAErCL,IAAAA,gBAAAA,CAAMM,SAAS,CAAC,IAAA;AACdJ,QAAAA,iBAAAA,CAAkBK,OAAO,IAAI,CAAA;;AAG7B,QAAA,IAAIL,iBAAAA,CAAkBK,OAAO,KAAKR,iBAAAA,CAAkBQ,OAAO,EAAE;;YAE3DR,iBAAAA,CAAkBQ,OAAO,GAAGL,iBAAAA,CAAkBK,OAAO;;;;;AAMrD,YAAA,MAAMC,aAAAA,GAAgBV,KAAAA,EAAOW,MAAAA,GAASC,oBAAAA,CAAqBrB,QAAQS,KAAAA,CAAAA,GAAS,IAAA;AAC5E,YAAA,MAAMa,WAAAA,GAAcD,oBAAAA,CAAqBrB,MAAAA,EAAQA,MAAAA,CAAOuB,QAAQ,CAAA;AAChE,YAAA,IAAIC,KAAKC,SAAS,CAACN,mBAAmBK,IAAAA,CAAKC,SAAS,CAACH,WAAAA,CAAAA,EAAc;AACjE,gBAAA;AACF,YAAA;;;;YAKA,IAAItB,MAAAA,CAAO0B,SAAS,EAAE;AACpBC,gBAAAA,gBAAAA,CAAWC,QAAQ,CAAC5B,MAAAA,CAAAA;AACtB,YAAA;;;YAIAe,MAAAA,CAAO,CAACc,cAAgBA,WAAAA,GAAc,CAAA,CAAA;AACxC,QAAA;IACF,CAAA,EAAG;AAAC7B,QAAAA,MAAAA;AAAQS,QAAAA;AAAM,KAAA,CAAA;IAElB,MAAMqB,0BAAAA,GAA6BnB,gBAAAA,CAAMoB,WAAW,CAAC,IAAA;AACnDrB,QAAAA,iBAAAA,CAAkBQ,OAAO,IAAI,CAAA;AAC/B,IAAA,CAAA,EAAG,EAAE,CAAA;IAEL,OAAO;AAAEJ,QAAAA,GAAAA;AAAKgB,QAAAA;AAA2B,KAAA;AAC3C;AAEA,MAAME,IAAAA,GACJ,CAAC,GAAGC,GAAAA,GACJ,CAACxB,KAAAA,GACCwB,GAAAA,CAAIC,MAAM,CAAS,CAACC,IAAAA,EAAMC,EAAAA,GAAOA,GAAGD,IAAAA,CAAAA,EAAO1B,KAAAA,CAAAA;AAE/C;;;IAIA,MAAMY,oBAAAA,GAAuB,CAC3BrB,MAAAA,EACAS,KAAAA,GAAAA;IAEA,MAAM4B,OAAAA,GACJ5B,KAAAA,CAAMW,MAAM,KAAK,CAAA,IAAKkB,YAAAA,CAAOD,OAAO,CAACrC,MAAAA,EAAQS,KAAK,CAAC,CAAA,CAAE,CAAA;AAEvD,IAAA,OAAO4B,UAAU,IAAA,GAAO5B,KAAAA;AAC1B;AAeA,MAAM8B,YAAAA,iBAAe5B,gBAAAA,CAAM6B,UAAU,CACnC,CACE,EACEC,QAAAA,GAAW,KAAK,EAChBC,IAAI,EACJC,QAAQ,EACRlC,KAAK,EACLmC,KAAK,EACLC,eAAAA,GAAkB,KAAK,EACvBC,UAAU,EACV,GAAGC,YAAAA,EACJ,EACDC,YAAAA,GAAAA;IAEA,MAAM,EAAEC,aAAa,EAAE,GAAGC,iBAAAA,EAAAA;AAC1B,IAAA,MAAMC,QAAAA,GAAWC,uBAAAA,EAAAA;AAEjB,IAAA,MAAMC,MAAAA,GAASC,wBAAAA,CACb,cAAA,EACA,CAACvD,KAAAA,GAEGA,KAAAA,CAAMwD,OAAO,CAAC,iBAAA,CAAkB,EAAEC,IAAAA,EAEjCC,uBAAwB,EAAC,CAAA;AAGhC,IAAA,MAAMC,sBAAAA,GAAyBC,MAAAA,CAAOC,MAAM,CAACP,MAAAA,CAAAA,CAC1CQ,GAAG,CAAC,CAACC,KAAAA,GAAUA,KAAAA,CAAMC,MAAM,CAAA,CAC3BC,MAAM,CAACC,mBAAAA,CAAAA;IAEV,MAAM,CAACjE,MAAAA,CAAO,GAAGW,gBAAAA,CAAMK,QAAQ,CAAC,IAC9BgB,IAAAA,CAAKkC,wBAAAA,EAAaC,iCAAAA,EAAkBC,oBAAAA,EAAAA,GAAcV,sBAAAA,CAAAA,CAAwBW,kBAAAA,EAAAA,CAAAA,CAAAA;AAE5E,IAAA,MAAM,CAACC,QAAAA,EAAUC,WAAAA,CAAY,GAAG5D,gBAAAA,CAAMK,QAAQ,CAAC,EAAA,CAAA;IAC/C,MAAMwD,iBAAAA,GAAoB7D,iBAAM8D,KAAK,EAAA;IACrC,MAAM,CAACC,cAAAA,EAAgBC,kBAAAA,CAAmB,GAAGhE,gBAAAA,CAAMiE,UAAU,CAAC,CAACzC,IAAAA,GAAS,CAACA,IAAAA,EAAM,KAAA,CAAA;AAE/E;;;;AAIC,QACDxB,gBAAAA,CAAMkE,mBAAmB,CACvB7B,YAAAA,EACA,KAAO;AACL8B,YAAAA,KAAAA,CAAAA,GAAAA;AACEC,gBAAAA,sBAAAA,CAAYD,KAAK,CAAC9E,MAAAA,CAAAA;AACpB,YAAA;AACF,SAAA,CAAA,EACA;AAACA,QAAAA;AAAO,KAAA,CAAA;AAGV,IAAA,MAAM,EAAEc,GAAG,EAAEgB,0BAA0B,EAAE,GAAGtB,YAAYR,MAAAA,EAAQS,KAAAA,CAAAA;IAEhE,MAAMuE,eAAAA,GAAkBrE,gBAAAA,CAAMC,MAAM,CAAwB,IAAA,CAAA;IAE5D,MAAMqE,oBAAAA,GAAuBtE,gBAAAA,CAAMoB,WAAW,CAAC,IAAA;QAC7C,IAAI,CAACiD,eAAAA,CAAgB9D,OAAO,EAAE;AAC5B,YAAA;AACF,QAAA;AACAgE,QAAAA,YAAAA,CAAaF,gBAAgB9D,OAAO,CAAA;AACpC8D,QAAAA,eAAAA,CAAgB9D,OAAO,GAAG,IAAA;;;QAG1BiE,kBAAAA,CAAU,IAAA;AACRxC,YAAAA,QAAAA,CACED,IAAAA,EACArB,oBAAAA,CAAqBrB,MAAAA,EAAQA,MAAAA,CAAOuB,QAAQ,CAAA,CAAA;AAEhD,QAAA,CAAA,CAAA;IACF,CAAA,EAAG;AAACvB,QAAAA,MAAAA;AAAQ0C,QAAAA,IAAAA;AAAMC,QAAAA;AAAS,KAAA,CAAA;AAE3B,IAAA,MAAMyC,iBAAAA,GAAoBzE,gBAAAA,CAAMoB,WAAW,CACzC,CAAChC,KAAAA,GAAAA;QACC,MAAMsF,WAAAA,GAAcrF,MAAAA,CAAOsF,UAAU,CAACC,IAAI,CAAC,CAACC,EAAAA,GAAOA,EAAAA,CAAGC,IAAI,KAAK,eAAA,CAAA;AAE/D,QAAA,IAAIJ,WAAAA,EAAa;AACf;;;;;;;;;;cAWAvD,0BAAAA,EAAAA;AACA,YAAA,IAAIe,eAAAA,EAAiB;gBACnBF,QAAAA,CAASD,IAAAA,EAAMrB,qBAAqBrB,MAAAA,EAAQD,KAAAA,CAAAA,CAAAA;AAC5C,gBAAA;AACF,YAAA;YAEA,IAAIiF,eAAAA,CAAgB9D,OAAO,EAAE;AAC3BgE,gBAAAA,YAAAA,CAAaF,gBAAgB9D,OAAO,CAAA;AACtC,YAAA;YAEA8D,eAAAA,CAAgB9D,OAAO,GAAGwE,UAAAA,CAAW,IAAA;;gBAEnC/C,QAAAA,CAASD,IAAAA,EAAMrB,qBAAqBrB,MAAAA,EAAQD,KAAAA,CAAAA,CAAAA;AAC5CiF,gBAAAA,eAAAA,CAAgB9D,OAAO,GAAG,IAAA;YAC5B,CAAA,EAAG,GAAA,CAAA;AACL,QAAA;IACF,CAAA,EACA;AAAClB,QAAAA,MAAAA;AAAQ8B,QAAAA,0BAAAA;AAA4Be,QAAAA,eAAAA;AAAiBH,QAAAA,IAAAA;AAAMC,QAAAA;AAAS,KAAA,CAAA;;AAIvEhC,IAAAA,gBAAAA,CAAMM,SAAS,CAAC,IAAA;QACd,OAAO,IAAA;YACL,IAAI+D,eAAAA,CAAgB9D,OAAO,EAAE;AAC3BgE,gBAAAA,YAAAA,CAAaF,gBAAgB9D,OAAO,CAAA;AACtC,YAAA;AACF,QAAA,CAAA;AACF,IAAA,CAAA,EAAG,EAAE,CAAA;;AAGLP,IAAAA,gBAAAA,CAAMM,SAAS,CAAC,IAAA;AACd,QAAA,IAAI6B,cAAc,IAAA,EAAM;QAExB,MAAM6C,WAAAA,GAAcC,KAAKC,GAAG,CAAC/C,YAAY9C,MAAAA,CAAOuB,QAAQ,CAACH,MAAM,GAAG,CAAA,CAAA;QAElE,IAAI;AACFO,YAAAA,gBAAAA,CAAWmE,MAAM,CAAC9F,MAAAA,EAAQsC,YAAAA,CAAOyD,KAAK,CAAC/F,MAAAA,EAAQ;AAAC2F,gBAAAA;AAAY,aAAA,CAAA,CAAA;AAC9D,QAAA,CAAA,CAAE,OAAM;;AAEN,YAAA;AACF,QAAA;QACA,IAAI;AACFZ,YAAAA,sBAAAA,CAAYD,KAAK,CAAC9E,MAAAA,CAAAA;AACpB,QAAA,CAAA,CAAE,OAAM;;AAER,QAAA;;;;AAKA,QAAA,MAAMgG,MAAMC,qBAAAA,CAAsB,IAAA;YAChC,IAAI;AACF,gBAAA,MAAMC,SAAAA,GAAYC,UAAAA,CAAKC,GAAG,CAACpG,MAAAA,EAAQ;AAAC2F,oBAAAA;AAAY,iBAAA,CAAA;AAChD,gBAAA,MAAMU,KAAAA,GAAQtB,sBAAAA,CAAYuB,SAAS,CAACtG,MAAAA,EAAQkG,SAAAA,CAAAA;;;gBAG5C,MAAMK,WAAAA,GAAcF,KAAAA,CAAMG,OAAO,CAAC,qBAAA,CAAA;AAClC,gBAAA,MAAMC,kBAAkBF,WAAAA,EAAaG,aAAAA;AACrC,gBAAA,IAAID,eAAAA,EAAiB;oBACnB,MAAME,SAAAA,GAAYN,MAAMO,qBAAqB,EAAA;oBAC7C,MAAMC,aAAAA,GAAgBJ,gBAAgBG,qBAAqB,EAAA;;oBAE3DH,eAAAA,CAAgBK,SAAS,GACvBH,SAAAA,CAAUI,GAAG,GAAGF,cAAcE,GAAG,GAAGN,eAAAA,CAAgBK,SAAS,GAAG,EAAA;gBACpE,CAAA,MAAO;AACLT,oBAAAA,KAAAA,CAAMW,cAAc,CAAC;wBAAElD,KAAAA,EAAO;AAAQ,qBAAA,CAAA;AACxC,gBAAA;AACF,YAAA,CAAA,CAAE,OAAM;;AAER,YAAA;AACF,QAAA,CAAA,CAAA;AAEA,QAAA,OAAO,IAAMmD,oBAAAA,CAAqBjB,GAAAA,CAAAA;;;IAGpC,CAAA,EAAG;AAAClD,QAAAA,UAAAA;AAAY9C,QAAAA,MAAAA;AAAQc,QAAAA;AAAI,KAAA,CAAA;;AAG5BH,IAAAA,gBAAAA,CAAMM,SAAS,CAAC,IAAA;;QAEd,IAAI8D,sBAAAA,CAAYmC,SAAS,CAAClH,MAAAA,CAAAA,EAAS;AACjC,YAAA;AACF,QAAA;;QAGA,MAAMmH,eAAAA,GAAkB1G,KAAAA,EAAOW,MAAAA,GAASX,KAAAA,GAAQ,IAAA;AAChD,QAAA,MAAM2G,qBAAAA,GAAwB/F,oBAAAA,CAAqBrB,MAAAA,EAAQA,MAAAA,CAAOuB,QAAQ,CAAA;;QAG1E,IACE4F,eAAAA,IACAC,yBACA5F,IAAAA,CAAKC,SAAS,CAAC2F,qBAAAA,CAAAA,KAA2B5F,IAAAA,CAAKC,SAAS,CAAC0F,eAAAA,CAAAA,EACzD;;AAEAxF,YAAAA,gBAAAA,CAAWC,QAAQ,CAAC5B,MAAAA,CAAAA;AACtB,QAAA;IACF,CAAA,EAAG;AAACA,QAAAA,MAAAA;AAAQS,QAAAA;AAAM,KAAA,CAAA;IAElB,qBACE4G,eAAA,CAAAC,mBAAA,EAAA;;0BACEC,cAAA,CAACC,2BAAAA,EAAAA;gBAAeC,EAAAA,EAAIjD,iBAAAA;0BACjBvB,aAAAA,CAAc;AACbwE,oBAAAA,EAAAA,EAAIC,2BAAAA,CAAe,mCAAA,CAAA;oBACnBC,cAAAA,EAAgB,CAAC,0FAA0F;AAC7G,iBAAA;;0BAEFJ,cAAA,CAACC,2BAAAA,EAAAA;gBAAeI,WAAAA,EAAU,WAAA;AAAatD,gBAAAA,QAAAA,EAAAA;;0BACvCiD,cAAA,CAACM,gBAAAA,EAAAA;gBACC7H,MAAAA,EAAQA,MAAAA;gBACR8H,YAAAA,EACErH,KAAAA,EAAOW,SAASX,KAAAA,GAAQ;AAAC,oBAAA;wBAAEgF,IAAAA,EAAM,WAAA;wBAAalE,QAAAA,EAAU;AAAC,4BAAA;gCAAEkE,IAAAA,EAAM,MAAA;gCAAQsC,IAAAA,EAAM;AAAG;AAAE;AAAC;AAAE,iBAAA;gBAEzFpF,QAAAA,EAAUyC,iBAAAA;AAGV,gBAAA,QAAA,gBAAAmC,cAAA,CAAC9H,oBAAAA,EAAAA;oBACC4D,MAAAA,EAAQA,MAAAA;oBACR2E,SAAAA,EAAWA,mBAAAA;oBACXvF,QAAAA,EAAUA,QAAAA;oBACVC,IAAAA,EAAMA,IAAAA;oBACN6B,WAAAA,EAAaA,WAAAA;oBACbG,cAAAA,EAAgBA,cAAAA;oBAChBO,oBAAAA,EAAsBA,oBAAAA;AAEtB,oBAAA,QAAA,gBAAAoC,eAAA,CAACY,yBAAAA,EAAAA;wBACCrF,KAAAA,EAAOA,KAAAA;wBACPH,QAAAA,EAAUA,QAAAA;wBACVyF,cAAAA,EAAgBvD,kBAAAA;wBAChBH,iBAAAA,EAAmBA,iBAAAA;wBACnB3B,eAAAA,EAAiBA,eAAAA;;0CAEjB0E,cAAA,CAACY,2BAAAA,EAAAA,EAAAA,CAAAA;0CACDZ,cAAA,CAACrH,aAAAA,EAAAA;gCAAckI,KAAAA,EAAM;;0CACrBb,cAAA,CAACc,2BAAAA,EAAAA;AAAe,gCAAA,GAAGtF;;4BAClB,CAAC2B,cAAAA,IAAkB,CAACvB,QAAAA,kBACnBoE,cAAA,CAACe,uBAAAA,EAAAA;gCACCC,QAAAA,EAAS,UAAA;gCACTC,MAAAA,EAAO,QAAA;gCACPC,KAAAA,EAAM,QAAA;gCACNC,MAAAA,EAAO,cAAA;AACPC,gCAAAA,KAAAA,EAAO1F,aAAAA,CAAc;AACnBwE,oCAAAA,EAAAA,EAAIC,2BAAAA,CAAe,0BAAA,CAAA;oCACnBC,cAAAA,EAAgB;AAClB,iCAAA,CAAA;gCACAiB,OAAAA,EAASjE,kBAAAA;AAET,gCAAA,QAAA,gBAAA4C,cAAA,CAACsB,YAAAA,EAAAA,EAAAA;;;;;AAjCJ/H,aAAAA,EAAAA,GAAAA;;;AAyCb,CAAA;;;;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BlocksEditor.mjs","sources":["../../../../../../../admin/src/pages/EditView/components/FormInputs/BlocksInput/BlocksEditor.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n createContext,\n useStrapiApp,\n type FieldValue,\n useIsMobile,\n} from '@strapi/admin/strapi-admin';\nimport { IconButton, Divider, VisuallyHidden } from '@strapi/design-system';\nimport { Expand } from '@strapi/icons';\nimport { flushSync } from 'react-dom';\nimport { MessageDescriptor, useIntl } from 'react-intl';\nimport { Editor, type Descendant, createEditor, Transforms, Element, Node } from 'slate';\nimport { withHistory } from 'slate-history';\nimport { type RenderElementProps, Slate, withReact, ReactEditor, useSlate } from 'slate-react';\nimport { styled, type CSSProperties } from 'styled-components';\n\nimport { ContentManagerPlugin } from '../../../../../content-manager';\nimport { getTranslation } from '../../../../../utils/translations';\n\nimport { BlocksContent, type BlocksContentProps } from './BlocksContent';\nimport { BlocksToolbar } from './BlocksToolbar';\nimport { EditorLayout } from './EditorLayout';\nimport { type ModifiersStore, modifiers } from './Modifiers';\nimport { withStrapiSchema } from './plugins/withStrapiSchema';\nimport { isNonNullable } from './utils/types';\n\nimport type { Schema } from '@strapi/types';\n\n/* -------------------------------------------------------------------------------------------------\n * BlocksEditorProvider\n * -----------------------------------------------------------------------------------------------*/\n\ninterface CustomNode extends Omit<Schema.Attribute.BlocksNode, 'type'> {\n type: Schema.Attribute.BlocksNode['type'] | string;\n level?: number;\n format?: string;\n}\n\ninterface BaseBlock {\n renderElement: (props: RenderElementProps) => React.JSX.Element;\n /** Function to check if a given node is of this type of block */\n matchNode: (node: Schema.Attribute.BlocksNode | CustomNode) => boolean;\n handleConvert?: (editor: Editor) => void | (() => React.JSX.Element);\n handleEnterKey?: (editor: Editor) => void;\n handleBackspaceKey?: (editor: Editor, event: React.KeyboardEvent<HTMLElement>) => void;\n handleTab?: (editor: Editor) => void;\n handleShiftTab?: (editor: Editor) => void;\n snippets?: string[];\n /** Adjust the vertical positioning of the drag-to-reorder grip icon */\n dragHandleTopMargin?: CSSProperties['marginTop'];\n /** A Slate plugin: function that will wrap the editor creation */\n plugin?: (editor: Editor) => Editor;\n /**\n * Function that checks if an element should be draggable\n * @default () => true */\n isDraggable?: (element: Element) => boolean;\n}\n\nexport interface NonSelectorBlock extends BaseBlock {\n isInBlocksSelector?: false;\n}\n\nexport interface SelectorBlock extends BaseBlock {\n isInBlocksSelector: true;\n icon?: React.ComponentType;\n label: MessageDescriptor;\n}\n\ntype NonSelectorBlockKey = 'list-item' | 'link';\n\nconst selectorBlockKeys = [\n 'paragraph',\n 'heading-one',\n 'heading-two',\n 'heading-three',\n 'heading-four',\n 'heading-five',\n 'heading-six',\n 'list-ordered',\n 'list-unordered',\n 'image',\n 'quote',\n 'code',\n] as const;\n\ntype SelectorBlockKey = (typeof selectorBlockKeys)[number];\n\nconst isSelectorBlockKey = (key: unknown): key is SelectorBlockKey => {\n return typeof key === 'string' && selectorBlockKeys.includes(key as SelectorBlockKey);\n};\n\ntype BlocksStore = {\n [K in SelectorBlockKey]: SelectorBlock;\n} & {\n [K in NonSelectorBlockKey]: NonSelectorBlock;\n};\n\ntype RichTextBlocksStore = Partial<BlocksStore> & Record<string, SelectorBlock | NonSelectorBlock>;\n\ninterface BlocksEditorContextValue {\n blocks: RichTextBlocksStore;\n modifiers: ModifiersStore;\n disabled: boolean;\n name: string;\n setLiveText: (text: string) => void;\n isExpandedMode: boolean;\n /** Push debounced Slate → form sync immediately (e.g. on Editable blur before Save). */\n flushPendingFormSync: () => void;\n}\n\nconst [BlocksEditorProvider, usePartialBlocksEditorContext] =\n createContext<BlocksEditorContextValue>('BlocksEditor');\n\nfunction useBlocksEditorContext(consumerName: string): BlocksEditorContextValue & {\n editor: Editor;\n} {\n const context = usePartialBlocksEditorContext(consumerName, (state) => state);\n const editor = useSlate();\n\n return {\n ...context,\n editor,\n };\n}\n\n/* -------------------------------------------------------------------------------------------------\n * BlocksEditor\n * -----------------------------------------------------------------------------------------------*/\n\nconst EditorDivider = styled(Divider)`\n background: ${({ theme }) => theme.colors.neutral200};\n`;\n\n/**\n * Forces an update of the Slate editor when the value prop changes from outside of Slate.\n * The root cause is that Slate is not a controlled component: https://github.com/ianstormtaylor/slate/issues/4612\n * Why not use JSON.stringify(value) as the key?\n * Because it would force a rerender of the entire editor every time the user types a character.\n * Why not use the entity id as the key, since it's unique for each locale?\n * Because it would not solve the problem when using the \"fill in from other locale\" feature\n */\nfunction useResetKey(\n editor: Editor,\n value?: Schema.Attribute.BlocksValue\n): {\n key: number;\n incrementSlateUpdatesCount: () => void;\n} {\n // Keep track how many times Slate detected a change from a user interaction in the editor\n const slateUpdatesCount = React.useRef(0);\n // Keep track of how many times the value prop was updated, whether from within editor or from outside\n const valueUpdatesCount = React.useRef(0);\n // Use a key to force a rerender of the Slate editor when needed\n const [key, setKey] = React.useState(0);\n\n React.useEffect(() => {\n valueUpdatesCount.current += 1;\n\n // If the 2 refs are not equal, it means the value was updated from outside\n if (valueUpdatesCount.current !== slateUpdatesCount.current) {\n // Bring the 2 refs back in sync\n slateUpdatesCount.current = valueUpdatesCount.current;\n\n // The update may just be an echo of the editor's own content coming back through the form\n // (e.g. the debounced sync, or a re-render while document queries settle). Remounting in\n // that case is pointless and destructive: it wipes pending input and the DOM under the\n // user's caret. Only force a remount when the content is actually different.\n const externalState = value?.length ? normalizeBlocksState(editor, value) : null;\n const editorState = normalizeBlocksState(editor, editor.children);\n if (JSON.stringify(externalState) === JSON.stringify(editorState)) {\n return;\n }\n\n // The remount reuses the same editor instance, so a selection pointing into the old\n // content would survive it and crash slate-react's toDOMPoint when the new content is\n // shorter. Drop the selection before swapping the children.\n if (editor.selection) {\n Transforms.deselect(editor);\n }\n\n // Change the key to force a rerender of the Slate editor,\n // which will pick up the new value through its initialValue prop\n setKey((previousKey) => previousKey + 1);\n }\n }, [editor, value]);\n\n const incrementSlateUpdatesCount = React.useCallback(() => {\n slateUpdatesCount.current += 1;\n }, []);\n\n return { key, incrementSlateUpdatesCount };\n}\n\nconst pipe =\n (...fns: ((baseEditor: Editor) => Editor)[]) =>\n (value: Editor) =>\n fns.reduce<Editor>((prev, fn) => fn(prev), value);\n\n/**\n * Normalize the blocks state to null if the editor state is considered empty,\n * otherwise return the state\n */\nconst normalizeBlocksState = (\n editor: Editor,\n value: Schema.Attribute.BlocksValue | Descendant[]\n): Schema.Attribute.BlocksValue | Descendant[] | null => {\n const isEmpty =\n value.length === 1 && Editor.isEmpty(editor, value[0] as Schema.Attribute.BlocksNode);\n\n return isEmpty ? null : value;\n};\n\ninterface BlocksEditorProps\n extends Pick<FieldValue<Schema.Attribute.BlocksValue>, 'onChange' | 'value' | 'error'>,\n BlocksContentProps {\n disabled?: boolean;\n name: string;\n /** When true, sync form state on every keystroke (Live Preview popover). */\n livePreviewSync?: boolean;\n /** Index of the block that was double-clicked in the live preview. When provided,\n * the editor positions the Slate cursor at that block on mount instead of using autoFocus. */\n blockIndex?: number | null;\n}\n\nconst BlocksEditor = React.forwardRef<{ focus: () => void }, BlocksEditorProps>(\n (\n {\n disabled = false,\n name,\n onChange,\n value,\n error,\n livePreviewSync = false,\n blockIndex,\n ...contentProps\n },\n forwardedRef\n ) => {\n const { formatMessage } = useIntl();\n const isMobile = useIsMobile();\n\n const blocks = useStrapiApp(\n 'BlocksEditor',\n (state) =>\n (\n state.plugins['content-manager']?.apis as\n | ContentManagerPlugin['config']['apis']\n | undefined\n )?.getRichTextBlocks() ?? ({} as RichTextBlocksStore)\n );\n\n const blockRegisteredPlugins = Object.values(blocks)\n .map((block) => block.plugin)\n .filter(isNonNullable);\n\n const [editor] = React.useState(() =>\n pipe(withHistory, withStrapiSchema, withReact, ...blockRegisteredPlugins)(createEditor())\n );\n const [liveText, setLiveText] = React.useState('');\n const ariaDescriptionId = React.useId();\n const [isExpandedMode, handleToggleExpand] = React.useReducer((prev) => !prev, false);\n\n /**\n * Editable is not able to hold the ref, https://github.com/ianstormtaylor/slate/issues/4082\n * so with \"useImperativeHandle\" we can use ReactEditor methods to expose to the parent above\n * also not passing forwarded ref here, gives console warning.\n */\n React.useImperativeHandle(\n forwardedRef,\n () => ({\n focus() {\n ReactEditor.focus(editor);\n },\n }),\n [editor]\n );\n\n const { key, incrementSlateUpdatesCount } = useResetKey(editor, value);\n\n const debounceTimeout = React.useRef<NodeJS.Timeout | null>(null);\n\n const flushPendingFormSync = React.useCallback(() => {\n if (!debounceTimeout.current) {\n return;\n }\n clearTimeout(debounceTimeout.current);\n debounceTimeout.current = null;\n // Counter was already bumped when the AST changed; only push form state here.\n // Ensure Strapi Form state updates before the next event (e.g. Save click) reads values.\n flushSync(() => {\n onChange(\n name,\n normalizeBlocksState(editor, editor.children) as Schema.Attribute.BlocksValue\n );\n });\n }, [editor, name, onChange]);\n\n const handleSlateChange = React.useCallback(\n (state: Descendant[]) => {\n const isAstChange = editor.operations.some((op) => op.type !== 'set_selection');\n\n if (isAstChange) {\n /**\n * Slate handles the state of the editor internally. We just need to keep Strapi's form\n * state in sync with it in order to make sure that things like the \"modified\" state\n * isn't broken. Updating the whole state on every change is very expensive however,\n * so we debounce calls to onChange to mitigate input lag.\n *\n * Bump the reset-key counter immediately (not inside the debounce). Otherwise any\n * value-prop identity change during the 300ms window — e.g. clicking the blocks\n * toolbar — looks like an external update with stale empty form state and remounts\n * the editor, wiping the pending input (blocks e2e flake).\n */\n incrementSlateUpdatesCount();\n if (livePreviewSync) {\n onChange(name, normalizeBlocksState(editor, state) as Schema.Attribute.BlocksValue);\n return;\n }\n\n if (debounceTimeout.current) {\n clearTimeout(debounceTimeout.current);\n }\n\n debounceTimeout.current = setTimeout(() => {\n // Normalize the state (empty editor becomes null)\n onChange(name, normalizeBlocksState(editor, state) as Schema.Attribute.BlocksValue);\n debounceTimeout.current = null;\n }, 300);\n }\n },\n [editor, incrementSlateUpdatesCount, livePreviewSync, name, onChange]\n );\n\n // Clean up the timeout on unmount\n React.useEffect(() => {\n return () => {\n if (debounceTimeout.current) {\n clearTimeout(debounceTimeout.current);\n }\n };\n }, []);\n\n // When opened from a live-preview double-click, position the cursor at the clicked block\n React.useEffect(() => {\n if (blockIndex == null) return;\n\n const targetIndex = Math.min(blockIndex, editor.children.length - 1);\n\n try {\n Transforms.select(editor, Editor.start(editor, [targetIndex]));\n } catch {\n // Slate tree not yet ready; skip cursor positioning and scroll\n return;\n }\n try {\n ReactEditor.focus(editor);\n } catch {\n // non-fatal — editor DOM not yet committed\n }\n\n // Defer scroll past the re-render triggered by Transforms.select above.\n // Slate's handleScrollSelectionIntoView runs as a layout effect during\n // that re-render; our rAF fires after it, letting us override the position.\n const raf = requestAnimationFrame(() => {\n try {\n const blockNode = Node.get(editor, [targetIndex]);\n const domEl = ReactEditor.toDOMNode(editor, blockNode as Element);\n // Walk to BlocksContent's scroll container via the Slate editor root,\n // bypassing scrollIntoView which can target overflow:hidden ancestors.\n const editorDomEl = domEl.closest('[data-slate-editor]');\n const scrollContainer = editorDomEl?.parentElement as HTMLElement | null;\n if (scrollContainer) {\n const blockRect = domEl.getBoundingClientRect();\n const containerRect = scrollContainer.getBoundingClientRect();\n // 24px = BlocksContent paddingTop={6} (design-system 4px scale)\n scrollContainer.scrollTop =\n blockRect.top - containerRect.top + scrollContainer.scrollTop - 24;\n } else {\n domEl.scrollIntoView({ block: 'start' });\n }\n } catch {\n // scroll errors are non-fatal; the cursor is already positioned\n }\n });\n\n return () => cancelAnimationFrame(raf);\n // `key` is included so that if useResetKey remounts the Slate editor (clearing\n // editor.selection to null), this effect re-runs and restores the cursor position.\n }, [blockIndex, editor, key]);\n\n // Ensure the editor is in sync after discard\n React.useEffect(() => {\n // Never deselect while the editor is actively focused (typing / editing),\n if (ReactEditor.isFocused(editor)) {\n return;\n }\n\n // Normalize empty states for comparison to avoid losing focus on the editor when content is deleted\n const normalizedValue = value?.length ? value : null;\n const normalizedEditorState = normalizeBlocksState(editor, editor.children);\n\n // Compare the field value with the editor state to check for a stale selection\n if (\n normalizedValue &&\n normalizedEditorState &&\n JSON.stringify(normalizedEditorState) !== JSON.stringify(normalizedValue)\n ) {\n // When there is a diff, unset selection to avoid an invalid state\n Transforms.deselect(editor);\n }\n }, [editor, value]);\n\n return (\n <>\n <VisuallyHidden id={ariaDescriptionId}>\n {formatMessage({\n id: getTranslation('components.Blocks.dnd.instruction'),\n defaultMessage: `To reorder blocks, press Command or Control along with Shift and the Up or Down arrow keys`,\n })}\n </VisuallyHidden>\n <VisuallyHidden aria-live=\"assertive\">{liveText}</VisuallyHidden>\n <Slate\n editor={editor}\n initialValue={\n value?.length ? value : [{ type: 'paragraph', children: [{ type: 'text', text: '' }] }]\n }\n onChange={handleSlateChange}\n key={key}\n >\n <BlocksEditorProvider\n blocks={blocks}\n modifiers={modifiers}\n disabled={disabled}\n name={name}\n setLiveText={setLiveText}\n isExpandedMode={isExpandedMode}\n flushPendingFormSync={flushPendingFormSync}\n >\n <EditorLayout\n error={error}\n disabled={disabled}\n onToggleExpand={handleToggleExpand}\n ariaDescriptionId={ariaDescriptionId}\n livePreviewSync={livePreviewSync}\n >\n <BlocksToolbar />\n <EditorDivider width=\"100%\" />\n <BlocksContent {...contentProps} />\n {!isExpandedMode && !isMobile && (\n <IconButton\n position=\"absolute\"\n bottom=\"1.2rem\"\n right=\"1.2rem\"\n shadow=\"filterShadow\"\n label={formatMessage({\n id: getTranslation('components.Blocks.expand'),\n defaultMessage: 'Expand',\n })}\n onClick={handleToggleExpand}\n >\n <Expand />\n </IconButton>\n )}\n </EditorLayout>\n </BlocksEditorProvider>\n </Slate>\n </>\n );\n }\n);\n\nexport {\n type BlocksStore,\n type RichTextBlocksStore,\n type SelectorBlockKey,\n BlocksEditor,\n BlocksEditorProvider,\n useBlocksEditorContext,\n isSelectorBlockKey,\n normalizeBlocksState,\n};\n"],"names":["BlocksEditorProvider","usePartialBlocksEditorContext","createContext","useBlocksEditorContext","consumerName","context","state","editor","useSlate","EditorDivider","styled","Divider","theme","colors","neutral200","useResetKey","value","slateUpdatesCount","React","useRef","valueUpdatesCount","key","setKey","useState","useEffect","current","externalState","length","normalizeBlocksState","editorState","children","JSON","stringify","selection","Transforms","deselect","previousKey","incrementSlateUpdatesCount","useCallback","pipe","fns","reduce","prev","fn","isEmpty","Editor","BlocksEditor","forwardRef","disabled","name","onChange","error","livePreviewSync","blockIndex","contentProps","forwardedRef","formatMessage","useIntl","isMobile","useIsMobile","blocks","useStrapiApp","plugins","apis","getRichTextBlocks","blockRegisteredPlugins","Object","values","map","block","plugin","filter","isNonNullable","withHistory","withStrapiSchema","withReact","createEditor","liveText","setLiveText","ariaDescriptionId","useId","isExpandedMode","handleToggleExpand","useReducer","useImperativeHandle","focus","ReactEditor","debounceTimeout","flushPendingFormSync","clearTimeout","flushSync","handleSlateChange","isAstChange","operations","some","op","type","setTimeout","targetIndex","Math","min","select","start","raf","requestAnimationFrame","blockNode","Node","get","domEl","toDOMNode","editorDomEl","closest","scrollContainer","parentElement","blockRect","getBoundingClientRect","containerRect","scrollTop","top","scrollIntoView","cancelAnimationFrame","isFocused","normalizedValue","normalizedEditorState","_jsxs","_Fragment","_jsx","VisuallyHidden","id","getTranslation","defaultMessage","aria-live","Slate","initialValue","text","modifiers","EditorLayout","onToggleExpand","BlocksToolbar","width","BlocksContent","IconButton","position","bottom","right","shadow","label","onClick","Expand"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BlocksEditor.mjs","sources":["../../../../../../../admin/src/pages/EditView/components/FormInputs/BlocksInput/BlocksEditor.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n createContext,\n useStrapiApp,\n type FieldValue,\n useIsMobile,\n} from '@strapi/admin/strapi-admin';\nimport { IconButton, Divider, VisuallyHidden } from '@strapi/design-system';\nimport { Expand } from '@strapi/icons';\nimport { flushSync } from 'react-dom';\nimport { MessageDescriptor, useIntl } from 'react-intl';\nimport { Editor, type Descendant, createEditor, Transforms, Element, Node } from 'slate';\nimport { withHistory } from 'slate-history';\nimport { type RenderElementProps, Slate, withReact, ReactEditor, useSlate } from 'slate-react';\nimport { styled, type CSSProperties } from 'styled-components';\n\nimport { ContentManagerPlugin } from '../../../../../content-manager';\nimport { getTranslation } from '../../../../../utils/translations';\n\nimport { BlocksContent, type BlocksContentProps } from './BlocksContent';\nimport { BlocksToolbar } from './BlocksToolbar';\nimport { EditorLayout } from './EditorLayout';\nimport { type ModifiersStore, modifiers } from './Modifiers';\nimport { withStrapiSchema } from './plugins/withStrapiSchema';\nimport { isNonNullable } from './utils/types';\n\nimport type { Schema } from '@strapi/types';\n\n/* -------------------------------------------------------------------------------------------------\n * BlocksEditorProvider\n * -----------------------------------------------------------------------------------------------*/\n\ninterface CustomNode extends Omit<Schema.Attribute.BlocksNode, 'type'> {\n type: Schema.Attribute.BlocksNode['type'] | string;\n level?: number;\n format?: string;\n}\n\ninterface BaseBlock {\n renderElement: (props: RenderElementProps) => React.JSX.Element;\n /** Function to check if a given node is of this type of block */\n matchNode: (node: Schema.Attribute.BlocksNode | CustomNode) => boolean;\n handleConvert?: (editor: Editor) => void | (() => React.JSX.Element);\n handleEnterKey?: (editor: Editor) => void;\n handleBackspaceKey?: (editor: Editor, event: React.KeyboardEvent<HTMLElement>) => void;\n handleTab?: (editor: Editor) => void;\n handleShiftTab?: (editor: Editor) => void;\n snippets?: string[];\n /** Adjust the vertical positioning of the drag-to-reorder grip icon */\n dragHandleTopMargin?: CSSProperties['marginTop'];\n /** A Slate plugin: function that will wrap the editor creation */\n plugin?: (editor: Editor) => Editor;\n /**\n * Function that checks if an element should be draggable\n * @default () => true */\n isDraggable?: (element: Element) => boolean;\n}\n\nexport interface NonSelectorBlock extends BaseBlock {\n isInBlocksSelector?: false;\n}\n\nexport interface SelectorBlock extends BaseBlock {\n isInBlocksSelector: true;\n icon?: React.ComponentType;\n label: MessageDescriptor;\n}\n\ntype NonSelectorBlockKey = 'list-item' | 'link';\n\nconst selectorBlockKeys = [\n 'paragraph',\n 'heading-one',\n 'heading-two',\n 'heading-three',\n 'heading-four',\n 'heading-five',\n 'heading-six',\n 'list-ordered',\n 'list-unordered',\n 'image',\n 'quote',\n 'code',\n] as const;\n\ntype SelectorBlockKey = (typeof selectorBlockKeys)[number];\n\nconst isSelectorBlockKey = (key: unknown): key is SelectorBlockKey => {\n return typeof key === 'string' && selectorBlockKeys.includes(key as SelectorBlockKey);\n};\n\ntype BlocksStore = {\n [K in SelectorBlockKey]: SelectorBlock;\n} & {\n [K in NonSelectorBlockKey]: NonSelectorBlock;\n};\n\ntype RichTextBlocksStore = Partial<BlocksStore> & Record<string, SelectorBlock | NonSelectorBlock>;\n\ninterface BlocksEditorContextValue {\n blocks: RichTextBlocksStore;\n modifiers: ModifiersStore;\n disabled: boolean;\n name: string;\n setLiveText: (text: string) => void;\n isExpandedMode: boolean;\n /** Push debounced Slate → form sync immediately (e.g. on Editable blur before Save). */\n flushPendingFormSync: () => void;\n}\n\nconst [BlocksEditorProvider, usePartialBlocksEditorContext] =\n createContext<BlocksEditorContextValue>('BlocksEditor');\n\nfunction useBlocksEditorContext(consumerName: string): BlocksEditorContextValue & {\n editor: Editor;\n} {\n const context = usePartialBlocksEditorContext(consumerName, (state) => state);\n const editor = useSlate();\n\n return {\n ...context,\n editor,\n };\n}\n\n/* -------------------------------------------------------------------------------------------------\n * BlocksEditor\n * -----------------------------------------------------------------------------------------------*/\n\nconst EditorDivider = styled(Divider)`\n background: ${({ theme }) => theme.colors.neutral200};\n`;\n\n/**\n * Forces an update of the Slate editor when the value prop changes from outside of Slate.\n * The root cause is that Slate is not a controlled component: https://github.com/ianstormtaylor/slate/issues/4612\n * Why not use JSON.stringify(value) as the key?\n * Because it would force a rerender of the entire editor every time the user types a character.\n * Why not use the entity id as the key, since it's unique for each locale?\n * Because it would not solve the problem when using the \"fill in from other locale\" feature\n */\nfunction useResetKey(\n editor: Editor,\n value?: Schema.Attribute.BlocksValue\n): {\n key: number;\n incrementSlateUpdatesCount: () => void;\n} {\n // Keep track how many times Slate detected a change from a user interaction in the editor\n const slateUpdatesCount = React.useRef(0);\n // Keep track of how many times the value prop was updated, whether from within editor or from outside\n const valueUpdatesCount = React.useRef(0);\n // Use a key to force a rerender of the Slate editor when needed\n const [key, setKey] = React.useState(0);\n\n React.useEffect(() => {\n valueUpdatesCount.current += 1;\n\n // If the 2 refs are not equal, it means the value was updated from outside\n if (valueUpdatesCount.current !== slateUpdatesCount.current) {\n // Bring the 2 refs back in sync\n slateUpdatesCount.current = valueUpdatesCount.current;\n\n // The update may just be an echo of the editor's own content coming back through the form\n // (e.g. the debounced sync, or a re-render while document queries settle). Remounting in\n // that case is pointless and destructive: it wipes pending input and the DOM under the\n // user's caret. Only force a remount when the content is actually different.\n const externalState = value?.length ? normalizeBlocksState(editor, value) : null;\n const editorState = normalizeBlocksState(editor, editor.children);\n if (JSON.stringify(externalState) === JSON.stringify(editorState)) {\n return;\n }\n\n // The remount reuses the same editor instance, so a selection pointing into the old\n // content would survive it and crash slate-react's toDOMPoint when the new content is\n // shorter. Drop the selection before swapping the children.\n if (editor.selection) {\n Transforms.deselect(editor);\n }\n\n // Change the key to force a rerender of the Slate editor,\n // which will pick up the new value through its initialValue prop\n setKey((previousKey) => previousKey + 1);\n }\n }, [editor, value]);\n\n const incrementSlateUpdatesCount = React.useCallback(() => {\n slateUpdatesCount.current += 1;\n }, []);\n\n return { key, incrementSlateUpdatesCount };\n}\n\nconst pipe =\n (...fns: ((baseEditor: Editor) => Editor)[]) =>\n (value: Editor) =>\n fns.reduce<Editor>((prev, fn) => fn(prev), value);\n\n/**\n * Normalize the blocks state to null if the editor state is considered empty,\n * otherwise return the state\n */\nconst normalizeBlocksState = (\n editor: Editor,\n value: Schema.Attribute.BlocksValue | Descendant[]\n): Schema.Attribute.BlocksValue | Descendant[] | null => {\n const isEmpty =\n value.length === 1 && Editor.isEmpty(editor, value[0] as Schema.Attribute.BlocksNode);\n\n return isEmpty ? null : value;\n};\n\ninterface BlocksEditorProps\n extends\n Pick<FieldValue<Schema.Attribute.BlocksValue>, 'onChange' | 'value' | 'error'>,\n BlocksContentProps {\n disabled?: boolean;\n name: string;\n /** When true, sync form state on every keystroke (Live Preview popover). */\n livePreviewSync?: boolean;\n /** Index of the block that was double-clicked in the live preview. When provided,\n * the editor positions the Slate cursor at that block on mount instead of using autoFocus. */\n blockIndex?: number | null;\n}\n\nconst BlocksEditor = React.forwardRef<{ focus: () => void }, BlocksEditorProps>(\n (\n {\n disabled = false,\n name,\n onChange,\n value,\n error,\n livePreviewSync = false,\n blockIndex,\n ...contentProps\n },\n forwardedRef\n ) => {\n const { formatMessage } = useIntl();\n const isMobile = useIsMobile();\n\n const blocks = useStrapiApp(\n 'BlocksEditor',\n (state) =>\n (\n state.plugins['content-manager']?.apis as\n ContentManagerPlugin['config']['apis'] | undefined\n )?.getRichTextBlocks() ?? ({} as RichTextBlocksStore)\n );\n\n const blockRegisteredPlugins = Object.values(blocks)\n .map((block) => block.plugin)\n .filter(isNonNullable);\n\n const [editor] = React.useState(() =>\n pipe(withHistory, withStrapiSchema, withReact, ...blockRegisteredPlugins)(createEditor())\n );\n const [liveText, setLiveText] = React.useState('');\n const ariaDescriptionId = React.useId();\n const [isExpandedMode, handleToggleExpand] = React.useReducer((prev) => !prev, false);\n\n /**\n * Editable is not able to hold the ref, https://github.com/ianstormtaylor/slate/issues/4082\n * so with \"useImperativeHandle\" we can use ReactEditor methods to expose to the parent above\n * also not passing forwarded ref here, gives console warning.\n */\n React.useImperativeHandle(\n forwardedRef,\n () => ({\n focus() {\n ReactEditor.focus(editor);\n },\n }),\n [editor]\n );\n\n const { key, incrementSlateUpdatesCount } = useResetKey(editor, value);\n\n const debounceTimeout = React.useRef<NodeJS.Timeout | null>(null);\n\n const flushPendingFormSync = React.useCallback(() => {\n if (!debounceTimeout.current) {\n return;\n }\n clearTimeout(debounceTimeout.current);\n debounceTimeout.current = null;\n // Counter was already bumped when the AST changed; only push form state here.\n // Ensure Strapi Form state updates before the next event (e.g. Save click) reads values.\n flushSync(() => {\n onChange(\n name,\n normalizeBlocksState(editor, editor.children) as Schema.Attribute.BlocksValue\n );\n });\n }, [editor, name, onChange]);\n\n const handleSlateChange = React.useCallback(\n (state: Descendant[]) => {\n const isAstChange = editor.operations.some((op) => op.type !== 'set_selection');\n\n if (isAstChange) {\n /**\n * Slate handles the state of the editor internally. We just need to keep Strapi's form\n * state in sync with it in order to make sure that things like the \"modified\" state\n * isn't broken. Updating the whole state on every change is very expensive however,\n * so we debounce calls to onChange to mitigate input lag.\n *\n * Bump the reset-key counter immediately (not inside the debounce). Otherwise any\n * value-prop identity change during the 300ms window — e.g. clicking the blocks\n * toolbar — looks like an external update with stale empty form state and remounts\n * the editor, wiping the pending input (blocks e2e flake).\n */\n incrementSlateUpdatesCount();\n if (livePreviewSync) {\n onChange(name, normalizeBlocksState(editor, state) as Schema.Attribute.BlocksValue);\n return;\n }\n\n if (debounceTimeout.current) {\n clearTimeout(debounceTimeout.current);\n }\n\n debounceTimeout.current = setTimeout(() => {\n // Normalize the state (empty editor becomes null)\n onChange(name, normalizeBlocksState(editor, state) as Schema.Attribute.BlocksValue);\n debounceTimeout.current = null;\n }, 300);\n }\n },\n [editor, incrementSlateUpdatesCount, livePreviewSync, name, onChange]\n );\n\n // Clean up the timeout on unmount\n React.useEffect(() => {\n return () => {\n if (debounceTimeout.current) {\n clearTimeout(debounceTimeout.current);\n }\n };\n }, []);\n\n // When opened from a live-preview double-click, position the cursor at the clicked block\n React.useEffect(() => {\n if (blockIndex == null) return;\n\n const targetIndex = Math.min(blockIndex, editor.children.length - 1);\n\n try {\n Transforms.select(editor, Editor.start(editor, [targetIndex]));\n } catch {\n // Slate tree not yet ready; skip cursor positioning and scroll\n return;\n }\n try {\n ReactEditor.focus(editor);\n } catch {\n // non-fatal — editor DOM not yet committed\n }\n\n // Defer scroll past the re-render triggered by Transforms.select above.\n // Slate's handleScrollSelectionIntoView runs as a layout effect during\n // that re-render; our rAF fires after it, letting us override the position.\n const raf = requestAnimationFrame(() => {\n try {\n const blockNode = Node.get(editor, [targetIndex]);\n const domEl = ReactEditor.toDOMNode(editor, blockNode as Element);\n // Walk to BlocksContent's scroll container via the Slate editor root,\n // bypassing scrollIntoView which can target overflow:hidden ancestors.\n const editorDomEl = domEl.closest('[data-slate-editor]');\n const scrollContainer = editorDomEl?.parentElement as HTMLElement | null;\n if (scrollContainer) {\n const blockRect = domEl.getBoundingClientRect();\n const containerRect = scrollContainer.getBoundingClientRect();\n // 24px = BlocksContent paddingTop={6} (design-system 4px scale)\n scrollContainer.scrollTop =\n blockRect.top - containerRect.top + scrollContainer.scrollTop - 24;\n } else {\n domEl.scrollIntoView({ block: 'start' });\n }\n } catch {\n // scroll errors are non-fatal; the cursor is already positioned\n }\n });\n\n return () => cancelAnimationFrame(raf);\n // `key` is included so that if useResetKey remounts the Slate editor (clearing\n // editor.selection to null), this effect re-runs and restores the cursor position.\n }, [blockIndex, editor, key]);\n\n // Ensure the editor is in sync after discard\n React.useEffect(() => {\n // Never deselect while the editor is actively focused (typing / editing),\n if (ReactEditor.isFocused(editor)) {\n return;\n }\n\n // Normalize empty states for comparison to avoid losing focus on the editor when content is deleted\n const normalizedValue = value?.length ? value : null;\n const normalizedEditorState = normalizeBlocksState(editor, editor.children);\n\n // Compare the field value with the editor state to check for a stale selection\n if (\n normalizedValue &&\n normalizedEditorState &&\n JSON.stringify(normalizedEditorState) !== JSON.stringify(normalizedValue)\n ) {\n // When there is a diff, unset selection to avoid an invalid state\n Transforms.deselect(editor);\n }\n }, [editor, value]);\n\n return (\n <>\n <VisuallyHidden id={ariaDescriptionId}>\n {formatMessage({\n id: getTranslation('components.Blocks.dnd.instruction'),\n defaultMessage: `To reorder blocks, press Command or Control along with Shift and the Up or Down arrow keys`,\n })}\n </VisuallyHidden>\n <VisuallyHidden aria-live=\"assertive\">{liveText}</VisuallyHidden>\n <Slate\n editor={editor}\n initialValue={\n value?.length ? value : [{ type: 'paragraph', children: [{ type: 'text', text: '' }] }]\n }\n onChange={handleSlateChange}\n key={key}\n >\n <BlocksEditorProvider\n blocks={blocks}\n modifiers={modifiers}\n disabled={disabled}\n name={name}\n setLiveText={setLiveText}\n isExpandedMode={isExpandedMode}\n flushPendingFormSync={flushPendingFormSync}\n >\n <EditorLayout\n error={error}\n disabled={disabled}\n onToggleExpand={handleToggleExpand}\n ariaDescriptionId={ariaDescriptionId}\n livePreviewSync={livePreviewSync}\n >\n <BlocksToolbar />\n <EditorDivider width=\"100%\" />\n <BlocksContent {...contentProps} />\n {!isExpandedMode && !isMobile && (\n <IconButton\n position=\"absolute\"\n bottom=\"1.2rem\"\n right=\"1.2rem\"\n shadow=\"filterShadow\"\n label={formatMessage({\n id: getTranslation('components.Blocks.expand'),\n defaultMessage: 'Expand',\n })}\n onClick={handleToggleExpand}\n >\n <Expand />\n </IconButton>\n )}\n </EditorLayout>\n </BlocksEditorProvider>\n </Slate>\n </>\n );\n }\n);\n\nexport {\n type BlocksStore,\n type RichTextBlocksStore,\n type SelectorBlockKey,\n BlocksEditor,\n BlocksEditorProvider,\n useBlocksEditorContext,\n isSelectorBlockKey,\n normalizeBlocksState,\n};\n"],"names":["BlocksEditorProvider","usePartialBlocksEditorContext","createContext","useBlocksEditorContext","consumerName","context","state","editor","useSlate","EditorDivider","styled","Divider","theme","colors","neutral200","useResetKey","value","slateUpdatesCount","React","useRef","valueUpdatesCount","key","setKey","useState","useEffect","current","externalState","length","normalizeBlocksState","editorState","children","JSON","stringify","selection","Transforms","deselect","previousKey","incrementSlateUpdatesCount","useCallback","pipe","fns","reduce","prev","fn","isEmpty","Editor","BlocksEditor","forwardRef","disabled","name","onChange","error","livePreviewSync","blockIndex","contentProps","forwardedRef","formatMessage","useIntl","isMobile","useIsMobile","blocks","useStrapiApp","plugins","apis","getRichTextBlocks","blockRegisteredPlugins","Object","values","map","block","plugin","filter","isNonNullable","withHistory","withStrapiSchema","withReact","createEditor","liveText","setLiveText","ariaDescriptionId","useId","isExpandedMode","handleToggleExpand","useReducer","useImperativeHandle","focus","ReactEditor","debounceTimeout","flushPendingFormSync","clearTimeout","flushSync","handleSlateChange","isAstChange","operations","some","op","type","setTimeout","targetIndex","Math","min","select","start","raf","requestAnimationFrame","blockNode","Node","get","domEl","toDOMNode","editorDomEl","closest","scrollContainer","parentElement","blockRect","getBoundingClientRect","containerRect","scrollTop","top","scrollIntoView","cancelAnimationFrame","isFocused","normalizedValue","normalizedEditorState","_jsxs","_Fragment","_jsx","VisuallyHidden","id","getTranslation","defaultMessage","aria-live","Slate","initialValue","text","modifiers","EditorLayout","onToggleExpand","BlocksToolbar","width","BlocksContent","IconButton","position","bottom","right","shadow","label","onClick","Expand"],"mappings":";;;;;;;;;;;;;;;;;;;AA+GA,MAAM,CAACA,oBAAAA,EAAsBC,6BAAAA,CAA8B,GACzDC,aAAAA,CAAwC,cAAA;AAE1C,SAASC,uBAAuBC,YAAoB,EAAA;AAGlD,IAAA,MAAMC,OAAAA,GAAUJ,6BAAAA,CAA8BG,YAAAA,EAAc,CAACE,KAAAA,GAAUA,KAAAA,CAAAA;AACvE,IAAA,MAAMC,MAAAA,GAASC,QAAAA,EAAAA;IAEf,OAAO;AACL,QAAA,GAAGH,OAAO;AACVE,QAAAA;AACF,KAAA;AACF;AAEA;;AAEkG,qGAElG,MAAME,aAAAA,GAAgBC,MAAAA,CAAOC,OAAAA,CAAQ;cACvB,EAAE,CAAC,EAAEC,KAAK,EAAE,GAAKA,KAAAA,CAAMC,MAAM,CAACC,UAAU,CAAC;AACvD,CAAC;AAED;;;;;;;AAOC,IACD,SAASC,WAAAA,CACPR,MAAc,EACdS,KAAoC,EAAA;;IAMpC,MAAMC,iBAAAA,GAAoBC,KAAAA,CAAMC,MAAM,CAAC,CAAA,CAAA;;IAEvC,MAAMC,iBAAAA,GAAoBF,KAAAA,CAAMC,MAAM,CAAC,CAAA,CAAA;;AAEvC,IAAA,MAAM,CAACE,GAAAA,EAAKC,MAAAA,CAAO,GAAGJ,KAAAA,CAAMK,QAAQ,CAAC,CAAA,CAAA;AAErCL,IAAAA,KAAAA,CAAMM,SAAS,CAAC,IAAA;AACdJ,QAAAA,iBAAAA,CAAkBK,OAAO,IAAI,CAAA;;AAG7B,QAAA,IAAIL,iBAAAA,CAAkBK,OAAO,KAAKR,iBAAAA,CAAkBQ,OAAO,EAAE;;YAE3DR,iBAAAA,CAAkBQ,OAAO,GAAGL,iBAAAA,CAAkBK,OAAO;;;;;AAMrD,YAAA,MAAMC,aAAAA,GAAgBV,KAAAA,EAAOW,MAAAA,GAASC,oBAAAA,CAAqBrB,QAAQS,KAAAA,CAAAA,GAAS,IAAA;AAC5E,YAAA,MAAMa,WAAAA,GAAcD,oBAAAA,CAAqBrB,MAAAA,EAAQA,MAAAA,CAAOuB,QAAQ,CAAA;AAChE,YAAA,IAAIC,KAAKC,SAAS,CAACN,mBAAmBK,IAAAA,CAAKC,SAAS,CAACH,WAAAA,CAAAA,EAAc;AACjE,gBAAA;AACF,YAAA;;;;YAKA,IAAItB,MAAAA,CAAO0B,SAAS,EAAE;AACpBC,gBAAAA,UAAAA,CAAWC,QAAQ,CAAC5B,MAAAA,CAAAA;AACtB,YAAA;;;YAIAe,MAAAA,CAAO,CAACc,cAAgBA,WAAAA,GAAc,CAAA,CAAA;AACxC,QAAA;IACF,CAAA,EAAG;AAAC7B,QAAAA,MAAAA;AAAQS,QAAAA;AAAM,KAAA,CAAA;IAElB,MAAMqB,0BAAAA,GAA6BnB,KAAAA,CAAMoB,WAAW,CAAC,IAAA;AACnDrB,QAAAA,iBAAAA,CAAkBQ,OAAO,IAAI,CAAA;AAC/B,IAAA,CAAA,EAAG,EAAE,CAAA;IAEL,OAAO;AAAEJ,QAAAA,GAAAA;AAAKgB,QAAAA;AAA2B,KAAA;AAC3C;AAEA,MAAME,IAAAA,GACJ,CAAC,GAAGC,GAAAA,GACJ,CAACxB,KAAAA,GACCwB,GAAAA,CAAIC,MAAM,CAAS,CAACC,IAAAA,EAAMC,EAAAA,GAAOA,GAAGD,IAAAA,CAAAA,EAAO1B,KAAAA,CAAAA;AAE/C;;;IAIA,MAAMY,oBAAAA,GAAuB,CAC3BrB,MAAAA,EACAS,KAAAA,GAAAA;IAEA,MAAM4B,OAAAA,GACJ5B,KAAAA,CAAMW,MAAM,KAAK,CAAA,IAAKkB,MAAAA,CAAOD,OAAO,CAACrC,MAAAA,EAAQS,KAAK,CAAC,CAAA,CAAE,CAAA;AAEvD,IAAA,OAAO4B,UAAU,IAAA,GAAO5B,KAAAA;AAC1B;AAeA,MAAM8B,YAAAA,iBAAe5B,KAAAA,CAAM6B,UAAU,CACnC,CACE,EACEC,QAAAA,GAAW,KAAK,EAChBC,IAAI,EACJC,QAAQ,EACRlC,KAAK,EACLmC,KAAK,EACLC,eAAAA,GAAkB,KAAK,EACvBC,UAAU,EACV,GAAGC,YAAAA,EACJ,EACDC,YAAAA,GAAAA;IAEA,MAAM,EAAEC,aAAa,EAAE,GAAGC,OAAAA,EAAAA;AAC1B,IAAA,MAAMC,QAAAA,GAAWC,WAAAA,EAAAA;AAEjB,IAAA,MAAMC,MAAAA,GAASC,YAAAA,CACb,cAAA,EACA,CAACvD,KAAAA,GAEGA,KAAAA,CAAMwD,OAAO,CAAC,iBAAA,CAAkB,EAAEC,IAAAA,EAEjCC,uBAAwB,EAAC,CAAA;AAGhC,IAAA,MAAMC,sBAAAA,GAAyBC,MAAAA,CAAOC,MAAM,CAACP,MAAAA,CAAAA,CAC1CQ,GAAG,CAAC,CAACC,KAAAA,GAAUA,KAAAA,CAAMC,MAAM,CAAA,CAC3BC,MAAM,CAACC,aAAAA,CAAAA;IAEV,MAAM,CAACjE,MAAAA,CAAO,GAAGW,KAAAA,CAAMK,QAAQ,CAAC,IAC9BgB,IAAAA,CAAKkC,WAAAA,EAAaC,gBAAAA,EAAkBC,SAAAA,EAAAA,GAAcV,sBAAAA,CAAAA,CAAwBW,YAAAA,EAAAA,CAAAA,CAAAA;AAE5E,IAAA,MAAM,CAACC,QAAAA,EAAUC,WAAAA,CAAY,GAAG5D,KAAAA,CAAMK,QAAQ,CAAC,EAAA,CAAA;IAC/C,MAAMwD,iBAAAA,GAAoB7D,MAAM8D,KAAK,EAAA;IACrC,MAAM,CAACC,cAAAA,EAAgBC,kBAAAA,CAAmB,GAAGhE,KAAAA,CAAMiE,UAAU,CAAC,CAACzC,IAAAA,GAAS,CAACA,IAAAA,EAAM,KAAA,CAAA;AAE/E;;;;AAIC,QACDxB,KAAAA,CAAMkE,mBAAmB,CACvB7B,YAAAA,EACA,KAAO;AACL8B,YAAAA,KAAAA,CAAAA,GAAAA;AACEC,gBAAAA,WAAAA,CAAYD,KAAK,CAAC9E,MAAAA,CAAAA;AACpB,YAAA;AACF,SAAA,CAAA,EACA;AAACA,QAAAA;AAAO,KAAA,CAAA;AAGV,IAAA,MAAM,EAAEc,GAAG,EAAEgB,0BAA0B,EAAE,GAAGtB,YAAYR,MAAAA,EAAQS,KAAAA,CAAAA;IAEhE,MAAMuE,eAAAA,GAAkBrE,KAAAA,CAAMC,MAAM,CAAwB,IAAA,CAAA;IAE5D,MAAMqE,oBAAAA,GAAuBtE,KAAAA,CAAMoB,WAAW,CAAC,IAAA;QAC7C,IAAI,CAACiD,eAAAA,CAAgB9D,OAAO,EAAE;AAC5B,YAAA;AACF,QAAA;AACAgE,QAAAA,YAAAA,CAAaF,gBAAgB9D,OAAO,CAAA;AACpC8D,QAAAA,eAAAA,CAAgB9D,OAAO,GAAG,IAAA;;;QAG1BiE,SAAAA,CAAU,IAAA;AACRxC,YAAAA,QAAAA,CACED,IAAAA,EACArB,oBAAAA,CAAqBrB,MAAAA,EAAQA,MAAAA,CAAOuB,QAAQ,CAAA,CAAA;AAEhD,QAAA,CAAA,CAAA;IACF,CAAA,EAAG;AAACvB,QAAAA,MAAAA;AAAQ0C,QAAAA,IAAAA;AAAMC,QAAAA;AAAS,KAAA,CAAA;AAE3B,IAAA,MAAMyC,iBAAAA,GAAoBzE,KAAAA,CAAMoB,WAAW,CACzC,CAAChC,KAAAA,GAAAA;QACC,MAAMsF,WAAAA,GAAcrF,MAAAA,CAAOsF,UAAU,CAACC,IAAI,CAAC,CAACC,EAAAA,GAAOA,EAAAA,CAAGC,IAAI,KAAK,eAAA,CAAA;AAE/D,QAAA,IAAIJ,WAAAA,EAAa;AACf;;;;;;;;;;cAWAvD,0BAAAA,EAAAA;AACA,YAAA,IAAIe,eAAAA,EAAiB;gBACnBF,QAAAA,CAASD,IAAAA,EAAMrB,qBAAqBrB,MAAAA,EAAQD,KAAAA,CAAAA,CAAAA;AAC5C,gBAAA;AACF,YAAA;YAEA,IAAIiF,eAAAA,CAAgB9D,OAAO,EAAE;AAC3BgE,gBAAAA,YAAAA,CAAaF,gBAAgB9D,OAAO,CAAA;AACtC,YAAA;YAEA8D,eAAAA,CAAgB9D,OAAO,GAAGwE,UAAAA,CAAW,IAAA;;gBAEnC/C,QAAAA,CAASD,IAAAA,EAAMrB,qBAAqBrB,MAAAA,EAAQD,KAAAA,CAAAA,CAAAA;AAC5CiF,gBAAAA,eAAAA,CAAgB9D,OAAO,GAAG,IAAA;YAC5B,CAAA,EAAG,GAAA,CAAA;AACL,QAAA;IACF,CAAA,EACA;AAAClB,QAAAA,MAAAA;AAAQ8B,QAAAA,0BAAAA;AAA4Be,QAAAA,eAAAA;AAAiBH,QAAAA,IAAAA;AAAMC,QAAAA;AAAS,KAAA,CAAA;;AAIvEhC,IAAAA,KAAAA,CAAMM,SAAS,CAAC,IAAA;QACd,OAAO,IAAA;YACL,IAAI+D,eAAAA,CAAgB9D,OAAO,EAAE;AAC3BgE,gBAAAA,YAAAA,CAAaF,gBAAgB9D,OAAO,CAAA;AACtC,YAAA;AACF,QAAA,CAAA;AACF,IAAA,CAAA,EAAG,EAAE,CAAA;;AAGLP,IAAAA,KAAAA,CAAMM,SAAS,CAAC,IAAA;AACd,QAAA,IAAI6B,cAAc,IAAA,EAAM;QAExB,MAAM6C,WAAAA,GAAcC,KAAKC,GAAG,CAAC/C,YAAY9C,MAAAA,CAAOuB,QAAQ,CAACH,MAAM,GAAG,CAAA,CAAA;QAElE,IAAI;AACFO,YAAAA,UAAAA,CAAWmE,MAAM,CAAC9F,MAAAA,EAAQsC,MAAAA,CAAOyD,KAAK,CAAC/F,MAAAA,EAAQ;AAAC2F,gBAAAA;AAAY,aAAA,CAAA,CAAA;AAC9D,QAAA,CAAA,CAAE,OAAM;;AAEN,YAAA;AACF,QAAA;QACA,IAAI;AACFZ,YAAAA,WAAAA,CAAYD,KAAK,CAAC9E,MAAAA,CAAAA;AACpB,QAAA,CAAA,CAAE,OAAM;;AAER,QAAA;;;;AAKA,QAAA,MAAMgG,MAAMC,qBAAAA,CAAsB,IAAA;YAChC,IAAI;AACF,gBAAA,MAAMC,SAAAA,GAAYC,IAAAA,CAAKC,GAAG,CAACpG,MAAAA,EAAQ;AAAC2F,oBAAAA;AAAY,iBAAA,CAAA;AAChD,gBAAA,MAAMU,KAAAA,GAAQtB,WAAAA,CAAYuB,SAAS,CAACtG,MAAAA,EAAQkG,SAAAA,CAAAA;;;gBAG5C,MAAMK,WAAAA,GAAcF,KAAAA,CAAMG,OAAO,CAAC,qBAAA,CAAA;AAClC,gBAAA,MAAMC,kBAAkBF,WAAAA,EAAaG,aAAAA;AACrC,gBAAA,IAAID,eAAAA,EAAiB;oBACnB,MAAME,SAAAA,GAAYN,MAAMO,qBAAqB,EAAA;oBAC7C,MAAMC,aAAAA,GAAgBJ,gBAAgBG,qBAAqB,EAAA;;oBAE3DH,eAAAA,CAAgBK,SAAS,GACvBH,SAAAA,CAAUI,GAAG,GAAGF,cAAcE,GAAG,GAAGN,eAAAA,CAAgBK,SAAS,GAAG,EAAA;gBACpE,CAAA,MAAO;AACLT,oBAAAA,KAAAA,CAAMW,cAAc,CAAC;wBAAElD,KAAAA,EAAO;AAAQ,qBAAA,CAAA;AACxC,gBAAA;AACF,YAAA,CAAA,CAAE,OAAM;;AAER,YAAA;AACF,QAAA,CAAA,CAAA;AAEA,QAAA,OAAO,IAAMmD,oBAAAA,CAAqBjB,GAAAA,CAAAA;;;IAGpC,CAAA,EAAG;AAAClD,QAAAA,UAAAA;AAAY9C,QAAAA,MAAAA;AAAQc,QAAAA;AAAI,KAAA,CAAA;;AAG5BH,IAAAA,KAAAA,CAAMM,SAAS,CAAC,IAAA;;QAEd,IAAI8D,WAAAA,CAAYmC,SAAS,CAAClH,MAAAA,CAAAA,EAAS;AACjC,YAAA;AACF,QAAA;;QAGA,MAAMmH,eAAAA,GAAkB1G,KAAAA,EAAOW,MAAAA,GAASX,KAAAA,GAAQ,IAAA;AAChD,QAAA,MAAM2G,qBAAAA,GAAwB/F,oBAAAA,CAAqBrB,MAAAA,EAAQA,MAAAA,CAAOuB,QAAQ,CAAA;;QAG1E,IACE4F,eAAAA,IACAC,yBACA5F,IAAAA,CAAKC,SAAS,CAAC2F,qBAAAA,CAAAA,KAA2B5F,IAAAA,CAAKC,SAAS,CAAC0F,eAAAA,CAAAA,EACzD;;AAEAxF,YAAAA,UAAAA,CAAWC,QAAQ,CAAC5B,MAAAA,CAAAA;AACtB,QAAA;IACF,CAAA,EAAG;AAACA,QAAAA,MAAAA;AAAQS,QAAAA;AAAM,KAAA,CAAA;IAElB,qBACE4G,IAAA,CAAAC,QAAA,EAAA;;0BACEC,GAAA,CAACC,cAAAA,EAAAA;gBAAeC,EAAAA,EAAIjD,iBAAAA;0BACjBvB,aAAAA,CAAc;AACbwE,oBAAAA,EAAAA,EAAIC,cAAAA,CAAe,mCAAA,CAAA;oBACnBC,cAAAA,EAAgB,CAAC,0FAA0F;AAC7G,iBAAA;;0BAEFJ,GAAA,CAACC,cAAAA,EAAAA;gBAAeI,WAAAA,EAAU,WAAA;AAAatD,gBAAAA,QAAAA,EAAAA;;0BACvCiD,GAAA,CAACM,KAAAA,EAAAA;gBACC7H,MAAAA,EAAQA,MAAAA;gBACR8H,YAAAA,EACErH,KAAAA,EAAOW,SAASX,KAAAA,GAAQ;AAAC,oBAAA;wBAAEgF,IAAAA,EAAM,WAAA;wBAAalE,QAAAA,EAAU;AAAC,4BAAA;gCAAEkE,IAAAA,EAAM,MAAA;gCAAQsC,IAAAA,EAAM;AAAG;AAAE;AAAC;AAAE,iBAAA;gBAEzFpF,QAAAA,EAAUyC,iBAAAA;AAGV,gBAAA,QAAA,gBAAAmC,GAAA,CAAC9H,oBAAAA,EAAAA;oBACC4D,MAAAA,EAAQA,MAAAA;oBACR2E,SAAAA,EAAWA,SAAAA;oBACXvF,QAAAA,EAAUA,QAAAA;oBACVC,IAAAA,EAAMA,IAAAA;oBACN6B,WAAAA,EAAaA,WAAAA;oBACbG,cAAAA,EAAgBA,cAAAA;oBAChBO,oBAAAA,EAAsBA,oBAAAA;AAEtB,oBAAA,QAAA,gBAAAoC,IAAA,CAACY,YAAAA,EAAAA;wBACCrF,KAAAA,EAAOA,KAAAA;wBACPH,QAAAA,EAAUA,QAAAA;wBACVyF,cAAAA,EAAgBvD,kBAAAA;wBAChBH,iBAAAA,EAAmBA,iBAAAA;wBACnB3B,eAAAA,EAAiBA,eAAAA;;0CAEjB0E,GAAA,CAACY,aAAAA,EAAAA,EAAAA,CAAAA;0CACDZ,GAAA,CAACrH,aAAAA,EAAAA;gCAAckI,KAAAA,EAAM;;0CACrBb,GAAA,CAACc,aAAAA,EAAAA;AAAe,gCAAA,GAAGtF;;4BAClB,CAAC2B,cAAAA,IAAkB,CAACvB,QAAAA,kBACnBoE,GAAA,CAACe,UAAAA,EAAAA;gCACCC,QAAAA,EAAS,UAAA;gCACTC,MAAAA,EAAO,QAAA;gCACPC,KAAAA,EAAM,QAAA;gCACNC,MAAAA,EAAO,cAAA;AACPC,gCAAAA,KAAAA,EAAO1F,aAAAA,CAAc;AACnBwE,oCAAAA,EAAAA,EAAIC,cAAAA,CAAe,0BAAA,CAAA;oCACnBC,cAAAA,EAAgB;AAClB,iCAAA,CAAA;gCACAiB,OAAAA,EAASjE,kBAAAA;AAET,gCAAA,QAAA,gBAAA4C,GAAA,CAACsB,MAAAA,EAAAA,EAAAA;;;;;AAjCJ/H,aAAAA,EAAAA,GAAAA;;;AAyCb,CAAA;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Input.js","sources":["../../../../../../../admin/src/pages/EditView/components/FormInputs/Component/Input.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { InputProps, useField } from '@strapi/admin/strapi-admin';\nimport { Field, Flex, IconButton } from '@strapi/design-system';\nimport { Trash } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\n\nimport { useDocumentContext } from '../../../../../hooks/useDocumentContext';\nimport { EditFieldLayout } from '../../../../../hooks/useDocumentLayout';\nimport { getTranslation } from '../../../../../utils/translations';\nimport { type AnyData, transformDocument } from '../../../utils/data';\nimport { createDefaultForm } from '../../../utils/forms';\nimport { type InputRendererProps } from '../../InputRenderer';\n\nimport { Initializer } from './Initializer';\nimport { NonRepeatableComponent } from './NonRepeatable';\nimport { RepeatableComponent } from './Repeatable';\n\ninterface ComponentInputProps\n extends
|
|
1
|
+
{"version":3,"file":"Input.js","sources":["../../../../../../../admin/src/pages/EditView/components/FormInputs/Component/Input.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { InputProps, useField } from '@strapi/admin/strapi-admin';\nimport { Field, Flex, IconButton } from '@strapi/design-system';\nimport { Trash } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\n\nimport { useDocumentContext } from '../../../../../hooks/useDocumentContext';\nimport { EditFieldLayout } from '../../../../../hooks/useDocumentLayout';\nimport { getTranslation } from '../../../../../utils/translations';\nimport { type AnyData, transformDocument } from '../../../utils/data';\nimport { createDefaultForm } from '../../../utils/forms';\nimport { type InputRendererProps } from '../../InputRenderer';\n\nimport { Initializer } from './Initializer';\nimport { NonRepeatableComponent } from './NonRepeatable';\nimport { RepeatableComponent } from './Repeatable';\n\ninterface ComponentInputProps\n extends\n Omit<Extract<EditFieldLayout, { type: 'component' }>, 'size' | 'hint'>,\n Pick<InputProps, 'hint'> {\n labelAction?: React.ReactNode;\n children: (props: InputRendererProps) => React.ReactNode;\n /**\n * We need layout to come from the props, and not via a hook, because Content History needs\n * a way to modify the normal component layout to add hidden fields.\n */\n layout: ReadonlyArray<ReadonlyArray<EditFieldLayout>>;\n}\n\nconst ComponentInput = ({\n label,\n required,\n name,\n attribute,\n disabled,\n labelAction,\n ...props\n}: ComponentInputProps) => {\n const { formatMessage } = useIntl();\n const field = useField<AnyData | AnyData[] | null>(name);\n\n const showResetComponent =\n !attribute.repeatable && field.value !== undefined && field.value !== null && !disabled;\n\n const {\n currentDocument: { components },\n } = useDocumentContext('ComponentInput');\n\n const handleInitialisationClick = () => {\n const schema = components[attribute.component];\n const form = createDefaultForm(schema, components);\n const data = transformDocument(schema, components)(form);\n\n field.onChange(name, data);\n };\n\n return (\n <Field.Root error={field.error} required={required}>\n <Flex justifyContent=\"space-between\">\n <Field.Label action={labelAction}>\n {label}\n {attribute.repeatable && (\n <> ({Array.isArray(field.value) ? field.value.length : 0})</>\n )}\n </Field.Label>\n\n {showResetComponent && (\n <IconButton\n label={formatMessage({\n id: getTranslation('components.reset-entry'),\n defaultMessage: 'Reset Entry',\n })}\n variant=\"ghost\"\n onClick={() => {\n field.onChange(name, null);\n }}\n >\n <Trash />\n </IconButton>\n )}\n </Flex>\n {/**\n * if the field isn't repeatable then we display a button to start the field\n * TODO: should this just live in the `NonRepeatableComponent`?\n */}\n {!attribute.repeatable && !field.value && (\n <Initializer disabled={disabled} name={name} onClick={handleInitialisationClick} />\n )}\n {!attribute.repeatable && field.value ? (\n <NonRepeatableComponent attribute={attribute} name={name} disabled={disabled} {...props}>\n {props.children}\n </NonRepeatableComponent>\n ) : null}\n {attribute.repeatable && (\n <RepeatableComponent attribute={attribute} name={name} disabled={disabled} {...props}>\n {props.children}\n </RepeatableComponent>\n )}\n <Field.Error />\n </Field.Root>\n );\n};\n\nconst MemoizedComponentInput = React.memo(ComponentInput);\n\nexport { MemoizedComponentInput as ComponentInput };\nexport type { ComponentInputProps };\n"],"names":["ComponentInput","label","required","name","attribute","disabled","labelAction","props","formatMessage","useIntl","field","useField","showResetComponent","repeatable","value","undefined","currentDocument","components","useDocumentContext","handleInitialisationClick","schema","component","form","createDefaultForm","data","transformDocument","onChange","_jsxs","Field","Root","error","Flex","justifyContent","Label","action","_Fragment","Array","isArray","length","_jsx","IconButton","id","getTranslation","defaultMessage","variant","onClick","Trash","Initializer","NonRepeatableComponent","children","RepeatableComponent","Error","MemoizedComponentInput","React","memo"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Input.mjs","sources":["../../../../../../../admin/src/pages/EditView/components/FormInputs/Component/Input.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { InputProps, useField } from '@strapi/admin/strapi-admin';\nimport { Field, Flex, IconButton } from '@strapi/design-system';\nimport { Trash } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\n\nimport { useDocumentContext } from '../../../../../hooks/useDocumentContext';\nimport { EditFieldLayout } from '../../../../../hooks/useDocumentLayout';\nimport { getTranslation } from '../../../../../utils/translations';\nimport { type AnyData, transformDocument } from '../../../utils/data';\nimport { createDefaultForm } from '../../../utils/forms';\nimport { type InputRendererProps } from '../../InputRenderer';\n\nimport { Initializer } from './Initializer';\nimport { NonRepeatableComponent } from './NonRepeatable';\nimport { RepeatableComponent } from './Repeatable';\n\ninterface ComponentInputProps\n extends
|
|
1
|
+
{"version":3,"file":"Input.mjs","sources":["../../../../../../../admin/src/pages/EditView/components/FormInputs/Component/Input.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { InputProps, useField } from '@strapi/admin/strapi-admin';\nimport { Field, Flex, IconButton } from '@strapi/design-system';\nimport { Trash } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\n\nimport { useDocumentContext } from '../../../../../hooks/useDocumentContext';\nimport { EditFieldLayout } from '../../../../../hooks/useDocumentLayout';\nimport { getTranslation } from '../../../../../utils/translations';\nimport { type AnyData, transformDocument } from '../../../utils/data';\nimport { createDefaultForm } from '../../../utils/forms';\nimport { type InputRendererProps } from '../../InputRenderer';\n\nimport { Initializer } from './Initializer';\nimport { NonRepeatableComponent } from './NonRepeatable';\nimport { RepeatableComponent } from './Repeatable';\n\ninterface ComponentInputProps\n extends\n Omit<Extract<EditFieldLayout, { type: 'component' }>, 'size' | 'hint'>,\n Pick<InputProps, 'hint'> {\n labelAction?: React.ReactNode;\n children: (props: InputRendererProps) => React.ReactNode;\n /**\n * We need layout to come from the props, and not via a hook, because Content History needs\n * a way to modify the normal component layout to add hidden fields.\n */\n layout: ReadonlyArray<ReadonlyArray<EditFieldLayout>>;\n}\n\nconst ComponentInput = ({\n label,\n required,\n name,\n attribute,\n disabled,\n labelAction,\n ...props\n}: ComponentInputProps) => {\n const { formatMessage } = useIntl();\n const field = useField<AnyData | AnyData[] | null>(name);\n\n const showResetComponent =\n !attribute.repeatable && field.value !== undefined && field.value !== null && !disabled;\n\n const {\n currentDocument: { components },\n } = useDocumentContext('ComponentInput');\n\n const handleInitialisationClick = () => {\n const schema = components[attribute.component];\n const form = createDefaultForm(schema, components);\n const data = transformDocument(schema, components)(form);\n\n field.onChange(name, data);\n };\n\n return (\n <Field.Root error={field.error} required={required}>\n <Flex justifyContent=\"space-between\">\n <Field.Label action={labelAction}>\n {label}\n {attribute.repeatable && (\n <> ({Array.isArray(field.value) ? field.value.length : 0})</>\n )}\n </Field.Label>\n\n {showResetComponent && (\n <IconButton\n label={formatMessage({\n id: getTranslation('components.reset-entry'),\n defaultMessage: 'Reset Entry',\n })}\n variant=\"ghost\"\n onClick={() => {\n field.onChange(name, null);\n }}\n >\n <Trash />\n </IconButton>\n )}\n </Flex>\n {/**\n * if the field isn't repeatable then we display a button to start the field\n * TODO: should this just live in the `NonRepeatableComponent`?\n */}\n {!attribute.repeatable && !field.value && (\n <Initializer disabled={disabled} name={name} onClick={handleInitialisationClick} />\n )}\n {!attribute.repeatable && field.value ? (\n <NonRepeatableComponent attribute={attribute} name={name} disabled={disabled} {...props}>\n {props.children}\n </NonRepeatableComponent>\n ) : null}\n {attribute.repeatable && (\n <RepeatableComponent attribute={attribute} name={name} disabled={disabled} {...props}>\n {props.children}\n </RepeatableComponent>\n )}\n <Field.Error />\n </Field.Root>\n );\n};\n\nconst MemoizedComponentInput = React.memo(ComponentInput);\n\nexport { MemoizedComponentInput as ComponentInput };\nexport type { ComponentInputProps };\n"],"names":["ComponentInput","label","required","name","attribute","disabled","labelAction","props","formatMessage","useIntl","field","useField","showResetComponent","repeatable","value","undefined","currentDocument","components","useDocumentContext","handleInitialisationClick","schema","component","form","createDefaultForm","data","transformDocument","onChange","_jsxs","Field","Root","error","Flex","justifyContent","Label","action","_Fragment","Array","isArray","length","_jsx","IconButton","id","getTranslation","defaultMessage","variant","onClick","Trash","Initializer","NonRepeatableComponent","children","RepeatableComponent","Error","MemoizedComponentInput","React","memo"],"mappings":"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"}
|
|
@@ -62,7 +62,7 @@ const NonRepeatableComponentFields = /*#__PURE__*/ React__namespace.memo(({ attr
|
|
|
62
62
|
direction: "column",
|
|
63
63
|
alignItems: "stretch",
|
|
64
64
|
gap: 6,
|
|
65
|
-
children: layout.map((row
|
|
65
|
+
children: layout.map((row)=>{
|
|
66
66
|
return /*#__PURE__*/ jsxRuntime.jsx(FormLayout.ResponsiveGridRoot, {
|
|
67
67
|
gap: {
|
|
68
68
|
initial: 3,
|
|
@@ -92,7 +92,7 @@ const NonRepeatableComponentFields = /*#__PURE__*/ React__namespace.memo(({ attr
|
|
|
92
92
|
})
|
|
93
93
|
}, completeFieldName);
|
|
94
94
|
})
|
|
95
|
-
},
|
|
95
|
+
}, row.map((field)=>field.name).join('.'));
|
|
96
96
|
})
|
|
97
97
|
});
|
|
98
98
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NonRepeatable.js","sources":["../../../../../../../admin/src/pages/EditView/components/FormInputs/Component/NonRepeatable.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { useForm, useIsMobile } from '@strapi/admin/strapi-admin';\nimport { Box, Flex } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\n\nimport { getIn } from '../../../../../utils/objects';\nimport { ResponsiveGridItem, ResponsiveGridRoot } from '../../FormLayout';\nimport { ComponentProvider, useComponent } from '../ComponentContext';\n\nimport type { ComponentInputProps } from './Input';\n\ntype NonRepeatableComponentProps = Omit<ComponentInputProps, 'required' | 'label'>;\n\nconst NonRepeatableComponent = ({\n attribute,\n name,\n children,\n layout,\n}: NonRepeatableComponentProps) => {\n const componentId = useForm(\n 'NonRepeatableComponent',\n (state) => getIn(state.values, `${name}.id`) as number | undefined\n );\n const level = useComponent('NonRepeatableComponent', (state) => state.level);\n const isNested = level > 0;\n const isMobile = useIsMobile();\n\n return (\n <ComponentProvider\n id={componentId}\n uid={attribute.component}\n level={level + 1}\n type=\"component\"\n >\n <Box\n background={'neutral100'}\n padding={{ initial: 4, medium: 6 }}\n hasRadius={isNested}\n borderColor={isNested || isMobile ? 'neutral200' : undefined}\n >\n <NonRepeatableComponentFields attribute={attribute} name={name} layout={layout}>\n {children}\n </NonRepeatableComponentFields>\n </Box>\n </ComponentProvider>\n );\n};\n\ninterface NonRepeatableComponentFieldsProps
|
|
1
|
+
{"version":3,"file":"NonRepeatable.js","sources":["../../../../../../../admin/src/pages/EditView/components/FormInputs/Component/NonRepeatable.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { useForm, useIsMobile } from '@strapi/admin/strapi-admin';\nimport { Box, Flex } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\n\nimport { getIn } from '../../../../../utils/objects';\nimport { ResponsiveGridItem, ResponsiveGridRoot } from '../../FormLayout';\nimport { ComponentProvider, useComponent } from '../ComponentContext';\n\nimport type { ComponentInputProps } from './Input';\n\ntype NonRepeatableComponentProps = Omit<ComponentInputProps, 'required' | 'label'>;\n\nconst NonRepeatableComponent = ({\n attribute,\n name,\n children,\n layout,\n}: NonRepeatableComponentProps) => {\n const componentId = useForm(\n 'NonRepeatableComponent',\n (state) => getIn(state.values, `${name}.id`) as number | undefined\n );\n const level = useComponent('NonRepeatableComponent', (state) => state.level);\n const isNested = level > 0;\n const isMobile = useIsMobile();\n\n return (\n <ComponentProvider\n id={componentId}\n uid={attribute.component}\n level={level + 1}\n type=\"component\"\n >\n <Box\n background={'neutral100'}\n padding={{ initial: 4, medium: 6 }}\n hasRadius={isNested}\n borderColor={isNested || isMobile ? 'neutral200' : undefined}\n >\n <NonRepeatableComponentFields attribute={attribute} name={name} layout={layout}>\n {children}\n </NonRepeatableComponentFields>\n </Box>\n </ComponentProvider>\n );\n};\n\ninterface NonRepeatableComponentFieldsProps extends Pick<\n NonRepeatableComponentProps,\n 'attribute' | 'children' | 'layout' | 'name'\n> {}\n\nconst NonRepeatableComponentFields = React.memo(\n ({ attribute, children, layout, name }: NonRepeatableComponentFieldsProps) => {\n const { formatMessage } = useIntl();\n\n return (\n <Flex direction=\"column\" alignItems=\"stretch\" gap={6}>\n {layout.map((row) => {\n return (\n <ResponsiveGridRoot\n gap={{ initial: 3, medium: 4 }}\n key={row.map((field) => field.name).join('.')}\n >\n {row.map(({ size, ...field }) => {\n /**\n * Layouts are built from schemas so they don't understand the complete\n * schema tree, for components we append the parent name to the field name\n * because this is the structure for the data & permissions also understand\n * the nesting involved.\n */\n const completeFieldName = `${name}.${field.name}`;\n\n const translatedLabel = formatMessage({\n id: `content-manager.components.${attribute.component}.${field.name}`,\n defaultMessage: field.label,\n });\n\n return (\n <ResponsiveGridItem\n col={size}\n key={completeFieldName}\n s={12}\n xs={12}\n direction=\"column\"\n alignItems=\"stretch\"\n >\n {children({\n ...field,\n label: translatedLabel,\n name: completeFieldName,\n })}\n </ResponsiveGridItem>\n );\n })}\n </ResponsiveGridRoot>\n );\n })}\n </Flex>\n );\n }\n);\n\nNonRepeatableComponentFields.displayName = 'NonRepeatableComponentFields';\n\nconst MemoizedNonRepeatableComponent = React.memo(NonRepeatableComponent);\n\nexport { MemoizedNonRepeatableComponent as NonRepeatableComponent };\nexport type { NonRepeatableComponentProps };\n"],"names":["NonRepeatableComponent","attribute","name","children","layout","componentId","useForm","state","getIn","values","level","useComponent","isNested","isMobile","useIsMobile","_jsx","ComponentProvider","id","uid","component","type","Box","background","padding","initial","medium","hasRadius","borderColor","undefined","NonRepeatableComponentFields","React","memo","formatMessage","useIntl","Flex","direction","alignItems","gap","map","row","ResponsiveGridRoot","size","field","completeFieldName","translatedLabel","defaultMessage","label","ResponsiveGridItem","col","s","xs","join","displayName","MemoizedNonRepeatableComponent"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAcA,MAAMA,sBAAAA,GAAyB,CAAC,EAC9BC,SAAS,EACTC,IAAI,EACJC,QAAQ,EACRC,MAAM,EACsB,GAAA;AAC5B,IAAA,MAAMC,WAAAA,GAAcC,mBAAAA,CAClB,wBAAA,EACA,CAACC,KAAAA,GAAUC,aAAAA,CAAMD,KAAAA,CAAME,MAAM,EAAE,CAAA,EAAGP,IAAAA,CAAK,GAAG,CAAC,CAAA,CAAA;AAE7C,IAAA,MAAMQ,QAAQC,6BAAAA,CAAa,wBAAA,EAA0B,CAACJ,KAAAA,GAAUA,MAAMG,KAAK,CAAA;AAC3E,IAAA,MAAME,WAAWF,KAAAA,GAAQ,CAAA;AACzB,IAAA,MAAMG,QAAAA,GAAWC,uBAAAA,EAAAA;AAEjB,IAAA,qBACEC,cAAA,CAACC,kCAAAA,EAAAA;QACCC,EAAAA,EAAIZ,WAAAA;AACJa,QAAAA,GAAAA,EAAKjB,UAAUkB,SAAS;AACxBT,QAAAA,KAAAA,EAAOA,KAAAA,GAAQ,CAAA;QACfU,IAAAA,EAAK,WAAA;AAEL,QAAA,QAAA,gBAAAL,cAAA,CAACM,gBAAAA,EAAAA;YACCC,UAAAA,EAAY,YAAA;YACZC,OAAAA,EAAS;gBAAEC,OAAAA,EAAS,CAAA;gBAAGC,MAAAA,EAAQ;AAAE,aAAA;YACjCC,SAAAA,EAAWd,QAAAA;YACXe,WAAAA,EAAaf,QAAAA,IAAYC,WAAW,YAAA,GAAee,SAAAA;AAEnD,YAAA,QAAA,gBAAAb,cAAA,CAACc,4BAAAA,EAAAA;gBAA6B5B,SAAAA,EAAWA,SAAAA;gBAAWC,IAAAA,EAAMA,IAAAA;gBAAME,MAAAA,EAAQA,MAAAA;AACrED,gBAAAA,QAAAA,EAAAA;;;;AAKX,CAAA;AAOA,MAAM0B,4BAAAA,iBAA+BC,gBAAAA,CAAMC,IAAI,CAC7C,CAAC,EAAE9B,SAAS,EAAEE,QAAQ,EAAEC,MAAM,EAAEF,IAAI,EAAqC,GAAA;IACvE,MAAM,EAAE8B,aAAa,EAAE,GAAGC,iBAAAA,EAAAA;AAE1B,IAAA,qBACElB,cAAA,CAACmB,iBAAAA,EAAAA;QAAKC,SAAAA,EAAU,QAAA;QAASC,UAAAA,EAAW,SAAA;QAAUC,GAAAA,EAAK,CAAA;kBAChDjC,MAAAA,CAAOkC,GAAG,CAAC,CAACC,GAAAA,GAAAA;AACX,YAAA,qBACExB,cAAA,CAACyB,6BAAAA,EAAAA;gBACCH,GAAAA,EAAK;oBAAEb,OAAAA,EAAS,CAAA;oBAAGC,MAAAA,EAAQ;AAAE,iBAAA;AAG5Bc,gBAAAA,QAAAA,EAAAA,GAAAA,CAAID,GAAG,CAAC,CAAC,EAAEG,IAAI,EAAE,GAAGC,KAAAA,EAAO,GAAA;AAC1B;;;;;oBAMA,MAAMC,oBAAoB,CAAA,EAAGzC,IAAAA,CAAK,CAAC,EAAEwC,KAAAA,CAAMxC,IAAI,CAAA,CAAE;AAEjD,oBAAA,MAAM0C,kBAAkBZ,aAAAA,CAAc;wBACpCf,EAAAA,EAAI,CAAC,2BAA2B,EAAEhB,SAAAA,CAAUkB,SAAS,CAAC,CAAC,EAAEuB,KAAAA,CAAMxC,IAAI,CAAA,CAAE;AACrE2C,wBAAAA,cAAAA,EAAgBH,MAAMI;AACxB,qBAAA,CAAA;AAEA,oBAAA,qBACE/B,cAAA,CAACgC,6BAAAA,EAAAA;wBACCC,GAAAA,EAAKP,IAAAA;wBAELQ,CAAAA,EAAG,EAAA;wBACHC,EAAAA,EAAI,EAAA;wBACJf,SAAAA,EAAU,QAAA;wBACVC,UAAAA,EAAW,SAAA;kCAEVjC,QAAAA,CAAS;AACR,4BAAA,GAAGuC,KAAK;4BACRI,KAAAA,EAAOF,eAAAA;4BACP1C,IAAAA,EAAMyC;AACR,yBAAA;AAVKA,qBAAAA,EAAAA,iBAAAA,CAAAA;AAaX,gBAAA,CAAA;eAhCKJ,GAAAA,CAAID,GAAG,CAAC,CAACI,KAAAA,GAAUA,MAAMxC,IAAI,CAAA,CAAEiD,IAAI,CAAC,GAAA,CAAA,CAAA;AAmC/C,QAAA,CAAA;;AAGN,CAAA,CAAA;AAGFtB,4BAAAA,CAA6BuB,WAAW,GAAG,8BAAA;AAE3C,MAAMC,8BAAAA,iBAAiCvB,gBAAAA,CAAMC,IAAI,CAAC/B,sBAAAA;;;;"}
|
|
@@ -40,7 +40,7 @@ const NonRepeatableComponentFields = /*#__PURE__*/ React.memo(({ attribute, chil
|
|
|
40
40
|
direction: "column",
|
|
41
41
|
alignItems: "stretch",
|
|
42
42
|
gap: 6,
|
|
43
|
-
children: layout.map((row
|
|
43
|
+
children: layout.map((row)=>{
|
|
44
44
|
return /*#__PURE__*/ jsx(ResponsiveGridRoot, {
|
|
45
45
|
gap: {
|
|
46
46
|
initial: 3,
|
|
@@ -70,7 +70,7 @@ const NonRepeatableComponentFields = /*#__PURE__*/ React.memo(({ attribute, chil
|
|
|
70
70
|
})
|
|
71
71
|
}, completeFieldName);
|
|
72
72
|
})
|
|
73
|
-
},
|
|
73
|
+
}, row.map((field)=>field.name).join('.'));
|
|
74
74
|
})
|
|
75
75
|
});
|
|
76
76
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NonRepeatable.mjs","sources":["../../../../../../../admin/src/pages/EditView/components/FormInputs/Component/NonRepeatable.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { useForm, useIsMobile } from '@strapi/admin/strapi-admin';\nimport { Box, Flex } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\n\nimport { getIn } from '../../../../../utils/objects';\nimport { ResponsiveGridItem, ResponsiveGridRoot } from '../../FormLayout';\nimport { ComponentProvider, useComponent } from '../ComponentContext';\n\nimport type { ComponentInputProps } from './Input';\n\ntype NonRepeatableComponentProps = Omit<ComponentInputProps, 'required' | 'label'>;\n\nconst NonRepeatableComponent = ({\n attribute,\n name,\n children,\n layout,\n}: NonRepeatableComponentProps) => {\n const componentId = useForm(\n 'NonRepeatableComponent',\n (state) => getIn(state.values, `${name}.id`) as number | undefined\n );\n const level = useComponent('NonRepeatableComponent', (state) => state.level);\n const isNested = level > 0;\n const isMobile = useIsMobile();\n\n return (\n <ComponentProvider\n id={componentId}\n uid={attribute.component}\n level={level + 1}\n type=\"component\"\n >\n <Box\n background={'neutral100'}\n padding={{ initial: 4, medium: 6 }}\n hasRadius={isNested}\n borderColor={isNested || isMobile ? 'neutral200' : undefined}\n >\n <NonRepeatableComponentFields attribute={attribute} name={name} layout={layout}>\n {children}\n </NonRepeatableComponentFields>\n </Box>\n </ComponentProvider>\n );\n};\n\ninterface NonRepeatableComponentFieldsProps
|
|
1
|
+
{"version":3,"file":"NonRepeatable.mjs","sources":["../../../../../../../admin/src/pages/EditView/components/FormInputs/Component/NonRepeatable.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { useForm, useIsMobile } from '@strapi/admin/strapi-admin';\nimport { Box, Flex } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\n\nimport { getIn } from '../../../../../utils/objects';\nimport { ResponsiveGridItem, ResponsiveGridRoot } from '../../FormLayout';\nimport { ComponentProvider, useComponent } from '../ComponentContext';\n\nimport type { ComponentInputProps } from './Input';\n\ntype NonRepeatableComponentProps = Omit<ComponentInputProps, 'required' | 'label'>;\n\nconst NonRepeatableComponent = ({\n attribute,\n name,\n children,\n layout,\n}: NonRepeatableComponentProps) => {\n const componentId = useForm(\n 'NonRepeatableComponent',\n (state) => getIn(state.values, `${name}.id`) as number | undefined\n );\n const level = useComponent('NonRepeatableComponent', (state) => state.level);\n const isNested = level > 0;\n const isMobile = useIsMobile();\n\n return (\n <ComponentProvider\n id={componentId}\n uid={attribute.component}\n level={level + 1}\n type=\"component\"\n >\n <Box\n background={'neutral100'}\n padding={{ initial: 4, medium: 6 }}\n hasRadius={isNested}\n borderColor={isNested || isMobile ? 'neutral200' : undefined}\n >\n <NonRepeatableComponentFields attribute={attribute} name={name} layout={layout}>\n {children}\n </NonRepeatableComponentFields>\n </Box>\n </ComponentProvider>\n );\n};\n\ninterface NonRepeatableComponentFieldsProps extends Pick<\n NonRepeatableComponentProps,\n 'attribute' | 'children' | 'layout' | 'name'\n> {}\n\nconst NonRepeatableComponentFields = React.memo(\n ({ attribute, children, layout, name }: NonRepeatableComponentFieldsProps) => {\n const { formatMessage } = useIntl();\n\n return (\n <Flex direction=\"column\" alignItems=\"stretch\" gap={6}>\n {layout.map((row) => {\n return (\n <ResponsiveGridRoot\n gap={{ initial: 3, medium: 4 }}\n key={row.map((field) => field.name).join('.')}\n >\n {row.map(({ size, ...field }) => {\n /**\n * Layouts are built from schemas so they don't understand the complete\n * schema tree, for components we append the parent name to the field name\n * because this is the structure for the data & permissions also understand\n * the nesting involved.\n */\n const completeFieldName = `${name}.${field.name}`;\n\n const translatedLabel = formatMessage({\n id: `content-manager.components.${attribute.component}.${field.name}`,\n defaultMessage: field.label,\n });\n\n return (\n <ResponsiveGridItem\n col={size}\n key={completeFieldName}\n s={12}\n xs={12}\n direction=\"column\"\n alignItems=\"stretch\"\n >\n {children({\n ...field,\n label: translatedLabel,\n name: completeFieldName,\n })}\n </ResponsiveGridItem>\n );\n })}\n </ResponsiveGridRoot>\n );\n })}\n </Flex>\n );\n }\n);\n\nNonRepeatableComponentFields.displayName = 'NonRepeatableComponentFields';\n\nconst MemoizedNonRepeatableComponent = React.memo(NonRepeatableComponent);\n\nexport { MemoizedNonRepeatableComponent as NonRepeatableComponent };\nexport type { NonRepeatableComponentProps };\n"],"names":["NonRepeatableComponent","attribute","name","children","layout","componentId","useForm","state","getIn","values","level","useComponent","isNested","isMobile","useIsMobile","_jsx","ComponentProvider","id","uid","component","type","Box","background","padding","initial","medium","hasRadius","borderColor","undefined","NonRepeatableComponentFields","React","memo","formatMessage","useIntl","Flex","direction","alignItems","gap","map","row","ResponsiveGridRoot","size","field","completeFieldName","translatedLabel","defaultMessage","label","ResponsiveGridItem","col","s","xs","join","displayName","MemoizedNonRepeatableComponent"],"mappings":"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"}
|
|
@@ -41,6 +41,10 @@ function _interopNamespace(e) {
|
|
|
41
41
|
|
|
42
42
|
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
43
43
|
|
|
44
|
+
const DEFAULT_MAIN_FIELD = {
|
|
45
|
+
name: 'id',
|
|
46
|
+
type: 'integer'
|
|
47
|
+
};
|
|
44
48
|
const RepeatableComponent = ({ attribute, disabled, name, mainField, children, layout })=>{
|
|
45
49
|
const { toggleNotification } = strapiAdmin.useNotification();
|
|
46
50
|
const { formatMessage } = reactIntl.useIntl();
|
|
@@ -307,7 +311,7 @@ const TextButtonCustom = styledComponents.styled(designSystem.TextButton)`
|
|
|
307
311
|
const RepeatableComponentFields = /*#__PURE__*/ React__namespace.memo(({ attributeComponent, children, layout, nameWithIndex })=>{
|
|
308
312
|
const { formatMessage } = reactIntl.useIntl();
|
|
309
313
|
return /*#__PURE__*/ jsxRuntime.jsx(jsxRuntime.Fragment, {
|
|
310
|
-
children: layout.map((row
|
|
314
|
+
children: layout.map((row)=>{
|
|
311
315
|
return /*#__PURE__*/ jsxRuntime.jsx(FormLayout.ResponsiveGridRoot, {
|
|
312
316
|
gap: 4,
|
|
313
317
|
children: row.map(({ size, ...field })=>{
|
|
@@ -334,15 +338,12 @@ const RepeatableComponentFields = /*#__PURE__*/ React__namespace.memo(({ attribu
|
|
|
334
338
|
})
|
|
335
339
|
}, completeFieldName);
|
|
336
340
|
})
|
|
337
|
-
},
|
|
341
|
+
}, row.map((field)=>field.name).join('.'));
|
|
338
342
|
})
|
|
339
343
|
});
|
|
340
344
|
});
|
|
341
345
|
RepeatableComponentFields.displayName = 'RepeatableComponentFields';
|
|
342
|
-
const Component = ({ attributeComponent, disabled, index, name, mainField = {
|
|
343
|
-
name: 'id',
|
|
344
|
-
type: 'integer'
|
|
345
|
-
}, layout, onDeleteComponent, renderField, toggleCollapses, __temp_key__, totalLength, onMoveItem, ...dragProps })=>{
|
|
346
|
+
const Component = ({ attributeComponent, disabled, index, name, mainField = DEFAULT_MAIN_FIELD, layout, onDeleteComponent, renderField, toggleCollapses, __temp_key__, totalLength, onMoveItem, ...dragProps })=>{
|
|
346
347
|
const { formatMessage } = reactIntl.useIntl();
|
|
347
348
|
const isDesktop = strapiAdmin.useIsDesktop();
|
|
348
349
|
const displayValue = strapiAdmin.useForm('RepeatableComponent', (state)=>{
|