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.
Files changed (119) hide show
  1. package/dist/admin/ErrorBoundary.d.ts +1 -10
  2. package/dist/admin/ErrorBoundary.js +14 -5
  3. package/dist/admin/ErrorBoundary.js.map +1 -1
  4. package/dist/admin/LiveEditorOverlay.js +4 -2
  5. package/dist/admin/LiveEditorOverlay.js.map +1 -1
  6. package/dist/admin/LiveEditorToggle.d.ts +2 -0
  7. package/dist/admin/LiveEditorToggle.js +14 -9
  8. package/dist/admin/LiveEditorToggle.js.map +1 -1
  9. package/dist/admin/PreviewFrame.js +6 -4
  10. package/dist/admin/PreviewFrame.js.map +1 -1
  11. package/dist/admin/PreviewToolbar.js +20 -13
  12. package/dist/admin/PreviewToolbar.js.map +1 -1
  13. package/dist/admin/SettingsBanner.js +10 -5
  14. package/dist/admin/SettingsBanner.js.map +1 -1
  15. package/dist/admin/ViewportToggle.js +30 -25
  16. package/dist/admin/ViewportToggle.js.map +1 -1
  17. package/dist/admin/blocks/AddBlockDrawer.js +7 -3
  18. package/dist/admin/blocks/AddBlockDrawer.js.map +1 -1
  19. package/dist/admin/blocks/BlockActionsToolbar.js +13 -11
  20. package/dist/admin/blocks/BlockActionsToolbar.js.map +1 -1
  21. package/dist/admin/blocks/BlockEmptyState.js +7 -3
  22. package/dist/admin/blocks/BlockEmptyState.js.map +1 -1
  23. package/dist/admin/blocks/BlockHeader.d.ts +1 -0
  24. package/dist/admin/blocks/BlockHeader.js +9 -8
  25. package/dist/admin/blocks/BlockHeader.js.map +1 -1
  26. package/dist/admin/blocks/schema.js +38 -7
  27. package/dist/admin/blocks/schema.js.map +1 -1
  28. package/dist/admin/sidebar/BlockSettingsTab.js +19 -4
  29. package/dist/admin/sidebar/BlockSettingsTab.js.map +1 -1
  30. package/dist/admin/sidebar/DocumentMetaTab.js +6 -2
  31. package/dist/admin/sidebar/DocumentMetaTab.js.map +1 -1
  32. package/dist/admin/sidebar/DocumentSettingsTab.js +6 -2
  33. package/dist/admin/sidebar/DocumentSettingsTab.js.map +1 -1
  34. package/dist/admin/sidebar/Sidebar.js +21 -16
  35. package/dist/admin/sidebar/Sidebar.js.map +1 -1
  36. package/dist/admin/sidebar/ValidationSummary.js +5 -2
  37. package/dist/admin/sidebar/ValidationSummary.js.map +1 -1
  38. package/dist/global.js +54 -39
  39. package/dist/global.js.map +1 -1
  40. package/dist/hooks/usePreviewBinding.js +6 -2
  41. package/dist/hooks/usePreviewBinding.js.map +1 -1
  42. package/dist/hooks/usePreviewSettingsSync.js +8 -3
  43. package/dist/hooks/usePreviewSettingsSync.js.map +1 -1
  44. package/dist/i18n/cs.d.ts +2 -0
  45. package/dist/i18n/cs.js +136 -0
  46. package/dist/i18n/cs.js.map +1 -0
  47. package/dist/i18n/da.d.ts +2 -0
  48. package/dist/i18n/da.js +136 -0
  49. package/dist/i18n/da.js.map +1 -0
  50. package/dist/i18n/de.d.ts +2 -0
  51. package/dist/i18n/de.js +135 -0
  52. package/dist/i18n/de.js.map +1 -0
  53. package/dist/i18n/en.d.ts +2 -0
  54. package/dist/i18n/en.js +135 -0
  55. package/dist/i18n/en.js.map +1 -0
  56. package/dist/i18n/es.d.ts +2 -0
  57. package/dist/i18n/es.js +136 -0
  58. package/dist/i18n/es.js.map +1 -0
  59. package/dist/i18n/fr.d.ts +2 -0
  60. package/dist/i18n/fr.js +136 -0
  61. package/dist/i18n/fr.js.map +1 -0
  62. package/dist/i18n/index.d.ts +2 -0
  63. package/dist/i18n/index.js +34 -0
  64. package/dist/i18n/index.js.map +1 -0
  65. package/dist/i18n/it.d.ts +2 -0
  66. package/dist/i18n/it.js +136 -0
  67. package/dist/i18n/it.js.map +1 -0
  68. package/dist/i18n/merge.d.ts +8 -0
  69. package/dist/i18n/merge.js +22 -0
  70. package/dist/i18n/merge.js.map +1 -0
  71. package/dist/i18n/nb.d.ts +2 -0
  72. package/dist/i18n/nb.js +136 -0
  73. package/dist/i18n/nb.js.map +1 -0
  74. package/dist/i18n/nl.d.ts +2 -0
  75. package/dist/i18n/nl.js +136 -0
  76. package/dist/i18n/nl.js.map +1 -0
  77. package/dist/i18n/pl.d.ts +2 -0
  78. package/dist/i18n/pl.js +136 -0
  79. package/dist/i18n/pl.js.map +1 -0
  80. package/dist/i18n/pt.d.ts +2 -0
  81. package/dist/i18n/pt.js +136 -0
  82. package/dist/i18n/pt.js.map +1 -0
  83. package/dist/i18n/ro.d.ts +2 -0
  84. package/dist/i18n/ro.js +136 -0
  85. package/dist/i18n/ro.js.map +1 -0
  86. package/dist/i18n/sv.d.ts +2 -0
  87. package/dist/i18n/sv.js +136 -0
  88. package/dist/i18n/sv.js.map +1 -0
  89. package/dist/i18n/tr.d.ts +2 -0
  90. package/dist/i18n/tr.js +136 -0
  91. package/dist/i18n/tr.js.map +1 -0
  92. package/dist/i18n/types.d.ts +133 -0
  93. package/dist/i18n/types.js +3 -0
  94. package/dist/i18n/types.js.map +1 -0
  95. package/dist/i18n/uk.d.ts +2 -0
  96. package/dist/i18n/uk.js +136 -0
  97. package/dist/i18n/uk.js.map +1 -0
  98. package/dist/i18n/useBetterEditorT.d.ts +2 -0
  99. package/dist/i18n/useBetterEditorT.js +10 -0
  100. package/dist/i18n/useBetterEditorT.js.map +1 -0
  101. package/dist/index.d.ts +2 -1
  102. package/dist/index.js +19 -2
  103. package/dist/index.js.map +1 -1
  104. package/dist/preview/HoverToolbar.d.ts +8 -0
  105. package/dist/preview/HoverToolbar.js +31 -29
  106. package/dist/preview/HoverToolbar.js.map +1 -1
  107. package/dist/preview/HoverToolbarController.d.ts +6 -0
  108. package/dist/preview/HoverToolbarController.js +20 -5
  109. package/dist/preview/HoverToolbarController.js.map +1 -1
  110. package/dist/styles/blocks-tab.css +1 -7
  111. package/dist/styles/overlay.css +2 -0
  112. package/dist/styles/sidebar.css +1 -0
  113. package/dist/styles/toggle.css +17 -0
  114. package/dist/types.d.ts +6 -0
  115. package/dist/types.js.map +1 -1
  116. package/dist/version.d.ts +1 -1
  117. package/dist/version.js +1 -1
  118. package/dist/version.js.map +1 -1
  119. 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":"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"}
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 = ()=>/*#__PURE__*/ _jsx(DocumentFieldsTab, {
7
+ export const DocumentMetaTab = ()=>{
8
+ const t = useBetterEditorT();
9
+ return /*#__PURE__*/ _jsx(DocumentFieldsTab, {
7
10
  filter: isSidebarField,
8
- emptyText: "No document settings."
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\n filter={isSidebarField}\n emptyText=\"No document settings.\"\n />\n)\n"],"names":["React","DocumentFieldsTab","isSidebarField","f","admin","position","DocumentMetaTab","filter","emptyText"],"mappings":"AAAA;;AAEA,OAAOA,WAAW,QAAO;AAEzB,SAASC,iBAAiB,QAAQ,sBAAqB;AAEvD,MAAMC,iBAAiB,CAACC,IACtB,WAAWA,KAAKA,EAAEC,KAAK,EAAEC,aAAa;AAExC,OAAO,MAAMC,kBAA4B,kBACvC,KAACL;QACCM,QAAQL;QACRM,WAAU;OAEb"}
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 = ()=>/*#__PURE__*/ _jsx(DocumentFieldsTab, {
43
+ export const DocumentSettingsTab = ()=>{
44
+ const t = useBetterEditorT();
45
+ return /*#__PURE__*/ _jsx(DocumentFieldsTab, {
43
46
  filter: isNotSidebar,
44
47
  transform: stripBlocks,
45
- emptyText: "No document-level fields found."
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 filter={isNotSidebar}\n transform={stripBlocks}\n emptyText=\"No document-level fields found.\"\n />\n)\n"],"names":["React","DocumentFieldsTab","isNotSidebar","f","admin","position","stripBlocks","fields","result","field","type","newTabs","tab","tabs","inner","length","push","DocumentSettingsTab","filter","transform","emptyText"],"mappings":"AAAA;;AAEA,OAAOA,WAAW,QAAO;AAEzB,SAASC,iBAAiB,QAAQ,sBAAqB;AAEvD,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,kBAC3C,KAAChB;QACCiB,QAAQhB;QACRiB,WAAWb;QACXc,WAAU;OAEb"}
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
- const TABS = [
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 })=>/*#__PURE__*/ _jsx("div", {
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 ? `Block selected: ${selectedBlockPath}` : 'No block selected'
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 TABS: ReadonlyArray<{ key: TabKey; label: string }> = [\n { key: 'page', label: 'Page' },\n { key: 'block', label: 'Blocks' },\n { key: 'settings', label: 'Settings' },\n]\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 [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 <div role=\"status\" aria-live=\"polite\" aria-atomic=\"true\" className=\"better-editor-sr-only\">\n {selectedBlockPath ? `Block selected: ${selectedBlockPath}` : 'No block selected'}\n </div>\n)\n"],"names":["React","useEffect","useState","DocumentSettingsTab","DocumentMetaTab","BlockSettingsTab","ValidationSummary","TABS","key","label","ROOT_CLASS","TAB_CLASS","tabId","panelId","SidebarTab","tabKey","active","onSelect","button","type","role","id","aria-selected","aria-controls","tabIndex","className","onClick","Sidebar","memo","selectedBlockPath","onClearSelection","onSelectPath","forceFullWidthFields","blocksField","addBelowRequestId","tab","setTab","div","map","t","aria-labelledby","SelectionAnnouncer","aria-live","aria-atomic"],"mappings":"AAAA;;AAEA,OAAOA,SAASC,SAAS,EAAEC,QAAQ,QAAQ,QAAO;AAClD,SAASC,mBAAmB,QAAQ,wBAAuB;AAC3D,SAASC,eAAe,QAAQ,oBAAmB;AACnD,SAASC,gBAAgB,QAAQ,qBAAoB;AACrD,SAASC,iBAAiB,QAAQ,sBAAqB;AAavD,MAAMC,OAAsD;IAC1D;QAAEC,KAAK;QAAQC,OAAO;IAAO;IAC7B;QAAED,KAAK;QAASC,OAAO;IAAS;IAChC;QAAED,KAAK;QAAYC,OAAO;IAAW;CACtC;AAED,MAAMC,aAAa;AACnB,MAAMC,YAAY,GAAGD,WAAW,KAAK,CAAC;AAEtC,MAAME,QAAQ,CAACJ,MAAgB,CAAC,kBAAkB,EAAEA,KAAK;AACzD,MAAMK,UAAU,CAACL,MAAgB,CAAC,oBAAoB,EAAEA,KAAK;AAS7D,MAAMM,aAAwC,CAAC,EAAEC,MAAM,EAAEN,KAAK,EAAEO,MAAM,EAAEC,QAAQ,EAAE,iBAChF,KAACC;QACCC,MAAK;QACLC,MAAK;QACLC,IAAIT,MAAMG;QACVO,iBAAeN;QACfO,iBAAeV,QAAQE;QACvBS,UAAUR,SAAS,IAAI,CAAC;QACxBS,WAAWT,SAAS,GAAGL,UAAU,CAAC,EAAEA,UAAU,QAAQ,CAAC,GAAGA;QAC1De,SAAS,IAAMT,SAASF;kBAEvBN;;AAIL,yEAAyE;AACzE,OAAO,MAAMkB,wBAAU3B,MAAM4B,IAAI,CAAC,SAASD,QAAQ,EACjDE,iBAAiB,EACjBC,gBAAgB,EAChBC,YAAY,EACZC,oBAAoB,EACpBC,WAAW,EACXC,oBAAoB,CAAC,EACR;IACb,MAAM,CAACC,KAAKC,OAAO,GAAGlC,SAAiB;IAEvC,kEAAkE;IAClED,UAAU;QACR,IAAI4B,mBAAmBO,OAAO;IAChC,GAAG;QAACP;KAAkB;IAEtB,MAAMJ,YAAYO,uBACd,GAAGtB,WAAW,CAAC,EAAEA,WAAW,kBAAkB,CAAC,GAC/CA;IAEJ,qBACE,MAAC2B;QAAIZ,WAAWA;;0BACd,KAACY;gBAAIjB,MAAK;gBAAUK,WAAW,GAAGf,WAAW,MAAM,CAAC;0BACjDH,KAAK+B,GAAG,CAAC,CAACC,kBACT,KAACzB;wBAECC,QAAQwB,EAAE/B,GAAG;wBACbC,OAAO8B,EAAE9B,KAAK;wBACdO,QAAQmB,QAAQI,EAAE/B,GAAG;wBACrBS,UAAUmB;uBAJLG,EAAE/B,GAAG;;0BAShB,KAACF;gBAAkB2B,aAAaA;gBAAaF,cAAcA;;0BAE3D,MAACM;gBACCZ,WAAW,GAAGf,WAAW,SAAS,CAAC;gBACnCU,MAAK;gBACLC,IAAIR,QAAQsB;gBACZK,mBAAiB5B,MAAMuB;gBACvBX,UAAU;;oBAETW,QAAQ,wBAAU,KAAChC;oBACnBgC,QAAQ,yBACP,KAAC9B;wBACCwB,mBAAmBA;wBACnBC,kBAAkBA;wBAClBC,cAAcA;wBACdE,aAAaA;wBACbC,mBAAmBA;;oBAGtBC,QAAQ,4BAAc,KAAC/B;;;0BAG1B,KAACqC;gBAAmBZ,mBAAmBA;;;;AAG7C,GAAE;AAEF,qEAAqE;AACrE,uEAAuE;AACvE,MAAMY,qBAAqE,CAAC,EAC1EZ,iBAAiB,EAClB,iBACC,KAACQ;QAAIjB,MAAK;QAASsB,aAAU;QAASC,eAAY;QAAOlB,WAAU;kBAChEI,oBAAoB,CAAC,gBAAgB,EAAEA,mBAAmB,GAAG"}
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": "Validation errors",
20
+ "aria-label": t.sidebar.validationLabel,
18
21
  children: [
19
22
  /*#__PURE__*/ _jsx("p", {
20
23
  className: "better-editor-sidebar__errors-title",
21
- children: errors.length === 1 ? '1 field needs attention' : `${errors.length} fields need attention`
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 className=\"better-editor-sidebar__errors\" role=\"region\" aria-label=\"Validation errors\">\n <p className=\"better-editor-sidebar__errors-title\">\n {errors.length === 1 ? '1 field needs attention' : `${errors.length} fields need attention`}\n </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","ValidationSummary","blocksField","onSelectPath","fields","errors","length","div","className","role","aria-label","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;AAOjD,2DAA2D;AAC3D,OAAO,MAAMC,oBAAsD,CAAC,EAClEC,WAAW,EACXC,YAAY,EACb;IACC,MAAM,CAACC,OAAO,GAAGL;IACjB,MAAMM,SAASP,QACb,IAAME,mBAAmBI,QAAqBF,cAC9C;QAACE;QAAQF;KAAY;IAGvB,IAAIG,OAAOC,MAAM,KAAK,GAAG,OAAO;IAEhC,qBACE,MAACC;QAAIC,WAAU;QAAgCC,MAAK;QAASC,cAAW;;0BACtE,KAACC;gBAAEH,WAAU;0BACVH,OAAOC,MAAM,KAAK,IAAI,4BAA4B,GAAGD,OAAOC,MAAM,CAAC,sBAAsB,CAAC;;0BAE7F,KAACM;gBAAGJ,WAAU;0BACXH,OAAOQ,GAAG,CAAC,CAACC,sBACX,MAACC;wBAAoBP,WAAU;;4BAC5BM,MAAME,SAAS,iBACd,KAACC;gCACCC,MAAK;gCACLV,WAAU;gCACVW,SAAS,IAAMhB,aAAaW,MAAME,SAAS;0CAE1CF,MAAMM,KAAK;+CAGd,KAACC;gCAAKb,WAAU;0CAAuCM,MAAMM,KAAK;;0CAEpE,KAACC;gCAAKb,WAAU;0CAAyCM,MAAMQ,OAAO;;;uBAZ/DR,MAAMS,IAAI;;;;AAkB7B,EAAC"}
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 validateHoverColor = (value)=>{
9
- if (typeof value !== 'string' || value.length === 0) return 'Color is required';
10
- if (!HOVER_COLOR_RE.test(value.trim())) {
11
- return 'Must be a hex color (e.g. #3b82f6) or rgb()/rgba()';
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
- if (typeof value !== 'number' || !Number.isFinite(value)) return 'Must be a number';
17
- if (value < HOVER_OUTLINE_MIN || value > HOVER_OUTLINE_MAX) {
18
- return `Must be between ${HOVER_OUTLINE_MIN} and ${HOVER_OUTLINE_MAX}`;
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: 'Settings',
39
+ label: translatedLabel('globalLabel'),
25
40
  access: {
26
41
  read: ()=>true
27
42
  },
28
43
  admin: {
29
44
  group: 'Better Editor',
30
- description: 'Editor-wide preferences for the Better Editor overlay.'
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: 'Sidebar',
47
- description: 'Where the sidebar sits and how its fields are stacked.',
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: 'Position',
67
+ label: translatedLabel('sidebar.position'),
53
68
  defaultValue: D.sidebarPosition,
54
69
  options: [
55
70
  {
56
- label: 'Right',
71
+ label: translatedLabel('sidebar.positionRight'),
57
72
  value: 'right'
58
73
  },
59
74
  {
60
- label: 'Left',
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: 'Stack fields full-width',
83
+ label: translatedLabel('sidebar.forceFullWidth'),
69
84
  defaultValue: D.forceFullWidthFields,
70
85
  admin: {
71
- description: 'Override admin.width on sidebar fields so they always span the full row.'
86
+ description: translatedLabel('sidebar.forceFullWidthDesc')
72
87
  }
73
88
  }
74
89
  ]
75
90
  },
76
91
  {
77
- label: 'Viewport',
78
- description: 'Pixel widths for the Tablet and Mobile preview modes.',
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: 'Tablet (px)',
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: 'Mobile (px)',
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: 'Outline',
113
- description: 'Outline + tint shown on the hovered or selected block.',
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: 'Top-level color',
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: 'Hex color (e.g. `#3b82f6`).'
142
+ description: translatedLabel('outline.topLevelColorDesc')
128
143
  }
129
144
  },
130
145
  {
131
146
  name: 'hoverColorNested',
132
147
  type: 'text',
133
- label: 'Nested color',
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: 'Hex color for blocks nested inside another block.'
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: 'Outline width (px)',
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: `Outline thickness in pixels (${HOVER_OUTLINE_MIN}–${HOVER_OUTLINE_MAX}).`
169
+ description: translatedLabel('outline.outlineWidthDesc')
155
170
  }
156
171
  }
157
172
  ]
158
173
  },
159
174
  {
160
- label: 'Toolbar',
161
- description: 'Floating Move / Duplicate / Delete toolbar that appears on the selected block.',
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: 'Enabled',
181
+ label: translatedLabel('toolbar.enabled'),
167
182
  defaultValue: D.showHoverToolbar
168
183
  },
169
184
  {
170
185
  name: 'hoverToolbarPosition',
171
186
  type: 'select',
172
- label: 'Anchor corner',
187
+ label: translatedLabel('toolbar.anchorCorner'),
173
188
  defaultValue: D.hoverToolbarPosition,
174
189
  options: [
175
190
  {
176
- label: 'Top right',
191
+ label: translatedLabel('toolbar.topRight'),
177
192
  value: 'top-right'
178
193
  },
179
194
  {
180
- label: 'Top left',
195
+ label: translatedLabel('toolbar.topLeft'),
181
196
  value: 'top-left'
182
197
  },
183
198
  {
184
- label: 'Bottom right',
199
+ label: translatedLabel('toolbar.bottomRight'),
185
200
  value: 'bottom-right'
186
201
  },
187
202
  {
188
- label: 'Bottom left',
203
+ label: translatedLabel('toolbar.bottomLeft'),
189
204
  value: 'bottom-left'
190
205
  }
191
206
  ]
@@ -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