@payloadcms/next 3.78.0-canary.6 → 3.78.0-internal.5219978

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 (47) hide show
  1. package/dist/prod/styles.css +1 -1
  2. package/dist/views/Dashboard/Default/ModularDashboard/WidgetConfigDrawer.d.ts +11 -0
  3. package/dist/views/Dashboard/Default/ModularDashboard/WidgetConfigDrawer.d.ts.map +1 -0
  4. package/dist/views/Dashboard/Default/ModularDashboard/WidgetConfigDrawer.js +128 -0
  5. package/dist/views/Dashboard/Default/ModularDashboard/WidgetConfigDrawer.js.map +1 -0
  6. package/dist/views/Dashboard/Default/ModularDashboard/WidgetEditControl.d.ts +8 -0
  7. package/dist/views/Dashboard/Default/ModularDashboard/WidgetEditControl.d.ts.map +1 -0
  8. package/dist/views/Dashboard/Default/ModularDashboard/WidgetEditControl.js +78 -0
  9. package/dist/views/Dashboard/Default/ModularDashboard/WidgetEditControl.js.map +1 -0
  10. package/dist/views/Dashboard/Default/ModularDashboard/index.client.d.ts +1 -0
  11. package/dist/views/Dashboard/Default/ModularDashboard/index.client.d.ts.map +1 -1
  12. package/dist/views/Dashboard/Default/ModularDashboard/index.client.js +30 -20
  13. package/dist/views/Dashboard/Default/ModularDashboard/index.client.js.map +1 -1
  14. package/dist/views/Dashboard/Default/ModularDashboard/index.d.ts.map +1 -1
  15. package/dist/views/Dashboard/Default/ModularDashboard/index.js +8 -30
  16. package/dist/views/Dashboard/Default/ModularDashboard/index.js.map +1 -1
  17. package/dist/views/Dashboard/Default/ModularDashboard/renderWidget/RenderWidget.d.ts +1 -0
  18. package/dist/views/Dashboard/Default/ModularDashboard/renderWidget/RenderWidget.d.ts.map +1 -1
  19. package/dist/views/Dashboard/Default/ModularDashboard/renderWidget/RenderWidget.js +30 -23
  20. package/dist/views/Dashboard/Default/ModularDashboard/renderWidget/RenderWidget.js.map +1 -1
  21. package/dist/views/Dashboard/Default/ModularDashboard/renderWidget/getDefaultLayoutServerFn.d.ts.map +1 -1
  22. package/dist/views/Dashboard/Default/ModularDashboard/renderWidget/getDefaultLayoutServerFn.js +2 -1
  23. package/dist/views/Dashboard/Default/ModularDashboard/renderWidget/getDefaultLayoutServerFn.js.map +1 -1
  24. package/dist/views/Dashboard/Default/ModularDashboard/renderWidget/renderWidgetServerFn.d.ts +1 -0
  25. package/dist/views/Dashboard/Default/ModularDashboard/renderWidget/renderWidgetServerFn.d.ts.map +1 -1
  26. package/dist/views/Dashboard/Default/ModularDashboard/renderWidget/renderWidgetServerFn.js +5 -3
  27. package/dist/views/Dashboard/Default/ModularDashboard/renderWidget/renderWidgetServerFn.js.map +1 -1
  28. package/dist/views/Dashboard/Default/ModularDashboard/useDashboardLayout.d.ts +1 -0
  29. package/dist/views/Dashboard/Default/ModularDashboard/useDashboardLayout.d.ts.map +1 -1
  30. package/dist/views/Dashboard/Default/ModularDashboard/useDashboardLayout.js +23 -3
  31. package/dist/views/Dashboard/Default/ModularDashboard/useDashboardLayout.js.map +1 -1
  32. package/dist/views/Dashboard/Default/ModularDashboard/utils/getItemsFromConfig.d.ts +4 -0
  33. package/dist/views/Dashboard/Default/ModularDashboard/utils/getItemsFromConfig.d.ts.map +1 -0
  34. package/dist/views/Dashboard/Default/ModularDashboard/utils/getItemsFromConfig.js +21 -0
  35. package/dist/views/Dashboard/Default/ModularDashboard/utils/getItemsFromConfig.js.map +1 -0
  36. package/dist/views/Dashboard/Default/ModularDashboard/utils/getItemsFromPreferences.d.ts +4 -0
  37. package/dist/views/Dashboard/Default/ModularDashboard/utils/getItemsFromPreferences.d.ts.map +1 -0
  38. package/dist/views/Dashboard/Default/ModularDashboard/utils/getItemsFromPreferences.js +10 -0
  39. package/dist/views/Dashboard/Default/ModularDashboard/utils/getItemsFromPreferences.js.map +1 -0
  40. package/dist/views/Dashboard/Default/ModularDashboard/utils/localeUtils.d.ts +23 -0
  41. package/dist/views/Dashboard/Default/ModularDashboard/utils/localeUtils.d.ts.map +1 -0
  42. package/dist/views/Dashboard/Default/ModularDashboard/utils/localeUtils.js +103 -0
  43. package/dist/views/Dashboard/Default/ModularDashboard/utils/localeUtils.js.map +1 -0
  44. package/dist/views/Version/Restore/index.d.ts.map +1 -1
  45. package/dist/views/Version/Restore/index.js +2 -3
  46. package/dist/views/Version/Restore/index.js.map +1 -1
  47. package/package.json +6 -6
@@ -0,0 +1,11 @@
1
+ import type { ClientWidget } from 'payload';
2
+ import React from 'react';
3
+ type WidgetConfigDrawerProps = {
4
+ drawerSlug: string;
5
+ onSave: (data: Record<string, unknown>) => void;
6
+ widget: ClientWidget;
7
+ widgetData?: Record<string, unknown>;
8
+ };
9
+ export declare function WidgetConfigDrawer({ drawerSlug, onSave, widget, widgetData, }: WidgetConfigDrawerProps): React.JSX.Element;
10
+ export {};
11
+ //# sourceMappingURL=WidgetConfigDrawer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WidgetConfigDrawer.d.ts","sourceRoot":"","sources":["../../../../../src/views/Dashboard/Default/ModularDashboard/WidgetConfigDrawer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAa,MAAM,SAAS,CAAA;AAetD,OAAO,KAA4D,MAAM,OAAO,CAAA;AAKhF,KAAK,uBAAuB,GAAG;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IAC/C,MAAM,EAAE,YAAY,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACrC,CAAA;AAMD,wBAAgB,kBAAkB,CAAC,EACjC,UAAU,EACV,MAAM,EACN,MAAM,EACN,UAAU,GACX,EAAE,uBAAuB,qBAwHzB"}
@@ -0,0 +1,128 @@
1
+ 'use client';
2
+
3
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
4
+ import { Drawer, Form, FormSubmit, OperationProvider, RenderFields, ShimmerEffect, useLocale, useModal, useServerFunctions, useTranslation } from '@payloadcms/ui';
5
+ import { abortAndIgnore } from '@payloadcms/ui/shared';
6
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
7
+ import { v4 as uuid } from 'uuid';
8
+ import { extractLocaleData, mergeLocaleData } from './utils/localeUtils.js';
9
+ const EMPTY_WIDGET_PREFERENCES = {
10
+ fields: {}
11
+ };
12
+ export function WidgetConfigDrawer({
13
+ drawerSlug,
14
+ onSave,
15
+ widget,
16
+ widgetData
17
+ }) {
18
+ const {
19
+ closeModal,
20
+ modalState
21
+ } = useModal();
22
+ const {
23
+ getFormState
24
+ } = useServerFunctions();
25
+ const {
26
+ t
27
+ } = useTranslation();
28
+ const locale = useLocale();
29
+ const localeCode = locale?.code ?? 'en';
30
+ const onChangeAbortControllerRef = useRef(null);
31
+ const [initialState, setInitialState] = useState(false);
32
+ const isOpen = Boolean(modalState?.[drawerSlug]?.isOpen);
33
+ const formUUID = useMemo(() => uuid(), []);
34
+ const widgetLabel = useMemo(() => typeof widget.label === 'string' ? widget.label : widget.slug, [widget.label, widget.slug]);
35
+ const fields = useMemo(() => widget.fields ?? [], [widget.fields]);
36
+ useEffect(() => {
37
+ if (!isOpen || fields.length === 0) {
38
+ setInitialState(false);
39
+ return;
40
+ }
41
+ const controller = new AbortController();
42
+ const loadInitialState = async () => {
43
+ const localeFilteredData = extractLocaleData(widgetData ?? {}, localeCode, fields);
44
+ const {
45
+ state
46
+ } = await getFormState({
47
+ data: localeFilteredData,
48
+ docPermissions: {
49
+ fields: true
50
+ },
51
+ docPreferences: EMPTY_WIDGET_PREFERENCES,
52
+ locale: localeCode,
53
+ operation: 'update',
54
+ renderAllFields: true,
55
+ schemaPath: widget.slug,
56
+ signal: controller.signal,
57
+ widgetSlug: widget.slug
58
+ });
59
+ if (state) {
60
+ setInitialState(state);
61
+ }
62
+ };
63
+ void loadInitialState();
64
+ return () => {
65
+ abortAndIgnore(controller);
66
+ };
67
+ }, [fields, getFormState, isOpen, localeCode, widget.slug, widgetData]);
68
+ const onChange = useCallback(async ({
69
+ formState: prevFormState
70
+ }) => {
71
+ abortAndIgnore(onChangeAbortControllerRef.current);
72
+ const controller_0 = new AbortController();
73
+ onChangeAbortControllerRef.current = controller_0;
74
+ const {
75
+ state: state_0
76
+ } = await getFormState({
77
+ docPermissions: {
78
+ fields: true
79
+ },
80
+ docPreferences: EMPTY_WIDGET_PREFERENCES,
81
+ formState: prevFormState,
82
+ operation: 'update',
83
+ schemaPath: widget.slug,
84
+ signal: controller_0.signal,
85
+ widgetSlug: widget.slug
86
+ });
87
+ if (!state_0) {
88
+ return prevFormState;
89
+ }
90
+ return state_0;
91
+ }, [getFormState, widget.slug]);
92
+ useEffect(() => {
93
+ return () => {
94
+ abortAndIgnore(onChangeAbortControllerRef.current);
95
+ };
96
+ }, []);
97
+ return /*#__PURE__*/_jsx(Drawer, {
98
+ slug: drawerSlug,
99
+ title: `${t('general:edit')} ${widgetLabel}`,
100
+ children: initialState === false ? /*#__PURE__*/_jsx(ShimmerEffect, {
101
+ height: "250px"
102
+ }) : /*#__PURE__*/_jsx(OperationProvider, {
103
+ operation: "update",
104
+ children: /*#__PURE__*/_jsxs(Form, {
105
+ fields: fields,
106
+ initialState: initialState,
107
+ onChange: [onChange],
108
+ onSubmit: (_, data) => {
109
+ onSave(mergeLocaleData(widgetData ?? {}, data, localeCode, fields));
110
+ closeModal(drawerSlug);
111
+ },
112
+ uuid: formUUID,
113
+ children: [/*#__PURE__*/_jsx(RenderFields, {
114
+ fields: fields,
115
+ forceRender: true,
116
+ parentIndexPath: "",
117
+ parentPath: "",
118
+ parentSchemaPath: widget.slug,
119
+ permissions: true,
120
+ readOnly: false
121
+ }), /*#__PURE__*/_jsx(FormSubmit, {
122
+ children: t('fields:saveChanges')
123
+ })]
124
+ })
125
+ })
126
+ });
127
+ }
128
+ //# sourceMappingURL=WidgetConfigDrawer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WidgetConfigDrawer.js","names":["Drawer","Form","FormSubmit","OperationProvider","RenderFields","ShimmerEffect","useLocale","useModal","useServerFunctions","useTranslation","abortAndIgnore","React","useCallback","useEffect","useMemo","useRef","useState","v4","uuid","extractLocaleData","mergeLocaleData","EMPTY_WIDGET_PREFERENCES","fields","WidgetConfigDrawer","drawerSlug","onSave","widget","widgetData","closeModal","modalState","getFormState","t","locale","localeCode","code","onChangeAbortControllerRef","initialState","setInitialState","isOpen","Boolean","formUUID","widgetLabel","label","slug","length","controller","AbortController","loadInitialState","localeFilteredData","state","data","docPermissions","docPreferences","operation","renderAllFields","schemaPath","signal","widgetSlug","onChange","formState","prevFormState","current","_jsx","title","height","_jsxs","onSubmit","_","forceRender","parentIndexPath","parentPath","parentSchemaPath","permissions","readOnly"],"sources":["../../../../../src/views/Dashboard/Default/ModularDashboard/WidgetConfigDrawer.tsx"],"sourcesContent":["'use client'\n\nimport type { ClientWidget, FormState } from 'payload'\n\nimport {\n Drawer,\n Form,\n FormSubmit,\n OperationProvider,\n RenderFields,\n ShimmerEffect,\n useLocale,\n useModal,\n useServerFunctions,\n useTranslation,\n} from '@payloadcms/ui'\nimport { abortAndIgnore } from '@payloadcms/ui/shared'\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { v4 as uuid } from 'uuid'\n\nimport { extractLocaleData, mergeLocaleData } from './utils/localeUtils.js'\n\ntype WidgetConfigDrawerProps = {\n drawerSlug: string\n onSave: (data: Record<string, unknown>) => void\n widget: ClientWidget\n widgetData?: Record<string, unknown>\n}\n\nconst EMPTY_WIDGET_PREFERENCES = {\n fields: {},\n}\n\nexport function WidgetConfigDrawer({\n drawerSlug,\n onSave,\n widget,\n widgetData,\n}: WidgetConfigDrawerProps) {\n const { closeModal, modalState } = useModal()\n const { getFormState } = useServerFunctions()\n const { t } = useTranslation()\n const locale = useLocale()\n const localeCode = locale?.code ?? 'en'\n const onChangeAbortControllerRef = useRef<AbortController>(null)\n\n const [initialState, setInitialState] = useState<false | FormState | undefined>(false)\n\n const isOpen = Boolean(modalState?.[drawerSlug]?.isOpen)\n const formUUID = useMemo(() => uuid(), [])\n const widgetLabel = useMemo(\n () => (typeof widget.label === 'string' ? widget.label : widget.slug),\n [widget.label, widget.slug],\n )\n const fields = useMemo(() => widget.fields ?? [], [widget.fields])\n\n useEffect(() => {\n if (!isOpen || fields.length === 0) {\n setInitialState(false)\n return\n }\n\n const controller = new AbortController()\n\n const loadInitialState = async () => {\n const localeFilteredData = extractLocaleData(widgetData ?? {}, localeCode, fields)\n\n const { state } = await getFormState({\n data: localeFilteredData,\n docPermissions: {\n fields: true,\n },\n docPreferences: EMPTY_WIDGET_PREFERENCES,\n locale: localeCode,\n operation: 'update',\n renderAllFields: true,\n schemaPath: widget.slug,\n signal: controller.signal,\n widgetSlug: widget.slug,\n })\n\n if (state) {\n setInitialState(state)\n }\n }\n\n void loadInitialState()\n\n return () => {\n abortAndIgnore(controller)\n }\n }, [fields, getFormState, isOpen, localeCode, widget.slug, widgetData])\n\n const onChange = useCallback(\n async ({ formState: prevFormState }: { formState: FormState }) => {\n abortAndIgnore(onChangeAbortControllerRef.current)\n\n const controller = new AbortController()\n onChangeAbortControllerRef.current = controller\n\n const { state } = await getFormState({\n docPermissions: {\n fields: true,\n },\n docPreferences: EMPTY_WIDGET_PREFERENCES,\n formState: prevFormState,\n operation: 'update',\n schemaPath: widget.slug,\n signal: controller.signal,\n widgetSlug: widget.slug,\n })\n\n if (!state) {\n return prevFormState\n }\n\n return state\n },\n [getFormState, widget.slug],\n )\n\n useEffect(() => {\n return () => {\n abortAndIgnore(onChangeAbortControllerRef.current)\n }\n }, [])\n\n return (\n <Drawer slug={drawerSlug} title={`${t('general:edit')} ${widgetLabel}`}>\n {initialState === false ? (\n <ShimmerEffect height=\"250px\" />\n ) : (\n <OperationProvider operation=\"update\">\n <Form\n fields={fields}\n initialState={initialState}\n onChange={[onChange]}\n onSubmit={(_, data) => {\n onSave(mergeLocaleData(widgetData ?? {}, data, localeCode, fields))\n closeModal(drawerSlug)\n }}\n uuid={formUUID}\n >\n <RenderFields\n fields={fields}\n forceRender\n parentIndexPath=\"\"\n parentPath=\"\"\n parentSchemaPath={widget.slug}\n permissions={true}\n readOnly={false}\n />\n <FormSubmit>{t('fields:saveChanges')}</FormSubmit>\n </Form>\n </OperationProvider>\n )}\n </Drawer>\n )\n}\n"],"mappings":"AAAA;;;AAIA,SACEA,MAAM,EACNC,IAAI,EACJC,UAAU,EACVC,iBAAiB,EACjBC,YAAY,EACZC,aAAa,EACbC,SAAS,EACTC,QAAQ,EACRC,kBAAkB,EAClBC,cAAc,QACT;AACP,SAASC,cAAc,QAAQ;AAC/B,OAAOC,KAAA,IAASC,WAAW,EAAEC,SAAS,EAAEC,OAAO,EAAEC,MAAM,EAAEC,QAAQ,QAAQ;AACzE,SAASC,EAAA,IAAMC,IAAI,QAAQ;AAE3B,SAASC,iBAAiB,EAAEC,eAAe,QAAQ;AASnD,MAAMC,wBAAA,GAA2B;EAC/BC,MAAA,EAAQ,CAAC;AACX;AAEA,OAAO,SAASC,mBAAmB;EACjCC,UAAU;EACVC,MAAM;EACNC,MAAM;EACNC;AAAU,CACc;EACxB,MAAM;IAAEC,UAAU;IAAEC;EAAU,CAAE,GAAGtB,QAAA;EACnC,MAAM;IAAEuB;EAAY,CAAE,GAAGtB,kBAAA;EACzB,MAAM;IAAEuB;EAAC,CAAE,GAAGtB,cAAA;EACd,MAAMuB,MAAA,GAAS1B,SAAA;EACf,MAAM2B,UAAA,GAAaD,MAAA,EAAQE,IAAA,IAAQ;EACnC,MAAMC,0BAAA,GAA6BpB,MAAA,CAAwB;EAE3D,MAAM,CAACqB,YAAA,EAAcC,eAAA,CAAgB,GAAGrB,QAAA,CAAwC;EAEhF,MAAMsB,MAAA,GAASC,OAAA,CAAQV,UAAA,GAAaL,UAAA,CAAW,EAAEc,MAAA;EACjD,MAAME,QAAA,GAAW1B,OAAA,CAAQ,MAAMI,IAAA,IAAQ,EAAE;EACzC,MAAMuB,WAAA,GAAc3B,OAAA,CAClB,MAAO,OAAOY,MAAA,CAAOgB,KAAK,KAAK,WAAWhB,MAAA,CAAOgB,KAAK,GAAGhB,MAAA,CAAOiB,IAAI,EACpE,CAACjB,MAAA,CAAOgB,KAAK,EAAEhB,MAAA,CAAOiB,IAAI,CAAC;EAE7B,MAAMrB,MAAA,GAASR,OAAA,CAAQ,MAAMY,MAAA,CAAOJ,MAAM,IAAI,EAAE,EAAE,CAACI,MAAA,CAAOJ,MAAM,CAAC;EAEjET,SAAA,CAAU;IACR,IAAI,CAACyB,MAAA,IAAUhB,MAAA,CAAOsB,MAAM,KAAK,GAAG;MAClCP,eAAA,CAAgB;MAChB;IACF;IAEA,MAAMQ,UAAA,GAAa,IAAIC,eAAA;IAEvB,MAAMC,gBAAA,GAAmB,MAAAA,CAAA;MACvB,MAAMC,kBAAA,GAAqB7B,iBAAA,CAAkBQ,UAAA,IAAc,CAAC,GAAGM,UAAA,EAAYX,MAAA;MAE3E,MAAM;QAAE2B;MAAK,CAAE,GAAG,MAAMnB,YAAA,CAAa;QACnCoB,IAAA,EAAMF,kBAAA;QACNG,cAAA,EAAgB;UACd7B,MAAA,EAAQ;QACV;QACA8B,cAAA,EAAgB/B,wBAAA;QAChBW,MAAA,EAAQC,UAAA;QACRoB,SAAA,EAAW;QACXC,eAAA,EAAiB;QACjBC,UAAA,EAAY7B,MAAA,CAAOiB,IAAI;QACvBa,MAAA,EAAQX,UAAA,CAAWW,MAAM;QACzBC,UAAA,EAAY/B,MAAA,CAAOiB;MACrB;MAEA,IAAIM,KAAA,EAAO;QACTZ,eAAA,CAAgBY,KAAA;MAClB;IACF;IAEA,KAAKF,gBAAA;IAEL,OAAO;MACLrC,cAAA,CAAemC,UAAA;IACjB;EACF,GAAG,CAACvB,MAAA,EAAQQ,YAAA,EAAcQ,MAAA,EAAQL,UAAA,EAAYP,MAAA,CAAOiB,IAAI,EAAEhB,UAAA,CAAW;EAEtE,MAAM+B,QAAA,GAAW9C,WAAA,CACf,OAAO;IAAE+C,SAAA,EAAWC;EAAa,CAA4B;IAC3DlD,cAAA,CAAeyB,0BAAA,CAA2B0B,OAAO;IAEjD,MAAMhB,YAAA,GAAa,IAAIC,eAAA;IACvBX,0BAAA,CAA2B0B,OAAO,GAAGhB,YAAA;IAErC,MAAM;MAAEI,KAAK,EAALA;IAAK,CAAE,GAAG,MAAMnB,YAAA,CAAa;MACnCqB,cAAA,EAAgB;QACd7B,MAAA,EAAQ;MACV;MACA8B,cAAA,EAAgB/B,wBAAA;MAChBsC,SAAA,EAAWC,aAAA;MACXP,SAAA,EAAW;MACXE,UAAA,EAAY7B,MAAA,CAAOiB,IAAI;MACvBa,MAAA,EAAQX,YAAA,CAAWW,MAAM;MACzBC,UAAA,EAAY/B,MAAA,CAAOiB;IACrB;IAEA,IAAI,CAACM,OAAA,EAAO;MACV,OAAOW,aAAA;IACT;IAEA,OAAOX,OAAA;EACT,GACA,CAACnB,YAAA,EAAcJ,MAAA,CAAOiB,IAAI,CAAC;EAG7B9B,SAAA,CAAU;IACR,OAAO;MACLH,cAAA,CAAeyB,0BAAA,CAA2B0B,OAAO;IACnD;EACF,GAAG,EAAE;EAEL,oBACEC,IAAA,CAAC9D,MAAA;IAAO2C,IAAA,EAAMnB,UAAA;IAAYuC,KAAA,EAAO,GAAGhC,CAAA,CAAE,mBAAmBU,WAAA,EAAa;cACnEL,YAAA,KAAiB,qBAChB0B,IAAA,CAACzD,aAAA;MAAc2D,MAAA,EAAO;sBAEtBF,IAAA,CAAC3D,iBAAA;MAAkBkD,SAAA,EAAU;gBAC3B,aAAAY,KAAA,CAAChE,IAAA;QACCqB,MAAA,EAAQA,MAAA;QACRc,YAAA,EAAcA,YAAA;QACdsB,QAAA,EAAU,CAACA,QAAA,CAAS;QACpBQ,QAAA,EAAUA,CAACC,CAAA,EAAGjB,IAAA;UACZzB,MAAA,CAAOL,eAAA,CAAgBO,UAAA,IAAc,CAAC,GAAGuB,IAAA,EAAMjB,UAAA,EAAYX,MAAA;UAC3DM,UAAA,CAAWJ,UAAA;QACb;QACAN,IAAA,EAAMsB,QAAA;gCAENsB,IAAA,CAAC1D,YAAA;UACCkB,MAAA,EAAQA,MAAA;UACR8C,WAAW;UACXC,eAAA,EAAgB;UAChBC,UAAA,EAAW;UACXC,gBAAA,EAAkB7C,MAAA,CAAOiB,IAAI;UAC7B6B,WAAA,EAAa;UACbC,QAAA,EAAU;yBAEZX,IAAA,CAAC5D,UAAA;oBAAY6B,CAAA,CAAE;;;;;AAM3B","ignoreList":[]}
@@ -0,0 +1,8 @@
1
+ import type { Data } from 'payload';
2
+ import React from 'react';
3
+ export declare function WidgetEditControl({ onSave, widgetData, widgetID, }: {
4
+ onSave: (data: Data) => void;
5
+ widgetData?: Record<string, unknown>;
6
+ widgetID: string;
7
+ }): React.JSX.Element;
8
+ //# sourceMappingURL=WidgetEditControl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WidgetEditControl.d.ts","sourceRoot":"","sources":["../../../../../src/views/Dashboard/Default/ModularDashboard/WidgetEditControl.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAGnC,OAAO,KAAgB,MAAM,OAAO,CAAA;AAOpC,wBAAgB,iBAAiB,CAAC,EAChC,MAAM,EACN,UAAU,EACV,QAAQ,GACT,EAAE;IACD,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAA;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACpC,QAAQ,EAAE,MAAM,CAAA;CACjB,qBAsCA"}
@@ -0,0 +1,78 @@
1
+ 'use client';
2
+
3
+ import { c as _c } from "react/compiler-runtime";
4
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
5
+ import { EditIcon, useConfig, useModal, useTranslation } from '@payloadcms/ui';
6
+ import React, { useId } from 'react';
7
+ import { WidgetConfigDrawer } from './WidgetConfigDrawer.js';
8
+ const getWidgetSlugFromID = widgetID => widgetID.slice(0, widgetID.lastIndexOf('-'));
9
+ export function WidgetEditControl(t0) {
10
+ const $ = _c(7);
11
+ const {
12
+ onSave,
13
+ widgetData,
14
+ widgetID
15
+ } = t0;
16
+ const {
17
+ t
18
+ } = useTranslation();
19
+ const {
20
+ openModal
21
+ } = useModal();
22
+ const {
23
+ widgets: t1
24
+ } = useConfig().config.admin.dashboard ?? {};
25
+ const configWidgets = t1 === undefined ? [] : t1;
26
+ let t2;
27
+ if ($[0] !== widgetID) {
28
+ t2 = getWidgetSlugFromID(widgetID);
29
+ $[0] = widgetID;
30
+ $[1] = t2;
31
+ } else {
32
+ t2 = $[1];
33
+ }
34
+ const widgetSlug = t2;
35
+ let t3;
36
+ if ($[2] !== widgetSlug) {
37
+ t3 = widget => widget.slug === widgetSlug;
38
+ $[2] = widgetSlug;
39
+ $[3] = t3;
40
+ } else {
41
+ t3 = $[3];
42
+ }
43
+ const widgetConfig = configWidgets.find(t3);
44
+ const hasEditableFields = Boolean(widgetConfig?.fields?.length);
45
+ const drawerID = useId();
46
+ const drawerSlug = `widget-editor-${drawerID}`;
47
+ if (!hasEditableFields) {
48
+ return null;
49
+ }
50
+ let t4;
51
+ if ($[4] !== drawerSlug || $[5] !== openModal) {
52
+ t4 = () => {
53
+ openModal(drawerSlug);
54
+ };
55
+ $[4] = drawerSlug;
56
+ $[5] = openModal;
57
+ $[6] = t4;
58
+ } else {
59
+ t4 = $[6];
60
+ }
61
+ return _jsxs(_Fragment, {
62
+ children: [_jsxs("button", {
63
+ className: "widget-wrapper__edit-btn",
64
+ onClick: t4,
65
+ type: "button",
66
+ children: [_jsxs("span", {
67
+ className: "sr-only",
68
+ children: [t("general:edit"), " ", widgetID]
69
+ }), _jsx(EditIcon, {})]
70
+ }), _jsx(WidgetConfigDrawer, {
71
+ drawerSlug,
72
+ onSave,
73
+ widget: widgetConfig,
74
+ widgetData
75
+ })]
76
+ });
77
+ }
78
+ //# sourceMappingURL=WidgetEditControl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WidgetEditControl.js","names":["c","_c","EditIcon","useConfig","useModal","useTranslation","React","useId","WidgetConfigDrawer","getWidgetSlugFromID","widgetID","slice","lastIndexOf","WidgetEditControl","t0","$","onSave","widgetData","t","openModal","widgets","t1","config","admin","dashboard","configWidgets","undefined","t2","widgetSlug","t3","widget","slug","widgetConfig","find","hasEditableFields","Boolean","fields","length","drawerID","drawerSlug","t4","_jsxs","_Fragment","children","className","onClick","type","_jsx"],"sources":["../../../../../src/views/Dashboard/Default/ModularDashboard/WidgetEditControl.tsx"],"sourcesContent":["'use client'\n\nimport type { Data } from 'payload'\n\nimport { EditIcon, useConfig, useModal, useTranslation } from '@payloadcms/ui'\nimport React, { useId } from 'react'\n\nimport { WidgetConfigDrawer } from './WidgetConfigDrawer.js'\n\nconst getWidgetSlugFromID = (widgetID: string): string =>\n widgetID.slice(0, widgetID.lastIndexOf('-'))\n\nexport function WidgetEditControl({\n onSave,\n widgetData,\n widgetID,\n}: {\n onSave: (data: Data) => void\n widgetData?: Record<string, unknown>\n widgetID: string\n}) {\n const { t } = useTranslation()\n const { openModal } = useModal()\n const { widgets: configWidgets = [] } = useConfig().config.admin.dashboard ?? {}\n\n const widgetSlug = getWidgetSlugFromID(widgetID)\n const widgetConfig = configWidgets.find((widget) => widget.slug === widgetSlug)\n const hasEditableFields = Boolean(widgetConfig?.fields?.length)\n\n const drawerID = useId()\n const drawerSlug = `widget-editor-${drawerID}`\n\n if (!hasEditableFields) {\n return null\n }\n\n return (\n <>\n <button\n className=\"widget-wrapper__edit-btn\"\n onClick={() => {\n openModal(drawerSlug)\n }}\n type=\"button\"\n >\n <span className=\"sr-only\">\n {t('general:edit')} {widgetID}\n </span>\n <EditIcon />\n </button>\n <WidgetConfigDrawer\n drawerSlug={drawerSlug}\n onSave={onSave}\n widget={widgetConfig}\n widgetData={widgetData}\n />\n </>\n )\n}\n"],"mappings":"AAAA;;AAAA,SAAAA,CAAA,IAAAC,EAAA;;AAIA,SAASC,QAAQ,EAAEC,SAAS,EAAEC,QAAQ,EAAEC,cAAc,QAAQ;AAC9D,OAAOC,KAAA,IAASC,KAAK,QAAQ;AAE7B,SAASC,kBAAkB,QAAQ;AAEnC,MAAMC,mBAAA,GAAuBC,QAAA,IAC3BA,QAAA,CAASC,KAAK,CAAC,GAAGD,QAAA,CAASE,WAAW,CAAC;AAEzC,OAAO,SAAAC,kBAAAC,EAAA;EAAA,MAAAC,CAAA,GAAAd,EAAA;EAA2B;IAAAe,MAAA;IAAAC,UAAA;IAAAP;EAAA,IAAAI,EAQjC;EACC;IAAAI;EAAA,IAAcb,cAAA;EACd;IAAAc;EAAA,IAAsBf,QAAA;EACtB;IAAAgB,OAAA,EAAAC;EAAA,IAAwClB,SAAA,GAAAmB,MAAA,CAAAC,KAAA,CAAAC,SAAA,MAAuC;EAA9D,MAAAC,aAAA,GAAAJ,EAAkB,KAAAK,SAAA,QAAlBL,EAAkB;EAAA,IAAAM,EAAA;EAAA,IAAAZ,CAAA,QAAAL,QAAA;IAEhBiB,EAAA,GAAAlB,mBAAA,CAAoBC,QAAA;IAAAK,CAAA,MAAAL,QAAA;IAAAK,CAAA,MAAAY,EAAA;EAAA;IAAAA,EAAA,GAAAZ,CAAA;EAAA;EAAvC,MAAAa,UAAA,GAAmBD,EAAoB;EAAA,IAAAE,EAAA;EAAA,IAAAd,CAAA,QAAAa,UAAA;IACCC,EAAA,GAAAC,MAAA,IAAYA,MAAA,CAAAC,IAAA,KAAgBH,UAAA;IAAAb,CAAA,MAAAa,UAAA;IAAAb,CAAA,MAAAc,EAAA;EAAA;IAAAA,EAAA,GAAAd,CAAA;EAAA;EAApE,MAAAiB,YAAA,GAAqBP,aAAA,CAAAQ,IAAA,CAAmBJ,EAA4B;EACpE,MAAAK,iBAAA,GAA0BC,OAAA,CAAQH,YAAA,EAAAI,MAAA,EAAAC,MAAsB;EAExD,MAAAC,QAAA,GAAiB/B,KAAA;EACjB,MAAAgC,UAAA,GAAmB,iBAAiBD,QAAA,EAAU;EAAA,KAEzCJ,iBAAA;IAAA;EAAA;EAAA,IAAAM,EAAA;EAAA,IAAAzB,CAAA,QAAAwB,UAAA,IAAAxB,CAAA,QAAAI,SAAA;IAQUqB,EAAA,GAAAA,CAAA;MACPrB,SAAA,CAAUoB,UAAA;IAAA;IACZxB,CAAA,MAAAwB,UAAA;IAAAxB,CAAA,MAAAI,SAAA;IAAAJ,CAAA,MAAAyB,EAAA;EAAA;IAAAA,EAAA,GAAAzB,CAAA;EAAA;EAAA,OALJ0B,KAAA,CAAAC,SAAA;IAAAC,QAAA,GACEF,KAAA,CAAC;MAAAG,SAAA,EACW;MAAAC,OAAA,EACDL,EAET;MAAAM,IAAA,EACK;MAAAH,QAAA,GAELF,KAAA,CAAC;QAAAG,SAAA,EAAe;QAAAD,QAAA,GACbzB,CAAA,CAAE,iBAAgB,KAAER,QAAA;MAAA,C,GAEvBqC,IAAA,CAAA7C,QAAA,IAAC;IAAA,C,GAEH6C,IAAA,CAAAvC,kBAAA;MAAA+B,UAAA;MAAAvB,MAAA;MAAAc,MAAA,EAGUE,YAAA;MAAAf;IAAA,C","ignoreList":[]}
@@ -1,6 +1,7 @@
1
1
  import type { ClientWidget, WidgetWidth } from 'payload';
2
2
  import React from 'react';
3
3
  export type WidgetItem = {
4
+ data?: Record<string, unknown>;
4
5
  id: string;
5
6
  maxWidth: WidgetWidth;
6
7
  minWidth: WidgetWidth;
@@ -1 +1 @@
1
- {"version":3,"file":"index.client.d.ts","sourceRoot":"","sources":["../../../../../src/views/Dashboard/Default/ModularDashboard/index.client.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAKxD,OAAO,KAA4B,MAAM,OAAO,CAAA;AAuBhD,MAAM,MAAM,UAAU,GAAG;IACvB,EAAE,EAAE,MAAM,CAAA;IACV,QAAQ,EAAE,WAAW,CAAA;IACrB,QAAQ,EAAE,WAAW,CAAA;IACrB,KAAK,EAAE,WAAW,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,SAAS,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,IAAI,EAAE,UAAU,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,EAAE,OAAO,GAAG,QAAQ,CAAA;IAC5B,MAAM,EAAE,oBAAoB,CAAA;CAC7B,GAAG,IAAI,CAAA;AAYR,wBAAgB,sBAAsB,CAAC,EACrC,YAAY,EAAE,aAAa,EAC3B,OAAO,GACR,EAAE;IACD,YAAY,EAAE,oBAAoB,EAAE,CAAA;IACpC,OAAO,EAAE,YAAY,EAAE,CAAA;CACxB,qBAyKA"}
1
+ {"version":3,"file":"index.client.d.ts","sourceRoot":"","sources":["../../../../../src/views/Dashboard/Default/ModularDashboard/index.client.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAKxD,OAAO,KAA4B,MAAM,OAAO,CAAA;AAwBhD,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,EAAE,EAAE,MAAM,CAAA;IACV,QAAQ,EAAE,WAAW,CAAA;IACrB,QAAQ,EAAE,WAAW,CAAA;IACrB,KAAK,EAAE,WAAW,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,SAAS,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,IAAI,EAAE,UAAU,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,EAAE,OAAO,GAAG,QAAQ,CAAA;IAC5B,MAAM,EAAE,oBAAoB,CAAA;CAC7B,GAAG,IAAI,CAAA;AAYR,wBAAgB,sBAAsB,CAAC,EACrC,YAAY,EAAE,aAAa,EAC3B,OAAO,GACR,EAAE;IACD,YAAY,EAAE,oBAAoB,EAAE,CAAA;IACpC,OAAO,EAAE,YAAY,EAAE,CAAA;CACxB,qBAiLA"}
@@ -25,6 +25,7 @@ import { DashboardStepNav } from './DashboardStepNav.js';
25
25
  import { useDashboardLayout } from './useDashboardLayout.js';
26
26
  import { closestInXAxis } from './utils/collisionDetection.js';
27
27
  import { useDashboardSensors } from './utils/sensors.js';
28
+ import { WidgetEditControl } from './WidgetEditControl.js';
28
29
  /* eslint-disable perfectionist/sort-objects */
29
30
  const WIDTH_TO_PERCENTAGE = {
30
31
  'x-small': 25,
@@ -35,7 +36,7 @@ const WIDTH_TO_PERCENTAGE = {
35
36
  full: 100
36
37
  };
37
38
  export function ModularDashboardClient(t0) {
38
- const $ = _c(21);
39
+ const $ = _c(22);
39
40
  const {
40
41
  clientLayout: initialLayout,
41
42
  widgets
@@ -54,23 +55,24 @@ export function ModularDashboardClient(t0) {
54
55
  resetLayout,
55
56
  resizeWidget,
56
57
  saveLayout,
57
- setIsEditing
58
+ setIsEditing,
59
+ updateWidgetData
58
60
  } = useDashboardLayout(initialLayout);
59
61
  const [activeDragId, setActiveDragId] = useState(null);
60
62
  const sensors = useDashboardSensors();
61
63
  let t1;
62
- if ($[0] !== activeDragId || $[1] !== addWidget || $[2] !== cancel || $[3] !== cancelModal || $[4] !== currentLayout || $[5] !== deleteWidget || $[6] !== isEditing || $[7] !== moveWidget || $[8] !== resetLayout || $[9] !== resizeWidget || $[10] !== saveLayout || $[11] !== sensors || $[12] !== setIsEditing || $[13] !== t || $[14] !== widgets) {
64
+ if ($[0] !== activeDragId || $[1] !== addWidget || $[2] !== cancel || $[3] !== cancelModal || $[4] !== currentLayout || $[5] !== deleteWidget || $[6] !== isEditing || $[7] !== moveWidget || $[8] !== resetLayout || $[9] !== resizeWidget || $[10] !== saveLayout || $[11] !== sensors || $[12] !== setIsEditing || $[13] !== t || $[14] !== updateWidgetData || $[15] !== widgets) {
63
65
  let t2;
64
- if ($[16] === Symbol.for("react.memo_cache_sentinel")) {
66
+ if ($[17] === Symbol.for("react.memo_cache_sentinel")) {
65
67
  t2 = () => {
66
68
  setActiveDragId(null);
67
69
  };
68
- $[16] = t2;
70
+ $[17] = t2;
69
71
  } else {
70
- t2 = $[16];
72
+ t2 = $[17];
71
73
  }
72
74
  let t3;
73
- if ($[17] !== currentLayout || $[18] !== moveWidget) {
75
+ if ($[18] !== currentLayout || $[19] !== moveWidget) {
74
76
  t3 = event => {
75
77
  if (!event.over) {
76
78
  setActiveDragId(null);
@@ -97,20 +99,20 @@ export function ModularDashboardClient(t0) {
97
99
  });
98
100
  setActiveDragId(null);
99
101
  };
100
- $[17] = currentLayout;
101
- $[18] = moveWidget;
102
- $[19] = t3;
102
+ $[18] = currentLayout;
103
+ $[19] = moveWidget;
104
+ $[20] = t3;
103
105
  } else {
104
- t3 = $[19];
106
+ t3 = $[20];
105
107
  }
106
108
  let t4;
107
- if ($[20] === Symbol.for("react.memo_cache_sentinel")) {
109
+ if ($[21] === Symbol.for("react.memo_cache_sentinel")) {
108
110
  t4 = event_0 => {
109
111
  setActiveDragId(event_0.active.id);
110
112
  };
111
- $[20] = t4;
113
+ $[21] = t4;
112
114
  } else {
113
- t4 = $[20];
115
+ t4 = $[21];
114
116
  }
115
117
  t1 = _jsxs("div", {
116
118
  children: [_jsx(DndContext, {
@@ -157,7 +159,13 @@ export function ModularDashboardClient(t0) {
157
159
  }), isEditing && _jsxs("div", {
158
160
  className: "widget-wrapper__controls",
159
161
  onPointerDown: _temp,
160
- children: [_jsx(WidgetWidthDropdown, {
162
+ children: [_jsx(WidgetEditControl, {
163
+ onSave: data => {
164
+ updateWidgetData(widget_1.item.id, data);
165
+ },
166
+ widgetData: widget_1.item.data,
167
+ widgetID: widget_1.item.id
168
+ }), _jsx(WidgetWidthDropdown, {
161
169
  currentWidth: widget_1.item.width,
162
170
  maxWidth: widget_1.item.maxWidth,
163
171
  minWidth: widget_1.item.minWidth,
@@ -223,10 +231,11 @@ export function ModularDashboardClient(t0) {
223
231
  $[11] = sensors;
224
232
  $[12] = setIsEditing;
225
233
  $[13] = t;
226
- $[14] = widgets;
227
- $[15] = t1;
234
+ $[14] = updateWidgetData;
235
+ $[15] = widgets;
236
+ $[16] = t1;
228
237
  } else {
229
- t1 = $[15];
238
+ t1 = $[16];
230
239
  }
231
240
  return t1;
232
241
  }
@@ -249,10 +258,12 @@ function WidgetWidthDropdown({
249
258
  })).filter(option => option.percentage >= minPercentage && option.percentage <= maxPercentage);
250
259
  }, [minWidth, maxWidth]);
251
260
  const isDisabled = validOptions.length <= 1;
261
+ if (isDisabled) {
262
+ return null;
263
+ }
252
264
  return /*#__PURE__*/_jsx(Popup, {
253
265
  button: /*#__PURE__*/_jsxs("button", {
254
266
  className: "widget-wrapper__size-btn",
255
- disabled: isDisabled,
256
267
  onPointerDown: e => e.stopPropagation(),
257
268
  type: "button",
258
269
  children: [/*#__PURE__*/_jsx("span", {
@@ -263,7 +274,6 @@ function WidgetWidthDropdown({
263
274
  })]
264
275
  }),
265
276
  buttonType: "custom",
266
- disabled: isDisabled,
267
277
  render: ({
268
278
  close
269
279
  }) => /*#__PURE__*/_jsx(PopupList.ButtonGroup, {
@@ -1 +1 @@
1
- {"version":3,"file":"index.client.js","names":["c","_c","DndContext","DragOverlay","useDraggable","useDroppable","snapCenterToCursor","ChevronIcon","Popup","PopupList","useTranslation","XIcon","React","useMemo","useState","snapCenterToCursorOnlyForPointer","args","activatorEvent","transform","DashboardStepNav","useDashboardLayout","closestInXAxis","useDashboardSensors","WIDTH_TO_PERCENTAGE","small","medium","large","full","ModularDashboardClient","t0","$","clientLayout","initialLayout","widgets","t","addWidget","cancel","cancelModal","currentLayout","deleteWidget","isEditing","moveWidget","resetLayout","resizeWidget","saveLayout","setIsEditing","activeDragId","setActiveDragId","sensors","t1","t2","Symbol","for","t3","event","over","droppableId","id","i","lastIndexOf","slug","slice","position","active","moveFromIndex","findIndex","widget","item","moveToIndex","widget_0","t4","event_0","_jsxs","children","_jsx","autoScroll","enabled","threshold","x","y","collisionDetection","onDragCancel","onDragEnd","onDragStart","className","style","display","flexWrap","length","map","widget_1","_index","Fragment","DraggableItem","disabled","width","padding","inert","component","onPointerDown","_temp","WidgetWidthDropdown","currentWidth","maxWidth","minWidth","onResize","onClick","type","dropAnimation","duration","modifiers","draggedWidget","find","widget_2","e","stopPropagation","validOptions","minPercentage","maxPercentage","Object","entries","key","value","percentage","filter","option","isDisabled","button","buttonType","render","close","ButtonGroup","isSelected","Button","toFixed","size","verticalAlign","props","attributes","isDragging","listeners","setNodeRef","mergedStyles","opacity","draggableProps","DroppableItem","ref","height","data","isOver","t5","t6","t7","t8","left","right","top","bottom","borderRadius","backgroundColor","marginBottom","marginTop","pointerEvents","zIndex"],"sources":["../../../../../src/views/Dashboard/Default/ModularDashboard/index.client.tsx"],"sourcesContent":["'use client'\n\nimport type { Modifier } from '@dnd-kit/core'\nimport type { ClientWidget, WidgetWidth } from 'payload'\n\nimport { DndContext, DragOverlay, useDraggable, useDroppable } from '@dnd-kit/core'\nimport { snapCenterToCursor } from '@dnd-kit/modifiers'\nimport { ChevronIcon, Popup, PopupList, useTranslation, XIcon } from '@payloadcms/ui'\nimport React, { useMemo, useState } from 'react'\n\n/**\n * Custom modifier that only applies snapCenterToCursor for pointer events.\n * During keyboard navigation, we handle positioning ourselves via the coordinate getter.\n */\nconst snapCenterToCursorOnlyForPointer: Modifier = (args) => {\n const { activatorEvent } = args\n\n // Only apply snap for pointer events (mouse/touch), not keyboard\n // Check activatorEvent.type since KeyboardEvent may not exist on server\n if (activatorEvent && 'key' in activatorEvent) {\n return args.transform\n }\n\n return snapCenterToCursor(args)\n}\n\nimport { DashboardStepNav } from './DashboardStepNav.js'\nimport { useDashboardLayout } from './useDashboardLayout.js'\nimport { closestInXAxis } from './utils/collisionDetection.js'\nimport { useDashboardSensors } from './utils/sensors.js'\n\nexport type WidgetItem = {\n id: string\n maxWidth: WidgetWidth\n minWidth: WidgetWidth\n width: WidgetWidth\n}\n\nexport type WidgetInstanceClient = {\n component: React.ReactNode\n item: WidgetItem\n}\n\nexport type DropTargetWidget = {\n position: 'after' | 'before'\n widget: WidgetInstanceClient\n} | null\n\n/* eslint-disable perfectionist/sort-objects */\nconst WIDTH_TO_PERCENTAGE = {\n 'x-small': 25,\n small: (1 / 3) * 100,\n medium: 50,\n large: (2 / 3) * 100,\n 'x-large': 75,\n full: 100,\n} as const\n\nexport function ModularDashboardClient({\n clientLayout: initialLayout,\n widgets,\n}: {\n clientLayout: WidgetInstanceClient[]\n widgets: ClientWidget[]\n}) {\n const { t } = useTranslation()\n const {\n addWidget,\n cancel,\n cancelModal,\n currentLayout,\n deleteWidget,\n isEditing,\n moveWidget,\n resetLayout,\n resizeWidget,\n saveLayout,\n setIsEditing,\n } = useDashboardLayout(initialLayout)\n\n const [activeDragId, setActiveDragId] = useState<null | string>(null)\n const sensors = useDashboardSensors()\n\n return (\n <div>\n <DndContext\n autoScroll={{\n enabled: true,\n threshold: {\n x: 0, // No horizontal scroll\n y: 0.2, // Allow vertical scroll at 20% from edge\n },\n }}\n collisionDetection={closestInXAxis}\n // https://github.com/clauderic/dnd-kit/issues/926#issuecomment-1640115665\n id=\"dashboard-dnd-context\"\n onDragCancel={() => {\n setActiveDragId(null)\n }}\n onDragEnd={(event) => {\n if (!event.over) {\n setActiveDragId(null)\n return\n }\n const droppableId = event.over.id as string\n const i = droppableId.lastIndexOf('-')\n const slug = droppableId.slice(0, i)\n const position = droppableId.slice(i + 1)\n\n if (slug === event.active.id) {\n return\n }\n\n const moveFromIndex = currentLayout?.findIndex(\n (widget) => widget.item.id === event.active.id,\n )\n let moveToIndex = currentLayout?.findIndex((widget) => widget.item.id === slug)\n if (moveFromIndex < moveToIndex) {\n moveToIndex--\n }\n if (position === 'after') {\n moveToIndex++\n }\n moveWidget({ moveFromIndex, moveToIndex })\n setActiveDragId(null)\n }}\n onDragStart={(event) => {\n setActiveDragId(event.active.id as string)\n }}\n sensors={sensors}\n >\n <div\n className={`modular-dashboard ${isEditing ? 'editing' : ''}`}\n style={{\n display: 'flex',\n flexWrap: 'wrap',\n // Don't add gap here! We need to use padding on the widgets instead\n // to make sure all rows have the same width always.\n }}\n >\n {currentLayout?.length === 0 && (\n <div className=\"modular-dashboard__empty\">\n <p>\n There are no widgets on your dashboard. You can add them from the \"Dashboard\" menu\n located in the top bar.\n </p>\n </div>\n )}\n {currentLayout?.map((widget, _index) => (\n <React.Fragment key={widget.item.id}>\n <DraggableItem\n disabled={!isEditing}\n id={widget.item.id}\n style={{\n width: `${WIDTH_TO_PERCENTAGE[widget.item.width]}%`,\n padding: '6px',\n }}\n width={widget.item.width}\n >\n <div className={`widget-wrapper ${isEditing ? 'widget-wrapper--editing' : ''}`}>\n <div aria-hidden={isEditing} className=\"widget-content\" inert={isEditing}>\n {widget.component}\n </div>\n {isEditing && (\n <div\n className=\"widget-wrapper__controls\"\n onPointerDown={(e) => e.stopPropagation()}\n >\n <WidgetWidthDropdown\n currentWidth={widget.item.width}\n maxWidth={widget.item.maxWidth}\n minWidth={widget.item.minWidth}\n onResize={(width) => resizeWidget(widget.item.id, width)}\n />\n <button\n className=\"widget-wrapper__delete-btn\"\n onClick={() => deleteWidget(widget.item.id)}\n type=\"button\"\n >\n <span className=\"sr-only\">\n {t('dashboard:deleteWidget', { id: widget.item.id })}\n </span>\n <XIcon />\n </button>\n </div>\n )}\n </div>\n </DraggableItem>\n </React.Fragment>\n ))}\n <DragOverlay\n className=\"drag-overlay\"\n dropAnimation={{\n duration: 100,\n }}\n // Uses custom modifier that only applies for pointer, not keyboard navigation.\n modifiers={[snapCenterToCursorOnlyForPointer]}\n >\n {activeDragId\n ? (() => {\n const draggedWidget = currentLayout?.find(\n (widget) => widget.item.id === activeDragId,\n )\n return draggedWidget ? (\n <div\n style={{\n transform: 'scale(0.25)',\n }}\n >\n <div\n className={`widget-wrapper ${isEditing ? 'widget-wrapper--editing' : ''}`}\n >\n <div className=\"widget-content\">{draggedWidget.component}</div>\n </div>\n </div>\n ) : null\n })()\n : null}\n </DragOverlay>\n </div>\n </DndContext>\n <DashboardStepNav\n addWidget={addWidget}\n cancel={cancel}\n isEditing={isEditing}\n resetLayout={resetLayout}\n saveLayout={saveLayout}\n setIsEditing={setIsEditing}\n widgets={widgets}\n />\n {cancelModal}\n </div>\n )\n}\n\nfunction WidgetWidthDropdown({\n currentWidth,\n maxWidth,\n minWidth,\n onResize,\n}: {\n currentWidth: WidgetWidth\n maxWidth: WidgetWidth\n minWidth: WidgetWidth\n onResize: (width: WidgetWidth) => void\n}) {\n // Filter options based on minWidth and maxWidth\n const validOptions = useMemo(() => {\n const minPercentage = WIDTH_TO_PERCENTAGE[minWidth]\n const maxPercentage = WIDTH_TO_PERCENTAGE[maxWidth]\n\n return Object.entries(WIDTH_TO_PERCENTAGE)\n .map(([key, value]) => ({\n width: key as WidgetWidth,\n percentage: value,\n }))\n .filter((option) => option.percentage >= minPercentage && option.percentage <= maxPercentage)\n }, [minWidth, maxWidth])\n\n const isDisabled = validOptions.length <= 1\n\n return (\n <Popup\n button={\n <button\n className=\"widget-wrapper__size-btn\"\n disabled={isDisabled}\n onPointerDown={(e) => e.stopPropagation()}\n type=\"button\"\n >\n <span className=\"widget-wrapper__size-btn-text\">{currentWidth}</span>\n <ChevronIcon className=\"widget-wrapper__size-btn-icon\" />\n </button>\n }\n buttonType=\"custom\"\n disabled={isDisabled}\n render={({ close }) => (\n <PopupList.ButtonGroup>\n {validOptions.map((option) => {\n const isSelected = option.width === currentWidth\n return (\n <PopupList.Button\n active={isSelected}\n key={option.width}\n onClick={() => {\n onResize(option.width)\n close()\n }}\n >\n <span className=\"widget-wrapper__size-btn-label\">{option.width}</span>\n <span className=\"widget-wrapper__size-btn-percentage\">\n {option.percentage.toFixed(0)}%\n </span>\n </PopupList.Button>\n )\n })}\n </PopupList.ButtonGroup>\n )}\n size=\"small\"\n verticalAlign=\"bottom\"\n />\n )\n}\n\nfunction DraggableItem(props: {\n children: React.ReactNode\n disabled?: boolean\n id: string\n style?: React.CSSProperties\n width: WidgetWidth\n}) {\n const { attributes, isDragging, listeners, setNodeRef } = useDraggable({\n id: props.id,\n disabled: props.disabled,\n })\n\n const mergedStyles: React.CSSProperties = {\n ...props.style,\n opacity: isDragging ? 0.3 : 1,\n position: 'relative',\n }\n\n // Only apply draggable attributes and listeners when not disabled\n // to prevent disabling interactive elements inside the widget\n const draggableProps = props.disabled ? {} : { ...listeners, ...attributes }\n\n return (\n <div className=\"widget\" data-slug={props.id} data-width={props.width} style={mergedStyles}>\n <DroppableItem id={props.id} position=\"before\" />\n <div\n className=\"draggable\"\n id={props.id}\n ref={setNodeRef}\n {...draggableProps}\n style={{\n width: '100%',\n height: '100%',\n }}\n >\n {props.children}\n </div>\n <DroppableItem id={props.id} position=\"after\" />\n </div>\n )\n}\n\nfunction DroppableItem({ id, position }: { id: string; position: 'after' | 'before' }) {\n const { setNodeRef, isOver } = useDroppable({ id: `${id}-${position}`, data: { position } })\n\n return (\n <div\n className=\"droppable-widget\"\n data-testid={`${id}-${position}`}\n ref={setNodeRef}\n style={{\n position: 'absolute',\n left: position === 'before' ? -2 : 'auto',\n right: position === 'after' ? -2 : 'auto',\n top: 0,\n bottom: 0,\n borderRadius: '1000px',\n width: '4px',\n backgroundColor: isOver ? 'var(--theme-success-400)' : 'transparent',\n marginBottom: '10px',\n marginTop: '10px',\n pointerEvents: 'none',\n zIndex: 1000,\n }}\n />\n )\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"index.client.js","names":["c","_c","DndContext","DragOverlay","useDraggable","useDroppable","snapCenterToCursor","ChevronIcon","Popup","PopupList","useTranslation","XIcon","React","useMemo","useState","snapCenterToCursorOnlyForPointer","args","activatorEvent","transform","DashboardStepNav","useDashboardLayout","closestInXAxis","useDashboardSensors","WidgetEditControl","WIDTH_TO_PERCENTAGE","small","medium","large","full","ModularDashboardClient","t0","$","clientLayout","initialLayout","widgets","t","addWidget","cancel","cancelModal","currentLayout","deleteWidget","isEditing","moveWidget","resetLayout","resizeWidget","saveLayout","setIsEditing","updateWidgetData","activeDragId","setActiveDragId","sensors","t1","t2","Symbol","for","t3","event","over","droppableId","id","i","lastIndexOf","slug","slice","position","active","moveFromIndex","findIndex","widget","item","moveToIndex","widget_0","t4","event_0","_jsxs","children","_jsx","autoScroll","enabled","threshold","x","y","collisionDetection","onDragCancel","onDragEnd","onDragStart","className","style","display","flexWrap","length","map","widget_1","_index","Fragment","DraggableItem","disabled","width","padding","inert","component","onPointerDown","_temp","onSave","data","widgetData","widgetID","WidgetWidthDropdown","currentWidth","maxWidth","minWidth","onResize","onClick","type","dropAnimation","duration","modifiers","draggedWidget","find","widget_2","e","stopPropagation","validOptions","minPercentage","maxPercentage","Object","entries","key","value","percentage","filter","option","isDisabled","button","buttonType","render","close","ButtonGroup","isSelected","Button","toFixed","size","verticalAlign","props","attributes","isDragging","listeners","setNodeRef","mergedStyles","opacity","draggableProps","DroppableItem","ref","height","isOver","t5","t6","t7","t8","left","right","top","bottom","borderRadius","backgroundColor","marginBottom","marginTop","pointerEvents","zIndex"],"sources":["../../../../../src/views/Dashboard/Default/ModularDashboard/index.client.tsx"],"sourcesContent":["'use client'\n\nimport type { Modifier } from '@dnd-kit/core'\nimport type { ClientWidget, WidgetWidth } from 'payload'\n\nimport { DndContext, DragOverlay, useDraggable, useDroppable } from '@dnd-kit/core'\nimport { snapCenterToCursor } from '@dnd-kit/modifiers'\nimport { ChevronIcon, Popup, PopupList, useTranslation, XIcon } from '@payloadcms/ui'\nimport React, { useMemo, useState } from 'react'\n\n/**\n * Custom modifier that only applies snapCenterToCursor for pointer events.\n * During keyboard navigation, we handle positioning ourselves via the coordinate getter.\n */\nconst snapCenterToCursorOnlyForPointer: Modifier = (args) => {\n const { activatorEvent } = args\n\n // Only apply snap for pointer events (mouse/touch), not keyboard\n // Check activatorEvent.type since KeyboardEvent may not exist on server\n if (activatorEvent && 'key' in activatorEvent) {\n return args.transform\n }\n\n return snapCenterToCursor(args)\n}\n\nimport { DashboardStepNav } from './DashboardStepNav.js'\nimport { useDashboardLayout } from './useDashboardLayout.js'\nimport { closestInXAxis } from './utils/collisionDetection.js'\nimport { useDashboardSensors } from './utils/sensors.js'\nimport { WidgetEditControl } from './WidgetEditControl.js'\n\nexport type WidgetItem = {\n data?: Record<string, unknown>\n id: string\n maxWidth: WidgetWidth\n minWidth: WidgetWidth\n width: WidgetWidth\n}\n\nexport type WidgetInstanceClient = {\n component: React.ReactNode\n item: WidgetItem\n}\n\nexport type DropTargetWidget = {\n position: 'after' | 'before'\n widget: WidgetInstanceClient\n} | null\n\n/* eslint-disable perfectionist/sort-objects */\nconst WIDTH_TO_PERCENTAGE = {\n 'x-small': 25,\n small: (1 / 3) * 100,\n medium: 50,\n large: (2 / 3) * 100,\n 'x-large': 75,\n full: 100,\n} as const\n\nexport function ModularDashboardClient({\n clientLayout: initialLayout,\n widgets,\n}: {\n clientLayout: WidgetInstanceClient[]\n widgets: ClientWidget[]\n}) {\n const { t } = useTranslation()\n const {\n addWidget,\n cancel,\n cancelModal,\n currentLayout,\n deleteWidget,\n isEditing,\n moveWidget,\n resetLayout,\n resizeWidget,\n saveLayout,\n setIsEditing,\n updateWidgetData,\n } = useDashboardLayout(initialLayout)\n\n const [activeDragId, setActiveDragId] = useState<null | string>(null)\n const sensors = useDashboardSensors()\n\n return (\n <div>\n <DndContext\n autoScroll={{\n enabled: true,\n threshold: {\n x: 0, // No horizontal scroll\n y: 0.2, // Allow vertical scroll at 20% from edge\n },\n }}\n collisionDetection={closestInXAxis}\n // https://github.com/clauderic/dnd-kit/issues/926#issuecomment-1640115665\n id=\"dashboard-dnd-context\"\n onDragCancel={() => {\n setActiveDragId(null)\n }}\n onDragEnd={(event) => {\n if (!event.over) {\n setActiveDragId(null)\n return\n }\n const droppableId = event.over.id as string\n const i = droppableId.lastIndexOf('-')\n const slug = droppableId.slice(0, i)\n const position = droppableId.slice(i + 1)\n\n if (slug === event.active.id) {\n return\n }\n\n const moveFromIndex = currentLayout?.findIndex(\n (widget) => widget.item.id === event.active.id,\n )\n let moveToIndex = currentLayout?.findIndex((widget) => widget.item.id === slug)\n if (moveFromIndex < moveToIndex) {\n moveToIndex--\n }\n if (position === 'after') {\n moveToIndex++\n }\n moveWidget({ moveFromIndex, moveToIndex })\n setActiveDragId(null)\n }}\n onDragStart={(event) => {\n setActiveDragId(event.active.id as string)\n }}\n sensors={sensors}\n >\n <div\n className={`modular-dashboard ${isEditing ? 'editing' : ''}`}\n style={{\n display: 'flex',\n flexWrap: 'wrap',\n // Don't add gap here! We need to use padding on the widgets instead\n // to make sure all rows have the same width always.\n }}\n >\n {currentLayout?.length === 0 && (\n <div className=\"modular-dashboard__empty\">\n <p>\n There are no widgets on your dashboard. You can add them from the \"Dashboard\" menu\n located in the top bar.\n </p>\n </div>\n )}\n {currentLayout?.map((widget, _index) => (\n <React.Fragment key={widget.item.id}>\n <DraggableItem\n disabled={!isEditing}\n id={widget.item.id}\n style={{\n width: `${WIDTH_TO_PERCENTAGE[widget.item.width]}%`,\n padding: '6px',\n }}\n width={widget.item.width}\n >\n <div className={`widget-wrapper ${isEditing ? 'widget-wrapper--editing' : ''}`}>\n <div aria-hidden={isEditing} className=\"widget-content\" inert={isEditing}>\n {widget.component}\n </div>\n {isEditing && (\n <div\n className=\"widget-wrapper__controls\"\n onPointerDown={(e) => e.stopPropagation()}\n >\n <WidgetEditControl\n onSave={(data) => {\n updateWidgetData(widget.item.id, data)\n }}\n widgetData={widget.item.data}\n widgetID={widget.item.id}\n />\n <WidgetWidthDropdown\n currentWidth={widget.item.width}\n maxWidth={widget.item.maxWidth}\n minWidth={widget.item.minWidth}\n onResize={(width) => resizeWidget(widget.item.id, width)}\n />\n <button\n className=\"widget-wrapper__delete-btn\"\n onClick={() => deleteWidget(widget.item.id)}\n type=\"button\"\n >\n <span className=\"sr-only\">\n {t('dashboard:deleteWidget', { id: widget.item.id })}\n </span>\n <XIcon />\n </button>\n </div>\n )}\n </div>\n </DraggableItem>\n </React.Fragment>\n ))}\n <DragOverlay\n className=\"drag-overlay\"\n dropAnimation={{\n duration: 100,\n }}\n // Uses custom modifier that only applies for pointer, not keyboard navigation.\n modifiers={[snapCenterToCursorOnlyForPointer]}\n >\n {activeDragId\n ? (() => {\n const draggedWidget = currentLayout?.find(\n (widget) => widget.item.id === activeDragId,\n )\n return draggedWidget ? (\n <div\n style={{\n transform: 'scale(0.25)',\n }}\n >\n <div\n className={`widget-wrapper ${isEditing ? 'widget-wrapper--editing' : ''}`}\n >\n <div className=\"widget-content\">{draggedWidget.component}</div>\n </div>\n </div>\n ) : null\n })()\n : null}\n </DragOverlay>\n </div>\n </DndContext>\n <DashboardStepNav\n addWidget={addWidget}\n cancel={cancel}\n isEditing={isEditing}\n resetLayout={resetLayout}\n saveLayout={saveLayout}\n setIsEditing={setIsEditing}\n widgets={widgets}\n />\n {cancelModal}\n </div>\n )\n}\n\nfunction WidgetWidthDropdown({\n currentWidth,\n maxWidth,\n minWidth,\n onResize,\n}: {\n currentWidth: WidgetWidth\n maxWidth: WidgetWidth\n minWidth: WidgetWidth\n onResize: (width: WidgetWidth) => void\n}) {\n // Filter options based on minWidth and maxWidth\n const validOptions = useMemo(() => {\n const minPercentage = WIDTH_TO_PERCENTAGE[minWidth]\n const maxPercentage = WIDTH_TO_PERCENTAGE[maxWidth]\n\n return Object.entries(WIDTH_TO_PERCENTAGE)\n .map(([key, value]) => ({\n width: key as WidgetWidth,\n percentage: value,\n }))\n .filter((option) => option.percentage >= minPercentage && option.percentage <= maxPercentage)\n }, [minWidth, maxWidth])\n\n const isDisabled = validOptions.length <= 1\n\n if (isDisabled) {\n return null\n }\n\n return (\n <Popup\n button={\n <button\n className=\"widget-wrapper__size-btn\"\n onPointerDown={(e) => e.stopPropagation()}\n type=\"button\"\n >\n <span className=\"widget-wrapper__size-btn-text\">{currentWidth}</span>\n <ChevronIcon className=\"widget-wrapper__size-btn-icon\" />\n </button>\n }\n buttonType=\"custom\"\n render={({ close }) => (\n <PopupList.ButtonGroup>\n {validOptions.map((option) => {\n const isSelected = option.width === currentWidth\n return (\n <PopupList.Button\n active={isSelected}\n key={option.width}\n onClick={() => {\n onResize(option.width)\n close()\n }}\n >\n <span className=\"widget-wrapper__size-btn-label\">{option.width}</span>\n <span className=\"widget-wrapper__size-btn-percentage\">\n {option.percentage.toFixed(0)}%\n </span>\n </PopupList.Button>\n )\n })}\n </PopupList.ButtonGroup>\n )}\n size=\"small\"\n verticalAlign=\"bottom\"\n />\n )\n}\n\nfunction DraggableItem(props: {\n children: React.ReactNode\n disabled?: boolean\n id: string\n style?: React.CSSProperties\n width: WidgetWidth\n}) {\n const { attributes, isDragging, listeners, setNodeRef } = useDraggable({\n id: props.id,\n disabled: props.disabled,\n })\n\n const mergedStyles: React.CSSProperties = {\n ...props.style,\n opacity: isDragging ? 0.3 : 1,\n position: 'relative',\n }\n\n // Only apply draggable attributes and listeners when not disabled\n // to prevent disabling interactive elements inside the widget\n const draggableProps = props.disabled ? {} : { ...listeners, ...attributes }\n\n return (\n <div className=\"widget\" data-slug={props.id} data-width={props.width} style={mergedStyles}>\n <DroppableItem id={props.id} position=\"before\" />\n <div\n className=\"draggable\"\n id={props.id}\n ref={setNodeRef}\n {...draggableProps}\n style={{\n width: '100%',\n height: '100%',\n }}\n >\n {props.children}\n </div>\n <DroppableItem id={props.id} position=\"after\" />\n </div>\n )\n}\n\nfunction DroppableItem({ id, position }: { id: string; position: 'after' | 'before' }) {\n const { setNodeRef, isOver } = useDroppable({ id: `${id}-${position}`, data: { position } })\n\n return (\n <div\n className=\"droppable-widget\"\n data-testid={`${id}-${position}`}\n ref={setNodeRef}\n style={{\n position: 'absolute',\n left: position === 'before' ? -2 : 'auto',\n right: position === 'after' ? -2 : 'auto',\n top: 0,\n bottom: 0,\n borderRadius: '1000px',\n width: '4px',\n backgroundColor: isOver ? 'var(--theme-success-400)' : 'transparent',\n marginBottom: '10px',\n marginTop: '10px',\n pointerEvents: 'none',\n zIndex: 1000,\n }}\n />\n )\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/views/Dashboard/Default/ModularDashboard/index.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAA;AAK3D,OAAO,cAAc,CAAA;AAIrB,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,wBAAwB,8BA6CrE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/views/Dashboard/Default/ModularDashboard/index.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAA;AAO3D,OAAO,cAAc,CAAA;AAIrB,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,wBAAwB,8BAiDrE"}
@@ -1,9 +1,10 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { RenderServerComponent } from '@payloadcms/ui/elements/RenderServerComponent';
3
- import { PREFERENCE_KEYS } from 'payload/shared';
4
3
  import React from 'react';
5
- import { getPreferences } from '../../../../utilities/getPreferences.js';
6
4
  import { ModularDashboardClient } from './index.client.js';
5
+ import { getItemsFromConfig } from './utils/getItemsFromConfig.js';
6
+ import { getItemsFromPreferences } from './utils/getItemsFromPreferences.js';
7
+ import { extractLocaleData } from './utils/localeUtils.js';
7
8
  export async function ModularDashboard(props) {
8
9
  const {
9
10
  defaultLayout = [],
@@ -27,15 +28,18 @@ export async function ModularDashboard(props) {
27
28
  const layout = (await getItemsFromPreferences(props.payload, user)) ?? (await getItemsFromConfig(defaultLayout, req, widgets));
28
29
  const serverLayout = layout.map(layoutItem => {
29
30
  const widgetSlug = layoutItem.id.slice(0, layoutItem.id.lastIndexOf('-'));
31
+ const widgetConfig = widgets.find(widget => widget.slug === widgetSlug);
32
+ const widgetData = widgetConfig?.fields?.length ? extractLocaleData(layoutItem.data || {}, req.locale || 'en', widgetConfig.fields) : layoutItem.data || {};
30
33
  return {
31
34
  component: RenderServerComponent({
32
- Component: widgets.find(widget => widget.slug === widgetSlug)?.ComponentPath,
35
+ Component: widgetConfig?.ComponentPath,
33
36
  importMap,
34
37
  serverProps: {
35
38
  cookies,
36
39
  locale,
37
40
  permissions,
38
41
  req,
42
+ widgetData,
39
43
  widgetSlug
40
44
  }
41
45
  }),
@@ -46,6 +50,7 @@ export async function ModularDashboard(props) {
46
50
  const clientWidgets = widgets.map(widget => {
47
51
  const {
48
52
  ComponentPath: _,
53
+ fields: __,
49
54
  label,
50
55
  ...rest
51
56
  } = widget;
@@ -64,31 +69,4 @@ export async function ModularDashboard(props) {
64
69
  })
65
70
  });
66
71
  }
67
- async function getItemsFromPreferences(payload, user) {
68
- const savedPreferences = await getPreferences(PREFERENCE_KEYS.DASHBOARD_LAYOUT, payload, user.id, user.collection);
69
- if (!savedPreferences?.value || typeof savedPreferences.value !== 'object' || !('layouts' in savedPreferences.value)) {
70
- return null;
71
- }
72
- return savedPreferences.value.layouts;
73
- }
74
- async function getItemsFromConfig(defaultLayout, req, widgets) {
75
- // Handle function format
76
- let widgetInstances;
77
- if (typeof defaultLayout === 'function') {
78
- widgetInstances = await defaultLayout({
79
- req
80
- });
81
- } else {
82
- widgetInstances = defaultLayout;
83
- }
84
- return widgetInstances.map((widgetInstance, index) => {
85
- const widget = widgets.find(widget => widget.slug === widgetInstance.widgetSlug);
86
- return {
87
- id: `${widgetInstance.widgetSlug}-${index}`,
88
- maxWidth: widget?.maxWidth ?? 'full',
89
- minWidth: widget?.minWidth ?? 'x-small',
90
- width: widgetInstance.width || 'x-small'
91
- };
92
- });
93
- }
94
72
  //# sourceMappingURL=index.js.map