payload-better-editor 1.2.2 → 1.3.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 (77) 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 +55 -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/de.d.ts +2 -0
  45. package/dist/i18n/de.js +135 -0
  46. package/dist/i18n/de.js.map +1 -0
  47. package/dist/i18n/en.d.ts +2 -0
  48. package/dist/i18n/en.js +135 -0
  49. package/dist/i18n/en.js.map +1 -0
  50. package/dist/i18n/merge.d.ts +8 -0
  51. package/dist/i18n/merge.js +22 -0
  52. package/dist/i18n/merge.js.map +1 -0
  53. package/dist/i18n/types.d.ts +133 -0
  54. package/dist/i18n/types.js +3 -0
  55. package/dist/i18n/types.js.map +1 -0
  56. package/dist/i18n/useBetterEditorT.d.ts +2 -0
  57. package/dist/i18n/useBetterEditorT.js +10 -0
  58. package/dist/i18n/useBetterEditorT.js.map +1 -0
  59. package/dist/index.d.ts +2 -1
  60. package/dist/index.js +21 -2
  61. package/dist/index.js.map +1 -1
  62. package/dist/preview/HoverToolbar.d.ts +8 -0
  63. package/dist/preview/HoverToolbar.js +31 -29
  64. package/dist/preview/HoverToolbar.js.map +1 -1
  65. package/dist/preview/HoverToolbarController.d.ts +6 -0
  66. package/dist/preview/HoverToolbarController.js +20 -5
  67. package/dist/preview/HoverToolbarController.js.map +1 -1
  68. package/dist/styles/blocks-tab.css +1 -7
  69. package/dist/styles/overlay.css +2 -0
  70. package/dist/styles/sidebar.css +1 -0
  71. package/dist/styles/toggle.css +17 -0
  72. package/dist/types.d.ts +6 -0
  73. package/dist/types.js.map +1 -1
  74. package/dist/version.d.ts +1 -1
  75. package/dist/version.js +1 -1
  76. package/dist/version.js.map +1 -1
  77. package/package.json +13 -14
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/admin/SettingsBanner.tsx"],"sourcesContent":["'use client'\n\nimport React from 'react'\nimport { BugIcon, GithubIcon, StarIcon } from './icons'\nimport { VERSION } from '../version'\nimport '../styles/settings-banner.css'\n\nconst REPO = 'scorpio-99/payload-better-editor'\nconst AUTHOR = 'scorpio-99'\n\nconst BANNER = {\n author: AUTHOR,\n repoUrl: `https://github.com/${REPO}`,\n issuesUrl: `https://github.com/${REPO}/issues/new`,\n authorUrl: `https://github.com/${AUTHOR}`,\n starBadgeUrl: `https://img.shields.io/github/stars/${REPO}?style=flat&label=&color=27272a&labelColor=27272a&logo=github&logoColor=white`,\n}\n\nexport const SettingsBanner: React.FC = () => (\n <div className=\"better-editor-banner\">\n <div className=\"better-editor-banner__header\">\n <div className=\"better-editor-banner__heading\">\n <div className=\"better-editor-banner__title\">\n <span>payload-better-editor</span>\n <span className=\"better-editor-banner__version\">v{VERSION}</span>\n </div>\n <div className=\"better-editor-banner__subtitle\">\n Built by{' '}\n <a href={BANNER.authorUrl} target=\"_blank\" rel=\"noreferrer noopener\">\n {BANNER.author}\n </a>\n . If you find this plugin useful, please leave a star ⭐\n </div>\n </div>\n </div>\n <div className=\"better-editor-banner__actions\">\n <a\n href={BANNER.repoUrl}\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n className=\"better-editor-banner__link\"\n >\n <StarIcon />\n <span>Star</span>\n <img\n src={BANNER.starBadgeUrl}\n alt=\"\"\n className=\"better-editor-banner__star-badge\"\n />\n </a>\n <a\n href={BANNER.repoUrl}\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n className=\"better-editor-banner__link\"\n >\n <GithubIcon />\n <span>GitHub</span>\n </a>\n <a\n href={BANNER.issuesUrl}\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n className=\"better-editor-banner__link\"\n >\n <BugIcon />\n <span>Report a bug</span>\n </a>\n </div>\n </div>\n)\n"],"names":["React","BugIcon","GithubIcon","StarIcon","VERSION","REPO","AUTHOR","BANNER","author","repoUrl","issuesUrl","authorUrl","starBadgeUrl","SettingsBanner","div","className","span","a","href","target","rel","img","src","alt"],"mappings":"AAAA;;AAEA,OAAOA,WAAW,QAAO;AACzB,SAASC,OAAO,EAAEC,UAAU,EAAEC,QAAQ,QAAQ,UAAS;AACvD,SAASC,OAAO,QAAQ,aAAY;AACpC,OAAO,gCAA+B;AAEtC,MAAMC,OAAO;AACb,MAAMC,SAAS;AAEf,MAAMC,SAAS;IACbC,QAAQF;IACRG,SAAS,CAAC,mBAAmB,EAAEJ,MAAM;IACrCK,WAAW,CAAC,mBAAmB,EAAEL,KAAK,WAAW,CAAC;IAClDM,WAAW,CAAC,mBAAmB,EAAEL,QAAQ;IACzCM,cAAc,CAAC,oCAAoC,EAAEP,KAAK,6EAA6E,CAAC;AAC1I;AAEA,OAAO,MAAMQ,iBAA2B,kBACtC,MAACC;QAAIC,WAAU;;0BACb,KAACD;gBAAIC,WAAU;0BACb,cAAA,MAACD;oBAAIC,WAAU;;sCACb,MAACD;4BAAIC,WAAU;;8CACb,KAACC;8CAAK;;8CACN,MAACA;oCAAKD,WAAU;;wCAAgC;wCAAEX;;;;;sCAEpD,MAACU;4BAAIC,WAAU;;gCAAiC;gCACrC;8CACT,KAACE;oCAAEC,MAAMX,OAAOI,SAAS;oCAAEQ,QAAO;oCAASC,KAAI;8CAC5Cb,OAAOC,MAAM;;gCACZ;;;;;;0BAKV,MAACM;gBAAIC,WAAU;;kCACb,MAACE;wBACCC,MAAMX,OAAOE,OAAO;wBACpBU,QAAO;wBACPC,KAAI;wBACJL,WAAU;;0CAEV,KAACZ;0CACD,KAACa;0CAAK;;0CACN,KAACK;gCACCC,KAAKf,OAAOK,YAAY;gCACxBW,KAAI;gCACJR,WAAU;;;;kCAGd,MAACE;wBACCC,MAAMX,OAAOE,OAAO;wBACpBU,QAAO;wBACPC,KAAI;wBACJL,WAAU;;0CAEV,KAACb;0CACD,KAACc;0CAAK;;;;kCAER,MAACC;wBACCC,MAAMX,OAAOG,SAAS;wBACtBS,QAAO;wBACPC,KAAI;wBACJL,WAAU;;0CAEV,KAACd;0CACD,KAACe;0CAAK;;;;;;;OAIb"}
1
+ {"version":3,"sources":["../../src/admin/SettingsBanner.tsx"],"sourcesContent":["'use client'\n\nimport React from 'react'\nimport { BugIcon, GithubIcon, StarIcon } from './icons'\nimport { VERSION } from '../version'\nimport { useBetterEditorT } from '../i18n/useBetterEditorT'\nimport '../styles/settings-banner.css'\n\nconst REPO = 'scorpio-99/payload-better-editor'\nconst AUTHOR = 'scorpio-99'\n\nconst BANNER = {\n author: AUTHOR,\n repoUrl: `https://github.com/${REPO}`,\n issuesUrl: `https://github.com/${REPO}/issues/new`,\n authorUrl: `https://github.com/${AUTHOR}`,\n starBadgeUrl: `https://img.shields.io/github/stars/${REPO}?style=flat&label=&color=27272a&labelColor=27272a&logo=github&logoColor=white`,\n}\n\nexport const SettingsBanner: React.FC = () => {\n const t = useBetterEditorT()\n return (\n <div className=\"better-editor-banner\">\n <div className=\"better-editor-banner__header\">\n <div className=\"better-editor-banner__heading\">\n <div className=\"better-editor-banner__title\">\n <span>payload-better-editor</span>\n <span className=\"better-editor-banner__version\">v{VERSION}</span>\n </div>\n <div className=\"better-editor-banner__subtitle\">\n Built by{' '}\n <a href={BANNER.authorUrl} target=\"_blank\" rel=\"noreferrer noopener\">\n {BANNER.author}\n </a>\n . {t.banner.builtBy}\n </div>\n </div>\n </div>\n <div className=\"better-editor-banner__actions\">\n <a\n href={BANNER.repoUrl}\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n className=\"better-editor-banner__link\"\n >\n <StarIcon />\n <span>{t.banner.star}</span>\n <img src={BANNER.starBadgeUrl} alt=\"\" className=\"better-editor-banner__star-badge\" />\n </a>\n <a\n href={BANNER.repoUrl}\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n className=\"better-editor-banner__link\"\n >\n <GithubIcon />\n <span>{t.banner.github}</span>\n </a>\n <a\n href={BANNER.issuesUrl}\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n className=\"better-editor-banner__link\"\n >\n <BugIcon />\n <span>{t.banner.reportBug}</span>\n </a>\n </div>\n </div>\n )\n}\n"],"names":["React","BugIcon","GithubIcon","StarIcon","VERSION","useBetterEditorT","REPO","AUTHOR","BANNER","author","repoUrl","issuesUrl","authorUrl","starBadgeUrl","SettingsBanner","t","div","className","span","a","href","target","rel","banner","builtBy","star","img","src","alt","github","reportBug"],"mappings":"AAAA;;AAEA,OAAOA,WAAW,QAAO;AACzB,SAASC,OAAO,EAAEC,UAAU,EAAEC,QAAQ,QAAQ,UAAS;AACvD,SAASC,OAAO,QAAQ,aAAY;AACpC,SAASC,gBAAgB,QAAQ,2BAA0B;AAC3D,OAAO,gCAA+B;AAEtC,MAAMC,OAAO;AACb,MAAMC,SAAS;AAEf,MAAMC,SAAS;IACbC,QAAQF;IACRG,SAAS,CAAC,mBAAmB,EAAEJ,MAAM;IACrCK,WAAW,CAAC,mBAAmB,EAAEL,KAAK,WAAW,CAAC;IAClDM,WAAW,CAAC,mBAAmB,EAAEL,QAAQ;IACzCM,cAAc,CAAC,oCAAoC,EAAEP,KAAK,6EAA6E,CAAC;AAC1I;AAEA,OAAO,MAAMQ,iBAA2B;IACtC,MAAMC,IAAIV;IACV,qBACE,MAACW;QAAIC,WAAU;;0BACb,KAACD;gBAAIC,WAAU;0BACb,cAAA,MAACD;oBAAIC,WAAU;;sCACb,MAACD;4BAAIC,WAAU;;8CACb,KAACC;8CAAK;;8CACN,MAACA;oCAAKD,WAAU;;wCAAgC;wCAAEb;;;;;sCAEpD,MAACY;4BAAIC,WAAU;;gCAAiC;gCACrC;8CACT,KAACE;oCAAEC,MAAMZ,OAAOI,SAAS;oCAAES,QAAO;oCAASC,KAAI;8CAC5Cd,OAAOC,MAAM;;gCACZ;gCACDM,EAAEQ,MAAM,CAACC,OAAO;;;;;;0BAIzB,MAACR;gBAAIC,WAAU;;kCACb,MAACE;wBACCC,MAAMZ,OAAOE,OAAO;wBACpBW,QAAO;wBACPC,KAAI;wBACJL,WAAU;;0CAEV,KAACd;0CACD,KAACe;0CAAMH,EAAEQ,MAAM,CAACE,IAAI;;0CACpB,KAACC;gCAAIC,KAAKnB,OAAOK,YAAY;gCAAEe,KAAI;gCAAGX,WAAU;;;;kCAElD,MAACE;wBACCC,MAAMZ,OAAOE,OAAO;wBACpBW,QAAO;wBACPC,KAAI;wBACJL,WAAU;;0CAEV,KAACf;0CACD,KAACgB;0CAAMH,EAAEQ,MAAM,CAACM,MAAM;;;;kCAExB,MAACV;wBACCC,MAAMZ,OAAOG,SAAS;wBACtBU,QAAO;wBACPC,KAAI;wBACJL,WAAU;;0CAEV,KAAChB;0CACD,KAACiB;0CAAMH,EAAEQ,MAAM,CAACO,SAAS;;;;;;;;AAKnC,EAAC"}
@@ -1,29 +1,8 @@
1
1
  'use client';
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
- import React, { useCallback, useRef } from 'react';
3
+ import React, { useCallback, useMemo, useRef } from 'react';
4
4
  import { DesktopIcon, MobileIcon, ResponsiveIcon, TabletIcon } from './icons';
5
- const ITEMS = [
6
- {
7
- id: 'desktop',
8
- label: 'Desktop',
9
- Icon: DesktopIcon
10
- },
11
- {
12
- id: 'tablet',
13
- label: 'Tablet',
14
- Icon: TabletIcon
15
- },
16
- {
17
- id: 'mobile',
18
- label: 'Mobile',
19
- Icon: MobileIcon
20
- },
21
- {
22
- id: 'responsive',
23
- label: 'Responsive (drag to resize)',
24
- Icon: ResponsiveIcon
25
- }
26
- ];
5
+ import { useBetterEditorT } from '../i18n/useBetterEditorT';
27
6
  const ROOT_CLASS = 'better-editor-viewport';
28
7
  const BTN_CLASS = `${ROOT_CLASS}__btn`;
29
8
  const ViewportButton = ({ item, active, onSelect, buttonRef })=>{
@@ -42,6 +21,31 @@ const ViewportButton = ({ item, active, onSelect, buttonRef })=>{
42
21
  });
43
22
  };
44
23
  export const ViewportToggle = ({ value, onChange })=>{
24
+ const t = useBetterEditorT();
25
+ const ITEMS = useMemo(()=>[
26
+ {
27
+ id: 'desktop',
28
+ label: t.viewport.desktop,
29
+ Icon: DesktopIcon
30
+ },
31
+ {
32
+ id: 'tablet',
33
+ label: t.viewport.tablet,
34
+ Icon: TabletIcon
35
+ },
36
+ {
37
+ id: 'mobile',
38
+ label: t.viewport.mobile,
39
+ Icon: MobileIcon
40
+ },
41
+ {
42
+ id: 'responsive',
43
+ label: t.viewport.responsive,
44
+ Icon: ResponsiveIcon
45
+ }
46
+ ], [
47
+ t
48
+ ]);
45
49
  const btnsRef = useRef([]);
46
50
  const onKeyDown = useCallback((e)=>{
47
51
  const isPrev = e.key === 'ArrowLeft' || e.key === 'ArrowUp';
@@ -58,12 +62,13 @@ export const ViewportToggle = ({ value, onChange })=>{
58
62
  btnsRef.current[nextIdx]?.focus();
59
63
  }, [
60
64
  onChange,
61
- value
65
+ value,
66
+ ITEMS
62
67
  ]);
63
68
  return /*#__PURE__*/ _jsx("div", {
64
69
  className: ROOT_CLASS,
65
70
  role: "radiogroup",
66
- "aria-label": "Preview viewport",
71
+ "aria-label": t.viewport.groupLabel,
67
72
  onKeyDown: onKeyDown,
68
73
  children: ITEMS.map((item, i)=>/*#__PURE__*/ _jsx(ViewportButton, {
69
74
  item: item,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/admin/ViewportToggle.tsx"],"sourcesContent":["'use client'\n\nimport React, { useCallback, useRef } from 'react'\nimport {\n DesktopIcon,\n MobileIcon,\n ResponsiveIcon,\n TabletIcon,\n type IconProps,\n} from './icons'\n\nexport type Viewport = 'desktop' | 'tablet' | 'mobile' | 'responsive'\n\ntype Item = { id: Viewport; label: string; Icon: React.FC<IconProps> }\n\nconst ITEMS: ReadonlyArray<Item> = [\n { id: 'desktop', label: 'Desktop', Icon: DesktopIcon },\n { id: 'tablet', label: 'Tablet', Icon: TabletIcon },\n { id: 'mobile', label: 'Mobile', Icon: MobileIcon },\n { id: 'responsive', label: 'Responsive (drag to resize)', Icon: ResponsiveIcon },\n]\n\nconst ROOT_CLASS = 'better-editor-viewport'\nconst BTN_CLASS = `${ROOT_CLASS}__btn`\n\nexport type ViewportToggleProps = {\n value: Viewport\n onChange: (next: Viewport) => void\n}\n\ntype ButtonProps = {\n item: Item\n active: boolean\n onSelect: (id: Viewport) => void\n buttonRef: (el: HTMLButtonElement | null) => void\n}\n\nconst ViewportButton: React.FC<ButtonProps> = ({ item, active, onSelect, buttonRef }) => {\n const { id, label, Icon } = item\n return (\n <button\n type=\"button\"\n ref={buttonRef}\n role=\"radio\"\n aria-checked={active}\n tabIndex={active ? 0 : -1}\n className={active ? `${BTN_CLASS} ${BTN_CLASS}--active` : BTN_CLASS}\n onClick={() => onSelect(id)}\n title={label}\n aria-label={label}\n >\n <Icon />\n </button>\n )\n}\n\nexport const ViewportToggle: React.FC<ViewportToggleProps> = ({ value, onChange }) => {\n const btnsRef = useRef<Array<HTMLButtonElement | null>>([])\n\n const onKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLDivElement>) => {\n const isPrev = e.key === 'ArrowLeft' || e.key === 'ArrowUp'\n const isNext = e.key === 'ArrowRight' || e.key === 'ArrowDown'\n if (!isPrev && !isNext) return\n e.preventDefault()\n const idx = ITEMS.findIndex((i) => i.id === value)\n const start = idx === -1 ? 0 : idx\n const len = ITEMS.length\n // Per radiogroup pattern, arrow keys move both selection and focus.\n const nextIdx = isPrev ? (start - 1 + len) % len : (start + 1) % len\n const next = ITEMS[nextIdx]\n onChange(next.id)\n btnsRef.current[nextIdx]?.focus()\n },\n [onChange, value],\n )\n\n return (\n <div\n className={ROOT_CLASS}\n role=\"radiogroup\"\n aria-label=\"Preview viewport\"\n onKeyDown={onKeyDown}\n >\n {ITEMS.map((item, i) => (\n <ViewportButton\n key={item.id}\n item={item}\n active={value === item.id}\n onSelect={onChange}\n buttonRef={(el) => {\n btnsRef.current[i] = el\n }}\n />\n ))}\n </div>\n )\n}\n"],"names":["React","useCallback","useRef","DesktopIcon","MobileIcon","ResponsiveIcon","TabletIcon","ITEMS","id","label","Icon","ROOT_CLASS","BTN_CLASS","ViewportButton","item","active","onSelect","buttonRef","button","type","ref","role","aria-checked","tabIndex","className","onClick","title","aria-label","ViewportToggle","value","onChange","btnsRef","onKeyDown","e","isPrev","key","isNext","preventDefault","idx","findIndex","i","start","len","length","nextIdx","next","current","focus","div","map","el"],"mappings":"AAAA;;AAEA,OAAOA,SAASC,WAAW,EAAEC,MAAM,QAAQ,QAAO;AAClD,SACEC,WAAW,EACXC,UAAU,EACVC,cAAc,EACdC,UAAU,QAEL,UAAS;AAMhB,MAAMC,QAA6B;IACjC;QAAEC,IAAI;QAAWC,OAAO;QAAWC,MAAMP;IAAY;IACrD;QAAEK,IAAI;QAAUC,OAAO;QAAUC,MAAMJ;IAAW;IAClD;QAAEE,IAAI;QAAUC,OAAO;QAAUC,MAAMN;IAAW;IAClD;QAAEI,IAAI;QAAcC,OAAO;QAA+BC,MAAML;IAAe;CAChF;AAED,MAAMM,aAAa;AACnB,MAAMC,YAAY,GAAGD,WAAW,KAAK,CAAC;AActC,MAAME,iBAAwC,CAAC,EAAEC,IAAI,EAAEC,MAAM,EAAEC,QAAQ,EAAEC,SAAS,EAAE;IAClF,MAAM,EAAET,EAAE,EAAEC,KAAK,EAAEC,IAAI,EAAE,GAAGI;IAC5B,qBACE,KAACI;QACCC,MAAK;QACLC,KAAKH;QACLI,MAAK;QACLC,gBAAcP;QACdQ,UAAUR,SAAS,IAAI,CAAC;QACxBS,WAAWT,SAAS,GAAGH,UAAU,CAAC,EAAEA,UAAU,QAAQ,CAAC,GAAGA;QAC1Da,SAAS,IAAMT,SAASR;QACxBkB,OAAOjB;QACPkB,cAAYlB;kBAEZ,cAAA,KAACC;;AAGP;AAEA,OAAO,MAAMkB,iBAAgD,CAAC,EAAEC,KAAK,EAAEC,QAAQ,EAAE;IAC/E,MAAMC,UAAU7B,OAAwC,EAAE;IAE1D,MAAM8B,YAAY/B,YAChB,CAACgC;QACC,MAAMC,SAASD,EAAEE,GAAG,KAAK,eAAeF,EAAEE,GAAG,KAAK;QAClD,MAAMC,SAASH,EAAEE,GAAG,KAAK,gBAAgBF,EAAEE,GAAG,KAAK;QACnD,IAAI,CAACD,UAAU,CAACE,QAAQ;QACxBH,EAAEI,cAAc;QAChB,MAAMC,MAAM/B,MAAMgC,SAAS,CAAC,CAACC,IAAMA,EAAEhC,EAAE,KAAKqB;QAC5C,MAAMY,QAAQH,QAAQ,CAAC,IAAI,IAAIA;QAC/B,MAAMI,MAAMnC,MAAMoC,MAAM;QACxB,oEAAoE;QACpE,MAAMC,UAAUV,SAAS,AAACO,CAAAA,QAAQ,IAAIC,GAAE,IAAKA,MAAM,AAACD,CAAAA,QAAQ,CAAA,IAAKC;QACjE,MAAMG,OAAOtC,KAAK,CAACqC,QAAQ;QAC3Bd,SAASe,KAAKrC,EAAE;QAChBuB,QAAQe,OAAO,CAACF,QAAQ,EAAEG;IAC5B,GACA;QAACjB;QAAUD;KAAM;IAGnB,qBACE,KAACmB;QACCxB,WAAWb;QACXU,MAAK;QACLM,cAAW;QACXK,WAAWA;kBAEVzB,MAAM0C,GAAG,CAAC,CAACnC,MAAM0B,kBAChB,KAAC3B;gBAECC,MAAMA;gBACNC,QAAQc,UAAUf,KAAKN,EAAE;gBACzBQ,UAAUc;gBACVb,WAAW,CAACiC;oBACVnB,QAAQe,OAAO,CAACN,EAAE,GAAGU;gBACvB;eANKpC,KAAKN,EAAE;;AAWtB,EAAC"}
1
+ {"version":3,"sources":["../../src/admin/ViewportToggle.tsx"],"sourcesContent":["'use client'\n\nimport React, { useCallback, useMemo, useRef } from 'react'\nimport {\n DesktopIcon,\n MobileIcon,\n ResponsiveIcon,\n TabletIcon,\n type IconProps,\n} from './icons'\nimport { useBetterEditorT } from '../i18n/useBetterEditorT'\n\nexport type Viewport = 'desktop' | 'tablet' | 'mobile' | 'responsive'\n\ntype Item = { id: Viewport; label: string; Icon: React.FC<IconProps> }\n\nconst ROOT_CLASS = 'better-editor-viewport'\nconst BTN_CLASS = `${ROOT_CLASS}__btn`\n\nexport type ViewportToggleProps = {\n value: Viewport\n onChange: (next: Viewport) => void\n}\n\ntype ButtonProps = {\n item: Item\n active: boolean\n onSelect: (id: Viewport) => void\n buttonRef: (el: HTMLButtonElement | null) => void\n}\n\nconst ViewportButton: React.FC<ButtonProps> = ({ item, active, onSelect, buttonRef }) => {\n const { id, label, Icon } = item\n return (\n <button\n type=\"button\"\n ref={buttonRef}\n role=\"radio\"\n aria-checked={active}\n tabIndex={active ? 0 : -1}\n className={active ? `${BTN_CLASS} ${BTN_CLASS}--active` : BTN_CLASS}\n onClick={() => onSelect(id)}\n title={label}\n aria-label={label}\n >\n <Icon />\n </button>\n )\n}\n\nexport const ViewportToggle: React.FC<ViewportToggleProps> = ({ value, onChange }) => {\n const t = useBetterEditorT()\n const ITEMS = useMemo<ReadonlyArray<Item>>(\n () => [\n { id: 'desktop', label: t.viewport.desktop, Icon: DesktopIcon },\n { id: 'tablet', label: t.viewport.tablet, Icon: TabletIcon },\n { id: 'mobile', label: t.viewport.mobile, Icon: MobileIcon },\n { id: 'responsive', label: t.viewport.responsive, Icon: ResponsiveIcon },\n ],\n [t],\n )\n const btnsRef = useRef<Array<HTMLButtonElement | null>>([])\n\n const onKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLDivElement>) => {\n const isPrev = e.key === 'ArrowLeft' || e.key === 'ArrowUp'\n const isNext = e.key === 'ArrowRight' || e.key === 'ArrowDown'\n if (!isPrev && !isNext) return\n e.preventDefault()\n const idx = ITEMS.findIndex((i) => i.id === value)\n const start = idx === -1 ? 0 : idx\n const len = ITEMS.length\n // Per radiogroup pattern, arrow keys move both selection and focus.\n const nextIdx = isPrev ? (start - 1 + len) % len : (start + 1) % len\n const next = ITEMS[nextIdx]\n onChange(next.id)\n btnsRef.current[nextIdx]?.focus()\n },\n [onChange, value, ITEMS],\n )\n\n return (\n <div\n className={ROOT_CLASS}\n role=\"radiogroup\"\n aria-label={t.viewport.groupLabel}\n onKeyDown={onKeyDown}\n >\n {ITEMS.map((item, i) => (\n <ViewportButton\n key={item.id}\n item={item}\n active={value === item.id}\n onSelect={onChange}\n buttonRef={(el) => {\n btnsRef.current[i] = el\n }}\n />\n ))}\n </div>\n )\n}\n"],"names":["React","useCallback","useMemo","useRef","DesktopIcon","MobileIcon","ResponsiveIcon","TabletIcon","useBetterEditorT","ROOT_CLASS","BTN_CLASS","ViewportButton","item","active","onSelect","buttonRef","id","label","Icon","button","type","ref","role","aria-checked","tabIndex","className","onClick","title","aria-label","ViewportToggle","value","onChange","t","ITEMS","viewport","desktop","tablet","mobile","responsive","btnsRef","onKeyDown","e","isPrev","key","isNext","preventDefault","idx","findIndex","i","start","len","length","nextIdx","next","current","focus","div","groupLabel","map","el"],"mappings":"AAAA;;AAEA,OAAOA,SAASC,WAAW,EAAEC,OAAO,EAAEC,MAAM,QAAQ,QAAO;AAC3D,SACEC,WAAW,EACXC,UAAU,EACVC,cAAc,EACdC,UAAU,QAEL,UAAS;AAChB,SAASC,gBAAgB,QAAQ,2BAA0B;AAM3D,MAAMC,aAAa;AACnB,MAAMC,YAAY,GAAGD,WAAW,KAAK,CAAC;AActC,MAAME,iBAAwC,CAAC,EAAEC,IAAI,EAAEC,MAAM,EAAEC,QAAQ,EAAEC,SAAS,EAAE;IAClF,MAAM,EAAEC,EAAE,EAAEC,KAAK,EAAEC,IAAI,EAAE,GAAGN;IAC5B,qBACE,KAACO;QACCC,MAAK;QACLC,KAAKN;QACLO,MAAK;QACLC,gBAAcV;QACdW,UAAUX,SAAS,IAAI,CAAC;QACxBY,WAAWZ,SAAS,GAAGH,UAAU,CAAC,EAAEA,UAAU,QAAQ,CAAC,GAAGA;QAC1DgB,SAAS,IAAMZ,SAASE;QACxBW,OAAOV;QACPW,cAAYX;kBAEZ,cAAA,KAACC;;AAGP;AAEA,OAAO,MAAMW,iBAAgD,CAAC,EAAEC,KAAK,EAAEC,QAAQ,EAAE;IAC/E,MAAMC,IAAIxB;IACV,MAAMyB,QAAQ/B,QACZ,IAAM;YACJ;gBAAEc,IAAI;gBAAWC,OAAOe,EAAEE,QAAQ,CAACC,OAAO;gBAAEjB,MAAMd;YAAY;YAC9D;gBAAEY,IAAI;gBAAUC,OAAOe,EAAEE,QAAQ,CAACE,MAAM;gBAAElB,MAAMX;YAAW;YAC3D;gBAAES,IAAI;gBAAUC,OAAOe,EAAEE,QAAQ,CAACG,MAAM;gBAAEnB,MAAMb;YAAW;YAC3D;gBAAEW,IAAI;gBAAcC,OAAOe,EAAEE,QAAQ,CAACI,UAAU;gBAAEpB,MAAMZ;YAAe;SACxE,EACD;QAAC0B;KAAE;IAEL,MAAMO,UAAUpC,OAAwC,EAAE;IAE1D,MAAMqC,YAAYvC,YAChB,CAACwC;QACC,MAAMC,SAASD,EAAEE,GAAG,KAAK,eAAeF,EAAEE,GAAG,KAAK;QAClD,MAAMC,SAASH,EAAEE,GAAG,KAAK,gBAAgBF,EAAEE,GAAG,KAAK;QACnD,IAAI,CAACD,UAAU,CAACE,QAAQ;QACxBH,EAAEI,cAAc;QAChB,MAAMC,MAAMb,MAAMc,SAAS,CAAC,CAACC,IAAMA,EAAEhC,EAAE,KAAKc;QAC5C,MAAMmB,QAAQH,QAAQ,CAAC,IAAI,IAAIA;QAC/B,MAAMI,MAAMjB,MAAMkB,MAAM;QACxB,oEAAoE;QACpE,MAAMC,UAAUV,SAAS,AAACO,CAAAA,QAAQ,IAAIC,GAAE,IAAKA,MAAM,AAACD,CAAAA,QAAQ,CAAA,IAAKC;QACjE,MAAMG,OAAOpB,KAAK,CAACmB,QAAQ;QAC3BrB,SAASsB,KAAKrC,EAAE;QAChBuB,QAAQe,OAAO,CAACF,QAAQ,EAAEG;IAC5B,GACA;QAACxB;QAAUD;QAAOG;KAAM;IAG1B,qBACE,KAACuB;QACC/B,WAAWhB;QACXa,MAAK;QACLM,cAAYI,EAAEE,QAAQ,CAACuB,UAAU;QACjCjB,WAAWA;kBAEVP,MAAMyB,GAAG,CAAC,CAAC9C,MAAMoC,kBAChB,KAACrC;gBAECC,MAAMA;gBACNC,QAAQiB,UAAUlB,KAAKI,EAAE;gBACzBF,UAAUiB;gBACVhB,WAAW,CAAC4C;oBACVpB,QAAQe,OAAO,CAACN,EAAE,GAAGW;gBACvB;eANK/C,KAAKI,EAAE;;AAWtB,EAAC"}
@@ -2,15 +2,19 @@
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import React from 'react';
4
4
  import { BlocksDrawer } from '@payloadcms/ui';
5
- export const AddBlockDrawer = ({ slug, blocks, addRow, addRowIndex })=>/*#__PURE__*/ _jsx(BlocksDrawer, {
5
+ import { useBetterEditorT } from '../../i18n/useBetterEditorT';
6
+ export const AddBlockDrawer = ({ slug, blocks, addRow, addRowIndex })=>{
7
+ const t = useBetterEditorT();
8
+ return /*#__PURE__*/ _jsx(BlocksDrawer, {
6
9
  addRow: addRow,
7
10
  addRowIndex: addRowIndex,
8
11
  blocks: blocks,
9
12
  drawerSlug: slug,
10
13
  labels: {
11
- singular: 'Block',
12
- plural: 'Blocks'
14
+ singular: t.blocks.drawerSingular,
15
+ plural: t.blocks.drawerPlural
13
16
  }
14
17
  });
18
+ };
15
19
 
16
20
  //# sourceMappingURL=AddBlockDrawer.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/admin/blocks/AddBlockDrawer.tsx"],"sourcesContent":["'use client'\n\nimport React from 'react'\nimport { BlocksDrawer } from '@payloadcms/ui'\nimport type { ClientBlock } from 'payload'\n\nexport type AddBlockDrawerProps = {\n slug: string\n blocks: ClientBlock[]\n addRow: (index: number, blockType?: string) => void\n addRowIndex: number\n}\n\nexport const AddBlockDrawer: React.FC<AddBlockDrawerProps> = ({\n slug,\n blocks,\n addRow,\n addRowIndex,\n}) => (\n <BlocksDrawer\n addRow={addRow}\n addRowIndex={addRowIndex}\n blocks={blocks}\n drawerSlug={slug}\n labels={{ singular: 'Block', plural: 'Blocks' }}\n />\n)\n"],"names":["React","BlocksDrawer","AddBlockDrawer","slug","blocks","addRow","addRowIndex","drawerSlug","labels","singular","plural"],"mappings":"AAAA;;AAEA,OAAOA,WAAW,QAAO;AACzB,SAASC,YAAY,QAAQ,iBAAgB;AAU7C,OAAO,MAAMC,iBAAgD,CAAC,EAC5DC,IAAI,EACJC,MAAM,EACNC,MAAM,EACNC,WAAW,EACZ,iBACC,KAACL;QACCI,QAAQA;QACRC,aAAaA;QACbF,QAAQA;QACRG,YAAYJ;QACZK,QAAQ;YAAEC,UAAU;YAASC,QAAQ;QAAS;OAEjD"}
1
+ {"version":3,"sources":["../../../src/admin/blocks/AddBlockDrawer.tsx"],"sourcesContent":["'use client'\n\nimport React from 'react'\nimport { BlocksDrawer } from '@payloadcms/ui'\nimport type { ClientBlock } from 'payload'\nimport { useBetterEditorT } from '../../i18n/useBetterEditorT'\n\nexport type AddBlockDrawerProps = {\n slug: string\n blocks: ClientBlock[]\n addRow: (index: number, blockType?: string) => void\n addRowIndex: number\n}\n\nexport const AddBlockDrawer: React.FC<AddBlockDrawerProps> = ({\n slug,\n blocks,\n addRow,\n addRowIndex,\n}) => {\n const t = useBetterEditorT()\n return (\n <BlocksDrawer\n addRow={addRow}\n addRowIndex={addRowIndex}\n blocks={blocks}\n drawerSlug={slug}\n labels={{ singular: t.blocks.drawerSingular, plural: t.blocks.drawerPlural }}\n />\n )\n}\n"],"names":["React","BlocksDrawer","useBetterEditorT","AddBlockDrawer","slug","blocks","addRow","addRowIndex","t","drawerSlug","labels","singular","drawerSingular","plural","drawerPlural"],"mappings":"AAAA;;AAEA,OAAOA,WAAW,QAAO;AACzB,SAASC,YAAY,QAAQ,iBAAgB;AAE7C,SAASC,gBAAgB,QAAQ,8BAA6B;AAS9D,OAAO,MAAMC,iBAAgD,CAAC,EAC5DC,IAAI,EACJC,MAAM,EACNC,MAAM,EACNC,WAAW,EACZ;IACC,MAAMC,IAAIN;IACV,qBACE,KAACD;QACCK,QAAQA;QACRC,aAAaA;QACbF,QAAQA;QACRI,YAAYL;QACZM,QAAQ;YAAEC,UAAUH,EAAEH,MAAM,CAACO,cAAc;YAAEC,QAAQL,EAAEH,MAAM,CAACS,YAAY;QAAC;;AAGjF,EAAC"}
@@ -2,6 +2,7 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import React, { useCallback, useRef, useState } from 'react';
4
4
  import { ChevronDown, ChevronUp, CopyIcon, PlusIcon, TrashIcon } from '../icons';
5
+ import { useBetterEditorT } from '../../i18n/useBetterEditorT';
5
6
  export const BlockActionsToolbar = ({ canMoveUp, canMoveDown, canMutate, canAddBelow, onMoveUp, onMoveDown, onDuplicate, onAddBelow, onDelete })=>{
6
7
  // Roving tabindex per WAI-ARIA toolbar pattern: only one button is in
7
8
  // the tab sequence; arrow keys move focus among siblings.
@@ -25,6 +26,7 @@ export const BlockActionsToolbar = ({ canMoveUp, canMoveDown, canMutate, canAddB
25
26
  const idx = btnsRef.current.indexOf(buttons[next]);
26
27
  if (idx >= 0) setFocusIdx(idx);
27
28
  }, []);
29
+ const t = useBetterEditorT();
28
30
  if (!canMutate) return null;
29
31
  const setRef = (i)=>(el)=>{
30
32
  btnsRef.current[i] = el;
@@ -34,7 +36,7 @@ export const BlockActionsToolbar = ({ canMoveUp, canMoveDown, canMutate, canAddB
34
36
  return /*#__PURE__*/ _jsxs("div", {
35
37
  className: "better-editor-tab__actions",
36
38
  role: "toolbar",
37
- "aria-label": "Block actions",
39
+ "aria-label": t.blocks.actions.toolbar,
38
40
  onKeyDown: onKeyDown,
39
41
  children: [
40
42
  /*#__PURE__*/ _jsx("button", {
@@ -45,8 +47,8 @@ export const BlockActionsToolbar = ({ canMoveUp, canMoveDown, canMutate, canAddB
45
47
  className: "better-editor-tab__action",
46
48
  onClick: onMoveUp,
47
49
  disabled: !canMoveUp,
48
- title: "Move up",
49
- "aria-label": "Move block up",
50
+ title: t.blocks.actions.moveUp,
51
+ "aria-label": t.blocks.actions.moveUpLabel,
50
52
  children: /*#__PURE__*/ _jsx(ChevronUp, {})
51
53
  }),
52
54
  /*#__PURE__*/ _jsx("button", {
@@ -57,8 +59,8 @@ export const BlockActionsToolbar = ({ canMoveUp, canMoveDown, canMutate, canAddB
57
59
  className: "better-editor-tab__action",
58
60
  onClick: onMoveDown,
59
61
  disabled: !canMoveDown,
60
- title: "Move down",
61
- "aria-label": "Move block down",
62
+ title: t.blocks.actions.moveDown,
63
+ "aria-label": t.blocks.actions.moveDownLabel,
62
64
  children: /*#__PURE__*/ _jsx(ChevronDown, {})
63
65
  }),
64
66
  /*#__PURE__*/ _jsx("button", {
@@ -68,8 +70,8 @@ export const BlockActionsToolbar = ({ canMoveUp, canMoveDown, canMutate, canAddB
68
70
  onFocus: onFocus(2),
69
71
  className: "better-editor-tab__action",
70
72
  onClick: onDuplicate,
71
- title: "Duplicate",
72
- "aria-label": "Duplicate block",
73
+ title: t.blocks.actions.duplicate,
74
+ "aria-label": t.blocks.actions.duplicateLabel,
73
75
  children: /*#__PURE__*/ _jsx(CopyIcon, {})
74
76
  }),
75
77
  /*#__PURE__*/ _jsx("button", {
@@ -80,8 +82,8 @@ export const BlockActionsToolbar = ({ canMoveUp, canMoveDown, canMutate, canAddB
80
82
  className: "better-editor-tab__action",
81
83
  onClick: onAddBelow,
82
84
  disabled: !canAddBelow,
83
- title: "Add block below",
84
- "aria-label": "Add block below",
85
+ title: t.blocks.actions.addBelow,
86
+ "aria-label": t.blocks.actions.addBelowLabel,
85
87
  children: /*#__PURE__*/ _jsx(PlusIcon, {})
86
88
  }),
87
89
  /*#__PURE__*/ _jsx("button", {
@@ -91,8 +93,8 @@ export const BlockActionsToolbar = ({ canMoveUp, canMoveDown, canMutate, canAddB
91
93
  onFocus: onFocus(4),
92
94
  className: "better-editor-tab__action better-editor-tab__action--danger",
93
95
  onClick: onDelete,
94
- title: "Delete",
95
- "aria-label": "Delete block",
96
+ title: t.blocks.actions.delete,
97
+ "aria-label": t.blocks.actions.deleteLabel,
96
98
  children: /*#__PURE__*/ _jsx(TrashIcon, {})
97
99
  })
98
100
  ]
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/admin/blocks/BlockActionsToolbar.tsx"],"sourcesContent":["'use client'\n\nimport React, { useCallback, useRef, useState } from 'react'\nimport { ChevronDown, ChevronUp, CopyIcon, PlusIcon, TrashIcon } from '../icons'\n\nexport type BlockActionsToolbarProps = {\n canMoveUp: boolean\n canMoveDown: boolean\n /** When false the toolbar renders nothing. */\n canMutate: boolean\n /** When false the \"Add below\" button is disabled (no parent blocks list). */\n canAddBelow: boolean\n onMoveUp: () => void\n onMoveDown: () => void\n onDuplicate: () => void\n onAddBelow: () => void\n onDelete: () => void\n}\n\nexport const BlockActionsToolbar: React.FC<BlockActionsToolbarProps> = ({\n canMoveUp,\n canMoveDown,\n canMutate,\n canAddBelow,\n onMoveUp,\n onMoveDown,\n onDuplicate,\n onAddBelow,\n onDelete,\n}) => {\n // Roving tabindex per WAI-ARIA toolbar pattern: only one button is in\n // the tab sequence; arrow keys move focus among siblings.\n const [focusIdx, setFocusIdx] = useState(0)\n const btnsRef = useRef<Array<HTMLButtonElement | null>>([])\n\n const onKeyDown = useCallback((e: React.KeyboardEvent<HTMLDivElement>) => {\n if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight' && e.key !== 'Home' && e.key !== 'End') {\n return\n }\n e.preventDefault()\n const buttons = btnsRef.current.filter((b): b is HTMLButtonElement => b !== null)\n if (buttons.length === 0) return\n const current = buttons.findIndex((b) => b === document.activeElement)\n const start = current === -1 ? 0 : current\n let next = start\n if (e.key === 'ArrowLeft') next = (start - 1 + buttons.length) % buttons.length\n else if (e.key === 'ArrowRight') next = (start + 1) % buttons.length\n else if (e.key === 'Home') next = 0\n else if (e.key === 'End') next = buttons.length - 1\n buttons[next].focus()\n const idx = btnsRef.current.indexOf(buttons[next])\n if (idx >= 0) setFocusIdx(idx)\n }, [])\n\n if (!canMutate) return null\n\n const setRef = (i: number) => (el: HTMLButtonElement | null) => {\n btnsRef.current[i] = el\n }\n const tabIndexFor = (i: number) => (i === focusIdx ? 0 : -1)\n const onFocus = (i: number) => () => setFocusIdx(i)\n\n return (\n <div\n className=\"better-editor-tab__actions\"\n role=\"toolbar\"\n aria-label=\"Block actions\"\n onKeyDown={onKeyDown}\n >\n <button\n type=\"button\"\n ref={setRef(0)}\n tabIndex={tabIndexFor(0)}\n onFocus={onFocus(0)}\n className=\"better-editor-tab__action\"\n onClick={onMoveUp}\n disabled={!canMoveUp}\n title=\"Move up\"\n aria-label=\"Move block up\"\n >\n <ChevronUp />\n </button>\n <button\n type=\"button\"\n ref={setRef(1)}\n tabIndex={tabIndexFor(1)}\n onFocus={onFocus(1)}\n className=\"better-editor-tab__action\"\n onClick={onMoveDown}\n disabled={!canMoveDown}\n title=\"Move down\"\n aria-label=\"Move block down\"\n >\n <ChevronDown />\n </button>\n <button\n type=\"button\"\n ref={setRef(2)}\n tabIndex={tabIndexFor(2)}\n onFocus={onFocus(2)}\n className=\"better-editor-tab__action\"\n onClick={onDuplicate}\n title=\"Duplicate\"\n aria-label=\"Duplicate block\"\n >\n <CopyIcon />\n </button>\n <button\n type=\"button\"\n ref={setRef(3)}\n tabIndex={tabIndexFor(3)}\n onFocus={onFocus(3)}\n className=\"better-editor-tab__action\"\n onClick={onAddBelow}\n disabled={!canAddBelow}\n title=\"Add block below\"\n aria-label=\"Add block below\"\n >\n <PlusIcon />\n </button>\n <button\n type=\"button\"\n ref={setRef(4)}\n tabIndex={tabIndexFor(4)}\n onFocus={onFocus(4)}\n className=\"better-editor-tab__action better-editor-tab__action--danger\"\n onClick={onDelete}\n title=\"Delete\"\n aria-label=\"Delete block\"\n >\n <TrashIcon />\n </button>\n </div>\n )\n}\n"],"names":["React","useCallback","useRef","useState","ChevronDown","ChevronUp","CopyIcon","PlusIcon","TrashIcon","BlockActionsToolbar","canMoveUp","canMoveDown","canMutate","canAddBelow","onMoveUp","onMoveDown","onDuplicate","onAddBelow","onDelete","focusIdx","setFocusIdx","btnsRef","onKeyDown","e","key","preventDefault","buttons","current","filter","b","length","findIndex","document","activeElement","start","next","focus","idx","indexOf","setRef","i","el","tabIndexFor","onFocus","div","className","role","aria-label","button","type","ref","tabIndex","onClick","disabled","title"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/admin/blocks/BlockActionsToolbar.tsx"],"sourcesContent":["'use client'\n\nimport React, { useCallback, useRef, useState } from 'react'\nimport { ChevronDown, ChevronUp, CopyIcon, PlusIcon, TrashIcon } from '../icons'\nimport { useBetterEditorT } from '../../i18n/useBetterEditorT'\n\nexport type BlockActionsToolbarProps = {\n canMoveUp: boolean\n canMoveDown: boolean\n /** When false the toolbar renders nothing. */\n canMutate: boolean\n /** When false the \"Add below\" button is disabled (no parent blocks list). */\n canAddBelow: boolean\n onMoveUp: () => void\n onMoveDown: () => void\n onDuplicate: () => void\n onAddBelow: () => void\n onDelete: () => void\n}\n\nexport const BlockActionsToolbar: React.FC<BlockActionsToolbarProps> = ({\n canMoveUp,\n canMoveDown,\n canMutate,\n canAddBelow,\n onMoveUp,\n onMoveDown,\n onDuplicate,\n onAddBelow,\n onDelete,\n}) => {\n // Roving tabindex per WAI-ARIA toolbar pattern: only one button is in\n // the tab sequence; arrow keys move focus among siblings.\n const [focusIdx, setFocusIdx] = useState(0)\n const btnsRef = useRef<Array<HTMLButtonElement | null>>([])\n\n const onKeyDown = useCallback((e: React.KeyboardEvent<HTMLDivElement>) => {\n if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight' && e.key !== 'Home' && e.key !== 'End') {\n return\n }\n e.preventDefault()\n const buttons = btnsRef.current.filter((b): b is HTMLButtonElement => b !== null)\n if (buttons.length === 0) return\n const current = buttons.findIndex((b) => b === document.activeElement)\n const start = current === -1 ? 0 : current\n let next = start\n if (e.key === 'ArrowLeft') next = (start - 1 + buttons.length) % buttons.length\n else if (e.key === 'ArrowRight') next = (start + 1) % buttons.length\n else if (e.key === 'Home') next = 0\n else if (e.key === 'End') next = buttons.length - 1\n buttons[next].focus()\n const idx = btnsRef.current.indexOf(buttons[next])\n if (idx >= 0) setFocusIdx(idx)\n }, [])\n\n const t = useBetterEditorT()\n\n if (!canMutate) return null\n\n const setRef = (i: number) => (el: HTMLButtonElement | null) => {\n btnsRef.current[i] = el\n }\n const tabIndexFor = (i: number) => (i === focusIdx ? 0 : -1)\n const onFocus = (i: number) => () => setFocusIdx(i)\n\n return (\n <div\n className=\"better-editor-tab__actions\"\n role=\"toolbar\"\n aria-label={t.blocks.actions.toolbar}\n onKeyDown={onKeyDown}\n >\n <button\n type=\"button\"\n ref={setRef(0)}\n tabIndex={tabIndexFor(0)}\n onFocus={onFocus(0)}\n className=\"better-editor-tab__action\"\n onClick={onMoveUp}\n disabled={!canMoveUp}\n title={t.blocks.actions.moveUp}\n aria-label={t.blocks.actions.moveUpLabel}\n >\n <ChevronUp />\n </button>\n <button\n type=\"button\"\n ref={setRef(1)}\n tabIndex={tabIndexFor(1)}\n onFocus={onFocus(1)}\n className=\"better-editor-tab__action\"\n onClick={onMoveDown}\n disabled={!canMoveDown}\n title={t.blocks.actions.moveDown}\n aria-label={t.blocks.actions.moveDownLabel}\n >\n <ChevronDown />\n </button>\n <button\n type=\"button\"\n ref={setRef(2)}\n tabIndex={tabIndexFor(2)}\n onFocus={onFocus(2)}\n className=\"better-editor-tab__action\"\n onClick={onDuplicate}\n title={t.blocks.actions.duplicate}\n aria-label={t.blocks.actions.duplicateLabel}\n >\n <CopyIcon />\n </button>\n <button\n type=\"button\"\n ref={setRef(3)}\n tabIndex={tabIndexFor(3)}\n onFocus={onFocus(3)}\n className=\"better-editor-tab__action\"\n onClick={onAddBelow}\n disabled={!canAddBelow}\n title={t.blocks.actions.addBelow}\n aria-label={t.blocks.actions.addBelowLabel}\n >\n <PlusIcon />\n </button>\n <button\n type=\"button\"\n ref={setRef(4)}\n tabIndex={tabIndexFor(4)}\n onFocus={onFocus(4)}\n className=\"better-editor-tab__action better-editor-tab__action--danger\"\n onClick={onDelete}\n title={t.blocks.actions.delete}\n aria-label={t.blocks.actions.deleteLabel}\n >\n <TrashIcon />\n </button>\n </div>\n )\n}\n"],"names":["React","useCallback","useRef","useState","ChevronDown","ChevronUp","CopyIcon","PlusIcon","TrashIcon","useBetterEditorT","BlockActionsToolbar","canMoveUp","canMoveDown","canMutate","canAddBelow","onMoveUp","onMoveDown","onDuplicate","onAddBelow","onDelete","focusIdx","setFocusIdx","btnsRef","onKeyDown","e","key","preventDefault","buttons","current","filter","b","length","findIndex","document","activeElement","start","next","focus","idx","indexOf","t","setRef","i","el","tabIndexFor","onFocus","div","className","role","aria-label","blocks","actions","toolbar","button","type","ref","tabIndex","onClick","disabled","title","moveUp","moveUpLabel","moveDown","moveDownLabel","duplicate","duplicateLabel","addBelow","addBelowLabel","delete","deleteLabel"],"mappings":"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"}
@@ -2,12 +2,15 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import React from 'react';
4
4
  import { PlusIcon } from '../icons';
5
- export const BlockEmptyState = ({ canAdd, onAddClick })=>/*#__PURE__*/ _jsxs("div", {
5
+ import { useBetterEditorT } from '../../i18n/useBetterEditorT';
6
+ export const BlockEmptyState = ({ canAdd, onAddClick })=>{
7
+ const t = useBetterEditorT();
8
+ return /*#__PURE__*/ _jsxs("div", {
6
9
  className: "better-editor-tab better-editor-tab--empty",
7
10
  children: [
8
11
  /*#__PURE__*/ _jsx("p", {
9
12
  className: "better-editor-tab__empty-text",
10
- children: "Select a block in the preview to edit its settings."
13
+ children: t.blocks.emptyPrompt
11
14
  }),
12
15
  canAdd ? /*#__PURE__*/ _jsxs("button", {
13
16
  type: "button",
@@ -16,11 +19,12 @@ export const BlockEmptyState = ({ canAdd, onAddClick })=>/*#__PURE__*/ _jsxs("di
16
19
  children: [
17
20
  /*#__PURE__*/ _jsx(PlusIcon, {}),
18
21
  /*#__PURE__*/ _jsx("span", {
19
- children: "Add Block"
22
+ children: t.blocks.addBlock
20
23
  })
21
24
  ]
22
25
  }) : null
23
26
  ]
24
27
  });
28
+ };
25
29
 
26
30
  //# sourceMappingURL=BlockEmptyState.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/admin/blocks/BlockEmptyState.tsx"],"sourcesContent":["'use client'\n\nimport React from 'react'\nimport { PlusIcon } from '../icons'\n\nexport type BlockEmptyStateProps = {\n canAdd: boolean\n onAddClick: () => void\n}\n\nexport const BlockEmptyState: React.FC<BlockEmptyStateProps> = ({ canAdd, onAddClick }) => (\n <div className=\"better-editor-tab better-editor-tab--empty\">\n <p className=\"better-editor-tab__empty-text\">\n Select a block in the preview to edit its settings.\n </p>\n {canAdd ? (\n <button\n type=\"button\"\n className=\"better-editor-tab__add-block\"\n onClick={onAddClick}\n >\n <PlusIcon />\n <span>Add Block</span>\n </button>\n ) : null}\n </div>\n)\n"],"names":["React","PlusIcon","BlockEmptyState","canAdd","onAddClick","div","className","p","button","type","onClick","span"],"mappings":"AAAA;;AAEA,OAAOA,WAAW,QAAO;AACzB,SAASC,QAAQ,QAAQ,WAAU;AAOnC,OAAO,MAAMC,kBAAkD,CAAC,EAAEC,MAAM,EAAEC,UAAU,EAAE,iBACpF,MAACC;QAAIC,WAAU;;0BACb,KAACC;gBAAED,WAAU;0BAAgC;;YAG5CH,uBACC,MAACK;gBACCC,MAAK;gBACLH,WAAU;gBACVI,SAASN;;kCAET,KAACH;kCACD,KAACU;kCAAK;;;iBAEN;;OAEP"}
1
+ {"version":3,"sources":["../../../src/admin/blocks/BlockEmptyState.tsx"],"sourcesContent":["'use client'\n\nimport React from 'react'\nimport { PlusIcon } from '../icons'\nimport { useBetterEditorT } from '../../i18n/useBetterEditorT'\n\nexport type BlockEmptyStateProps = {\n canAdd: boolean\n onAddClick: () => void\n}\n\nexport const BlockEmptyState: React.FC<BlockEmptyStateProps> = ({ canAdd, onAddClick }) => {\n const t = useBetterEditorT()\n return (\n <div className=\"better-editor-tab better-editor-tab--empty\">\n <p className=\"better-editor-tab__empty-text\">{t.blocks.emptyPrompt}</p>\n {canAdd ? (\n <button type=\"button\" className=\"better-editor-tab__add-block\" onClick={onAddClick}>\n <PlusIcon />\n <span>{t.blocks.addBlock}</span>\n </button>\n ) : null}\n </div>\n )\n}\n"],"names":["React","PlusIcon","useBetterEditorT","BlockEmptyState","canAdd","onAddClick","t","div","className","p","blocks","emptyPrompt","button","type","onClick","span","addBlock"],"mappings":"AAAA;;AAEA,OAAOA,WAAW,QAAO;AACzB,SAASC,QAAQ,QAAQ,WAAU;AACnC,SAASC,gBAAgB,QAAQ,8BAA6B;AAO9D,OAAO,MAAMC,kBAAkD,CAAC,EAAEC,MAAM,EAAEC,UAAU,EAAE;IACpF,MAAMC,IAAIJ;IACV,qBACE,MAACK;QAAIC,WAAU;;0BACb,KAACC;gBAAED,WAAU;0BAAiCF,EAAEI,MAAM,CAACC,WAAW;;YACjEP,uBACC,MAACQ;gBAAOC,MAAK;gBAASL,WAAU;gBAA+BM,SAAST;;kCACtE,KAACJ;kCACD,KAACc;kCAAMT,EAAEI,MAAM,CAACM,QAAQ;;;iBAExB;;;AAGV,EAAC"}
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  export type BlockHeaderProps = {
3
3
  blockType: string;
4
+ blockLabel?: string;
4
5
  path: string;
5
6
  onClearSelection: () => void;
6
7
  };
@@ -1,22 +1,22 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import React from 'react';
4
- export const BlockHeader = ({ blockType, path, onClearSelection })=>/*#__PURE__*/ _jsxs("div", {
4
+ import { useBetterEditorT } from '../../i18n/useBetterEditorT';
5
+ export const BlockHeader = ({ blockType, blockLabel, path, onClearSelection })=>{
6
+ const t = useBetterEditorT();
7
+ return /*#__PURE__*/ _jsxs("div", {
5
8
  className: "better-editor-tab__header",
6
9
  children: [
7
10
  /*#__PURE__*/ _jsxs("div", {
8
11
  children: [
9
12
  /*#__PURE__*/ _jsx("span", {
10
13
  className: "better-editor-tab__kicker",
11
- children: "Block"
14
+ children: t.blocks.kicker
12
15
  }),
13
16
  /*#__PURE__*/ _jsx("h3", {
14
17
  className: "better-editor-tab__heading",
15
- children: blockType
16
- }),
17
- /*#__PURE__*/ _jsx("code", {
18
- className: "better-editor-tab__path",
19
- children: path
18
+ title: blockLabel ? `${blockType} | ${path}` : path,
19
+ children: blockLabel || blockType
20
20
  })
21
21
  ]
22
22
  }),
@@ -24,9 +24,10 @@ export const BlockHeader = ({ blockType, path, onClearSelection })=>/*#__PURE__*
24
24
  type: "button",
25
25
  className: "better-editor-tab__clear",
26
26
  onClick: onClearSelection,
27
- children: "Deselect"
27
+ children: t.blocks.deselect
28
28
  })
29
29
  ]
30
30
  });
31
+ };
31
32
 
32
33
  //# sourceMappingURL=BlockHeader.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/admin/blocks/BlockHeader.tsx"],"sourcesContent":["'use client'\n\nimport React from 'react'\n\nexport type BlockHeaderProps = {\n blockType: string\n path: string\n onClearSelection: () => void\n}\n\nexport const BlockHeader: React.FC<BlockHeaderProps> = ({\n blockType,\n path,\n onClearSelection,\n}) => (\n <div className=\"better-editor-tab__header\">\n <div>\n <span className=\"better-editor-tab__kicker\">Block</span>\n <h3 className=\"better-editor-tab__heading\">{blockType}</h3>\n <code className=\"better-editor-tab__path\">{path}</code>\n </div>\n <button\n type=\"button\"\n className=\"better-editor-tab__clear\"\n onClick={onClearSelection}\n >\n Deselect\n </button>\n </div>\n)\n"],"names":["React","BlockHeader","blockType","path","onClearSelection","div","className","span","h3","code","button","type","onClick"],"mappings":"AAAA;;AAEA,OAAOA,WAAW,QAAO;AAQzB,OAAO,MAAMC,cAA0C,CAAC,EACtDC,SAAS,EACTC,IAAI,EACJC,gBAAgB,EACjB,iBACC,MAACC;QAAIC,WAAU;;0BACb,MAACD;;kCACC,KAACE;wBAAKD,WAAU;kCAA4B;;kCAC5C,KAACE;wBAAGF,WAAU;kCAA8BJ;;kCAC5C,KAACO;wBAAKH,WAAU;kCAA2BH;;;;0BAE7C,KAACO;gBACCC,MAAK;gBACLL,WAAU;gBACVM,SAASR;0BACV;;;OAIJ"}
1
+ {"version":3,"sources":["../../../src/admin/blocks/BlockHeader.tsx"],"sourcesContent":["'use client'\n\nimport React from 'react'\nimport { useBetterEditorT } from '../../i18n/useBetterEditorT'\n\nexport type BlockHeaderProps = {\n blockType: string\n blockLabel?: string\n path: string\n onClearSelection: () => void\n}\n\nexport const BlockHeader: React.FC<BlockHeaderProps> = ({\n blockType,\n blockLabel,\n path,\n onClearSelection,\n}) => {\n const t = useBetterEditorT()\n return (\n <div className=\"better-editor-tab__header\">\n <div>\n <span className=\"better-editor-tab__kicker\">{t.blocks.kicker}</span>\n <h3\n className=\"better-editor-tab__heading\"\n title={blockLabel ? `${blockType} | ${path}` : path}\n >\n {blockLabel || blockType}\n </h3>\n </div>\n <button\n type=\"button\"\n className=\"better-editor-tab__clear\"\n onClick={onClearSelection}\n >\n {t.blocks.deselect}\n </button>\n </div>\n )\n}\n"],"names":["React","useBetterEditorT","BlockHeader","blockType","blockLabel","path","onClearSelection","t","div","className","span","blocks","kicker","h3","title","button","type","onClick","deselect"],"mappings":"AAAA;;AAEA,OAAOA,WAAW,QAAO;AACzB,SAASC,gBAAgB,QAAQ,8BAA6B;AAS9D,OAAO,MAAMC,cAA0C,CAAC,EACtDC,SAAS,EACTC,UAAU,EACVC,IAAI,EACJC,gBAAgB,EACjB;IACC,MAAMC,IAAIN;IACV,qBACE,MAACO;QAAIC,WAAU;;0BACb,MAACD;;kCACC,KAACE;wBAAKD,WAAU;kCAA6BF,EAAEI,MAAM,CAACC,MAAM;;kCAC5D,KAACC;wBACCJ,WAAU;wBACVK,OAAOV,aAAa,GAAGD,UAAU,GAAG,EAAEE,MAAM,GAAGA;kCAE9CD,cAAcD;;;;0BAGnB,KAACY;gBACCC,MAAK;gBACLP,WAAU;gBACVQ,SAASX;0BAERC,EAAEI,MAAM,CAACO,QAAQ;;;;AAI1B,EAAC"}
@@ -21,8 +21,23 @@ export const findNamedField = (fields, name, schemaPath)=>{
21
21
  }
22
22
  if (field.type === 'tabs') {
23
23
  for (const tab of field.tabs){
24
- const tabSchemaPath = tabHasName(tab) ? `${schemaPath}.${tab.name}` : schemaPath;
25
- const found = findNamedField(tab.fields, name, tabSchemaPath);
24
+ if (tabHasName(tab)) {
25
+ // Named tabs own a path segment like groups do — surface as group
26
+ // so the resolver handles them without an extra field type.
27
+ if (tab.name === name) {
28
+ return {
29
+ field: {
30
+ type: 'group',
31
+ name: tab.name,
32
+ fields: tab.fields
33
+ },
34
+ schemaPath: `${schemaPath}.${tab.name}`
35
+ };
36
+ }
37
+ continue;
38
+ }
39
+ // Unnamed (presentational) tabs are "transparent".
40
+ const found = findNamedField(tab.fields, name, schemaPath);
26
41
  if (found) return found;
27
42
  }
28
43
  } else if (field.type === 'collapsible' || field.type === 'row') {
@@ -44,18 +59,25 @@ export const resolveBlockSchema = (context, blockPath)=>{
44
59
  let blockConfig = null;
45
60
  let blocksFieldSchemaPath = '';
46
61
  let blocksFieldBlocks = [];
47
- for(let i = 0; i < segments.length; i += 2){
62
+ // Walk the path segment by segment. `blocks`/`array` consume a following
63
+ // array index; named tabs/groups consume only their own segment (data
64
+ // nesting without an index), so a fixed field/index pairing cannot be
65
+ // assumed.
66
+ let i = 0;
67
+ while(i < segments.length){
48
68
  const fieldName = segments[i];
49
- const indexStr = segments[i + 1];
50
- if (indexStr === undefined) break;
51
- const index = Number(indexStr);
52
- if (!Number.isInteger(index) || index < 0) return null;
53
69
  const found = findNamedField(currentFields, fieldName, currentSchemaPath);
54
70
  if (!found) return null;
55
71
  const field = found.field;
56
72
  currentSchemaPath = found.schemaPath;
57
73
  currentPath = currentPath ? `${currentPath}.${fieldName}` : fieldName;
74
+ i += 1;
58
75
  if (field.type === 'blocks') {
76
+ const indexStr = segments[i];
77
+ if (indexStr === undefined) return null;
78
+ const index = Number(indexStr);
79
+ if (!Number.isInteger(index) || index < 0) return null;
80
+ i += 1;
59
81
  const rows = formFields[currentPath]?.rows;
60
82
  if (!Array.isArray(rows) || index >= rows.length) return null;
61
83
  const row = rows[index];
@@ -71,8 +93,17 @@ export const resolveBlockSchema = (context, blockPath)=>{
71
93
  currentSchemaPath = `${currentSchemaPath}.${blockType}`;
72
94
  currentPath = `${currentPath}.${index}`;
73
95
  } else if (field.type === 'array') {
96
+ const indexStr = segments[i];
97
+ if (indexStr === undefined) return null;
98
+ const index = Number(indexStr);
99
+ if (!Number.isInteger(index) || index < 0) return null;
100
+ i += 1;
74
101
  currentFields = field.fields;
75
102
  currentPath = `${currentPath}.${index}`;
103
+ } else if (field.type === 'group') {
104
+ // Named groups (and named tabs surfaced as groups) nest data under
105
+ // their own segment with no array index — just descend.
106
+ currentFields = field.fields;
76
107
  } else {
77
108
  return null;
78
109
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/admin/blocks/schema.ts"],"sourcesContent":["import type { ClientTab } from 'payload'\nimport type { ClientBlock, ClientField, FormState } from 'payload'\n\nexport type Resolved = {\n blockType: string\n blockFields: ClientField[]\n schemaPath: string\n parentPath: string\n blocksFieldSchemaPath: string\n blocksFieldBlocks: ClientBlock[]\n}\n\nexport type BlockSchemaContext = {\n docFields: ClientField[]\n docSlug: string\n formFields: FormState\n /** Client config block registry, used to resolve `blockReferences` slugs. */\n blocksMap?: Record<string, ClientBlock>\n}\n\ntype BlocksLikeField = {\n blocks?: ClientBlock[]\n blockReferences?: (ClientBlock | string)[]\n}\n\n// Resolves a blocks field's block configs, handling `blockReferences` (slugs\n// looked up in the config block registry) where the field's own `blocks` is empty.\nexport const resolveFieldBlocks = (\n field: BlocksLikeField,\n blocksMap: Record<string, ClientBlock> | undefined,\n): ClientBlock[] => {\n if (!field.blockReferences) return field.blocks ?? []\n const out: ClientBlock[] = []\n for (const ref of field.blockReferences) {\n const block = typeof ref === 'string' ? blocksMap?.[ref] : ref\n if (block) out.push(block)\n }\n return out\n}\n\nconst tabHasName = (tab: ClientTab): tab is ClientTab & { name: string } =>\n typeof (tab as { name?: unknown }).name === 'string'\n\nexport const findNamedField = (\n fields: ClientField[],\n name: string,\n schemaPath: string,\n): { field: ClientField; schemaPath: string } | null => {\n for (const field of fields) {\n if (!field || typeof field !== 'object') continue\n\n if ('name' in field && typeof field.name === 'string' && field.name === name) {\n return { field, schemaPath: `${schemaPath}.${name}` }\n }\n\n if (field.type === 'tabs') {\n for (const tab of field.tabs) {\n const tabSchemaPath = tabHasName(tab) ? `${schemaPath}.${tab.name}` : schemaPath\n const found = findNamedField(tab.fields, name, tabSchemaPath)\n if (found) return found\n }\n } else if (field.type === 'collapsible' || field.type === 'row') {\n const found = findNamedField(field.fields, name, schemaPath)\n if (found) return found\n }\n // Groups are not transparent: their inner fields are reached via the\n // group's own name as the next path segment.\n }\n return null\n}\n\nexport const resolveBlockSchema = (\n context: BlockSchemaContext,\n blockPath: string,\n): Resolved | null => {\n const { docFields, docSlug, formFields, blocksMap } = context\n const segments = blockPath.split('.')\n let currentFields: ClientField[] = docFields\n let currentSchemaPath = docSlug\n let currentPath = ''\n let blockType: string | null = null\n let blockConfig: ClientBlock | null = null\n let blocksFieldSchemaPath = ''\n let blocksFieldBlocks: ClientBlock[] = []\n\n for (let i = 0; i < segments.length; i += 2) {\n const fieldName = segments[i]\n const indexStr = segments[i + 1]\n if (indexStr === undefined) break\n const index = Number(indexStr)\n if (!Number.isInteger(index) || index < 0) return null\n\n const found = findNamedField(currentFields, fieldName, currentSchemaPath)\n if (!found) return null\n const field = found.field\n currentSchemaPath = found.schemaPath\n currentPath = currentPath ? `${currentPath}.${fieldName}` : fieldName\n\n if (field.type === 'blocks') {\n const rows = formFields[currentPath]?.rows\n if (!Array.isArray(rows) || index >= rows.length) return null\n const row = rows[index] as { blockType?: string } | undefined\n if (!row?.blockType) return null\n blockType = row.blockType\n const blocks = resolveFieldBlocks(field, blocksMap)\n blockConfig = blocks.find((b) => b.slug === blockType) ?? null\n if (!blockConfig) return null\n // Capture parent before descending — used by \"add sibling block\".\n blocksFieldSchemaPath = currentSchemaPath\n blocksFieldBlocks = blocks\n currentFields = blockConfig.fields\n currentSchemaPath = `${currentSchemaPath}.${blockType}`\n currentPath = `${currentPath}.${index}`\n } else if (field.type === 'array') {\n currentFields = field.fields\n currentPath = `${currentPath}.${index}`\n } else {\n return null\n }\n }\n\n if (!blockType || !blockConfig) return null\n\n return {\n blockType,\n blockFields: currentFields,\n schemaPath: currentSchemaPath,\n parentPath: currentPath,\n blocksFieldSchemaPath,\n blocksFieldBlocks,\n }\n}\n"],"names":["resolveFieldBlocks","field","blocksMap","blockReferences","blocks","out","ref","block","push","tabHasName","tab","name","findNamedField","fields","schemaPath","type","tabs","tabSchemaPath","found","resolveBlockSchema","context","blockPath","docFields","docSlug","formFields","segments","split","currentFields","currentSchemaPath","currentPath","blockType","blockConfig","blocksFieldSchemaPath","blocksFieldBlocks","i","length","fieldName","indexStr","undefined","index","Number","isInteger","rows","Array","isArray","row","find","b","slug","blockFields","parentPath"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/admin/blocks/schema.ts"],"sourcesContent":["import type { ClientTab } from 'payload'\nimport type { ClientBlock, ClientField, FormState } from 'payload'\n\nexport type Resolved = {\n blockType: string\n blockFields: ClientField[]\n schemaPath: string\n parentPath: string\n blocksFieldSchemaPath: string\n blocksFieldBlocks: ClientBlock[]\n}\n\nexport type BlockSchemaContext = {\n docFields: ClientField[]\n docSlug: string\n formFields: FormState\n /** Client config block registry, used to resolve `blockReferences` slugs. */\n blocksMap?: Record<string, ClientBlock>\n}\n\ntype BlocksLikeField = {\n blocks?: ClientBlock[]\n blockReferences?: (ClientBlock | string)[]\n}\n\n// Resolves a blocks field's block configs, handling `blockReferences` (slugs\n// looked up in the config block registry) where the field's own `blocks` is empty.\nexport const resolveFieldBlocks = (\n field: BlocksLikeField,\n blocksMap: Record<string, ClientBlock> | undefined,\n): ClientBlock[] => {\n if (!field.blockReferences) return field.blocks ?? []\n const out: ClientBlock[] = []\n for (const ref of field.blockReferences) {\n const block = typeof ref === 'string' ? blocksMap?.[ref] : ref\n if (block) out.push(block)\n }\n return out\n}\n\nconst tabHasName = (tab: ClientTab): tab is ClientTab & { name: string } =>\n typeof (tab as { name?: unknown }).name === 'string'\n\nexport const findNamedField = (\n fields: ClientField[],\n name: string,\n schemaPath: string,\n): { field: ClientField; schemaPath: string } | null => {\n for (const field of fields) {\n if (!field || typeof field !== 'object') continue\n\n if ('name' in field && typeof field.name === 'string' && field.name === name) {\n return { field, schemaPath: `${schemaPath}.${name}` }\n }\n\n if (field.type === 'tabs') {\n for (const tab of field.tabs) {\n if (tabHasName(tab)) {\n // Named tabs own a path segment like groups do — surface as group\n // so the resolver handles them without an extra field type.\n if (tab.name === name) {\n return {\n field: { type: 'group', name: tab.name, fields: tab.fields } as ClientField,\n schemaPath: `${schemaPath}.${tab.name}`,\n }\n }\n continue\n }\n\n // Unnamed (presentational) tabs are \"transparent\".\n const found = findNamedField(tab.fields, name, schemaPath)\n if (found) return found\n }\n } else if (field.type === 'collapsible' || field.type === 'row') {\n const found = findNamedField(field.fields, name, schemaPath)\n if (found) return found\n }\n // Groups are not transparent: their inner fields are reached via the\n // group's own name as the next path segment.\n }\n return null\n}\n\nexport const resolveBlockSchema = (\n context: BlockSchemaContext,\n blockPath: string,\n): Resolved | null => {\n const { docFields, docSlug, formFields, blocksMap } = context\n const segments = blockPath.split('.')\n let currentFields: ClientField[] = docFields\n let currentSchemaPath = docSlug\n let currentPath = ''\n let blockType: string | null = null\n let blockConfig: ClientBlock | null = null\n let blocksFieldSchemaPath = ''\n let blocksFieldBlocks: ClientBlock[] = []\n\n // Walk the path segment by segment. `blocks`/`array` consume a following\n // array index; named tabs/groups consume only their own segment (data\n // nesting without an index), so a fixed field/index pairing cannot be\n // assumed.\n let i = 0\n while (i < segments.length) {\n const fieldName = segments[i]\n const found = findNamedField(currentFields, fieldName, currentSchemaPath)\n if (!found) return null\n const field = found.field\n currentSchemaPath = found.schemaPath\n currentPath = currentPath ? `${currentPath}.${fieldName}` : fieldName\n i += 1\n\n if (field.type === 'blocks') {\n const indexStr = segments[i]\n if (indexStr === undefined) return null\n const index = Number(indexStr)\n if (!Number.isInteger(index) || index < 0) return null\n i += 1\n const rows = formFields[currentPath]?.rows\n if (!Array.isArray(rows) || index >= rows.length) return null\n const row = rows[index] as { blockType?: string } | undefined\n if (!row?.blockType) return null\n blockType = row.blockType\n const blocks = resolveFieldBlocks(field, blocksMap)\n blockConfig = blocks.find((b) => b.slug === blockType) ?? null\n if (!blockConfig) return null\n // Capture parent before descending — used by \"add sibling block\".\n blocksFieldSchemaPath = currentSchemaPath\n blocksFieldBlocks = blocks\n currentFields = blockConfig.fields\n currentSchemaPath = `${currentSchemaPath}.${blockType}`\n currentPath = `${currentPath}.${index}`\n } else if (field.type === 'array') {\n const indexStr = segments[i]\n if (indexStr === undefined) return null\n const index = Number(indexStr)\n if (!Number.isInteger(index) || index < 0) return null\n i += 1\n currentFields = field.fields\n currentPath = `${currentPath}.${index}`\n } else if (field.type === 'group') {\n // Named groups (and named tabs surfaced as groups) nest data under\n // their own segment with no array index — just descend.\n currentFields = field.fields\n } else {\n return null\n }\n }\n\n if (!blockType || !blockConfig) return null\n\n return {\n blockType,\n blockFields: currentFields,\n schemaPath: currentSchemaPath,\n parentPath: currentPath,\n blocksFieldSchemaPath,\n blocksFieldBlocks,\n }\n}\n"],"names":["resolveFieldBlocks","field","blocksMap","blockReferences","blocks","out","ref","block","push","tabHasName","tab","name","findNamedField","fields","schemaPath","type","tabs","found","resolveBlockSchema","context","blockPath","docFields","docSlug","formFields","segments","split","currentFields","currentSchemaPath","currentPath","blockType","blockConfig","blocksFieldSchemaPath","blocksFieldBlocks","i","length","fieldName","indexStr","undefined","index","Number","isInteger","rows","Array","isArray","row","find","b","slug","blockFields","parentPath"],"mappings":"AAyBA,6EAA6E;AAC7E,mFAAmF;AACnF,OAAO,MAAMA,qBAAqB,CAChCC,OACAC;IAEA,IAAI,CAACD,MAAME,eAAe,EAAE,OAAOF,MAAMG,MAAM,IAAI,EAAE;IACrD,MAAMC,MAAqB,EAAE;IAC7B,KAAK,MAAMC,OAAOL,MAAME,eAAe,CAAE;QACvC,MAAMI,QAAQ,OAAOD,QAAQ,WAAWJ,WAAW,CAACI,IAAI,GAAGA;QAC3D,IAAIC,OAAOF,IAAIG,IAAI,CAACD;IACtB;IACA,OAAOF;AACT,EAAC;AAED,MAAMI,aAAa,CAACC,MAClB,OAAO,AAACA,IAA2BC,IAAI,KAAK;AAE9C,OAAO,MAAMC,iBAAiB,CAC5BC,QACAF,MACAG;IAEA,KAAK,MAAMb,SAASY,OAAQ;QAC1B,IAAI,CAACZ,SAAS,OAAOA,UAAU,UAAU;QAEzC,IAAI,UAAUA,SAAS,OAAOA,MAAMU,IAAI,KAAK,YAAYV,MAAMU,IAAI,KAAKA,MAAM;YAC5E,OAAO;gBAAEV;gBAAOa,YAAY,GAAGA,WAAW,CAAC,EAAEH,MAAM;YAAC;QACtD;QAEA,IAAIV,MAAMc,IAAI,KAAK,QAAQ;YACzB,KAAK,MAAML,OAAOT,MAAMe,IAAI,CAAE;gBAC5B,IAAIP,WAAWC,MAAM;oBACnB,kEAAkE;oBAClE,4DAA4D;oBAC5D,IAAIA,IAAIC,IAAI,KAAKA,MAAM;wBACrB,OAAO;4BACLV,OAAO;gCAAEc,MAAM;gCAASJ,MAAMD,IAAIC,IAAI;gCAAEE,QAAQH,IAAIG,MAAM;4BAAC;4BAC3DC,YAAY,GAAGA,WAAW,CAAC,EAAEJ,IAAIC,IAAI,EAAE;wBACzC;oBACF;oBACA;gBACF;gBAEA,mDAAmD;gBACnD,MAAMM,QAAQL,eAAeF,IAAIG,MAAM,EAAEF,MAAMG;gBAC/C,IAAIG,OAAO,OAAOA;YACpB;QACF,OAAO,IAAIhB,MAAMc,IAAI,KAAK,iBAAiBd,MAAMc,IAAI,KAAK,OAAO;YAC/D,MAAME,QAAQL,eAAeX,MAAMY,MAAM,EAAEF,MAAMG;YACjD,IAAIG,OAAO,OAAOA;QACpB;IACA,qEAAqE;IACrE,6CAA6C;IAC/C;IACA,OAAO;AACT,EAAC;AAED,OAAO,MAAMC,qBAAqB,CAChCC,SACAC;IAEA,MAAM,EAAEC,SAAS,EAAEC,OAAO,EAAEC,UAAU,EAAErB,SAAS,EAAE,GAAGiB;IACtD,MAAMK,WAAWJ,UAAUK,KAAK,CAAC;IACjC,IAAIC,gBAA+BL;IACnC,IAAIM,oBAAoBL;IACxB,IAAIM,cAAc;IAClB,IAAIC,YAA2B;IAC/B,IAAIC,cAAkC;IACtC,IAAIC,wBAAwB;IAC5B,IAAIC,oBAAmC,EAAE;IAEzC,yEAAyE;IACzE,sEAAsE;IACtE,sEAAsE;IACtE,WAAW;IACX,IAAIC,IAAI;IACR,MAAOA,IAAIT,SAASU,MAAM,CAAE;QAC1B,MAAMC,YAAYX,QAAQ,CAACS,EAAE;QAC7B,MAAMhB,QAAQL,eAAec,eAAeS,WAAWR;QACvD,IAAI,CAACV,OAAO,OAAO;QACnB,MAAMhB,QAAQgB,MAAMhB,KAAK;QACzB0B,oBAAoBV,MAAMH,UAAU;QACpCc,cAAcA,cAAc,GAAGA,YAAY,CAAC,EAAEO,WAAW,GAAGA;QAC5DF,KAAK;QAEL,IAAIhC,MAAMc,IAAI,KAAK,UAAU;YAC3B,MAAMqB,WAAWZ,QAAQ,CAACS,EAAE;YAC5B,IAAIG,aAAaC,WAAW,OAAO;YACnC,MAAMC,QAAQC,OAAOH;YACrB,IAAI,CAACG,OAAOC,SAAS,CAACF,UAAUA,QAAQ,GAAG,OAAO;YAClDL,KAAK;YACL,MAAMQ,OAAOlB,UAAU,CAACK,YAAY,EAAEa;YACtC,IAAI,CAACC,MAAMC,OAAO,CAACF,SAASH,SAASG,KAAKP,MAAM,EAAE,OAAO;YACzD,MAAMU,MAAMH,IAAI,CAACH,MAAM;YACvB,IAAI,CAACM,KAAKf,WAAW,OAAO;YAC5BA,YAAYe,IAAIf,SAAS;YACzB,MAAMzB,SAASJ,mBAAmBC,OAAOC;YACzC4B,cAAc1B,OAAOyC,IAAI,CAAC,CAACC,IAAMA,EAAEC,IAAI,KAAKlB,cAAc;YAC1D,IAAI,CAACC,aAAa,OAAO;YACzB,kEAAkE;YAClEC,wBAAwBJ;YACxBK,oBAAoB5B;YACpBsB,gBAAgBI,YAAYjB,MAAM;YAClCc,oBAAoB,GAAGA,kBAAkB,CAAC,EAAEE,WAAW;YACvDD,cAAc,GAAGA,YAAY,CAAC,EAAEU,OAAO;QACzC,OAAO,IAAIrC,MAAMc,IAAI,KAAK,SAAS;YACjC,MAAMqB,WAAWZ,QAAQ,CAACS,EAAE;YAC5B,IAAIG,aAAaC,WAAW,OAAO;YACnC,MAAMC,QAAQC,OAAOH;YACrB,IAAI,CAACG,OAAOC,SAAS,CAACF,UAAUA,QAAQ,GAAG,OAAO;YAClDL,KAAK;YACLP,gBAAgBzB,MAAMY,MAAM;YAC5Be,cAAc,GAAGA,YAAY,CAAC,EAAEU,OAAO;QACzC,OAAO,IAAIrC,MAAMc,IAAI,KAAK,SAAS;YACjC,mEAAmE;YACnE,wDAAwD;YACxDW,gBAAgBzB,MAAMY,MAAM;QAC9B,OAAO;YACL,OAAO;QACT;IACF;IAEA,IAAI,CAACgB,aAAa,CAACC,aAAa,OAAO;IAEvC,OAAO;QACLD;QACAmB,aAAatB;QACbZ,YAAYa;QACZsB,YAAYrB;QACZG;QACAC;IACF;AACF,EAAC"}
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import React, { useMemo } from 'react';
4
- import { RenderFields, useAllFormFields, useConfig, useDrawerSlug, useField, useModal } from '@payloadcms/ui';
4
+ import { RenderFields, useAllFormFields, useConfig, useDrawerSlug, useField, useModal, useTranslation } from '@payloadcms/ui';
5
5
  import { useDocConfig } from '../../hooks/useDocConfig';
6
6
  import { useAddBlockDrawer } from '../../hooks/useAddBlockDrawer';
7
7
  import { AddBlockDrawer } from '../blocks/AddBlockDrawer';
@@ -10,7 +10,10 @@ import { useBlockActions } from '../blocks/useBlockActions';
10
10
  import { findNamedField, resolveBlockSchema, resolveFieldBlocks } from '../blocks/schema';
11
11
  import { BlockEmptyState } from '../blocks/BlockEmptyState';
12
12
  import { BlockHeader } from '../blocks/BlockHeader';
13
+ import { useBetterEditorT } from '../../i18n/useBetterEditorT';
13
14
  export const BlockSettingsTab = ({ selectedBlockPath, onClearSelection, onSelectPath, blocksField, addBelowRequestId = 0 })=>{
15
+ const t = useBetterEditorT();
16
+ const { i18n } = useTranslation();
14
17
  const { fields: docFields, slug: docSlug } = useDocConfig();
15
18
  const [fields] = useAllFormFields();
16
19
  const { config } = useConfig();
@@ -68,11 +71,22 @@ export const BlockSettingsTab = ({ selectedBlockPath, onClearSelection, onSelect
68
71
  formFields: fields,
69
72
  blocksMap
70
73
  }, selectedBlockPath) : null;
74
+ const blockLabel = (()=>{
75
+ if (!resolved) return undefined;
76
+ const cfg = resolved.blocksFieldBlocks.find((b)=>b.slug === resolved.blockType);
77
+ const singular = cfg?.labels?.singular;
78
+ if (typeof singular === 'string') return singular;
79
+ if (singular && typeof singular === 'object') {
80
+ return singular[i18n.language] ?? Object.values(singular)[0];
81
+ }
82
+ return undefined;
83
+ })();
71
84
  return /*#__PURE__*/ _jsxs("div", {
72
85
  className: "better-editor-tab better-editor-tab--native",
73
86
  children: [
74
87
  /*#__PURE__*/ _jsx(BlockHeader, {
75
88
  blockType: resolved?.blockType || 'unknown',
89
+ blockLabel: blockLabel,
76
90
  path: selectedBlockPath,
77
91
  onClearSelection: onClearSelection
78
92
  }),
@@ -104,7 +118,7 @@ export const BlockSettingsTab = ({ selectedBlockPath, onClearSelection, onSelect
104
118
  }) : null,
105
119
  !resolved ? /*#__PURE__*/ _jsx("div", {
106
120
  className: "better-editor-tab__empty",
107
- children: "Could not resolve block schema for this path."
121
+ children: t.blocks.schemaError
108
122
  }) : /*#__PURE__*/ _jsxs(_Fragment, {
109
123
  children: [
110
124
  /*#__PURE__*/ _jsx(BlockNameInput, {
@@ -132,6 +146,7 @@ const BlockNameInput = ({ path })=>{
132
146
  const { value, setValue } = useField({
133
147
  path
134
148
  });
149
+ const t = useBetterEditorT();
135
150
  const inputId = `be-blockname-${path}`;
136
151
  return /*#__PURE__*/ _jsxs("div", {
137
152
  className: "better-editor-tab__block-name",
@@ -139,7 +154,7 @@ const BlockNameInput = ({ path })=>{
139
154
  /*#__PURE__*/ _jsx("label", {
140
155
  className: "better-editor-tab__block-name-label",
141
156
  htmlFor: inputId,
142
- children: "Block Name"
157
+ children: t.blocks.blockName
143
158
  }),
144
159
  /*#__PURE__*/ _jsx("input", {
145
160
  id: inputId,
@@ -147,7 +162,7 @@ const BlockNameInput = ({ path })=>{
147
162
  type: "text",
148
163
  value: value || '',
149
164
  onChange: (e)=>setValue(e.target.value),
150
- placeholder: "Optional label for this block"
165
+ placeholder: t.blocks.blockNamePlaceholder
151
166
  })
152
167
  ]
153
168
  });