payload-better-editor 1.2.2 → 1.4.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/ErrorBoundary.d.ts +1 -10
- package/dist/admin/ErrorBoundary.js +14 -5
- package/dist/admin/ErrorBoundary.js.map +1 -1
- package/dist/admin/LiveEditorOverlay.js +4 -2
- package/dist/admin/LiveEditorOverlay.js.map +1 -1
- package/dist/admin/LiveEditorToggle.d.ts +2 -0
- package/dist/admin/LiveEditorToggle.js +14 -9
- package/dist/admin/LiveEditorToggle.js.map +1 -1
- package/dist/admin/PreviewFrame.js +6 -4
- package/dist/admin/PreviewFrame.js.map +1 -1
- package/dist/admin/PreviewToolbar.js +20 -13
- package/dist/admin/PreviewToolbar.js.map +1 -1
- package/dist/admin/SettingsBanner.js +10 -5
- package/dist/admin/SettingsBanner.js.map +1 -1
- package/dist/admin/ViewportToggle.js +30 -25
- package/dist/admin/ViewportToggle.js.map +1 -1
- package/dist/admin/blocks/AddBlockDrawer.js +7 -3
- package/dist/admin/blocks/AddBlockDrawer.js.map +1 -1
- package/dist/admin/blocks/BlockActionsToolbar.js +13 -11
- package/dist/admin/blocks/BlockActionsToolbar.js.map +1 -1
- package/dist/admin/blocks/BlockEmptyState.js +7 -3
- package/dist/admin/blocks/BlockEmptyState.js.map +1 -1
- package/dist/admin/blocks/BlockHeader.d.ts +1 -0
- package/dist/admin/blocks/BlockHeader.js +9 -8
- package/dist/admin/blocks/BlockHeader.js.map +1 -1
- package/dist/admin/blocks/schema.js +38 -7
- package/dist/admin/blocks/schema.js.map +1 -1
- package/dist/admin/sidebar/BlockSettingsTab.js +19 -4
- package/dist/admin/sidebar/BlockSettingsTab.js.map +1 -1
- package/dist/admin/sidebar/DocumentMetaTab.js +6 -2
- package/dist/admin/sidebar/DocumentMetaTab.js.map +1 -1
- package/dist/admin/sidebar/DocumentSettingsTab.js +6 -2
- package/dist/admin/sidebar/DocumentSettingsTab.js.map +1 -1
- package/dist/admin/sidebar/Sidebar.js +21 -16
- package/dist/admin/sidebar/Sidebar.js.map +1 -1
- package/dist/admin/sidebar/ValidationSummary.js +5 -2
- package/dist/admin/sidebar/ValidationSummary.js.map +1 -1
- package/dist/global.js +54 -39
- package/dist/global.js.map +1 -1
- package/dist/hooks/usePreviewBinding.js +6 -2
- package/dist/hooks/usePreviewBinding.js.map +1 -1
- package/dist/hooks/usePreviewSettingsSync.js +8 -3
- package/dist/hooks/usePreviewSettingsSync.js.map +1 -1
- package/dist/i18n/cs.d.ts +2 -0
- package/dist/i18n/cs.js +136 -0
- package/dist/i18n/cs.js.map +1 -0
- package/dist/i18n/da.d.ts +2 -0
- package/dist/i18n/da.js +136 -0
- package/dist/i18n/da.js.map +1 -0
- package/dist/i18n/de.d.ts +2 -0
- package/dist/i18n/de.js +135 -0
- package/dist/i18n/de.js.map +1 -0
- package/dist/i18n/en.d.ts +2 -0
- package/dist/i18n/en.js +135 -0
- package/dist/i18n/en.js.map +1 -0
- package/dist/i18n/es.d.ts +2 -0
- package/dist/i18n/es.js +136 -0
- package/dist/i18n/es.js.map +1 -0
- package/dist/i18n/fr.d.ts +2 -0
- package/dist/i18n/fr.js +136 -0
- package/dist/i18n/fr.js.map +1 -0
- package/dist/i18n/index.d.ts +2 -0
- package/dist/i18n/index.js +34 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/i18n/it.d.ts +2 -0
- package/dist/i18n/it.js +136 -0
- package/dist/i18n/it.js.map +1 -0
- package/dist/i18n/merge.d.ts +8 -0
- package/dist/i18n/merge.js +22 -0
- package/dist/i18n/merge.js.map +1 -0
- package/dist/i18n/nb.d.ts +2 -0
- package/dist/i18n/nb.js +136 -0
- package/dist/i18n/nb.js.map +1 -0
- package/dist/i18n/nl.d.ts +2 -0
- package/dist/i18n/nl.js +136 -0
- package/dist/i18n/nl.js.map +1 -0
- package/dist/i18n/pl.d.ts +2 -0
- package/dist/i18n/pl.js +136 -0
- package/dist/i18n/pl.js.map +1 -0
- package/dist/i18n/pt.d.ts +2 -0
- package/dist/i18n/pt.js +136 -0
- package/dist/i18n/pt.js.map +1 -0
- package/dist/i18n/ro.d.ts +2 -0
- package/dist/i18n/ro.js +136 -0
- package/dist/i18n/ro.js.map +1 -0
- package/dist/i18n/sv.d.ts +2 -0
- package/dist/i18n/sv.js +136 -0
- package/dist/i18n/sv.js.map +1 -0
- package/dist/i18n/tr.d.ts +2 -0
- package/dist/i18n/tr.js +136 -0
- package/dist/i18n/tr.js.map +1 -0
- package/dist/i18n/types.d.ts +133 -0
- package/dist/i18n/types.js +3 -0
- package/dist/i18n/types.js.map +1 -0
- package/dist/i18n/uk.d.ts +2 -0
- package/dist/i18n/uk.js +136 -0
- package/dist/i18n/uk.js.map +1 -0
- package/dist/i18n/useBetterEditorT.d.ts +2 -0
- package/dist/i18n/useBetterEditorT.js +10 -0
- package/dist/i18n/useBetterEditorT.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +19 -2
- package/dist/index.js.map +1 -1
- package/dist/preview/HoverToolbar.d.ts +8 -0
- package/dist/preview/HoverToolbar.js +31 -29
- package/dist/preview/HoverToolbar.js.map +1 -1
- package/dist/preview/HoverToolbarController.d.ts +6 -0
- package/dist/preview/HoverToolbarController.js +20 -5
- package/dist/preview/HoverToolbarController.js.map +1 -1
- package/dist/styles/blocks-tab.css +1 -7
- package/dist/styles/overlay.css +2 -0
- package/dist/styles/sidebar.css +1 -0
- package/dist/styles/toggle.css +17 -0
- package/dist/types.d.ts +6 -0
- package/dist/types.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +13 -14
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/admin/sidebar/BlockSettingsTab.tsx"],"sourcesContent":["'use client'\n\nimport React, { useMemo } from 'react'\nimport {\n RenderFields,\n useAllFormFields,\n useConfig,\n useDrawerSlug,\n useField,\n useModal,\n} from '@payloadcms/ui'\nimport { useDocConfig } from '../../hooks/useDocConfig'\nimport { useAddBlockDrawer } from '../../hooks/useAddBlockDrawer'\nimport { AddBlockDrawer } from '../blocks/AddBlockDrawer'\nimport { BlockActionsToolbar } from '../blocks/BlockActionsToolbar'\nimport { useBlockActions } from '../blocks/useBlockActions'\nimport { findNamedField, resolveBlockSchema, resolveFieldBlocks } from '../blocks/schema'\nimport type { ClientBlock } from 'payload'\nimport { BlockEmptyState } from '../blocks/BlockEmptyState'\nimport { BlockHeader } from '../blocks/BlockHeader'\n\nexport type BlockSettingsTabProps = {\n selectedBlockPath: string | null\n onClearSelection: () => void\n onSelectPath: (path: string | null) => void\n blocksField: string\n /** Bump to open the add-after drawer externally (iframe `+` button). */\n addBelowRequestId?: number\n}\n\nexport const BlockSettingsTab: React.FC<BlockSettingsTabProps> = ({\n selectedBlockPath,\n onClearSelection,\n onSelectPath,\n blocksField,\n addBelowRequestId = 0,\n}) => {\n const { fields: docFields, slug: docSlug } = useDocConfig()\n const [fields] = useAllFormFields()\n const { config } = useConfig()\n const blocksMap = config.blocksMap\n const { toggleModal } = useModal()\n const addBlockDrawerSlug = useDrawerSlug('better-editor-add-block')\n const addAfterDrawerSlug = useDrawerSlug('better-editor-add-after')\n\n const actions = useBlockActions({\n selectedBlockPath,\n onSelectPath,\n onClearSelection,\n })\n\n useAddBlockDrawer({\n drawerSlug: addAfterDrawerSlug,\n requestId: addBelowRequestId,\n selectedBlockPath,\n })\n\n const blocksFieldInfo = useMemo(() => {\n if (!docFields) return null\n return findNamedField(docFields, blocksField, docSlug || '')\n }, [docFields, blocksField, docSlug])\n\n const blocksFieldField = blocksFieldInfo?.field\n const availableBlocks: ClientBlock[] =\n blocksFieldField && blocksFieldField.type === 'blocks'\n ? resolveFieldBlocks(blocksFieldField, blocksMap)\n : []\n const blocksSchemaPath = blocksFieldInfo?.schemaPath || ''\n const topLevelRows = fields[blocksField]?.rows\n const addRowIndex = Array.isArray(topLevelRows) ? topLevelRows.length : 0\n\n if (!selectedBlockPath) {\n return (\n <>\n <BlockEmptyState\n canAdd={availableBlocks.length > 0}\n onAddClick={() => toggleModal(addBlockDrawerSlug)}\n />\n {availableBlocks.length > 0 ? (\n <AddBlockDrawer\n slug={addBlockDrawerSlug}\n blocks={availableBlocks}\n addRow={(index, blockType) =>\n actions.addAfter({\n blockType,\n schemaPath: blocksSchemaPath,\n containerPath: blocksField,\n index,\n })\n }\n addRowIndex={addRowIndex}\n />\n ) : null}\n </>\n )\n }\n\n const resolved = docFields\n ? resolveBlockSchema(\n { docFields, docSlug: docSlug || '', formFields: fields, blocksMap },\n selectedBlockPath,\n )\n : null\n\n return (\n <div className=\"better-editor-tab better-editor-tab--native\">\n <BlockHeader\n blockType={resolved?.blockType || 'unknown'}\n path={selectedBlockPath}\n onClearSelection={onClearSelection}\n />\n\n <hr className=\"better-editor-tab__divider\" aria-hidden=\"true\" />\n\n <BlockActionsToolbar\n canMoveUp={actions.canMoveUp}\n canMoveDown={actions.canMoveDown}\n canMutate={actions.canMutate}\n canAddBelow={!!resolved}\n onMoveUp={actions.moveUp}\n onMoveDown={actions.moveDown}\n onDuplicate={actions.duplicate}\n onAddBelow={() => toggleModal(addAfterDrawerSlug)}\n onDelete={actions.remove}\n />\n\n {actions.canMutate && resolved && resolved.blocksFieldBlocks.length > 0 ? (\n <AddBlockDrawer\n slug={addAfterDrawerSlug}\n blocks={resolved.blocksFieldBlocks}\n addRow={(index, blockType) =>\n actions.addAfter({\n blockType,\n schemaPath: resolved.blocksFieldSchemaPath,\n containerPath: actions.parentPath,\n index,\n })\n }\n addRowIndex={actions.rowIndex + 1}\n />\n ) : null}\n\n {!resolved ? (\n <div className=\"better-editor-tab__empty\">\n Could not resolve block schema for this path.\n </div>\n ) : (\n <>\n <BlockNameInput path={`${selectedBlockPath}.blockName`} />\n <hr className=\"better-editor-tab__divider\" aria-hidden=\"true\" />\n <RenderFields\n fields={resolved.blockFields}\n parentPath={resolved.parentPath}\n parentIndexPath=\"\"\n parentSchemaPath={resolved.schemaPath}\n // RenderFields' client read-gate is bypassed; the server-side\n // write check still runs on save.\n permissions={true}\n />\n </>\n )}\n </div>\n )\n}\n\nconst BlockNameInput: React.FC<{ path: string }> = ({ path }) => {\n const { value, setValue } = useField<string>({ path })\n const inputId = `be-blockname-${path}`\n return (\n <div className=\"better-editor-tab__block-name\">\n <label className=\"better-editor-tab__block-name-label\" htmlFor={inputId}>\n Block Name\n </label>\n <input\n id={inputId}\n className=\"better-editor-tab__block-name-input\"\n type=\"text\"\n value={value || ''}\n onChange={(e) => setValue(e.target.value)}\n placeholder=\"Optional label for this block\"\n />\n </div>\n )\n}\n"],"names":["React","useMemo","RenderFields","useAllFormFields","useConfig","useDrawerSlug","useField","useModal","useDocConfig","useAddBlockDrawer","AddBlockDrawer","BlockActionsToolbar","useBlockActions","findNamedField","resolveBlockSchema","resolveFieldBlocks","BlockEmptyState","BlockHeader","BlockSettingsTab","selectedBlockPath","onClearSelection","onSelectPath","blocksField","addBelowRequestId","fields","docFields","slug","docSlug","config","blocksMap","toggleModal","addBlockDrawerSlug","addAfterDrawerSlug","actions","drawerSlug","requestId","blocksFieldInfo","blocksFieldField","field","availableBlocks","type","blocksSchemaPath","schemaPath","topLevelRows","rows","addRowIndex","Array","isArray","length","canAdd","onAddClick","blocks","addRow","index","blockType","addAfter","containerPath","resolved","formFields","div","className","path","hr","aria-hidden","canMoveUp","canMoveDown","canMutate","canAddBelow","onMoveUp","moveUp","onMoveDown","moveDown","onDuplicate","duplicate","onAddBelow","onDelete","remove","blocksFieldBlocks","blocksFieldSchemaPath","parentPath","rowIndex","BlockNameInput","blockFields","parentIndexPath","parentSchemaPath","permissions","value","setValue","inputId","label","htmlFor","input","id","onChange","e","target","placeholder"],"mappings":"AAAA;;AAEA,OAAOA,SAASC,OAAO,QAAQ,QAAO;AACtC,SACEC,YAAY,EACZC,gBAAgB,EAChBC,SAAS,EACTC,aAAa,EACbC,QAAQ,EACRC,QAAQ,QACH,iBAAgB;AACvB,SAASC,YAAY,QAAQ,2BAA0B;AACvD,SAASC,iBAAiB,QAAQ,gCAA+B;AACjE,SAASC,cAAc,QAAQ,2BAA0B;AACzD,SAASC,mBAAmB,QAAQ,gCAA+B;AACnE,SAASC,eAAe,QAAQ,4BAA2B;AAC3D,SAASC,cAAc,EAAEC,kBAAkB,EAAEC,kBAAkB,QAAQ,mBAAkB;AAEzF,SAASC,eAAe,QAAQ,4BAA2B;AAC3D,SAASC,WAAW,QAAQ,wBAAuB;AAWnD,OAAO,MAAMC,mBAAoD,CAAC,EAChEC,iBAAiB,EACjBC,gBAAgB,EAChBC,YAAY,EACZC,WAAW,EACXC,oBAAoB,CAAC,EACtB;IACC,MAAM,EAAEC,QAAQC,SAAS,EAAEC,MAAMC,OAAO,EAAE,GAAGnB;IAC7C,MAAM,CAACgB,OAAO,GAAGrB;IACjB,MAAM,EAAEyB,MAAM,EAAE,GAAGxB;IACnB,MAAMyB,YAAYD,OAAOC,SAAS;IAClC,MAAM,EAAEC,WAAW,EAAE,GAAGvB;IACxB,MAAMwB,qBAAqB1B,cAAc;IACzC,MAAM2B,qBAAqB3B,cAAc;IAEzC,MAAM4B,UAAUrB,gBAAgB;QAC9BO;QACAE;QACAD;IACF;IAEAX,kBAAkB;QAChByB,YAAYF;QACZG,WAAWZ;QACXJ;IACF;IAEA,MAAMiB,kBAAkBnC,QAAQ;QAC9B,IAAI,CAACwB,WAAW,OAAO;QACvB,OAAOZ,eAAeY,WAAWH,aAAaK,WAAW;IAC3D,GAAG;QAACF;QAAWH;QAAaK;KAAQ;IAEpC,MAAMU,mBAAmBD,iBAAiBE;IAC1C,MAAMC,kBACJF,oBAAoBA,iBAAiBG,IAAI,KAAK,WAC1CzB,mBAAmBsB,kBAAkBR,aACrC,EAAE;IACR,MAAMY,mBAAmBL,iBAAiBM,cAAc;IACxD,MAAMC,eAAenB,MAAM,CAACF,YAAY,EAAEsB;IAC1C,MAAMC,cAAcC,MAAMC,OAAO,CAACJ,gBAAgBA,aAAaK,MAAM,GAAG;IAExE,IAAI,CAAC7B,mBAAmB;QACtB,qBACE;;8BACE,KAACH;oBACCiC,QAAQV,gBAAgBS,MAAM,GAAG;oBACjCE,YAAY,IAAMpB,YAAYC;;gBAE/BQ,gBAAgBS,MAAM,GAAG,kBACxB,KAACtC;oBACCgB,MAAMK;oBACNoB,QAAQZ;oBACRa,QAAQ,CAACC,OAAOC,YACdrB,QAAQsB,QAAQ,CAAC;4BACfD;4BACAZ,YAAYD;4BACZe,eAAelC;4BACf+B;wBACF;oBAEFR,aAAaA;qBAEb;;;IAGV;IAEA,MAAMY,WAAWhC,YACbX,mBACE;QAAEW;QAAWE,SAASA,WAAW;QAAI+B,YAAYlC;QAAQK;IAAU,GACnEV,qBAEF;IAEJ,qBACE,MAACwC;QAAIC,WAAU;;0BACb,KAAC3C;gBACCqC,WAAWG,UAAUH,aAAa;gBAClCO,MAAM1C;gBACNC,kBAAkBA;;0BAGpB,KAAC0C;gBAAGF,WAAU;gBAA6BG,eAAY;;0BAEvD,KAACpD;gBACCqD,WAAW/B,QAAQ+B,SAAS;gBAC5BC,aAAahC,QAAQgC,WAAW;gBAChCC,WAAWjC,QAAQiC,SAAS;gBAC5BC,aAAa,CAAC,CAACV;gBACfW,UAAUnC,QAAQoC,MAAM;gBACxBC,YAAYrC,QAAQsC,QAAQ;gBAC5BC,aAAavC,QAAQwC,SAAS;gBAC9BC,YAAY,IAAM5C,YAAYE;gBAC9B2C,UAAU1C,QAAQ2C,MAAM;;YAGzB3C,QAAQiC,SAAS,IAAIT,YAAYA,SAASoB,iBAAiB,CAAC7B,MAAM,GAAG,kBACpE,KAACtC;gBACCgB,MAAMM;gBACNmB,QAAQM,SAASoB,iBAAiB;gBAClCzB,QAAQ,CAACC,OAAOC,YACdrB,QAAQsB,QAAQ,CAAC;wBACfD;wBACAZ,YAAYe,SAASqB,qBAAqB;wBAC1CtB,eAAevB,QAAQ8C,UAAU;wBACjC1B;oBACF;gBAEFR,aAAaZ,QAAQ+C,QAAQ,GAAG;iBAEhC;YAEH,CAACvB,yBACA,KAACE;gBAAIC,WAAU;0BAA2B;+BAI1C;;kCACE,KAACqB;wBAAepB,MAAM,GAAG1C,kBAAkB,UAAU,CAAC;;kCACtD,KAAC2C;wBAAGF,WAAU;wBAA6BG,eAAY;;kCACvD,KAAC7D;wBACCsB,QAAQiC,SAASyB,WAAW;wBAC5BH,YAAYtB,SAASsB,UAAU;wBAC/BI,iBAAgB;wBAChBC,kBAAkB3B,SAASf,UAAU;wBACrC,8DAA8D;wBAC9D,kCAAkC;wBAClC2C,aAAa;;;;;;AAMzB,EAAC;AAED,MAAMJ,iBAA6C,CAAC,EAAEpB,IAAI,EAAE;IAC1D,MAAM,EAAEyB,KAAK,EAAEC,QAAQ,EAAE,GAAGjF,SAAiB;QAAEuD;IAAK;IACpD,MAAM2B,UAAU,CAAC,aAAa,EAAE3B,MAAM;IACtC,qBACE,MAACF;QAAIC,WAAU;;0BACb,KAAC6B;gBAAM7B,WAAU;gBAAsC8B,SAASF;0BAAS;;0BAGzE,KAACG;gBACCC,IAAIJ;gBACJ5B,WAAU;gBACVpB,MAAK;gBACL8C,OAAOA,SAAS;gBAChBO,UAAU,CAACC,IAAMP,SAASO,EAAEC,MAAM,CAACT,KAAK;gBACxCU,aAAY;;;;AAIpB"}
|
|
1
|
+
{"version":3,"sources":["../../../src/admin/sidebar/BlockSettingsTab.tsx"],"sourcesContent":["'use client'\n\nimport React, { useMemo } from 'react'\nimport {\n RenderFields,\n useAllFormFields,\n useConfig,\n useDrawerSlug,\n useField,\n useModal,\n useTranslation,\n} from '@payloadcms/ui'\nimport { useDocConfig } from '../../hooks/useDocConfig'\nimport { useAddBlockDrawer } from '../../hooks/useAddBlockDrawer'\nimport { AddBlockDrawer } from '../blocks/AddBlockDrawer'\nimport { BlockActionsToolbar } from '../blocks/BlockActionsToolbar'\nimport { useBlockActions } from '../blocks/useBlockActions'\nimport { findNamedField, resolveBlockSchema, resolveFieldBlocks } from '../blocks/schema'\nimport type { ClientBlock } from 'payload'\nimport { BlockEmptyState } from '../blocks/BlockEmptyState'\nimport { BlockHeader } from '../blocks/BlockHeader'\nimport { useBetterEditorT } from '../../i18n/useBetterEditorT'\n\nexport type BlockSettingsTabProps = {\n selectedBlockPath: string | null\n onClearSelection: () => void\n onSelectPath: (path: string | null) => void\n blocksField: string\n /** Bump to open the add-after drawer externally (iframe `+` button). */\n addBelowRequestId?: number\n}\n\nexport const BlockSettingsTab: React.FC<BlockSettingsTabProps> = ({\n selectedBlockPath,\n onClearSelection,\n onSelectPath,\n blocksField,\n addBelowRequestId = 0,\n}) => {\n const t = useBetterEditorT()\n const { i18n } = useTranslation()\n const { fields: docFields, slug: docSlug } = useDocConfig()\n const [fields] = useAllFormFields()\n const { config } = useConfig()\n const blocksMap = config.blocksMap\n const { toggleModal } = useModal()\n const addBlockDrawerSlug = useDrawerSlug('better-editor-add-block')\n const addAfterDrawerSlug = useDrawerSlug('better-editor-add-after')\n\n const actions = useBlockActions({\n selectedBlockPath,\n onSelectPath,\n onClearSelection,\n })\n\n useAddBlockDrawer({\n drawerSlug: addAfterDrawerSlug,\n requestId: addBelowRequestId,\n selectedBlockPath,\n })\n\n const blocksFieldInfo = useMemo(() => {\n if (!docFields) return null\n return findNamedField(docFields, blocksField, docSlug || '')\n }, [docFields, blocksField, docSlug])\n\n const blocksFieldField = blocksFieldInfo?.field\n const availableBlocks: ClientBlock[] =\n blocksFieldField && blocksFieldField.type === 'blocks'\n ? resolveFieldBlocks(blocksFieldField, blocksMap)\n : []\n const blocksSchemaPath = blocksFieldInfo?.schemaPath || ''\n const topLevelRows = fields[blocksField]?.rows\n const addRowIndex = Array.isArray(topLevelRows) ? topLevelRows.length : 0\n\n if (!selectedBlockPath) {\n return (\n <>\n <BlockEmptyState\n canAdd={availableBlocks.length > 0}\n onAddClick={() => toggleModal(addBlockDrawerSlug)}\n />\n {availableBlocks.length > 0 ? (\n <AddBlockDrawer\n slug={addBlockDrawerSlug}\n blocks={availableBlocks}\n addRow={(index, blockType) =>\n actions.addAfter({\n blockType,\n schemaPath: blocksSchemaPath,\n containerPath: blocksField,\n index,\n })\n }\n addRowIndex={addRowIndex}\n />\n ) : null}\n </>\n )\n }\n\n const resolved = docFields\n ? resolveBlockSchema(\n { docFields, docSlug: docSlug || '', formFields: fields, blocksMap },\n selectedBlockPath,\n )\n : null\n\n const blockLabel = (() => {\n if (!resolved) return undefined\n const cfg = resolved.blocksFieldBlocks.find((b) => b.slug === resolved.blockType)\n const singular = cfg?.labels?.singular\n if (typeof singular === 'string') return singular\n if (singular && typeof singular === 'object') {\n return (singular as Record<string, string>)[i18n.language] ?? Object.values(singular)[0] as string | undefined\n }\n return undefined\n })()\n\n return (\n <div className=\"better-editor-tab better-editor-tab--native\">\n <BlockHeader\n blockType={resolved?.blockType || 'unknown'}\n blockLabel={blockLabel}\n path={selectedBlockPath}\n onClearSelection={onClearSelection}\n />\n\n <hr className=\"better-editor-tab__divider\" aria-hidden=\"true\" />\n\n <BlockActionsToolbar\n canMoveUp={actions.canMoveUp}\n canMoveDown={actions.canMoveDown}\n canMutate={actions.canMutate}\n canAddBelow={!!resolved}\n onMoveUp={actions.moveUp}\n onMoveDown={actions.moveDown}\n onDuplicate={actions.duplicate}\n onAddBelow={() => toggleModal(addAfterDrawerSlug)}\n onDelete={actions.remove}\n />\n\n {actions.canMutate && resolved && resolved.blocksFieldBlocks.length > 0 ? (\n <AddBlockDrawer\n slug={addAfterDrawerSlug}\n blocks={resolved.blocksFieldBlocks}\n addRow={(index, blockType) =>\n actions.addAfter({\n blockType,\n schemaPath: resolved.blocksFieldSchemaPath,\n containerPath: actions.parentPath,\n index,\n })\n }\n addRowIndex={actions.rowIndex + 1}\n />\n ) : null}\n\n {!resolved ? (\n <div className=\"better-editor-tab__empty\">{t.blocks.schemaError}</div>\n ) : (\n <>\n <BlockNameInput path={`${selectedBlockPath}.blockName`} />\n <hr className=\"better-editor-tab__divider\" aria-hidden=\"true\" />\n <RenderFields\n fields={resolved.blockFields}\n parentPath={resolved.parentPath}\n parentIndexPath=\"\"\n parentSchemaPath={resolved.schemaPath}\n // RenderFields' client read-gate is bypassed; the server-side\n // write check still runs on save.\n permissions={true}\n />\n </>\n )}\n </div>\n )\n}\n\nconst BlockNameInput: React.FC<{ path: string }> = ({ path }) => {\n const { value, setValue } = useField<string>({ path })\n const t = useBetterEditorT()\n const inputId = `be-blockname-${path}`\n return (\n <div className=\"better-editor-tab__block-name\">\n <label className=\"better-editor-tab__block-name-label\" htmlFor={inputId}>\n {t.blocks.blockName}\n </label>\n <input\n id={inputId}\n className=\"better-editor-tab__block-name-input\"\n type=\"text\"\n value={value || ''}\n onChange={(e) => setValue(e.target.value)}\n placeholder={t.blocks.blockNamePlaceholder}\n />\n </div>\n )\n}\n"],"names":["React","useMemo","RenderFields","useAllFormFields","useConfig","useDrawerSlug","useField","useModal","useTranslation","useDocConfig","useAddBlockDrawer","AddBlockDrawer","BlockActionsToolbar","useBlockActions","findNamedField","resolveBlockSchema","resolveFieldBlocks","BlockEmptyState","BlockHeader","useBetterEditorT","BlockSettingsTab","selectedBlockPath","onClearSelection","onSelectPath","blocksField","addBelowRequestId","t","i18n","fields","docFields","slug","docSlug","config","blocksMap","toggleModal","addBlockDrawerSlug","addAfterDrawerSlug","actions","drawerSlug","requestId","blocksFieldInfo","blocksFieldField","field","availableBlocks","type","blocksSchemaPath","schemaPath","topLevelRows","rows","addRowIndex","Array","isArray","length","canAdd","onAddClick","blocks","addRow","index","blockType","addAfter","containerPath","resolved","formFields","blockLabel","undefined","cfg","blocksFieldBlocks","find","b","singular","labels","language","Object","values","div","className","path","hr","aria-hidden","canMoveUp","canMoveDown","canMutate","canAddBelow","onMoveUp","moveUp","onMoveDown","moveDown","onDuplicate","duplicate","onAddBelow","onDelete","remove","blocksFieldSchemaPath","parentPath","rowIndex","schemaError","BlockNameInput","blockFields","parentIndexPath","parentSchemaPath","permissions","value","setValue","inputId","label","htmlFor","blockName","input","id","onChange","e","target","placeholder","blockNamePlaceholder"],"mappings":"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"}
|
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import React from 'react';
|
|
4
4
|
import { DocumentFieldsTab } from './DocumentFieldsTab';
|
|
5
|
+
import { useBetterEditorT } from '../../i18n/useBetterEditorT';
|
|
5
6
|
const isSidebarField = (f)=>'admin' in f && f.admin?.position === 'sidebar';
|
|
6
|
-
export const DocumentMetaTab = ()
|
|
7
|
+
export const DocumentMetaTab = ()=>{
|
|
8
|
+
const t = useBetterEditorT();
|
|
9
|
+
return /*#__PURE__*/ _jsx(DocumentFieldsTab, {
|
|
7
10
|
filter: isSidebarField,
|
|
8
|
-
emptyText:
|
|
11
|
+
emptyText: t.documentFields.noSettings
|
|
9
12
|
});
|
|
13
|
+
};
|
|
10
14
|
|
|
11
15
|
//# sourceMappingURL=DocumentMetaTab.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/admin/sidebar/DocumentMetaTab.tsx"],"sourcesContent":["'use client'\n\nimport React from 'react'\nimport type { ClientField } from 'payload'\nimport { DocumentFieldsTab } from './DocumentFieldsTab'\n\nconst isSidebarField = (f: ClientField): boolean =>\n 'admin' in f && f.admin?.position === 'sidebar'\n\nexport const DocumentMetaTab: React.FC = () => (\n <DocumentFieldsTab
|
|
1
|
+
{"version":3,"sources":["../../../src/admin/sidebar/DocumentMetaTab.tsx"],"sourcesContent":["'use client'\n\nimport React from 'react'\nimport type { ClientField } from 'payload'\nimport { DocumentFieldsTab } from './DocumentFieldsTab'\nimport { useBetterEditorT } from '../../i18n/useBetterEditorT'\n\nconst isSidebarField = (f: ClientField): boolean =>\n 'admin' in f && f.admin?.position === 'sidebar'\n\nexport const DocumentMetaTab: React.FC = () => {\n const t = useBetterEditorT()\n return <DocumentFieldsTab filter={isSidebarField} emptyText={t.documentFields.noSettings} />\n}\n"],"names":["React","DocumentFieldsTab","useBetterEditorT","isSidebarField","f","admin","position","DocumentMetaTab","t","filter","emptyText","documentFields","noSettings"],"mappings":"AAAA;;AAEA,OAAOA,WAAW,QAAO;AAEzB,SAASC,iBAAiB,QAAQ,sBAAqB;AACvD,SAASC,gBAAgB,QAAQ,8BAA6B;AAE9D,MAAMC,iBAAiB,CAACC,IACtB,WAAWA,KAAKA,EAAEC,KAAK,EAAEC,aAAa;AAExC,OAAO,MAAMC,kBAA4B;IACvC,MAAMC,IAAIN;IACV,qBAAO,KAACD;QAAkBQ,QAAQN;QAAgBO,WAAWF,EAAEG,cAAc,CAACC,UAAU;;AAC1F,EAAC"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import React from 'react';
|
|
4
4
|
import { DocumentFieldsTab } from './DocumentFieldsTab';
|
|
5
|
+
import { useBetterEditorT } from '../../i18n/useBetterEditorT';
|
|
5
6
|
const isNotSidebar = (f)=>!('admin' in f) || f.admin?.position !== 'sidebar';
|
|
6
7
|
// The blocks tab owns layout-block editing; stripping `blocks` fields here
|
|
7
8
|
// avoids rendering them twice and keeps this tab focused on document meta.
|
|
@@ -39,10 +40,13 @@ const stripBlocks = (fields)=>{
|
|
|
39
40
|
}
|
|
40
41
|
return result;
|
|
41
42
|
};
|
|
42
|
-
export const DocumentSettingsTab = ()
|
|
43
|
+
export const DocumentSettingsTab = ()=>{
|
|
44
|
+
const t = useBetterEditorT();
|
|
45
|
+
return /*#__PURE__*/ _jsx(DocumentFieldsTab, {
|
|
43
46
|
filter: isNotSidebar,
|
|
44
47
|
transform: stripBlocks,
|
|
45
|
-
emptyText:
|
|
48
|
+
emptyText: t.documentFields.noFields
|
|
46
49
|
});
|
|
50
|
+
};
|
|
47
51
|
|
|
48
52
|
//# sourceMappingURL=DocumentSettingsTab.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/admin/sidebar/DocumentSettingsTab.tsx"],"sourcesContent":["'use client'\n\nimport React from 'react'\nimport type { ClientField, ClientTab } from 'payload'\nimport { DocumentFieldsTab } from './DocumentFieldsTab'\n\nconst isNotSidebar = (f: ClientField): boolean =>\n !('admin' in f) || f.admin?.position !== 'sidebar'\n\n// The blocks tab owns layout-block editing; stripping `blocks` fields here\n// avoids rendering them twice and keeps this tab focused on document meta.\nconst stripBlocks = (fields: ClientField[]): ClientField[] => {\n const result: ClientField[] = []\n for (const field of fields) {\n const type = field.type\n\n if (type === 'blocks') continue\n\n if (type === 'tabs') {\n const newTabs: ClientTab[] = []\n for (const tab of field.tabs) {\n const inner = stripBlocks(tab.fields ?? [])\n if (inner.length > 0) newTabs.push({ ...tab, fields: inner })\n }\n if (newTabs.length === 0) continue\n result.push({ ...field, tabs: newTabs })\n continue\n }\n\n if (type === 'collapsible' || type === 'row' || type === 'group') {\n const inner = stripBlocks(field.fields)\n if (inner.length === 0) continue\n result.push({ ...field, fields: inner })\n continue\n }\n\n result.push(field)\n }\n return result\n}\n\nexport const DocumentSettingsTab: React.FC = () => (\n <DocumentFieldsTab\n
|
|
1
|
+
{"version":3,"sources":["../../../src/admin/sidebar/DocumentSettingsTab.tsx"],"sourcesContent":["'use client'\n\nimport React from 'react'\nimport type { ClientField, ClientTab } from 'payload'\nimport { DocumentFieldsTab } from './DocumentFieldsTab'\nimport { useBetterEditorT } from '../../i18n/useBetterEditorT'\n\nconst isNotSidebar = (f: ClientField): boolean =>\n !('admin' in f) || f.admin?.position !== 'sidebar'\n\n// The blocks tab owns layout-block editing; stripping `blocks` fields here\n// avoids rendering them twice and keeps this tab focused on document meta.\nconst stripBlocks = (fields: ClientField[]): ClientField[] => {\n const result: ClientField[] = []\n for (const field of fields) {\n const type = field.type\n\n if (type === 'blocks') continue\n\n if (type === 'tabs') {\n const newTabs: ClientTab[] = []\n for (const tab of field.tabs) {\n const inner = stripBlocks(tab.fields ?? [])\n if (inner.length > 0) newTabs.push({ ...tab, fields: inner })\n }\n if (newTabs.length === 0) continue\n result.push({ ...field, tabs: newTabs })\n continue\n }\n\n if (type === 'collapsible' || type === 'row' || type === 'group') {\n const inner = stripBlocks(field.fields)\n if (inner.length === 0) continue\n result.push({ ...field, fields: inner })\n continue\n }\n\n result.push(field)\n }\n return result\n}\n\nexport const DocumentSettingsTab: React.FC = () => {\n const t = useBetterEditorT()\n return (\n <DocumentFieldsTab\n filter={isNotSidebar}\n transform={stripBlocks}\n emptyText={t.documentFields.noFields}\n />\n )\n}\n"],"names":["React","DocumentFieldsTab","useBetterEditorT","isNotSidebar","f","admin","position","stripBlocks","fields","result","field","type","newTabs","tab","tabs","inner","length","push","DocumentSettingsTab","t","filter","transform","emptyText","documentFields","noFields"],"mappings":"AAAA;;AAEA,OAAOA,WAAW,QAAO;AAEzB,SAASC,iBAAiB,QAAQ,sBAAqB;AACvD,SAASC,gBAAgB,QAAQ,8BAA6B;AAE9D,MAAMC,eAAe,CAACC,IACpB,CAAE,CAAA,WAAWA,CAAAA,KAAMA,EAAEC,KAAK,EAAEC,aAAa;AAE3C,2EAA2E;AAC3E,2EAA2E;AAC3E,MAAMC,cAAc,CAACC;IACnB,MAAMC,SAAwB,EAAE;IAChC,KAAK,MAAMC,SAASF,OAAQ;QAC1B,MAAMG,OAAOD,MAAMC,IAAI;QAEvB,IAAIA,SAAS,UAAU;QAEvB,IAAIA,SAAS,QAAQ;YACnB,MAAMC,UAAuB,EAAE;YAC/B,KAAK,MAAMC,OAAOH,MAAMI,IAAI,CAAE;gBAC5B,MAAMC,QAAQR,YAAYM,IAAIL,MAAM,IAAI,EAAE;gBAC1C,IAAIO,MAAMC,MAAM,GAAG,GAAGJ,QAAQK,IAAI,CAAC;oBAAE,GAAGJ,GAAG;oBAAEL,QAAQO;gBAAM;YAC7D;YACA,IAAIH,QAAQI,MAAM,KAAK,GAAG;YAC1BP,OAAOQ,IAAI,CAAC;gBAAE,GAAGP,KAAK;gBAAEI,MAAMF;YAAQ;YACtC;QACF;QAEA,IAAID,SAAS,iBAAiBA,SAAS,SAASA,SAAS,SAAS;YAChE,MAAMI,QAAQR,YAAYG,MAAMF,MAAM;YACtC,IAAIO,MAAMC,MAAM,KAAK,GAAG;YACxBP,OAAOQ,IAAI,CAAC;gBAAE,GAAGP,KAAK;gBAAEF,QAAQO;YAAM;YACtC;QACF;QAEAN,OAAOQ,IAAI,CAACP;IACd;IACA,OAAOD;AACT;AAEA,OAAO,MAAMS,sBAAgC;IAC3C,MAAMC,IAAIjB;IACV,qBACE,KAACD;QACCmB,QAAQjB;QACRkB,WAAWd;QACXe,WAAWH,EAAEI,cAAc,CAACC,QAAQ;;AAG1C,EAAC"}
|
|
@@ -5,20 +5,7 @@ import { DocumentSettingsTab } from './DocumentSettingsTab';
|
|
|
5
5
|
import { DocumentMetaTab } from './DocumentMetaTab';
|
|
6
6
|
import { BlockSettingsTab } from './BlockSettingsTab';
|
|
7
7
|
import { ValidationSummary } from './ValidationSummary';
|
|
8
|
-
|
|
9
|
-
{
|
|
10
|
-
key: 'page',
|
|
11
|
-
label: 'Page'
|
|
12
|
-
},
|
|
13
|
-
{
|
|
14
|
-
key: 'block',
|
|
15
|
-
label: 'Blocks'
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
key: 'settings',
|
|
19
|
-
label: 'Settings'
|
|
20
|
-
}
|
|
21
|
-
];
|
|
8
|
+
import { useBetterEditorT } from '../../i18n/useBetterEditorT';
|
|
22
9
|
const ROOT_CLASS = 'better-editor-sidebar';
|
|
23
10
|
const TAB_CLASS = `${ROOT_CLASS}__tab`;
|
|
24
11
|
const tabId = (key)=>`better-editor-tab-${key}`;
|
|
@@ -36,6 +23,21 @@ const SidebarTab = ({ tabKey, label, active, onSelect })=>/*#__PURE__*/ _jsx("bu
|
|
|
36
23
|
});
|
|
37
24
|
// Memoized so resize-drag re-renders of the overlay skip the field tree.
|
|
38
25
|
export const Sidebar = /*#__PURE__*/ React.memo(function Sidebar({ selectedBlockPath, onClearSelection, onSelectPath, forceFullWidthFields, blocksField, addBelowRequestId = 0 }) {
|
|
26
|
+
const t = useBetterEditorT();
|
|
27
|
+
const TABS = [
|
|
28
|
+
{
|
|
29
|
+
key: 'page',
|
|
30
|
+
label: t.sidebar.tabs.page
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
key: 'block',
|
|
34
|
+
label: t.sidebar.tabs.block
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
key: 'settings',
|
|
38
|
+
label: t.sidebar.tabs.settings
|
|
39
|
+
}
|
|
40
|
+
];
|
|
39
41
|
const [tab, setTab] = useState('page');
|
|
40
42
|
// Auto-jump to the block tab when the iframe selects a new block.
|
|
41
43
|
useEffect(()=>{
|
|
@@ -87,12 +89,15 @@ export const Sidebar = /*#__PURE__*/ React.memo(function Sidebar({ selectedBlock
|
|
|
87
89
|
});
|
|
88
90
|
// Off-screen live region announces block-selection changes to screen
|
|
89
91
|
// readers; visible UI updates handle sighted users via the tab switch.
|
|
90
|
-
const SelectionAnnouncer = ({ selectedBlockPath })
|
|
92
|
+
const SelectionAnnouncer = ({ selectedBlockPath })=>{
|
|
93
|
+
const t = useBetterEditorT();
|
|
94
|
+
return /*#__PURE__*/ _jsx("div", {
|
|
91
95
|
role: "status",
|
|
92
96
|
"aria-live": "polite",
|
|
93
97
|
"aria-atomic": "true",
|
|
94
98
|
className: "better-editor-sr-only",
|
|
95
|
-
children: selectedBlockPath ?
|
|
99
|
+
children: selectedBlockPath ? `${t.sidebar.blockSelected}${selectedBlockPath}` : t.sidebar.noBlockSelected
|
|
96
100
|
});
|
|
101
|
+
};
|
|
97
102
|
|
|
98
103
|
//# sourceMappingURL=Sidebar.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/admin/sidebar/Sidebar.tsx"],"sourcesContent":["'use client'\n\nimport React, { useEffect, useState } from 'react'\nimport { DocumentSettingsTab } from './DocumentSettingsTab'\nimport { DocumentMetaTab } from './DocumentMetaTab'\nimport { BlockSettingsTab } from './BlockSettingsTab'\nimport { ValidationSummary } from './ValidationSummary'\n\nexport type SidebarProps = {\n selectedBlockPath: string | null\n onClearSelection: () => void\n onSelectPath: (path: string | null) => void\n forceFullWidthFields: boolean\n blocksField: string\n addBelowRequestId?: number\n}\n\ntype TabKey = 'page' | 'block' | 'settings'\n\nconst
|
|
1
|
+
{"version":3,"sources":["../../../src/admin/sidebar/Sidebar.tsx"],"sourcesContent":["'use client'\n\nimport React, { useEffect, useState } from 'react'\nimport { DocumentSettingsTab } from './DocumentSettingsTab'\nimport { DocumentMetaTab } from './DocumentMetaTab'\nimport { BlockSettingsTab } from './BlockSettingsTab'\nimport { ValidationSummary } from './ValidationSummary'\nimport { useBetterEditorT } from '../../i18n/useBetterEditorT'\n\nexport type SidebarProps = {\n selectedBlockPath: string | null\n onClearSelection: () => void\n onSelectPath: (path: string | null) => void\n forceFullWidthFields: boolean\n blocksField: string\n addBelowRequestId?: number\n}\n\ntype TabKey = 'page' | 'block' | 'settings'\n\nconst ROOT_CLASS = 'better-editor-sidebar'\nconst TAB_CLASS = `${ROOT_CLASS}__tab`\n\nconst tabId = (key: TabKey) => `better-editor-tab-${key}`\nconst panelId = (key: TabKey) => `better-editor-panel-${key}`\n\ntype SidebarTabProps = {\n tabKey: TabKey\n label: string\n active: boolean\n onSelect: (key: TabKey) => void\n}\n\nconst SidebarTab: React.FC<SidebarTabProps> = ({ tabKey, label, active, onSelect }) => (\n <button\n type=\"button\"\n role=\"tab\"\n id={tabId(tabKey)}\n aria-selected={active}\n aria-controls={panelId(tabKey)}\n tabIndex={active ? 0 : -1}\n className={active ? `${TAB_CLASS} ${TAB_CLASS}--active` : TAB_CLASS}\n onClick={() => onSelect(tabKey)}\n >\n {label}\n </button>\n)\n\n// Memoized so resize-drag re-renders of the overlay skip the field tree.\nexport const Sidebar = React.memo(function Sidebar({\n selectedBlockPath,\n onClearSelection,\n onSelectPath,\n forceFullWidthFields,\n blocksField,\n addBelowRequestId = 0,\n}: SidebarProps) {\n const t = useBetterEditorT()\n const TABS: ReadonlyArray<{ key: TabKey; label: string }> = [\n { key: 'page', label: t.sidebar.tabs.page },\n { key: 'block', label: t.sidebar.tabs.block },\n { key: 'settings', label: t.sidebar.tabs.settings },\n ]\n const [tab, setTab] = useState<TabKey>('page')\n\n // Auto-jump to the block tab when the iframe selects a new block.\n useEffect(() => {\n if (selectedBlockPath) setTab('block')\n }, [selectedBlockPath])\n\n const className = forceFullWidthFields\n ? `${ROOT_CLASS} ${ROOT_CLASS}--force-full-width`\n : ROOT_CLASS\n\n return (\n <div className={className}>\n <div role=\"tablist\" className={`${ROOT_CLASS}__tabs`}>\n {TABS.map((t) => (\n <SidebarTab\n key={t.key}\n tabKey={t.key}\n label={t.label}\n active={tab === t.key}\n onSelect={setTab}\n />\n ))}\n </div>\n\n <ValidationSummary blocksField={blocksField} onSelectPath={onSelectPath} />\n\n <div\n className={`${ROOT_CLASS}__content`}\n role=\"tabpanel\"\n id={panelId(tab)}\n aria-labelledby={tabId(tab)}\n tabIndex={0}\n >\n {tab === 'page' && <DocumentSettingsTab />}\n {tab === 'block' && (\n <BlockSettingsTab\n selectedBlockPath={selectedBlockPath}\n onClearSelection={onClearSelection}\n onSelectPath={onSelectPath}\n blocksField={blocksField}\n addBelowRequestId={addBelowRequestId}\n />\n )}\n {tab === 'settings' && <DocumentMetaTab />}\n </div>\n\n <SelectionAnnouncer selectedBlockPath={selectedBlockPath} />\n </div>\n )\n})\n\n// Off-screen live region announces block-selection changes to screen\n// readers; visible UI updates handle sighted users via the tab switch.\nconst SelectionAnnouncer: React.FC<{ selectedBlockPath: string | null }> = ({\n selectedBlockPath,\n}) => {\n const t = useBetterEditorT()\n return (\n <div role=\"status\" aria-live=\"polite\" aria-atomic=\"true\" className=\"better-editor-sr-only\">\n {selectedBlockPath\n ? `${t.sidebar.blockSelected}${selectedBlockPath}`\n : t.sidebar.noBlockSelected}\n </div>\n )\n}\n"],"names":["React","useEffect","useState","DocumentSettingsTab","DocumentMetaTab","BlockSettingsTab","ValidationSummary","useBetterEditorT","ROOT_CLASS","TAB_CLASS","tabId","key","panelId","SidebarTab","tabKey","label","active","onSelect","button","type","role","id","aria-selected","aria-controls","tabIndex","className","onClick","Sidebar","memo","selectedBlockPath","onClearSelection","onSelectPath","forceFullWidthFields","blocksField","addBelowRequestId","t","TABS","sidebar","tabs","page","block","settings","tab","setTab","div","map","aria-labelledby","SelectionAnnouncer","aria-live","aria-atomic","blockSelected","noBlockSelected"],"mappings":"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"}
|
|
@@ -3,22 +3,25 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import React, { useMemo } from 'react';
|
|
4
4
|
import { useAllFormFields } from '@payloadcms/ui';
|
|
5
5
|
import { collectFieldErrors } from './validation';
|
|
6
|
+
import { useBetterEditorT } from '../../i18n/useBetterEditorT';
|
|
6
7
|
// Sidebar banner listing invalid fields across all blocks.
|
|
7
8
|
export const ValidationSummary = ({ blocksField, onSelectPath })=>{
|
|
9
|
+
const t = useBetterEditorT();
|
|
8
10
|
const [fields] = useAllFormFields();
|
|
9
11
|
const errors = useMemo(()=>collectFieldErrors(fields, blocksField), [
|
|
10
12
|
fields,
|
|
11
13
|
blocksField
|
|
12
14
|
]);
|
|
13
15
|
if (errors.length === 0) return null;
|
|
16
|
+
const countLabel = errors.length === 1 ? t.sidebar.validationSingular : `${errors.length}${t.sidebar.validationPlural}`;
|
|
14
17
|
return /*#__PURE__*/ _jsxs("div", {
|
|
15
18
|
className: "better-editor-sidebar__errors",
|
|
16
19
|
role: "region",
|
|
17
|
-
"aria-label":
|
|
20
|
+
"aria-label": t.sidebar.validationLabel,
|
|
18
21
|
children: [
|
|
19
22
|
/*#__PURE__*/ _jsx("p", {
|
|
20
23
|
className: "better-editor-sidebar__errors-title",
|
|
21
|
-
children:
|
|
24
|
+
children: countLabel
|
|
22
25
|
}),
|
|
23
26
|
/*#__PURE__*/ _jsx("ul", {
|
|
24
27
|
className: "better-editor-sidebar__errors-list",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/admin/sidebar/ValidationSummary.tsx"],"sourcesContent":["'use client'\n\nimport React, { useMemo } from 'react'\nimport { useAllFormFields } from '@payloadcms/ui'\nimport type { FormState } from 'payload'\nimport { collectFieldErrors } from './validation'\n\nexport type ValidationSummaryProps = {\n blocksField: string\n onSelectPath: (path: string | null) => void\n}\n\n// Sidebar banner listing invalid fields across all blocks.\nexport const ValidationSummary: React.FC<ValidationSummaryProps> = ({\n blocksField,\n onSelectPath,\n}) => {\n const [fields] = useAllFormFields()\n const errors = useMemo(\n () => collectFieldErrors(fields as FormState, blocksField),\n [fields, blocksField],\n )\n\n if (errors.length === 0) return null\n\n return (\n <div
|
|
1
|
+
{"version":3,"sources":["../../../src/admin/sidebar/ValidationSummary.tsx"],"sourcesContent":["'use client'\n\nimport React, { useMemo } from 'react'\nimport { useAllFormFields } from '@payloadcms/ui'\nimport type { FormState } from 'payload'\nimport { collectFieldErrors } from './validation'\nimport { useBetterEditorT } from '../../i18n/useBetterEditorT'\n\nexport type ValidationSummaryProps = {\n blocksField: string\n onSelectPath: (path: string | null) => void\n}\n\n// Sidebar banner listing invalid fields across all blocks.\nexport const ValidationSummary: React.FC<ValidationSummaryProps> = ({\n blocksField,\n onSelectPath,\n}) => {\n const t = useBetterEditorT()\n const [fields] = useAllFormFields()\n const errors = useMemo(\n () => collectFieldErrors(fields as FormState, blocksField),\n [fields, blocksField],\n )\n\n if (errors.length === 0) return null\n\n const countLabel =\n errors.length === 1\n ? t.sidebar.validationSingular\n : `${errors.length}${t.sidebar.validationPlural}`\n\n return (\n <div\n className=\"better-editor-sidebar__errors\"\n role=\"region\"\n aria-label={t.sidebar.validationLabel}\n >\n <p className=\"better-editor-sidebar__errors-title\">{countLabel}</p>\n <ul className=\"better-editor-sidebar__errors-list\">\n {errors.map((error) => (\n <li key={error.path} className=\"better-editor-sidebar__errors-item\">\n {error.blockPath ? (\n <button\n type=\"button\"\n className=\"better-editor-sidebar__errors-jump\"\n onClick={() => onSelectPath(error.blockPath)}\n >\n {error.label}\n </button>\n ) : (\n <span className=\"better-editor-sidebar__errors-label\">{error.label}</span>\n )}\n <span className=\"better-editor-sidebar__errors-message\">{error.message}</span>\n </li>\n ))}\n </ul>\n </div>\n )\n}\n"],"names":["React","useMemo","useAllFormFields","collectFieldErrors","useBetterEditorT","ValidationSummary","blocksField","onSelectPath","t","fields","errors","length","countLabel","sidebar","validationSingular","validationPlural","div","className","role","aria-label","validationLabel","p","ul","map","error","li","blockPath","button","type","onClick","label","span","message","path"],"mappings":"AAAA;;AAEA,OAAOA,SAASC,OAAO,QAAQ,QAAO;AACtC,SAASC,gBAAgB,QAAQ,iBAAgB;AAEjD,SAASC,kBAAkB,QAAQ,eAAc;AACjD,SAASC,gBAAgB,QAAQ,8BAA6B;AAO9D,2DAA2D;AAC3D,OAAO,MAAMC,oBAAsD,CAAC,EAClEC,WAAW,EACXC,YAAY,EACb;IACC,MAAMC,IAAIJ;IACV,MAAM,CAACK,OAAO,GAAGP;IACjB,MAAMQ,SAAST,QACb,IAAME,mBAAmBM,QAAqBH,cAC9C;QAACG;QAAQH;KAAY;IAGvB,IAAII,OAAOC,MAAM,KAAK,GAAG,OAAO;IAEhC,MAAMC,aACJF,OAAOC,MAAM,KAAK,IACdH,EAAEK,OAAO,CAACC,kBAAkB,GAC5B,GAAGJ,OAAOC,MAAM,GAAGH,EAAEK,OAAO,CAACE,gBAAgB,EAAE;IAErD,qBACE,MAACC;QACCC,WAAU;QACVC,MAAK;QACLC,cAAYX,EAAEK,OAAO,CAACO,eAAe;;0BAErC,KAACC;gBAAEJ,WAAU;0BAAuCL;;0BACpD,KAACU;gBAAGL,WAAU;0BACXP,OAAOa,GAAG,CAAC,CAACC,sBACX,MAACC;wBAAoBR,WAAU;;4BAC5BO,MAAME,SAAS,iBACd,KAACC;gCACCC,MAAK;gCACLX,WAAU;gCACVY,SAAS,IAAMtB,aAAaiB,MAAME,SAAS;0CAE1CF,MAAMM,KAAK;+CAGd,KAACC;gCAAKd,WAAU;0CAAuCO,MAAMM,KAAK;;0CAEpE,KAACC;gCAAKd,WAAU;0CAAyCO,MAAMQ,OAAO;;;uBAZ/DR,MAAMS,IAAI;;;;AAkB7B,EAAC"}
|
package/dist/global.js
CHANGED
|
@@ -1,33 +1,48 @@
|
|
|
1
1
|
import { DEFAULT_BETTER_EDITOR_SETTINGS as D } from './internal/constants';
|
|
2
2
|
import { HOVER_OUTLINE_MAX, HOVER_OUTLINE_MIN, MOBILE_WIDTH_MAX, MOBILE_WIDTH_MIN, TABLET_WIDTH_MAX, TABLET_WIDTH_MIN } from './internal/limits';
|
|
3
|
+
import { translations } from './i18n';
|
|
3
4
|
export const BETTER_EDITOR_SETTINGS_SLUG = 'better-editor-settings';
|
|
4
5
|
export const BETTER_EDITOR_SETTINGS_BANNER_FIELD = 'betterEditorSettingsBanner';
|
|
5
6
|
// Mirrors the runtime regex in `preview/hover-css.ts` so the admin UI rejects
|
|
6
7
|
// values that would silently be skipped at render time.
|
|
7
8
|
const HOVER_COLOR_RE = /^(?:#[0-9a-fA-F]{3,8}|rgba?\([^()\n\r]*\))$/i;
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
const settingsKey = (path)=>`betterEditor:settings.${path}`;
|
|
10
|
+
// Settings-label locale maps, derived from every bundled translation.
|
|
11
|
+
const SETTINGS_TRANSLATIONS = Object.fromEntries(Object.entries(translations).map(([locale, t])=>[
|
|
12
|
+
locale,
|
|
13
|
+
t.settings
|
|
14
|
+
]));
|
|
15
|
+
const lookupSetting = (settings, path)=>path.split('.').reduce((value, key)=>value?.[key], settings);
|
|
16
|
+
// Entity/field labels and descriptions are serialized into the admin RootLayout
|
|
17
|
+
// (a Client Component), so they must be plain data — a function (e.g. `({ t }) => …`)
|
|
18
|
+
// can't cross that RSC boundary. Return a Payload locale map built from our bundled
|
|
19
|
+
// translations; Payload selects the entry for the admin UI language. (Runtime `t()`
|
|
20
|
+
// stays available for `validate`, which Payload strips before client serialization.)
|
|
21
|
+
const translatedLabel = (path)=>Object.fromEntries(Object.entries(SETTINGS_TRANSLATIONS).map(([locale, settings])=>[
|
|
22
|
+
locale,
|
|
23
|
+
lookupSetting(settings, path)
|
|
24
|
+
]));
|
|
25
|
+
const validateHoverColor = (value, args)=>{
|
|
26
|
+
const t = args?.t ?? ((k)=>k);
|
|
27
|
+
if (typeof value !== 'string' || value.length === 0) return t(settingsKey('validation.colorRequired'));
|
|
28
|
+
if (!HOVER_COLOR_RE.test(value.trim())) return t(settingsKey('validation.colorInvalid'));
|
|
13
29
|
return true;
|
|
14
30
|
};
|
|
15
|
-
const validateHoverOutline = (value)=>{
|
|
16
|
-
|
|
17
|
-
if (value
|
|
18
|
-
|
|
19
|
-
}
|
|
31
|
+
const validateHoverOutline = (value, args)=>{
|
|
32
|
+
const t = args?.t ?? ((k)=>k);
|
|
33
|
+
if (typeof value !== 'number' || !Number.isFinite(value)) return t(settingsKey('validation.mustBeNumber'));
|
|
34
|
+
if (value < HOVER_OUTLINE_MIN || value > HOVER_OUTLINE_MAX) return t(settingsKey('validation.outlineRange'));
|
|
20
35
|
return true;
|
|
21
36
|
};
|
|
22
37
|
export const betterEditorSettingsGlobal = {
|
|
23
38
|
slug: BETTER_EDITOR_SETTINGS_SLUG,
|
|
24
|
-
label: '
|
|
39
|
+
label: translatedLabel('globalLabel'),
|
|
25
40
|
access: {
|
|
26
41
|
read: ()=>true
|
|
27
42
|
},
|
|
28
43
|
admin: {
|
|
29
44
|
group: 'Better Editor',
|
|
30
|
-
description: '
|
|
45
|
+
description: translatedLabel('globalDescription')
|
|
31
46
|
},
|
|
32
47
|
fields: [
|
|
33
48
|
{
|
|
@@ -43,21 +58,21 @@ export const betterEditorSettingsGlobal = {
|
|
|
43
58
|
type: 'tabs',
|
|
44
59
|
tabs: [
|
|
45
60
|
{
|
|
46
|
-
label: '
|
|
47
|
-
description: '
|
|
61
|
+
label: translatedLabel('sidebar.tabLabel'),
|
|
62
|
+
description: translatedLabel('sidebar.tabDescription'),
|
|
48
63
|
fields: [
|
|
49
64
|
{
|
|
50
65
|
name: 'sidebarPosition',
|
|
51
66
|
type: 'select',
|
|
52
|
-
label: '
|
|
67
|
+
label: translatedLabel('sidebar.position'),
|
|
53
68
|
defaultValue: D.sidebarPosition,
|
|
54
69
|
options: [
|
|
55
70
|
{
|
|
56
|
-
label: '
|
|
71
|
+
label: translatedLabel('sidebar.positionRight'),
|
|
57
72
|
value: 'right'
|
|
58
73
|
},
|
|
59
74
|
{
|
|
60
|
-
label: '
|
|
75
|
+
label: translatedLabel('sidebar.positionLeft'),
|
|
61
76
|
value: 'left'
|
|
62
77
|
}
|
|
63
78
|
]
|
|
@@ -65,17 +80,17 @@ export const betterEditorSettingsGlobal = {
|
|
|
65
80
|
{
|
|
66
81
|
name: 'forceFullWidthFields',
|
|
67
82
|
type: 'checkbox',
|
|
68
|
-
label: '
|
|
83
|
+
label: translatedLabel('sidebar.forceFullWidth'),
|
|
69
84
|
defaultValue: D.forceFullWidthFields,
|
|
70
85
|
admin: {
|
|
71
|
-
description: '
|
|
86
|
+
description: translatedLabel('sidebar.forceFullWidthDesc')
|
|
72
87
|
}
|
|
73
88
|
}
|
|
74
89
|
]
|
|
75
90
|
},
|
|
76
91
|
{
|
|
77
|
-
label: '
|
|
78
|
-
description: '
|
|
92
|
+
label: translatedLabel('viewport.tabLabel'),
|
|
93
|
+
description: translatedLabel('viewport.tabDescription'),
|
|
79
94
|
fields: [
|
|
80
95
|
{
|
|
81
96
|
type: 'row',
|
|
@@ -83,7 +98,7 @@ export const betterEditorSettingsGlobal = {
|
|
|
83
98
|
{
|
|
84
99
|
name: 'tabletWidth',
|
|
85
100
|
type: 'number',
|
|
86
|
-
label: '
|
|
101
|
+
label: translatedLabel('viewport.tabletWidth'),
|
|
87
102
|
defaultValue: D.tabletWidth,
|
|
88
103
|
min: TABLET_WIDTH_MIN,
|
|
89
104
|
max: TABLET_WIDTH_MAX,
|
|
@@ -95,7 +110,7 @@ export const betterEditorSettingsGlobal = {
|
|
|
95
110
|
{
|
|
96
111
|
name: 'mobileWidth',
|
|
97
112
|
type: 'number',
|
|
98
|
-
label: '
|
|
113
|
+
label: translatedLabel('viewport.mobileWidth'),
|
|
99
114
|
defaultValue: D.mobileWidth,
|
|
100
115
|
min: MOBILE_WIDTH_MIN,
|
|
101
116
|
max: MOBILE_WIDTH_MAX,
|
|
@@ -109,8 +124,8 @@ export const betterEditorSettingsGlobal = {
|
|
|
109
124
|
]
|
|
110
125
|
},
|
|
111
126
|
{
|
|
112
|
-
label: '
|
|
113
|
-
description: '
|
|
127
|
+
label: translatedLabel('outline.tabLabel'),
|
|
128
|
+
description: translatedLabel('outline.tabDescription'),
|
|
114
129
|
fields: [
|
|
115
130
|
{
|
|
116
131
|
type: 'row',
|
|
@@ -118,25 +133,25 @@ export const betterEditorSettingsGlobal = {
|
|
|
118
133
|
{
|
|
119
134
|
name: 'hoverColorTopLevel',
|
|
120
135
|
type: 'text',
|
|
121
|
-
label: '
|
|
136
|
+
label: translatedLabel('outline.topLevelColor'),
|
|
122
137
|
defaultValue: D.hoverColorTopLevel,
|
|
123
138
|
validate: validateHoverColor,
|
|
124
139
|
admin: {
|
|
125
140
|
width: '50%',
|
|
126
141
|
placeholder: D.hoverColorTopLevel,
|
|
127
|
-
description: '
|
|
142
|
+
description: translatedLabel('outline.topLevelColorDesc')
|
|
128
143
|
}
|
|
129
144
|
},
|
|
130
145
|
{
|
|
131
146
|
name: 'hoverColorNested',
|
|
132
147
|
type: 'text',
|
|
133
|
-
label: '
|
|
148
|
+
label: translatedLabel('outline.nestedColor'),
|
|
134
149
|
defaultValue: D.hoverColorNested,
|
|
135
150
|
validate: validateHoverColor,
|
|
136
151
|
admin: {
|
|
137
152
|
width: '50%',
|
|
138
153
|
placeholder: D.hoverColorNested,
|
|
139
|
-
description: '
|
|
154
|
+
description: translatedLabel('outline.nestedColorDesc')
|
|
140
155
|
}
|
|
141
156
|
}
|
|
142
157
|
]
|
|
@@ -144,48 +159,48 @@ export const betterEditorSettingsGlobal = {
|
|
|
144
159
|
{
|
|
145
160
|
name: 'hoverOutlineWidth',
|
|
146
161
|
type: 'number',
|
|
147
|
-
label: '
|
|
162
|
+
label: translatedLabel('outline.outlineWidth'),
|
|
148
163
|
defaultValue: D.hoverOutlineWidth,
|
|
149
164
|
min: HOVER_OUTLINE_MIN,
|
|
150
165
|
max: HOVER_OUTLINE_MAX,
|
|
151
166
|
validate: validateHoverOutline,
|
|
152
167
|
admin: {
|
|
153
168
|
placeholder: String(D.hoverOutlineWidth),
|
|
154
|
-
description:
|
|
169
|
+
description: translatedLabel('outline.outlineWidthDesc')
|
|
155
170
|
}
|
|
156
171
|
}
|
|
157
172
|
]
|
|
158
173
|
},
|
|
159
174
|
{
|
|
160
|
-
label: '
|
|
161
|
-
description: '
|
|
175
|
+
label: translatedLabel('toolbar.tabLabel'),
|
|
176
|
+
description: translatedLabel('toolbar.tabDescription'),
|
|
162
177
|
fields: [
|
|
163
178
|
{
|
|
164
179
|
name: 'showHoverToolbar',
|
|
165
180
|
type: 'checkbox',
|
|
166
|
-
label: '
|
|
181
|
+
label: translatedLabel('toolbar.enabled'),
|
|
167
182
|
defaultValue: D.showHoverToolbar
|
|
168
183
|
},
|
|
169
184
|
{
|
|
170
185
|
name: 'hoverToolbarPosition',
|
|
171
186
|
type: 'select',
|
|
172
|
-
label: '
|
|
187
|
+
label: translatedLabel('toolbar.anchorCorner'),
|
|
173
188
|
defaultValue: D.hoverToolbarPosition,
|
|
174
189
|
options: [
|
|
175
190
|
{
|
|
176
|
-
label: '
|
|
191
|
+
label: translatedLabel('toolbar.topRight'),
|
|
177
192
|
value: 'top-right'
|
|
178
193
|
},
|
|
179
194
|
{
|
|
180
|
-
label: '
|
|
195
|
+
label: translatedLabel('toolbar.topLeft'),
|
|
181
196
|
value: 'top-left'
|
|
182
197
|
},
|
|
183
198
|
{
|
|
184
|
-
label: '
|
|
199
|
+
label: translatedLabel('toolbar.bottomRight'),
|
|
185
200
|
value: 'bottom-right'
|
|
186
201
|
},
|
|
187
202
|
{
|
|
188
|
-
label: '
|
|
203
|
+
label: translatedLabel('toolbar.bottomLeft'),
|
|
189
204
|
value: 'bottom-left'
|
|
190
205
|
}
|
|
191
206
|
]
|
package/dist/global.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/global.ts"],"sourcesContent":["import type { GlobalConfig } from 'payload'\nimport { DEFAULT_BETTER_EDITOR_SETTINGS as D } from './internal/constants'\nimport {\n HOVER_OUTLINE_MAX,\n HOVER_OUTLINE_MIN,\n MOBILE_WIDTH_MAX,\n MOBILE_WIDTH_MIN,\n TABLET_WIDTH_MAX,\n TABLET_WIDTH_MIN,\n} from './internal/limits'\n\nexport const BETTER_EDITOR_SETTINGS_SLUG = 'better-editor-settings'\n\nexport const BETTER_EDITOR_SETTINGS_BANNER_FIELD = 'betterEditorSettingsBanner'\n\n// Mirrors the runtime regex in `preview/hover-css.ts` so the admin UI rejects\n// values that would silently be skipped at render time.\nconst HOVER_COLOR_RE = /^(?:#[0-9a-fA-F]{3,8}|rgba?\\([^()\\n\\r]*\\))$/i\n\nconst validateHoverColor = (value: unknown): string | true => {\n if (typeof value !== 'string' || value.length === 0) return 'Color is required'\n if (!HOVER_COLOR_RE.test(value.trim())) {\n return 'Must be a hex color (e.g. #3b82f6) or rgb()/rgba()'\n }\n return true\n}\n\nconst validateHoverOutline = (value: unknown): string | true => {\n if (typeof value !== 'number' || !Number.isFinite(value)) return 'Must be a number'\n if (value < HOVER_OUTLINE_MIN || value > HOVER_OUTLINE_MAX) {\n return `Must be between ${HOVER_OUTLINE_MIN} and ${HOVER_OUTLINE_MAX}`\n }\n return true\n}\n\nexport const betterEditorSettingsGlobal: GlobalConfig = {\n slug: BETTER_EDITOR_SETTINGS_SLUG,\n label: 'Settings',\n access: {\n read: () => true,\n },\n admin: {\n group: 'Better Editor',\n description: 'Editor-wide preferences for the Better Editor overlay.',\n },\n\n fields: [\n {\n name: 'betterEditorSettingsBanner',\n type: 'ui',\n admin: {\n components: {\n Field: 'payload-better-editor/client#SettingsBanner',\n },\n },\n },\n {\n type: 'tabs',\n tabs: [\n {\n label: 'Sidebar',\n description: 'Where the sidebar sits and how its fields are stacked.',\n fields: [\n {\n name: 'sidebarPosition',\n type: 'select',\n label: 'Position',\n defaultValue: D.sidebarPosition,\n options: [\n { label: 'Right', value: 'right' },\n { label: 'Left', value: 'left' },\n ],\n },\n {\n name: 'forceFullWidthFields',\n type: 'checkbox',\n label: 'Stack fields full-width',\n defaultValue: D.forceFullWidthFields,\n admin: {\n description:\n 'Override admin.width on sidebar fields so they always span the full row.',\n },\n },\n ],\n },\n {\n label: 'Viewport',\n description: 'Pixel widths for the Tablet and Mobile preview modes.',\n fields: [\n {\n type: 'row',\n fields: [\n {\n name: 'tabletWidth',\n type: 'number',\n label: 'Tablet (px)',\n defaultValue: D.tabletWidth,\n min: TABLET_WIDTH_MIN,\n max: TABLET_WIDTH_MAX,\n admin: { width: '50%', placeholder: String(D.tabletWidth) },\n },\n {\n name: 'mobileWidth',\n type: 'number',\n label: 'Mobile (px)',\n defaultValue: D.mobileWidth,\n min: MOBILE_WIDTH_MIN,\n max: MOBILE_WIDTH_MAX,\n admin: { width: '50%', placeholder: String(D.mobileWidth) },\n },\n ],\n },\n ],\n },\n {\n label: 'Outline',\n description: 'Outline + tint shown on the hovered or selected block.',\n fields: [\n {\n type: 'row',\n fields: [\n {\n name: 'hoverColorTopLevel',\n type: 'text',\n label: 'Top-level color',\n defaultValue: D.hoverColorTopLevel,\n validate: validateHoverColor,\n admin: {\n width: '50%',\n placeholder: D.hoverColorTopLevel,\n description: 'Hex color (e.g. `#3b82f6`).',\n },\n },\n {\n name: 'hoverColorNested',\n type: 'text',\n label: 'Nested color',\n defaultValue: D.hoverColorNested,\n validate: validateHoverColor,\n admin: {\n width: '50%',\n placeholder: D.hoverColorNested,\n description: 'Hex color for blocks nested inside another block.',\n },\n },\n ],\n },\n {\n name: 'hoverOutlineWidth',\n type: 'number',\n label: 'Outline width (px)',\n defaultValue: D.hoverOutlineWidth,\n min: HOVER_OUTLINE_MIN,\n max: HOVER_OUTLINE_MAX,\n validate: validateHoverOutline,\n admin: {\n placeholder: String(D.hoverOutlineWidth),\n description: `Outline thickness in pixels (${HOVER_OUTLINE_MIN}–${HOVER_OUTLINE_MAX}).`,\n },\n },\n ],\n },\n {\n label: 'Toolbar',\n description:\n 'Floating Move / Duplicate / Delete toolbar that appears on the selected block.',\n fields: [\n {\n name: 'showHoverToolbar',\n type: 'checkbox',\n label: 'Enabled',\n defaultValue: D.showHoverToolbar,\n },\n {\n name: 'hoverToolbarPosition',\n type: 'select',\n label: 'Anchor corner',\n defaultValue: D.hoverToolbarPosition,\n options: [\n { label: 'Top right', value: 'top-right' },\n { label: 'Top left', value: 'top-left' },\n { label: 'Bottom right', value: 'bottom-right' },\n { label: 'Bottom left', value: 'bottom-left' },\n ],\n },\n ],\n },\n ],\n },\n ],\n}\n"],"names":["DEFAULT_BETTER_EDITOR_SETTINGS","D","HOVER_OUTLINE_MAX","HOVER_OUTLINE_MIN","MOBILE_WIDTH_MAX","MOBILE_WIDTH_MIN","TABLET_WIDTH_MAX","TABLET_WIDTH_MIN","BETTER_EDITOR_SETTINGS_SLUG","BETTER_EDITOR_SETTINGS_BANNER_FIELD","HOVER_COLOR_RE","validateHoverColor","value","length","test","trim","validateHoverOutline","Number","isFinite","betterEditorSettingsGlobal","slug","label","access","read","admin","group","description","fields","name","type","components","Field","tabs","defaultValue","sidebarPosition","options","forceFullWidthFields","tabletWidth","min","max","width","placeholder","String","mobileWidth","hoverColorTopLevel","validate","hoverColorNested","hoverOutlineWidth","showHoverToolbar","hoverToolbarPosition"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/global.ts"],"sourcesContent":["import type { GlobalConfig } from 'payload'\nimport { DEFAULT_BETTER_EDITOR_SETTINGS as D } from './internal/constants'\nimport {\n HOVER_OUTLINE_MAX,\n HOVER_OUTLINE_MIN,\n MOBILE_WIDTH_MAX,\n MOBILE_WIDTH_MIN,\n TABLET_WIDTH_MAX,\n TABLET_WIDTH_MIN,\n} from './internal/limits'\nimport type { BetterEditorTranslations } from './i18n/types'\nimport { translations } from './i18n'\n\nexport const BETTER_EDITOR_SETTINGS_SLUG = 'better-editor-settings'\n\nexport const BETTER_EDITOR_SETTINGS_BANNER_FIELD = 'betterEditorSettingsBanner'\n\n// Mirrors the runtime regex in `preview/hover-css.ts` so the admin UI rejects\n// values that would silently be skipped at render time.\nconst HOVER_COLOR_RE = /^(?:#[0-9a-fA-F]{3,8}|rgba?\\([^()\\n\\r]*\\))$/i\n\n// Payload's TFunction is strictly typed to known keys — cast to allow custom plugin keys.\ntype AnyT = (key: string) => string\n\nconst settingsKey = (path: string) => `betterEditor:settings.${path}`\n\n// Settings-label locale maps, derived from every bundled translation.\nconst SETTINGS_TRANSLATIONS: Record<string, BetterEditorTranslations['settings']> =\n Object.fromEntries(Object.entries(translations).map(([locale, t]) => [locale, t.settings]))\n\nconst lookupSetting = (settings: BetterEditorTranslations['settings'], path: string): string =>\n path\n .split('.')\n .reduce<unknown>((value, key) => (value as Record<string, unknown> | undefined)?.[key], settings) as string\n\n// Entity/field labels and descriptions are serialized into the admin RootLayout\n// (a Client Component), so they must be plain data — a function (e.g. `({ t }) => …`)\n// can't cross that RSC boundary. Return a Payload locale map built from our bundled\n// translations; Payload selects the entry for the admin UI language. (Runtime `t()`\n// stays available for `validate`, which Payload strips before client serialization.)\nconst translatedLabel = (path: string): Record<string, string> =>\n Object.fromEntries(\n Object.entries(SETTINGS_TRANSLATIONS).map(([locale, settings]) => [locale, lookupSetting(settings, path)]),\n )\n\nconst validateHoverColor = (value: unknown, args: unknown): string | true => {\n const t: AnyT = (args as { t?: AnyT })?.t ?? ((k) => k)\n if (typeof value !== 'string' || value.length === 0) return t(settingsKey('validation.colorRequired'))\n if (!HOVER_COLOR_RE.test(value.trim())) return t(settingsKey('validation.colorInvalid'))\n return true\n}\n\nconst validateHoverOutline = (value: unknown, args: unknown): string | true => {\n const t: AnyT = (args as { t?: AnyT })?.t ?? ((k) => k)\n if (typeof value !== 'number' || !Number.isFinite(value)) return t(settingsKey('validation.mustBeNumber'))\n if (value < HOVER_OUTLINE_MIN || value > HOVER_OUTLINE_MAX) return t(settingsKey('validation.outlineRange'))\n return true\n}\n\nexport const betterEditorSettingsGlobal: GlobalConfig = {\n slug: BETTER_EDITOR_SETTINGS_SLUG,\n label: translatedLabel('globalLabel'),\n access: {\n read: () => true,\n },\n admin: {\n group: 'Better Editor',\n description: translatedLabel('globalDescription'),\n },\n\n fields: [\n {\n name: 'betterEditorSettingsBanner',\n type: 'ui',\n admin: {\n components: {\n Field: 'payload-better-editor/client#SettingsBanner',\n },\n },\n },\n {\n type: 'tabs',\n tabs: [\n {\n label: translatedLabel('sidebar.tabLabel'),\n description: translatedLabel('sidebar.tabDescription'),\n fields: [\n {\n name: 'sidebarPosition',\n type: 'select',\n label: translatedLabel('sidebar.position'),\n defaultValue: D.sidebarPosition,\n options: [\n { label: translatedLabel('sidebar.positionRight'), value: 'right' },\n { label: translatedLabel('sidebar.positionLeft'), value: 'left' },\n ],\n },\n {\n name: 'forceFullWidthFields',\n type: 'checkbox',\n label: translatedLabel('sidebar.forceFullWidth'),\n defaultValue: D.forceFullWidthFields,\n admin: {\n description: translatedLabel('sidebar.forceFullWidthDesc'),\n },\n },\n ],\n },\n {\n label: translatedLabel('viewport.tabLabel'),\n description: translatedLabel('viewport.tabDescription'),\n fields: [\n {\n type: 'row',\n fields: [\n {\n name: 'tabletWidth',\n type: 'number',\n label: translatedLabel('viewport.tabletWidth'),\n defaultValue: D.tabletWidth,\n min: TABLET_WIDTH_MIN,\n max: TABLET_WIDTH_MAX,\n admin: { width: '50%', placeholder: String(D.tabletWidth) },\n },\n {\n name: 'mobileWidth',\n type: 'number',\n label: translatedLabel('viewport.mobileWidth'),\n defaultValue: D.mobileWidth,\n min: MOBILE_WIDTH_MIN,\n max: MOBILE_WIDTH_MAX,\n admin: { width: '50%', placeholder: String(D.mobileWidth) },\n },\n ],\n },\n ],\n },\n {\n label: translatedLabel('outline.tabLabel'),\n description: translatedLabel('outline.tabDescription'),\n fields: [\n {\n type: 'row',\n fields: [\n {\n name: 'hoverColorTopLevel',\n type: 'text',\n label: translatedLabel('outline.topLevelColor'),\n defaultValue: D.hoverColorTopLevel,\n validate: validateHoverColor,\n admin: {\n width: '50%',\n placeholder: D.hoverColorTopLevel,\n description: translatedLabel('outline.topLevelColorDesc'),\n },\n },\n {\n name: 'hoverColorNested',\n type: 'text',\n label: translatedLabel('outline.nestedColor'),\n defaultValue: D.hoverColorNested,\n validate: validateHoverColor,\n admin: {\n width: '50%',\n placeholder: D.hoverColorNested,\n description: translatedLabel('outline.nestedColorDesc'),\n },\n },\n ],\n },\n {\n name: 'hoverOutlineWidth',\n type: 'number',\n label: translatedLabel('outline.outlineWidth'),\n defaultValue: D.hoverOutlineWidth,\n min: HOVER_OUTLINE_MIN,\n max: HOVER_OUTLINE_MAX,\n validate: validateHoverOutline,\n admin: {\n placeholder: String(D.hoverOutlineWidth),\n description: translatedLabel('outline.outlineWidthDesc'),\n },\n },\n ],\n },\n {\n label: translatedLabel('toolbar.tabLabel'),\n description: translatedLabel('toolbar.tabDescription'),\n fields: [\n {\n name: 'showHoverToolbar',\n type: 'checkbox',\n label: translatedLabel('toolbar.enabled'),\n defaultValue: D.showHoverToolbar,\n },\n {\n name: 'hoverToolbarPosition',\n type: 'select',\n label: translatedLabel('toolbar.anchorCorner'),\n defaultValue: D.hoverToolbarPosition,\n options: [\n { label: translatedLabel('toolbar.topRight'), value: 'top-right' },\n { label: translatedLabel('toolbar.topLeft'), value: 'top-left' },\n { label: translatedLabel('toolbar.bottomRight'), value: 'bottom-right' },\n { label: translatedLabel('toolbar.bottomLeft'), value: 'bottom-left' },\n ],\n },\n ],\n },\n ],\n },\n ],\n}\n"],"names":["DEFAULT_BETTER_EDITOR_SETTINGS","D","HOVER_OUTLINE_MAX","HOVER_OUTLINE_MIN","MOBILE_WIDTH_MAX","MOBILE_WIDTH_MIN","TABLET_WIDTH_MAX","TABLET_WIDTH_MIN","translations","BETTER_EDITOR_SETTINGS_SLUG","BETTER_EDITOR_SETTINGS_BANNER_FIELD","HOVER_COLOR_RE","settingsKey","path","SETTINGS_TRANSLATIONS","Object","fromEntries","entries","map","locale","t","settings","lookupSetting","split","reduce","value","key","translatedLabel","validateHoverColor","args","k","length","test","trim","validateHoverOutline","Number","isFinite","betterEditorSettingsGlobal","slug","label","access","read","admin","group","description","fields","name","type","components","Field","tabs","defaultValue","sidebarPosition","options","forceFullWidthFields","tabletWidth","min","max","width","placeholder","String","mobileWidth","hoverColorTopLevel","validate","hoverColorNested","hoverOutlineWidth","showHoverToolbar","hoverToolbarPosition"],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { useCallback, useEffect, useRef } from 'react';
|
|
3
|
-
import { HoverToolbarController } from '../preview/HoverToolbarController';
|
|
3
|
+
import { HoverToolbarController, toHoverToolbarLabels } from '../preview/HoverToolbarController';
|
|
4
|
+
import { useBetterEditorT } from '../i18n/useBetterEditorT';
|
|
4
5
|
import { installClickToFocus } from '../preview/installClickToFocus';
|
|
5
6
|
import { installHoverStyles } from '../preview/installHoverStyles';
|
|
6
7
|
import { BLOCK_ID_SELECTOR } from '../internal/dom';
|
|
@@ -11,6 +12,8 @@ import { useLatestRef } from './useLatestRef';
|
|
|
11
12
|
* lifecycle. Idempotent: tears down previous bindings before installing
|
|
12
13
|
* new ones, and unbinds on unmount.
|
|
13
14
|
*/ export const usePreviewBinding = ({ iframeRef, settings, interactModeRef, onFocusBlock, onBlockAction, onLoadingChange })=>{
|
|
15
|
+
const t = useBetterEditorT();
|
|
16
|
+
const labelsRef = useLatestRef(t.blocks.actions);
|
|
14
17
|
const teardownRef = useRef(null);
|
|
15
18
|
const controllerRef = useRef(null);
|
|
16
19
|
const isBoundRef = useRef(false);
|
|
@@ -39,7 +42,8 @@ import { useLatestRef } from './useLatestRef';
|
|
|
39
42
|
controllerRef.current = new HoverToolbarController(doc, {
|
|
40
43
|
position: s.hoverToolbarPosition,
|
|
41
44
|
outlineWidth: s.hoverOutlineWidth,
|
|
42
|
-
onAction: (id, action)=>onBlockActionRef.current(id, action)
|
|
45
|
+
onAction: (id, action)=>onBlockActionRef.current(id, action),
|
|
46
|
+
labels: toHoverToolbarLabels(labelsRef.current)
|
|
43
47
|
});
|
|
44
48
|
}
|
|
45
49
|
// Dev-only sanity check: zero [data-better-editor-id] elements means
|