@webiny/app-admin 6.4.0-beta.3 → 6.4.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/base/Base/FieldRenderers/ObjectRenderer/ObjectRenderer.js +1 -1
- package/base/Base/FieldRenderers/ObjectRenderer/ObjectRenderer.js.map +1 -1
- package/base/ui/FileManager.d.ts +15 -14
- package/base/ui/FileManager.js +5 -2
- package/base/ui/FileManager.js.map +1 -1
- package/config/AdminConfig/Menu/MenuItem.d.ts +1 -0
- package/config/AdminConfig/Menu/MenuItem.js +2 -1
- package/config/AdminConfig/Menu/MenuItem.js.map +1 -1
- package/config/AdminConfig/Menu/MenuLink.d.ts +1 -0
- package/config/AdminConfig/Menu/MenuLink.js +2 -1
- package/config/AdminConfig/Menu/MenuLink.js.map +1 -1
- package/config/AdminConfig/Menu.d.ts +2 -0
- package/config/AdminConfig.d.ts +2 -0
- package/config/AdminConfig.js +1 -0
- package/config/AdminConfig.js.map +1 -1
- package/exports/admin/ui/file-manager.d.ts +3 -0
- package/exports/admin/ui/file-manager.js +2 -0
- package/features/formModel/FormModel.js +2 -2
- package/features/formModel/FormModel.js.map +1 -1
- package/features/formModel/FormModel.test.js +3 -1
- package/features/formModel/FormModel.test.js.map +1 -1
- package/features/newsletter/NewsletterSubscriptionService.d.ts +13 -0
- package/features/newsletter/NewsletterSubscriptionService.js +36 -0
- package/features/newsletter/NewsletterSubscriptionService.js.map +1 -0
- package/features/newsletter/abstractions.d.ts +11 -0
- package/features/newsletter/abstractions.js +5 -0
- package/features/newsletter/abstractions.js.map +1 -0
- package/features/newsletter/index.d.ts +1 -0
- package/features/newsletter/index.js +1 -0
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/package.json +30 -28
- package/presentation/installation/components/SystemInstaller/steps/FinishSetup/handleRestartInstallation.d.ts +1 -0
- package/presentation/installation/components/SystemInstaller/steps/FinishSetup/handleRestartInstallation.js +6 -0
- package/presentation/installation/components/SystemInstaller/steps/FinishSetup/handleRestartInstallation.js.map +1 -0
- package/presentation/installation/components/SystemInstaller/steps/FinishSetup/handleStartUsing.d.ts +2 -0
- package/presentation/installation/components/SystemInstaller/steps/FinishSetup/handleStartUsing.js +27 -0
- package/presentation/installation/components/SystemInstaller/steps/FinishSetup/handleStartUsing.js.map +1 -0
- package/presentation/installation/components/SystemInstaller/steps/FinishSetup.js +4 -4
- package/presentation/installation/components/SystemInstaller/steps/FinishSetup.js.map +1 -1
- package/presentation/installation/presenters/SystemInstaller/SystemInstallerPresenter.d.ts +3 -1
- package/presentation/installation/presenters/SystemInstaller/SystemInstallerPresenter.js +9 -3
- package/presentation/installation/presenters/SystemInstaller/SystemInstallerPresenter.js.map +1 -1
- package/presentation/installation/presenters/SystemInstaller/feature.js +2 -0
- package/presentation/installation/presenters/SystemInstaller/feature.js.map +1 -1
- package/presentation/listPresenter/ListPresenter.d.ts +1 -0
- package/presentation/listPresenter/ListPresenter.js +8 -2
- package/presentation/listPresenter/ListPresenter.js.map +1 -1
- package/presentation/listPresenter/feature.js +1 -1
- package/presentation/listPresenter/feature.js.map +1 -1
|
@@ -7,7 +7,7 @@ const ObjectRenderer = createObjectFieldRenderer(({ field })=>/*#__PURE__*/ reac
|
|
|
7
7
|
variant: "container"
|
|
8
8
|
}, /*#__PURE__*/ react.createElement(Accordion.Item, {
|
|
9
9
|
title: field.label,
|
|
10
|
-
defaultOpen: true,
|
|
10
|
+
defaultOpen: field.rendererSettings?.open ?? true,
|
|
11
11
|
className: "pl-sm"
|
|
12
12
|
}, /*#__PURE__*/ react.createElement(NestedLayout, {
|
|
13
13
|
layout: field.layout
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base/Base/FieldRenderers/ObjectRenderer/ObjectRenderer.js","sources":["../../../../../src/base/Base/FieldRenderers/ObjectRenderer/ObjectRenderer.tsx"],"sourcesContent":["import React from \"react\";\nimport { Accordion } from \"@webiny/admin-ui\";\nimport { createObjectFieldRenderer } from \"~/features/formModel/createFieldRenderer.js\";\nimport { NestedLayout } from \"./ObjectFieldComponents.js\";\n\ndeclare module \"../../../../features/formModel/abstractions.js\" {\n interface IFieldRendererRegistry {\n objectAccordionSingle: {\n fieldType: \"object\";\n settings?: {\n open?: boolean;\n };\n };\n }\n}\n\nexport const ObjectRenderer = createObjectFieldRenderer<\"objectAccordionSingle\">(({ field }) => {\n return (\n <Accordion background={\"base\"} variant={\"container\"}>\n <Accordion.Item
|
|
1
|
+
{"version":3,"file":"base/Base/FieldRenderers/ObjectRenderer/ObjectRenderer.js","sources":["../../../../../src/base/Base/FieldRenderers/ObjectRenderer/ObjectRenderer.tsx"],"sourcesContent":["import React from \"react\";\nimport { Accordion } from \"@webiny/admin-ui\";\nimport { createObjectFieldRenderer } from \"~/features/formModel/createFieldRenderer.js\";\nimport { NestedLayout } from \"./ObjectFieldComponents.js\";\n\ndeclare module \"../../../../features/formModel/abstractions.js\" {\n interface IFieldRendererRegistry {\n objectAccordionSingle: {\n fieldType: \"object\";\n settings?: {\n open?: boolean;\n };\n };\n }\n}\n\nexport const ObjectRenderer = createObjectFieldRenderer<\"objectAccordionSingle\">(({ field }) => {\n return (\n <Accordion background={\"base\"} variant={\"container\"}>\n <Accordion.Item\n title={field.label}\n defaultOpen={field.rendererSettings?.open ?? true}\n className={\"pl-sm\"}\n >\n <NestedLayout layout={field.layout} />\n </Accordion.Item>\n </Accordion>\n );\n});\n"],"names":["ObjectRenderer","createObjectFieldRenderer","field","Accordion","NestedLayout"],"mappings":";;;;AAgBO,MAAMA,iBAAiBC,0BAAmD,CAAC,EAAEC,KAAK,EAAE,GAChF,WAAP,GACI,oBAACC,WAASA;QAAC,YAAY;QAAQ,SAAS;qBACpC,oBAACA,UAAU,IAAI;QACX,OAAOD,MAAM,KAAK;QAClB,aAAaA,MAAM,gBAAgB,EAAE,QAAQ;QAC7C,WAAW;qBAEX,oBAACE,cAAYA;QAAC,QAAQF,MAAM,MAAM"}
|
package/base/ui/FileManager.d.ts
CHANGED
|
@@ -51,24 +51,25 @@ export type FileManagerProps = {
|
|
|
51
51
|
} & MultipleProps;
|
|
52
52
|
type DistributiveOmit<T, K extends keyof T> = T extends unknown ? Omit<T, K> : never;
|
|
53
53
|
export type FileManagerRendererProps = DistributiveOmit<FileManagerProps, "render">;
|
|
54
|
-
export declare const
|
|
55
|
-
|
|
56
|
-
originalName: string;
|
|
57
|
-
displayName: string;
|
|
58
|
-
} & {
|
|
59
|
-
original: ((props: FileManagerRendererProps) => React.JSX.Element | null) & {
|
|
54
|
+
export declare const FileManager: (({ render, onChange, ...rest }: FileManagerProps) => React.JSX.Element) & {
|
|
55
|
+
Renderer: ((props: FileManagerRendererProps) => React.JSX.Element | null) & {
|
|
60
56
|
original: (props: FileManagerRendererProps) => React.JSX.Element | null;
|
|
61
57
|
originalName: string;
|
|
62
58
|
displayName: string;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
59
|
+
} & {
|
|
60
|
+
original: ((props: FileManagerRendererProps) => React.JSX.Element | null) & {
|
|
61
|
+
original: (props: FileManagerRendererProps) => React.JSX.Element | null;
|
|
62
|
+
originalName: string;
|
|
63
|
+
displayName: string;
|
|
64
|
+
};
|
|
69
65
|
originalName: string;
|
|
70
66
|
displayName: string;
|
|
71
|
-
}
|
|
67
|
+
} & {
|
|
68
|
+
createDecorator: (decorator: import("@webiny/react-composition").ComponentDecorator<((props: FileManagerRendererProps) => React.JSX.Element | null) & {
|
|
69
|
+
original: (props: FileManagerRendererProps) => React.JSX.Element | null;
|
|
70
|
+
originalName: string;
|
|
71
|
+
displayName: string;
|
|
72
|
+
}>) => (props: unknown) => React.JSX.Element;
|
|
73
|
+
};
|
|
72
74
|
};
|
|
73
|
-
export declare const FileManager: ({ render, onChange, ...rest }: FileManagerProps) => React.JSX.Element;
|
|
74
75
|
export {};
|
package/base/ui/FileManager.js
CHANGED
|
@@ -2,7 +2,7 @@ import react, { useCallback, useEffect, useRef, useState } from "react";
|
|
|
2
2
|
import { Portal } from "@webiny/admin-ui";
|
|
3
3
|
import { createVoidComponent, makeDecoratable } from "@webiny/react-composition";
|
|
4
4
|
const FileManagerRenderer = makeDecoratable("FileManagerRenderer", createVoidComponent());
|
|
5
|
-
const
|
|
5
|
+
const BaseFileManager = ({ render, onChange, ...rest })=>{
|
|
6
6
|
const [isFileManagerVisible, setFileManagerVisible] = useState(rest.show);
|
|
7
7
|
const onChangeRef = useRef(onChange);
|
|
8
8
|
useEffect(()=>{
|
|
@@ -39,6 +39,9 @@ const FileManager = ({ render, onChange, ...rest })=>{
|
|
|
39
39
|
};
|
|
40
40
|
return /*#__PURE__*/ react.createElement(react.Fragment, null, renderFileManager(), renderContent());
|
|
41
41
|
};
|
|
42
|
-
|
|
42
|
+
const FileManager = Object.assign(BaseFileManager, {
|
|
43
|
+
Renderer: FileManagerRenderer
|
|
44
|
+
});
|
|
45
|
+
export { FileManager };
|
|
43
46
|
|
|
44
47
|
//# sourceMappingURL=FileManager.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base/ui/FileManager.js","sources":["../../../src/base/ui/FileManager.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { Portal } from \"@webiny/admin-ui\";\nimport { createVoidComponent, makeDecoratable } from \"@webiny/react-composition\";\n\nexport interface FileManagerOnChange<T> {\n (value: T): void;\n}\n\n/**\n * Represents a file object managed by the File Manager.\n */\nexport interface FileManagerFileItem {\n // Required - every DAM must provide these\n id: string;\n src: string;\n name: string;\n type: string; // MIME type\n size: number; // bytes\n // Required for images (apps depend on these for Next.js Image, etc.)\n width?: number;\n height?: number;\n // DAM-specific metadata\n [key: string]: any;\n}\n\nexport type FileManagerRenderPropParams<TValue> = {\n showFileManager: (onChange?: FileManagerOnChange<TValue>) => void;\n};\n\ninterface SingleFileRenderProp {\n (params: FileManagerRenderPropParams<FileManagerFileItem>): React.ReactNode;\n}\n\ninterface MultiFileRenderProp {\n (params: FileManagerRenderPropParams<FileManagerFileItem[]>): React.ReactNode;\n}\n\nexport type MultipleProps =\n | {\n multiple?: never;\n multipleMaxCount?: never;\n multipleMaxSize?: never;\n onChange?: FileManagerOnChange<FileManagerFileItem>;\n render?: SingleFileRenderProp;\n }\n | {\n multiple: true;\n multipleMaxCount?: number;\n multipleMaxSize?: number | string;\n onChange?: FileManagerOnChange<FileManagerFileItem[]>;\n render?: MultiFileRenderProp;\n };\n\nexport type FileManagerProps = {\n accept?: string[];\n images?: boolean;\n maxSize?: number | string;\n onClose?: () => void;\n onUploadCompletion?: (files: FileManagerFileItem[]) => void;\n own?: boolean;\n scope?: string;\n tags?: string[];\n show?: boolean;\n overlay?: boolean;\n} & MultipleProps;\n\n// This jewel was taken from https://davidgomes.com/pick-omit-over-union-types-in-typescript/. Massive thanks, David!\ntype DistributiveOmit<T, K extends keyof T> = T extends unknown ? Omit<T, K> : never;\n\nexport type FileManagerRendererProps = DistributiveOmit<FileManagerProps, \"render\">;\n\
|
|
1
|
+
{"version":3,"file":"base/ui/FileManager.js","sources":["../../../src/base/ui/FileManager.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { Portal } from \"@webiny/admin-ui\";\nimport { createVoidComponent, makeDecoratable } from \"@webiny/react-composition\";\n\nexport interface FileManagerOnChange<T> {\n (value: T): void;\n}\n\n/**\n * Represents a file object managed by the File Manager.\n */\nexport interface FileManagerFileItem {\n // Required - every DAM must provide these\n id: string;\n src: string;\n name: string;\n type: string; // MIME type\n size: number; // bytes\n // Required for images (apps depend on these for Next.js Image, etc.)\n width?: number;\n height?: number;\n // DAM-specific metadata\n [key: string]: any;\n}\n\nexport type FileManagerRenderPropParams<TValue> = {\n showFileManager: (onChange?: FileManagerOnChange<TValue>) => void;\n};\n\ninterface SingleFileRenderProp {\n (params: FileManagerRenderPropParams<FileManagerFileItem>): React.ReactNode;\n}\n\ninterface MultiFileRenderProp {\n (params: FileManagerRenderPropParams<FileManagerFileItem[]>): React.ReactNode;\n}\n\nexport type MultipleProps =\n | {\n multiple?: never;\n multipleMaxCount?: never;\n multipleMaxSize?: never;\n onChange?: FileManagerOnChange<FileManagerFileItem>;\n render?: SingleFileRenderProp;\n }\n | {\n multiple: true;\n multipleMaxCount?: number;\n multipleMaxSize?: number | string;\n onChange?: FileManagerOnChange<FileManagerFileItem[]>;\n render?: MultiFileRenderProp;\n };\n\nexport type FileManagerProps = {\n accept?: string[];\n images?: boolean;\n maxSize?: number | string;\n onClose?: () => void;\n onUploadCompletion?: (files: FileManagerFileItem[]) => void;\n own?: boolean;\n scope?: string;\n tags?: string[];\n show?: boolean;\n overlay?: boolean;\n} & MultipleProps;\n\n// This jewel was taken from https://davidgomes.com/pick-omit-over-union-types-in-typescript/. Massive thanks, David!\ntype DistributiveOmit<T, K extends keyof T> = T extends unknown ? Omit<T, K> : never;\n\nexport type FileManagerRendererProps = DistributiveOmit<FileManagerProps, \"render\">;\n\nconst FileManagerRenderer = makeDecoratable(\n \"FileManagerRenderer\",\n createVoidComponent<FileManagerRendererProps>()\n);\n\ntype ShowFileManagerProps =\n | FileManagerOnChange<FileManagerFileItem>\n | FileManagerOnChange<FileManagerFileItem[]>\n | undefined;\n\nconst BaseFileManager = ({ render, onChange, ...rest }: FileManagerProps) => {\n const [isFileManagerVisible, setFileManagerVisible] = useState(rest.show);\n const onChangeRef = useRef(onChange);\n\n useEffect(() => {\n onChangeRef.current = onChange;\n }, [onChange]);\n\n const handleShowFileManager = useCallback((newOnChange: ShowFileManagerProps) => {\n if (typeof newOnChange === \"function\") {\n onChangeRef.current = newOnChange;\n }\n setFileManagerVisible(true);\n }, []);\n\n const handleCloseFileManager = useCallback(() => {\n setFileManagerVisible(false);\n }, []);\n\n const renderFileManager = () => {\n if (!isFileManagerVisible) {\n return null;\n }\n\n // Render as overlay\n if (rest.overlay) {\n return (\n <Portal>\n {/*@ts-expect-error*/}\n <FileManagerRenderer\n onClose={handleCloseFileManager}\n onChange={onChangeRef.current}\n {...rest}\n />\n </Portal>\n );\n }\n\n // Render inline\n return (\n // @ts-expect-error\n <FileManagerRenderer\n onClose={handleCloseFileManager}\n onChange={onChangeRef.current}\n {...rest}\n />\n );\n };\n\n const renderContent = () => {\n const renderProps = { showFileManager: handleShowFileManager };\n\n if (render) {\n return render(renderProps);\n }\n\n return null;\n };\n\n return (\n <>\n {renderFileManager()}\n {renderContent()}\n </>\n );\n};\n\nexport const FileManager = Object.assign(BaseFileManager, { Renderer: FileManagerRenderer });\n"],"names":["FileManagerRenderer","makeDecoratable","createVoidComponent","BaseFileManager","render","onChange","rest","isFileManagerVisible","setFileManagerVisible","useState","onChangeRef","useRef","useEffect","handleShowFileManager","useCallback","newOnChange","handleCloseFileManager","renderFileManager","Portal","renderContent","renderProps","FileManager","Object"],"mappings":";;;AAuEA,MAAMA,sBAAsBC,gBACxB,uBACAC;AAQJ,MAAMC,kBAAkB,CAAC,EAAEC,MAAM,EAAEC,QAAQ,EAAE,GAAGC,MAAwB;IACpE,MAAM,CAACC,sBAAsBC,sBAAsB,GAAGC,SAASH,KAAK,IAAI;IACxE,MAAMI,cAAcC,OAAON;IAE3BO,UAAU;QACNF,YAAY,OAAO,GAAGL;IAC1B,GAAG;QAACA;KAAS;IAEb,MAAMQ,wBAAwBC,YAAY,CAACC;QACvC,IAAI,AAAuB,cAAvB,OAAOA,aACPL,YAAY,OAAO,GAAGK;QAE1BP,sBAAsB;IAC1B,GAAG,EAAE;IAEL,MAAMQ,yBAAyBF,YAAY;QACvCN,sBAAsB;IAC1B,GAAG,EAAE;IAEL,MAAMS,oBAAoB;QACtB,IAAI,CAACV,sBACD,OAAO;QAIX,IAAID,KAAK,OAAO,EACZ,OAAO,WAAP,GACI,oBAACY,QAAMA,MAAAA,WAAAA,GAEH,oBAAClB,qBAAmBA;YAChB,SAASgB;YACT,UAAUN,YAAY,OAAO;YAC5B,GAAGJ,IAAI;;QAOxB,O,cAEI,oBAACN,qBAAmBA;YAChB,SAASgB;YACT,UAAUN,YAAY,OAAO;YAC5B,GAAGJ,IAAI;;IAGpB;IAEA,MAAMa,gBAAgB;QAClB,MAAMC,cAAc;YAAE,iBAAiBP;QAAsB;QAE7D,IAAIT,QACA,OAAOA,OAAOgB;QAGlB,OAAO;IACX;IAEA,OAAO,WAAP,GACI,0CACKH,qBACAE;AAGb;AAEO,MAAME,cAAcC,OAAO,MAAM,CAACnB,iBAAiB;IAAE,UAAUH;AAAoB"}
|
|
@@ -39,5 +39,6 @@ declare const MenuItem: ((props: SidebarMenuItemButtonProps) => React.JSX.Elemen
|
|
|
39
39
|
displayName: string;
|
|
40
40
|
}>) => (props: unknown) => React.JSX.Element;
|
|
41
41
|
};
|
|
42
|
+
Badge: ({ text }: import("@webiny/admin-ui/Sidebar/components/items/SidebarMenuItemBadge").SidebarMenuItemBadgeProps) => React.JSX.Element;
|
|
42
43
|
};
|
|
43
44
|
export { MenuItem };
|
|
@@ -5,7 +5,8 @@ const MenuLinkBase = (props)=>/*#__PURE__*/ react.createElement(Sidebar.Item, pr
|
|
|
5
5
|
const DecoratableMenuItem = makeDecoratable("MenuItem", MenuLinkBase);
|
|
6
6
|
const MenuItem = Object.assign(DecoratableMenuItem, {
|
|
7
7
|
Action: Sidebar.Item.Action,
|
|
8
|
-
Icon: Sidebar.Item.Icon
|
|
8
|
+
Icon: Sidebar.Item.Icon,
|
|
9
|
+
Badge: Sidebar.Item.Badge
|
|
9
10
|
});
|
|
10
11
|
export { MenuItem };
|
|
11
12
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config/AdminConfig/Menu/MenuItem.js","sources":["../../../../src/config/AdminConfig/Menu/MenuItem.tsx"],"sourcesContent":["import React from \"react\";\nimport { makeDecoratable } from \"@webiny/react-composition\";\nimport { Sidebar } from \"@webiny/admin-ui\";\nimport { type SidebarMenuItemButtonProps } from \"@webiny/admin-ui/Sidebar/components/items/SidebarMenuItem.js\";\n\nconst MenuLinkBase = (props: SidebarMenuItemButtonProps) => {\n return <Sidebar.Item {...props} />;\n};\n\nconst DecoratableMenuItem = makeDecoratable(\"MenuItem\", MenuLinkBase);\n\nconst MenuItem = Object.assign(DecoratableMenuItem, {\n Action: Sidebar.Item.Action,\n Icon: Sidebar.Item.Icon\n});\n\nexport { MenuItem };\n"],"names":["MenuLinkBase","props","Sidebar","DecoratableMenuItem","makeDecoratable","MenuItem","Object"],"mappings":";;;AAKA,MAAMA,eAAe,CAACC,QACX,WAAP,GAAO,oBAACC,QAAQ,IAAI,EAAKD;AAG7B,MAAME,sBAAsBC,gBAAgB,YAAYJ;AAExD,MAAMK,WAAWC,OAAO,MAAM,CAACH,qBAAqB;IAChD,QAAQD,QAAQ,IAAI,CAAC,MAAM;IAC3B,MAAMA,QAAQ,IAAI,CAAC,IAAI;
|
|
1
|
+
{"version":3,"file":"config/AdminConfig/Menu/MenuItem.js","sources":["../../../../src/config/AdminConfig/Menu/MenuItem.tsx"],"sourcesContent":["import React from \"react\";\nimport { makeDecoratable } from \"@webiny/react-composition\";\nimport { Sidebar } from \"@webiny/admin-ui\";\nimport { type SidebarMenuItemButtonProps } from \"@webiny/admin-ui/Sidebar/components/items/SidebarMenuItem.js\";\n\nconst MenuLinkBase = (props: SidebarMenuItemButtonProps) => {\n return <Sidebar.Item {...props} />;\n};\n\nconst DecoratableMenuItem = makeDecoratable(\"MenuItem\", MenuLinkBase);\n\nconst MenuItem = Object.assign(DecoratableMenuItem, {\n Action: Sidebar.Item.Action,\n Icon: Sidebar.Item.Icon,\n Badge: Sidebar.Item.Badge\n});\n\nexport { MenuItem };\n"],"names":["MenuLinkBase","props","Sidebar","DecoratableMenuItem","makeDecoratable","MenuItem","Object"],"mappings":";;;AAKA,MAAMA,eAAe,CAACC,QACX,WAAP,GAAO,oBAACC,QAAQ,IAAI,EAAKD;AAG7B,MAAME,sBAAsBC,gBAAgB,YAAYJ;AAExD,MAAMK,WAAWC,OAAO,MAAM,CAACH,qBAAqB;IAChD,QAAQD,QAAQ,IAAI,CAAC,MAAM;IAC3B,MAAMA,QAAQ,IAAI,CAAC,IAAI;IACvB,OAAOA,QAAQ,IAAI,CAAC,KAAK;AAC7B"}
|
|
@@ -39,5 +39,6 @@ declare const MenuLink: ((props: SidebarMenuItemLinkProps) => React.JSX.Element
|
|
|
39
39
|
displayName: string;
|
|
40
40
|
}>) => (props: unknown) => React.JSX.Element;
|
|
41
41
|
};
|
|
42
|
+
Badge: ({ text }: import("@webiny/admin-ui/Sidebar/components/items/SidebarMenuItemBadge").SidebarMenuItemBadgeProps) => React.JSX.Element;
|
|
42
43
|
};
|
|
43
44
|
export { MenuLink };
|
|
@@ -14,7 +14,8 @@ const MenuLinkBase = (props)=>{
|
|
|
14
14
|
const DecoratableMenuLink = makeDecoratable("MenuLink", MenuLinkBase);
|
|
15
15
|
const MenuLink = Object.assign(DecoratableMenuLink, {
|
|
16
16
|
Action: Sidebar.Link.Action,
|
|
17
|
-
Icon: Sidebar.Link.Icon
|
|
17
|
+
Icon: Sidebar.Link.Icon,
|
|
18
|
+
Badge: Sidebar.Link.Badge
|
|
18
19
|
});
|
|
19
20
|
export { MenuLink };
|
|
20
21
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config/AdminConfig/Menu/MenuLink.js","sources":["../../../../src/config/AdminConfig/Menu/MenuLink.tsx"],"sourcesContent":["import React from \"react\";\nimport { makeDecoratable } from \"@webiny/react-composition\";\nimport { Sidebar } from \"@webiny/admin-ui\";\nimport { type SidebarMenuItemLinkProps } from \"@webiny/admin-ui/Sidebar/components/items/SidebarMenuLink.js\";\nimport { useRoute } from \"@webiny/app\";\n\nconst MenuLinkBase = (props: SidebarMenuItemLinkProps) => {\n const { route } = useRoute();\n\n if (!route) {\n return null;\n }\n\n const active = route.pathname === props.to.split(\"?\")[0];\n\n return <Sidebar.Link {...props} active={active} />;\n};\n\nconst DecoratableMenuLink = makeDecoratable(\"MenuLink\", MenuLinkBase);\n\nconst MenuLink = Object.assign(DecoratableMenuLink, {\n Action: Sidebar.Link.Action,\n Icon: Sidebar.Link.Icon\n});\n\nexport { MenuLink };\n"],"names":["MenuLinkBase","props","route","useRoute","active","Sidebar","DecoratableMenuLink","makeDecoratable","MenuLink","Object"],"mappings":";;;;AAMA,MAAMA,eAAe,CAACC;IAClB,MAAM,EAAEC,KAAK,EAAE,GAAGC;IAElB,IAAI,CAACD,OACD,OAAO;IAGX,MAAME,SAASF,MAAM,QAAQ,KAAKD,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;IAExD,OAAO,WAAP,GAAO,oBAACI,QAAQ,IAAI;QAAE,GAAGJ,KAAK;QAAE,QAAQG;;AAC5C;AAEA,MAAME,sBAAsBC,gBAAgB,YAAYP;AAExD,MAAMQ,WAAWC,OAAO,MAAM,CAACH,qBAAqB;IAChD,QAAQD,QAAQ,IAAI,CAAC,MAAM;IAC3B,MAAMA,QAAQ,IAAI,CAAC,IAAI;
|
|
1
|
+
{"version":3,"file":"config/AdminConfig/Menu/MenuLink.js","sources":["../../../../src/config/AdminConfig/Menu/MenuLink.tsx"],"sourcesContent":["import React from \"react\";\nimport { makeDecoratable } from \"@webiny/react-composition\";\nimport { Sidebar } from \"@webiny/admin-ui\";\nimport { type SidebarMenuItemLinkProps } from \"@webiny/admin-ui/Sidebar/components/items/SidebarMenuLink.js\";\nimport { useRoute } from \"@webiny/app\";\n\nconst MenuLinkBase = (props: SidebarMenuItemLinkProps) => {\n const { route } = useRoute();\n\n if (!route) {\n return null;\n }\n\n const active = route.pathname === props.to.split(\"?\")[0];\n\n return <Sidebar.Link {...props} active={active} />;\n};\n\nconst DecoratableMenuLink = makeDecoratable(\"MenuLink\", MenuLinkBase);\n\nconst MenuLink = Object.assign(DecoratableMenuLink, {\n Action: Sidebar.Link.Action,\n Icon: Sidebar.Link.Icon,\n Badge: Sidebar.Link.Badge\n});\n\nexport { MenuLink };\n"],"names":["MenuLinkBase","props","route","useRoute","active","Sidebar","DecoratableMenuLink","makeDecoratable","MenuLink","Object"],"mappings":";;;;AAMA,MAAMA,eAAe,CAACC;IAClB,MAAM,EAAEC,KAAK,EAAE,GAAGC;IAElB,IAAI,CAACD,OACD,OAAO;IAGX,MAAME,SAASF,MAAM,QAAQ,KAAKD,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;IAExD,OAAO,WAAP,GAAO,oBAACI,QAAQ,IAAI;QAAE,GAAGJ,KAAK;QAAE,QAAQG;;AAC5C;AAEA,MAAME,sBAAsBC,gBAAgB,YAAYP;AAExD,MAAMQ,WAAWC,OAAO,MAAM,CAACH,qBAAqB;IAChD,QAAQD,QAAQ,IAAI,CAAC,MAAM;IAC3B,MAAMA,QAAQ,IAAI,CAAC,IAAI;IACvB,OAAOA,QAAQ,IAAI,CAAC,KAAK;AAC7B"}
|
|
@@ -70,6 +70,7 @@ export declare const Menu: (({ name, parent, hideIfEmpty, tags, element, remove,
|
|
|
70
70
|
displayName: string;
|
|
71
71
|
}>) => (props: unknown) => React.JSX.Element;
|
|
72
72
|
};
|
|
73
|
+
Badge: ({ text }: import("@webiny/admin-ui/Sidebar/components/items/SidebarMenuItemBadge.js").SidebarMenuItemBadgeProps) => React.JSX.Element;
|
|
73
74
|
};
|
|
74
75
|
Link: ((props: import("@webiny/admin-ui/Sidebar/components/items/SidebarMenuItem.js").SidebarMenuItemLinkProps) => React.JSX.Element | null) & {
|
|
75
76
|
original: (props: import("@webiny/admin-ui/Sidebar/components/items/SidebarMenuItem.js").SidebarMenuItemLinkProps) => React.JSX.Element | null;
|
|
@@ -110,6 +111,7 @@ export declare const Menu: (({ name, parent, hideIfEmpty, tags, element, remove,
|
|
|
110
111
|
displayName: string;
|
|
111
112
|
}>) => (props: unknown) => React.JSX.Element;
|
|
112
113
|
};
|
|
114
|
+
Badge: ({ text }: import("@webiny/admin-ui/Sidebar/components/items/SidebarMenuItemBadge.js").SidebarMenuItemBadgeProps) => React.JSX.Element;
|
|
113
115
|
};
|
|
114
116
|
Group: ((props: import("@webiny/admin-ui/Sidebar/components/items/SidebarMenuItem.js").SidebarMenuItemGroupProps) => React.JSX.Element) & {
|
|
115
117
|
original: (props: import("@webiny/admin-ui/Sidebar/components/items/SidebarMenuItem.js").SidebarMenuItemGroupProps) => React.JSX.Element;
|
package/config/AdminConfig.d.ts
CHANGED
|
@@ -102,6 +102,7 @@ export declare const AdminConfig: (({ children }: PrivateProps) => React.JSX.Ele
|
|
|
102
102
|
displayName: string;
|
|
103
103
|
}>) => (props: unknown) => React.JSX.Element;
|
|
104
104
|
};
|
|
105
|
+
Badge: ({ text }: import("@webiny/admin-ui/Sidebar/components/items/SidebarMenuItemBadge.js").SidebarMenuItemBadgeProps) => React.JSX.Element;
|
|
105
106
|
};
|
|
106
107
|
Link: ((props: import("@webiny/admin-ui/Sidebar/components/items/SidebarMenuItem.js").SidebarMenuItemLinkProps) => React.JSX.Element | null) & {
|
|
107
108
|
original: (props: import("@webiny/admin-ui/Sidebar/components/items/SidebarMenuItem.js").SidebarMenuItemLinkProps) => React.JSX.Element | null;
|
|
@@ -142,6 +143,7 @@ export declare const AdminConfig: (({ children }: PrivateProps) => React.JSX.Ele
|
|
|
142
143
|
displayName: string;
|
|
143
144
|
}>) => (props: unknown) => React.JSX.Element;
|
|
144
145
|
};
|
|
146
|
+
Badge: ({ text }: import("@webiny/admin-ui/Sidebar/components/items/SidebarMenuItemBadge.js").SidebarMenuItemBadgeProps) => React.JSX.Element;
|
|
145
147
|
};
|
|
146
148
|
Group: ((props: import("@webiny/admin-ui/Sidebar/components/items/SidebarMenuItem.js").SidebarMenuItemGroupProps) => React.JSX.Element) & {
|
|
147
149
|
original: (props: import("@webiny/admin-ui/Sidebar/components/items/SidebarMenuItem.js").SidebarMenuItemGroupProps) => React.JSX.Element;
|
package/config/AdminConfig.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config/AdminConfig.js","sources":["../../src/config/AdminConfig.tsx"],"sourcesContent":["import React from \"react\";\nimport { createProvider } from \"@webiny/app\";\nimport { Menu, type MenuConfig } from \"./AdminConfig/Menu.js\";\nimport type { TenantConfig } from \"./AdminConfig/Tenant.js\";\nimport { Tenant } from \"./AdminConfig/Tenant.js\";\nimport type { SupportMenuConfig } from \"./AdminConfig/Menu/SupportMenu.js\";\nimport type { UserMenuConfig } from \"./AdminConfig/Menu/UserMenu.js\";\nimport { Route } from \"./AdminConfig/Route.js\";\nimport { Theme } from \"./AdminConfig/Theme.js\";\nimport { Dashboard } from \"./AdminConfig/Dashboard.js\";\nimport { type WidgetConfig } from \"./AdminConfig/Widget.js\";\nimport { Security } from \"./AdminConfig/Security.js\";\nimport type { PermissionRendererConfig } from \"../permissions/types.js\";\nimport { LexicalTheme } from \"./AdminConfig/LexicalTheme.js\";\nimport { Title } from \"./AdminConfig/Title.js\";\nimport { Logo } from \"./AdminConfig/Logo.js\";\nimport { Dialog } from \"./AdminConfig/Dialog.js\";\nimport type { DialogConfig } from \"./AdminConfig/Dialog.js\";\nimport { Form } from \"./AdminConfig/Form.js\";\nimport type { FieldRendererConfig } from \"./AdminConfig/FieldRenderer.js\";\nimport type { LayoutRendererConfig } from \"./AdminConfig/LayoutRenderer.js\";\nimport { createAdminConfig } from \"./createAdminConfig.js\";\nimport type { EditorTheme } from \"@webiny/lexical-theme\";\nimport { createLexicalTokens } from \"@webiny/lexical-theme/createLexicalEditorTokens.js\";\n\nconst base = createAdminConfig<AdminConfig>();\n\nexport const AdminWithConfig = Object.assign(base.WithConfig, {\n displayName: \"AdminWithConfig\"\n});\n\ninterface AdminConfig {\n menus: MenuConfig[];\n supportMenus: SupportMenuConfig[];\n userMenus: UserMenuConfig[];\n tenant: TenantConfig;\n title: string;\n squareLogo: React.ReactNode;\n horizontalLogo: React.ReactNode;\n widgets: WidgetConfig[];\n permissionRenderers: PermissionRendererConfig[];\n lexicalTheme: EditorTheme;\n dialogs: DialogConfig[];\n fieldRenderers: FieldRendererConfig[];\n layoutRenderers: LayoutRendererConfig[];\n}\n\n/* Once the app fully renders (after the LoginScreen), apply protected configs. */\nexport const AdminConfigPlugin = <base.ApplyProtectedConfig />;\n\nexport const AdminConfigProvider = createProvider(Original => {\n return function AdminConfigProvider({ children }) {\n return (\n <AdminWithConfig>\n <base.ApplyPublicConfig />\n <Original>{children}</Original>\n </AdminWithConfig>\n );\n };\n});\n\nconst lexicalTokens = createLexicalTokens(\"wa-lx-\");\n\nexport const useAdminConfig = () => {\n const baseConfig = base.useConfig();\n\n const lexicalTheme: EditorTheme = {\n colors: baseConfig.lexicalTheme?.colors,\n typography: baseConfig.lexicalTheme?.typography || {},\n tokens: lexicalTokens\n };\n\n return {\n menus: baseConfig.menus ?? [],\n userMenus: baseConfig.userMenus ?? [],\n supportMenus: baseConfig.supportMenus ?? [],\n title: baseConfig.title,\n logo: {\n squareLogo: baseConfig.squareLogo,\n horizontalLogo: baseConfig.horizontalLogo\n },\n widgets: baseConfig.widgets ?? [],\n permissionRenderers: baseConfig.permissionRenderers ?? [],\n lexicalTheme,\n dialogs: baseConfig.dialogs ?? [],\n fieldRenderers: baseConfig.fieldRenderers ?? [],\n layoutRenderers: baseConfig.layoutRenderers ?? []\n };\n};\n\nexport interface PublicProps {\n children: React.ReactNode;\n}\n\nexport const Public = ({ children }: PublicProps) => {\n return <base.PublicConfig>{children}</base.PublicConfig>;\n};\n\nexport interface PrivateProps {\n children: React.ReactNode;\n}\n\nexport const Private = ({ children }: PrivateProps) => {\n return <base.PrivateConfig>{children}</base.PrivateConfig>;\n};\n\nexport const AdminConfig = Object.assign(Private, {\n Public,\n Theme,\n Menu,\n Route,\n Tenant,\n Title,\n Logo,\n Dashboard,\n Security,\n LexicalTheme,\n Dialog,\n Form,\n useAdminConfig\n});\n"],"names":["base","createAdminConfig","AdminWithConfig","Object","AdminConfigPlugin","AdminConfigProvider","createProvider","Original","children","lexicalTokens","createLexicalTokens","useAdminConfig","baseConfig","lexicalTheme","Public","Private","AdminConfig","Theme","Menu","Route","Tenant","Title","Logo","Dashboard","Security","LexicalTheme","Dialog","Form"],"mappings":";;;;;;;;;;;;;;;AAyBA,MAAMA,OAAOC;AAEN,MAAMC,kBAAkBC,OAAO,MAAM,CAACH,KAAK,UAAU,EAAE;IAC1D,aAAa;AACjB;AAmBO,MAAMI,oBAAoB,WAAHA,GAAG,oBAACJ,KAAK,oBAAoB;AAEpD,MAAMK,kCAAsBC,eAAeC,CAAAA,WACvC,SAA6B,EAAEC,QAAQ,EAAE;QAC5C,OAAO,WAAP,GACI,oBAACN,iBAAeA,MAAAA,WAAAA,GACZ,oBAACF,KAAK,iBAAiB,uBACvB,oBAACO,UAAAA,MAAUC;IAGvB;AAGJ,MAAMC,gBAAgBC,oBAAoB;AAEnC,MAAMC,iBAAiB;IAC1B,MAAMC,aAAaZ,KAAK,SAAS;IAEjC,MAAMa,eAA4B;QAC9B,QAAQD,WAAW,YAAY,EAAE;QACjC,YAAYA,WAAW,YAAY,EAAE,cAAc,CAAC;QACpD,QAAQH;IACZ;IAEA,OAAO;QACH,OAAOG,WAAW,KAAK,IAAI,EAAE;QAC7B,WAAWA,WAAW,SAAS,IAAI,EAAE;QACrC,cAAcA,WAAW,YAAY,IAAI,EAAE;QAC3C,OAAOA,WAAW,KAAK;QACvB,MAAM;YACF,YAAYA,WAAW,UAAU;YACjC,gBAAgBA,WAAW,cAAc;QAC7C;QACA,SAASA,WAAW,OAAO,IAAI,EAAE;QACjC,qBAAqBA,WAAW,mBAAmB,IAAI,EAAE;QACzDC;QACA,SAASD,WAAW,OAAO,IAAI,EAAE;QACjC,gBAAgBA,WAAW,cAAc,IAAI,EAAE;QAC/C,iBAAiBA,WAAW,eAAe,IAAI,EAAE;IACrD;AACJ;AAMO,MAAME,SAAS,CAAC,EAAEN,QAAQ,EAAe,GACrC,WAAP,GAAO,oBAACR,KAAK,YAAY,QAAEQ;AAOxB,MAAMO,UAAU,CAAC,EAAEP,QAAQ,EAAgB,GACvC,WAAP,GAAO,oBAACR,KAAK,aAAa,QAAEQ;AAGzB,MAAMQ,cAAcb,OAAO,MAAM,CAACY,SAAS;IAC9CD,QAAAA;IACAG,OAAKA;IACLC,MAAIA;IACJC,OAAKA;IACLC,QAAMA;IACNC,OAAKA;IACLC,MAAIA;IACJC,WAASA;IACTC,UAAQA;IACRC,cAAYA;IACZC,QAAMA;IACNC,MAAIA;IACJhB,gBAAAA;AACJ"}
|
|
1
|
+
{"version":3,"file":"config/AdminConfig.js","sources":["../../src/config/AdminConfig.tsx"],"sourcesContent":["import React from \"react\";\nimport { createProvider } from \"@webiny/app\";\nimport { Menu, type MenuConfig } from \"./AdminConfig/Menu.js\";\nimport type { TenantConfig } from \"./AdminConfig/Tenant.js\";\nimport { Tenant } from \"./AdminConfig/Tenant.js\";\nimport type { SupportMenuConfig } from \"./AdminConfig/Menu/SupportMenu.js\";\nimport type { UserMenuConfig } from \"./AdminConfig/Menu/UserMenu.js\";\nimport { Route } from \"./AdminConfig/Route.js\";\nimport { Theme } from \"./AdminConfig/Theme.js\";\nimport { Dashboard } from \"./AdminConfig/Dashboard.js\";\nimport { type WidgetConfig } from \"./AdminConfig/Widget.js\";\nimport { Security } from \"./AdminConfig/Security.js\";\nimport type { PermissionRendererConfig } from \"../permissions/types.js\";\nimport { LexicalTheme } from \"./AdminConfig/LexicalTheme.js\";\nimport { Title } from \"./AdminConfig/Title.js\";\nimport { Logo } from \"./AdminConfig/Logo.js\";\nimport { Dialog } from \"./AdminConfig/Dialog.js\";\nimport type { DialogConfig } from \"./AdminConfig/Dialog.js\";\nimport { Form } from \"./AdminConfig/Form.js\";\nimport type { FieldRendererConfig } from \"./AdminConfig/FieldRenderer.js\";\nimport type { LayoutRendererConfig } from \"./AdminConfig/LayoutRenderer.js\";\nimport { createAdminConfig } from \"./createAdminConfig.js\";\nimport type { EditorTheme } from \"@webiny/lexical-theme\";\nimport { createLexicalTokens } from \"@webiny/lexical-theme/createLexicalEditorTokens.js\";\n\nconst base = createAdminConfig<AdminConfig>();\n\nexport const AdminWithConfig = Object.assign(base.WithConfig, {\n displayName: \"AdminWithConfig\"\n});\n\ninterface AdminConfig {\n menus: MenuConfig[];\n supportMenus: SupportMenuConfig[];\n userMenus: UserMenuConfig[];\n tenant: TenantConfig;\n title: string;\n squareLogo: React.ReactNode;\n horizontalLogo: React.ReactNode;\n widgets: WidgetConfig[];\n permissionRenderers: PermissionRendererConfig[];\n lexicalTheme: EditorTheme;\n dialogs: DialogConfig[];\n fieldRenderers: FieldRendererConfig[];\n layoutRenderers: LayoutRendererConfig[];\n}\n\n/* Once the app fully renders (after the LoginScreen), apply protected configs. */\nexport const AdminConfigPlugin = <base.ApplyProtectedConfig />;\n\nexport const AdminConfigProvider = createProvider(Original => {\n return function AdminConfigProvider({ children }) {\n return (\n <AdminWithConfig>\n <base.ApplyPublicConfig />\n <Original>{children}</Original>\n </AdminWithConfig>\n );\n };\n});\n\nconst lexicalTokens = createLexicalTokens(\"wa-lx-\");\n\nexport const useAdminConfig = () => {\n const baseConfig = base.useConfig();\n\n const lexicalTheme: EditorTheme = {\n colors: baseConfig.lexicalTheme?.colors,\n typography: baseConfig.lexicalTheme?.typography || {},\n fontSizes: [],\n tokens: lexicalTokens\n };\n\n return {\n menus: baseConfig.menus ?? [],\n userMenus: baseConfig.userMenus ?? [],\n supportMenus: baseConfig.supportMenus ?? [],\n title: baseConfig.title,\n logo: {\n squareLogo: baseConfig.squareLogo,\n horizontalLogo: baseConfig.horizontalLogo\n },\n widgets: baseConfig.widgets ?? [],\n permissionRenderers: baseConfig.permissionRenderers ?? [],\n lexicalTheme,\n dialogs: baseConfig.dialogs ?? [],\n fieldRenderers: baseConfig.fieldRenderers ?? [],\n layoutRenderers: baseConfig.layoutRenderers ?? []\n };\n};\n\nexport interface PublicProps {\n children: React.ReactNode;\n}\n\nexport const Public = ({ children }: PublicProps) => {\n return <base.PublicConfig>{children}</base.PublicConfig>;\n};\n\nexport interface PrivateProps {\n children: React.ReactNode;\n}\n\nexport const Private = ({ children }: PrivateProps) => {\n return <base.PrivateConfig>{children}</base.PrivateConfig>;\n};\n\nexport const AdminConfig = Object.assign(Private, {\n Public,\n Theme,\n Menu,\n Route,\n Tenant,\n Title,\n Logo,\n Dashboard,\n Security,\n LexicalTheme,\n Dialog,\n Form,\n useAdminConfig\n});\n"],"names":["base","createAdminConfig","AdminWithConfig","Object","AdminConfigPlugin","AdminConfigProvider","createProvider","Original","children","lexicalTokens","createLexicalTokens","useAdminConfig","baseConfig","lexicalTheme","Public","Private","AdminConfig","Theme","Menu","Route","Tenant","Title","Logo","Dashboard","Security","LexicalTheme","Dialog","Form"],"mappings":";;;;;;;;;;;;;;;AAyBA,MAAMA,OAAOC;AAEN,MAAMC,kBAAkBC,OAAO,MAAM,CAACH,KAAK,UAAU,EAAE;IAC1D,aAAa;AACjB;AAmBO,MAAMI,oBAAoB,WAAHA,GAAG,oBAACJ,KAAK,oBAAoB;AAEpD,MAAMK,kCAAsBC,eAAeC,CAAAA,WACvC,SAA6B,EAAEC,QAAQ,EAAE;QAC5C,OAAO,WAAP,GACI,oBAACN,iBAAeA,MAAAA,WAAAA,GACZ,oBAACF,KAAK,iBAAiB,uBACvB,oBAACO,UAAAA,MAAUC;IAGvB;AAGJ,MAAMC,gBAAgBC,oBAAoB;AAEnC,MAAMC,iBAAiB;IAC1B,MAAMC,aAAaZ,KAAK,SAAS;IAEjC,MAAMa,eAA4B;QAC9B,QAAQD,WAAW,YAAY,EAAE;QACjC,YAAYA,WAAW,YAAY,EAAE,cAAc,CAAC;QACpD,WAAW,EAAE;QACb,QAAQH;IACZ;IAEA,OAAO;QACH,OAAOG,WAAW,KAAK,IAAI,EAAE;QAC7B,WAAWA,WAAW,SAAS,IAAI,EAAE;QACrC,cAAcA,WAAW,YAAY,IAAI,EAAE;QAC3C,OAAOA,WAAW,KAAK;QACvB,MAAM;YACF,YAAYA,WAAW,UAAU;YACjC,gBAAgBA,WAAW,cAAc;QAC7C;QACA,SAASA,WAAW,OAAO,IAAI,EAAE;QACjC,qBAAqBA,WAAW,mBAAmB,IAAI,EAAE;QACzDC;QACA,SAASD,WAAW,OAAO,IAAI,EAAE;QACjC,gBAAgBA,WAAW,cAAc,IAAI,EAAE;QAC/C,iBAAiBA,WAAW,eAAe,IAAI,EAAE;IACrD;AACJ;AAMO,MAAME,SAAS,CAAC,EAAEN,QAAQ,EAAe,GACrC,WAAP,GAAO,oBAACR,KAAK,YAAY,QAAEQ;AAOxB,MAAMO,UAAU,CAAC,EAAEP,QAAQ,EAAgB,GACvC,WAAP,GAAO,oBAACR,KAAK,aAAa,QAAEQ;AAGzB,MAAMQ,cAAcb,OAAO,MAAM,CAACY,SAAS;IAC9CD,QAAAA;IACAG,OAAKA;IACLC,MAAIA;IACJC,OAAKA;IACLC,QAAMA;IACNC,OAAKA;IACLC,MAAIA;IACJC,WAASA;IACTC,UAAQA;IACRC,cAAYA;IACZC,QAAMA;IACNC,MAAIA;IACJhB,gBAAAA;AACJ"}
|
|
@@ -205,14 +205,14 @@ class FormModel {
|
|
|
205
205
|
const path = pathPrefix ? `${pathPrefix}.${field.name}` : field.name;
|
|
206
206
|
const segment = field.config.label || field.name;
|
|
207
207
|
if (isObjectField(field)) {
|
|
208
|
-
if (false === field.vm.validation.isValid && !ruleErrorPaths.has(path)) errors.push({
|
|
208
|
+
if (false === field.vm.validation.isValid && field.vm.validation.message && !ruleErrorPaths.has(path)) errors.push({
|
|
209
209
|
path,
|
|
210
210
|
label: field.config.label,
|
|
211
211
|
breadcrumb: [
|
|
212
212
|
...trail,
|
|
213
213
|
segment
|
|
214
214
|
],
|
|
215
|
-
message: field.vm.validation.message
|
|
215
|
+
message: field.vm.validation.message
|
|
216
216
|
});
|
|
217
217
|
if (field.config.isList) for (const [index, item] of field.items.entries())collectErrors(item.children, `${path}.${index}`, [
|
|
218
218
|
...trail,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/formModel/FormModel.js","sources":["../../../src/features/formModel/FormModel.ts"],"sourcesContent":["import { makeAutoObservable, computed, toJS, runInAction, observable } from \"mobx\";\nimport { Field } from \"./Field.js\";\nimport { ObjectField, isObjectField } from \"./ObjectField.js\";\nimport { LayoutBuilderFactory } from \"./LayoutBuilderFactory.js\";\nimport { LayoutMutator } from \"./LayoutMutator.js\";\nimport { LayoutResolver } from \"./LayoutResolver.js\";\nimport { FocusManager } from \"./FocusManager.js\";\nimport type {\n IFormModel,\n IField,\n IFieldBuilder,\n IFieldBuilderRegistry,\n IObjectFieldConfig,\n IFormVM,\n IFormError,\n IFormModelConfig,\n ILayoutBuilder,\n ILayoutNodeBuilder,\n ILayoutModifier,\n IPositionedLayoutNode,\n ILayoutNodeAccessHandle,\n IRule,\n IRuleEvaluator,\n LayoutNode,\n LayoutNodeVM,\n FormRule,\n FormRuleFn\n} from \"./abstractions.js\";\n\nexport class FormModel implements IFormModel {\n private _fields = new Map<string, IField>();\n private _builders = new Map<string, IFieldBuilder>();\n private _layout: LayoutNode[] = [];\n private _baseline = new Map<string, unknown>();\n private _submitted = false;\n private _submitCount = 0;\n private _validateOnChange = false;\n private _isValid: boolean | null = null;\n private _formRuleErrors: IFormError[] = [];\n private _activeTabs = observable.map<string, string>();\n private _ruleEvaluators: IRuleEvaluator[] = [];\n private _warnedRuleTypes = new Set<string>();\n private _formRules: FormRule[] = [];\n private _lastFocusedField: IField | null = null;\n private _registry: IFieldBuilderRegistry;\n\n private _layoutMutator = new LayoutMutator();\n private _layoutResolver: LayoutResolver = null!;\n private _focusManager: FocusManager = null!;\n\n constructor(config: IFormModelConfig, registry: IFieldBuilderRegistry) {\n this._registry = registry;\n this._ruleEvaluators = config.ruleEvaluators ?? [];\n\n const builders = config.fields(registry);\n\n for (const [name, builder] of Object.entries(builders)) {\n this._builders.set(name, builder);\n const fieldConfig = builder.build(name);\n const field = this._createField(fieldConfig);\n field.setForm(this);\n this._fields.set(name, field);\n }\n\n if (config.layout) {\n this._layout = LayoutBuilderFactory.buildNodes(\n config.layout(LayoutBuilderFactory.create())\n );\n this._warnOrphanFields();\n } else {\n this._layout = this._generateDefaultLayout();\n }\n\n this._registerObjectNodeLayouts(this._layout);\n this._propagateAncestorRules();\n\n this._validateOnChange = config.validateOnSubmit === false;\n this._snapshotBaseline();\n\n makeAutoObservable(\n this,\n {\n vm: computed,\n _layoutMutator: false,\n _layoutResolver: false,\n _focusManager: false\n } as any,\n { autoBind: true }\n );\n\n this._layoutResolver = new LayoutResolver(\n this._fields,\n this._activeTabs,\n this.evaluateRules.bind(this)\n );\n this._focusManager = new FocusManager(this._fields);\n }\n\n evaluateRules(rules: IRule[] | undefined): { visible: boolean; disabled: boolean } {\n let visible = true;\n let disabled = false;\n if (!rules || rules.length === 0) {\n return { visible, disabled };\n }\n\n for (const rule of rules) {\n const evaluator = this._ruleEvaluators.find(e => e.canEvaluate(rule));\n if (!evaluator) {\n if (\n process.env.NODE_ENV === \"development\" &&\n !this._warnedRuleTypes.has(rule.type)\n ) {\n this._warnedRuleTypes.add(rule.type);\n console.warn(\n `[FormModel] No evaluator registered for rule type \"${rule.type}\". Rule is ignored.`\n );\n }\n continue;\n }\n const matched = evaluator.evaluate(rule, this);\n if (!matched) {\n continue;\n }\n if (rule.action === \"hide\") {\n visible = false;\n } else if (rule.action === \"disable\") {\n disabled = true;\n }\n }\n\n return { visible, disabled };\n }\n\n field(name: string): IField {\n const field = this._fields.get(name);\n if (field) {\n return field;\n }\n\n const parts = name.split(\".\");\n if (parts.length > 1) {\n let current: IField | undefined = this._fields.get(parts[0]);\n for (let i = 1; i < parts.length && current; i++) {\n if (isObjectField(current)) {\n if (current.isList) {\n const index = parseInt(parts[i], 10);\n if (!isNaN(index)) {\n const item = current.items[index];\n if (item && i + 1 < parts.length) {\n current = item.children.get(parts[i + 1]);\n i++;\n } else {\n current = undefined;\n }\n continue;\n }\n }\n current = current.getChild(parts[i]);\n } else {\n current = undefined;\n }\n }\n if (current) {\n return current;\n }\n }\n\n throw new Error(`Field \"${name}\" not found.`);\n }\n\n focusField(name: string): void {\n if (this._lastFocusedField) {\n this._lastFocusedField.clearFocusRequest();\n this._lastFocusedField = null;\n }\n\n const activations = this._focusManager.buildFocusPath(name, this._layout);\n let field: IField | undefined;\n try {\n field = this.field(name);\n } catch {\n // Field not found — no-op.\n }\n\n runInAction(() => {\n if (activations) {\n for (const act of activations) {\n this._activeTabs.set(act.tabKey, act.tabId);\n }\n }\n if (field) {\n field.requestFocus();\n this._lastFocusedField = field;\n }\n });\n }\n\n fields(\n factory: (registry: IFieldBuilderRegistry) => Record<string, IFieldBuilder | undefined>\n ): void {\n const builders = factory(this._registry);\n\n for (const [name, builder] of Object.entries(builders)) {\n if (builder === undefined) {\n this._builders.delete(name);\n this.removeField(name);\n continue;\n }\n\n this._builders.set(name, builder);\n const fieldConfig = builder.build(name);\n const field = this._createField(fieldConfig);\n field.setForm(this);\n\n this._fields.set(name, field);\n }\n\n this._snapshotBaseline();\n this._propagateAncestorRules();\n }\n\n layout(factory: (layout: ILayoutModifier) => (LayoutNode | IPositionedLayoutNode)[]): void;\n layout(nodeId: string): ILayoutNodeAccessHandle;\n layout(\n factoryOrNodeId:\n | ((layout: ILayoutModifier) => (LayoutNode | IPositionedLayoutNode)[])\n | string\n ): void | ILayoutNodeAccessHandle {\n if (typeof factoryOrNodeId === \"string\") {\n return this._layoutMutator.accessNode(this._layout, factoryOrNodeId);\n }\n\n this._layout = this._layoutMutator.applyModifications(this._layout, factoryOrNodeId);\n this._registerObjectNodeLayouts(this._layout);\n this._propagateAncestorRules();\n }\n\n removeField(name: string): void {\n this._fields.delete(name);\n this._baseline.delete(name);\n this._layout = this._layoutMutator.removeFromLayout(this._layout, name);\n }\n\n getData(): Record<string, unknown> {\n const data: Record<string, unknown> = {};\n for (const [name, field] of this._fields) {\n if (isObjectField(field)) {\n data[name] = toJS(field.getData());\n } else {\n data[name] = toJS(field.getValue());\n }\n }\n return data;\n }\n\n setData(data: Record<string, unknown>): void {\n for (const [name, value] of Object.entries(data)) {\n const field = this._fields.get(name);\n if (field) {\n field.setValueSilent(value);\n }\n }\n this._snapshotBaseline();\n this._resetAllValidation();\n this._submitted = false;\n this._submitCount = 0;\n this._isValid = null;\n this._formRuleErrors = [];\n }\n\n reset(): void {\n for (const [name, field] of this._fields) {\n const baselineValue = this._baseline.get(name);\n field.setValueSilent(baselineValue ?? field.config.defaultValue ?? null);\n }\n this._resetAllValidation();\n this._submitted = false;\n this._submitCount = 0;\n this._isValid = null;\n this._formRuleErrors = [];\n }\n\n get isDirty(): boolean {\n for (const [name, field] of this._fields) {\n const baseline = this._baseline.get(name);\n const current = isObjectField(field) ? field.getData() : field.getValue();\n if (JSON.stringify(toJS(current)) !== JSON.stringify(toJS(baseline))) {\n return true;\n }\n }\n return false;\n }\n\n get isValid(): boolean | null {\n return this._isValid;\n }\n\n get submitted(): boolean {\n return this._submitted;\n }\n\n get submitCount(): number {\n return this._submitCount;\n }\n\n get errors(): IFormError[] {\n if (!this._submitted) {\n return [];\n }\n const ruleErrorPaths = new Set(this._formRuleErrors.filter(e => e.path).map(e => e.path));\n const errors: IFormError[] = [];\n\n const collectErrors = (\n fields: Map<string, IField>,\n pathPrefix: string,\n trail: string[]\n ) => {\n for (const [, field] of fields) {\n const path = pathPrefix ? `${pathPrefix}.${field.name}` : field.name;\n const segment = field.config.label || field.name;\n if (isObjectField(field)) {\n if (field.vm.validation.isValid === false && !ruleErrorPaths.has(path)) {\n errors.push({\n path,\n label: field.config.label,\n breadcrumb: [...trail, segment],\n message: field.vm.validation.message || \"Invalid value.\"\n });\n }\n if (field.config.isList) {\n for (const [index, item] of field.items.entries()) {\n collectErrors(item.children, `${path}.${index}`, [\n ...trail,\n `${segment} [${index + 1}]`\n ]);\n }\n } else {\n collectErrors(field.children, path, [...trail, segment]);\n }\n } else if (field.vm.validation.isValid === false && !ruleErrorPaths.has(path)) {\n errors.push({\n path,\n label: field.config.label,\n breadcrumb: [...trail, segment],\n message: field.vm.validation.message || \"Invalid value.\"\n });\n }\n }\n };\n\n collectErrors(this._fields, \"\", []);\n return [...errors, ...this._formRuleErrors];\n }\n\n addRule(rule: FormRule): void {\n this._formRules.push(rule);\n }\n\n setLayout(factory: (layout: ILayoutBuilder) => ILayoutNodeBuilder[]): void {\n this._layout = LayoutBuilderFactory.buildNodes(factory(LayoutBuilderFactory.create()));\n this._warnOrphanFields();\n this._registerObjectNodeLayouts(this._layout);\n this._propagateAncestorRules();\n }\n\n async validate(): Promise<boolean> {\n let allFieldsValid = true;\n\n for (const [, field] of this._fields) {\n const valid = await field.validate({ force: true });\n if (!valid) {\n allFieldsValid = false;\n }\n }\n\n const ruleErrors: IFormError[] = [];\n for (const rule of this._formRules) {\n const errors = await this._runFormRule(rule);\n for (const err of errors) {\n ruleErrors.push(err);\n if (err.path) {\n const target = this._tryGetField(err.path);\n if (target) {\n target.setValidation({ isValid: false, message: err.message });\n }\n }\n }\n }\n\n const isValid = allFieldsValid && ruleErrors.length === 0;\n runInAction(() => {\n this._formRuleErrors = ruleErrors;\n this._isValid = isValid;\n this._submitted = true;\n this._submitCount++;\n });\n return isValid;\n }\n\n async submit<T = Record<string, unknown>>(): Promise<T | false> {\n const valid = await this.validate();\n if (!valid) {\n return false;\n }\n return this.getData() as T;\n }\n\n get vm(): IFormVM {\n return {\n layout: this._layoutResolver.resolve(this._layout),\n errors: this.errors,\n isDirty: this.isDirty,\n isValid: this._isValid,\n submitCount: this._submitCount,\n focusField: (path: string) => this.focusField(path),\n getData: () => this.getData() as Record<string, unknown>,\n setData: (data: Record<string, unknown>) => this.setData(data)\n };\n }\n\n get registry(): IFieldBuilderRegistry {\n return this._registry;\n }\n\n public resolveChildLayout(layout: LayoutNode[], children: Map<string, IField>): LayoutNodeVM[] {\n return this._layoutResolver.resolveChildLayout(layout, children);\n }\n\n getField(name: string): IField | undefined {\n return this._fields.get(name);\n }\n\n getFields(): Map<string, IField> {\n return this._fields;\n }\n\n getFieldBuilders(predicate?: (builder: IFieldBuilder) => boolean): IFieldBuilder[] {\n const pred = predicate ?? (() => true);\n const result: IFieldBuilder[] = [];\n LayoutBuilderFactory.collectBuilders(this._fields, this._builders, pred, result);\n return result;\n }\n\n private async _runFormRule(rule: FormRule): Promise<IFormError[]> {\n if (typeof rule === \"function\") {\n const fn = rule as FormRuleFn;\n const result = await fn(this);\n return Array.isArray(result) ? result : [];\n }\n const data = this.getData();\n const result = await rule.safeParseAsync(data);\n if (result.success) {\n return [];\n }\n return result.error.issues.map(issue => {\n const path = issue.path.map(String).join(\".\");\n const field = path ? this._tryGetField(path) : undefined;\n return {\n path,\n label: field?.config.label,\n message: issue.message || \"Invalid value.\"\n };\n });\n }\n\n private _tryGetField(path: string): IField | undefined {\n try {\n return this.field(path);\n } catch {\n return undefined;\n }\n }\n\n private _registerObjectNodeLayouts(layout: LayoutNode[]): void {\n for (const node of layout) {\n if (node.type === \"object\") {\n const field = this._fields.get(node.fieldName);\n if (field && isObjectField(field)) {\n field.setInnerLayout(node.inner);\n }\n } else if (node.type === \"tabs\") {\n for (const tab of node.tabs) {\n this._registerObjectNodeLayouts(tab.layout);\n }\n }\n }\n }\n\n private _propagateAncestorRules(): void {\n const ancestry = new Map<string, IRule[]>();\n const walk = (nodes: LayoutNode[], rules: IRule[]) => {\n for (const node of nodes) {\n if (node.type === \"row\") {\n for (const id of node.fieldIds) {\n const existing = ancestry.get(id) ?? [];\n ancestry.set(id, [...existing, ...rules]);\n }\n } else if (node.type === \"tabs\") {\n const containerRules = [...rules, ...(node.rules ?? [])];\n for (const tab of node.tabs) {\n const tabRules = [...containerRules, ...(tab.rules ?? [])];\n walk(tab.layout, tabRules);\n }\n } else if (node.type === \"object\") {\n const existing = ancestry.get(node.fieldName) ?? [];\n ancestry.set(node.fieldName, [...existing, ...rules]);\n }\n }\n };\n\n walk(this._layout, []);\n\n for (const [, field] of this._fields) {\n field.setAncestorRules(ancestry.get(field.name) ?? []);\n }\n }\n\n private _generateDefaultLayout(): LayoutNode[] {\n const layout: LayoutNode[] = [];\n for (const [name, field] of this._fields) {\n if (field.visible) {\n layout.push({ type: \"row\", fieldIds: [name] });\n }\n }\n return layout;\n }\n\n private _warnOrphanFields(): void {\n const layoutFieldIds = new Set(LayoutBuilderFactory.collectFieldIds(this._layout));\n\n for (const [name, field] of this._fields) {\n if (field.visible && !layoutFieldIds.has(name)) {\n console.warn(\n `[FormModel] Field \"${name}\" is not in the layout and not marked as .hidden(). ` +\n `Add it to the layout or mark it as .hidden() to suppress this warning.`\n );\n }\n }\n }\n\n private _snapshotBaseline(): void {\n this._baseline.clear();\n for (const [name, field] of this._fields) {\n this._baseline.set(name, toJS(field.getValue()));\n }\n }\n\n private _resetAllValidation(): void {\n for (const [, field] of this._fields) {\n field.resetValidation();\n }\n }\n\n private _createField(config: any): IField {\n if (config.childBuilders) {\n return new ObjectField(config as IObjectFieldConfig);\n }\n return new Field(config);\n }\n}\n"],"names":["FormModel","config","registry","Map","observable","Set","LayoutMutator","builders","name","builder","Object","fieldConfig","field","LayoutBuilderFactory","makeAutoObservable","computed","LayoutResolver","FocusManager","rules","visible","disabled","rule","evaluator","e","process","console","matched","parts","current","i","isObjectField","index","parseInt","isNaN","item","undefined","Error","activations","runInAction","act","factory","factoryOrNodeId","data","toJS","value","baselineValue","baseline","JSON","ruleErrorPaths","errors","collectErrors","fields","pathPrefix","trail","path","segment","allFieldsValid","valid","ruleErrors","err","target","isValid","layout","children","predicate","pred","result","fn","Array","issue","String","node","tab","ancestry","walk","nodes","id","existing","containerRules","tabRules","layoutFieldIds","ObjectField","Field"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"features/formModel/FormModel.js","sources":["../../../src/features/formModel/FormModel.ts"],"sourcesContent":["import { makeAutoObservable, computed, toJS, runInAction, observable } from \"mobx\";\nimport { Field } from \"./Field.js\";\nimport { ObjectField, isObjectField } from \"./ObjectField.js\";\nimport { LayoutBuilderFactory } from \"./LayoutBuilderFactory.js\";\nimport { LayoutMutator } from \"./LayoutMutator.js\";\nimport { LayoutResolver } from \"./LayoutResolver.js\";\nimport { FocusManager } from \"./FocusManager.js\";\nimport type {\n IFormModel,\n IField,\n IFieldBuilder,\n IFieldBuilderRegistry,\n IObjectFieldConfig,\n IFormVM,\n IFormError,\n IFormModelConfig,\n ILayoutBuilder,\n ILayoutNodeBuilder,\n ILayoutModifier,\n IPositionedLayoutNode,\n ILayoutNodeAccessHandle,\n IRule,\n IRuleEvaluator,\n LayoutNode,\n LayoutNodeVM,\n FormRule,\n FormRuleFn\n} from \"./abstractions.js\";\n\nexport class FormModel implements IFormModel {\n private _fields = new Map<string, IField>();\n private _builders = new Map<string, IFieldBuilder>();\n private _layout: LayoutNode[] = [];\n private _baseline = new Map<string, unknown>();\n private _submitted = false;\n private _submitCount = 0;\n private _validateOnChange = false;\n private _isValid: boolean | null = null;\n private _formRuleErrors: IFormError[] = [];\n private _activeTabs = observable.map<string, string>();\n private _ruleEvaluators: IRuleEvaluator[] = [];\n private _warnedRuleTypes = new Set<string>();\n private _formRules: FormRule[] = [];\n private _lastFocusedField: IField | null = null;\n private _registry: IFieldBuilderRegistry;\n\n private _layoutMutator = new LayoutMutator();\n private _layoutResolver: LayoutResolver = null!;\n private _focusManager: FocusManager = null!;\n\n constructor(config: IFormModelConfig, registry: IFieldBuilderRegistry) {\n this._registry = registry;\n this._ruleEvaluators = config.ruleEvaluators ?? [];\n\n const builders = config.fields(registry);\n\n for (const [name, builder] of Object.entries(builders)) {\n this._builders.set(name, builder);\n const fieldConfig = builder.build(name);\n const field = this._createField(fieldConfig);\n field.setForm(this);\n this._fields.set(name, field);\n }\n\n if (config.layout) {\n this._layout = LayoutBuilderFactory.buildNodes(\n config.layout(LayoutBuilderFactory.create())\n );\n this._warnOrphanFields();\n } else {\n this._layout = this._generateDefaultLayout();\n }\n\n this._registerObjectNodeLayouts(this._layout);\n this._propagateAncestorRules();\n\n this._validateOnChange = config.validateOnSubmit === false;\n this._snapshotBaseline();\n\n makeAutoObservable(\n this,\n {\n vm: computed,\n _layoutMutator: false,\n _layoutResolver: false,\n _focusManager: false\n } as any,\n { autoBind: true }\n );\n\n this._layoutResolver = new LayoutResolver(\n this._fields,\n this._activeTabs,\n this.evaluateRules.bind(this)\n );\n this._focusManager = new FocusManager(this._fields);\n }\n\n evaluateRules(rules: IRule[] | undefined): { visible: boolean; disabled: boolean } {\n let visible = true;\n let disabled = false;\n if (!rules || rules.length === 0) {\n return { visible, disabled };\n }\n\n for (const rule of rules) {\n const evaluator = this._ruleEvaluators.find(e => e.canEvaluate(rule));\n if (!evaluator) {\n if (\n process.env.NODE_ENV === \"development\" &&\n !this._warnedRuleTypes.has(rule.type)\n ) {\n this._warnedRuleTypes.add(rule.type);\n console.warn(\n `[FormModel] No evaluator registered for rule type \"${rule.type}\". Rule is ignored.`\n );\n }\n continue;\n }\n const matched = evaluator.evaluate(rule, this);\n if (!matched) {\n continue;\n }\n if (rule.action === \"hide\") {\n visible = false;\n } else if (rule.action === \"disable\") {\n disabled = true;\n }\n }\n\n return { visible, disabled };\n }\n\n field(name: string): IField {\n const field = this._fields.get(name);\n if (field) {\n return field;\n }\n\n const parts = name.split(\".\");\n if (parts.length > 1) {\n let current: IField | undefined = this._fields.get(parts[0]);\n for (let i = 1; i < parts.length && current; i++) {\n if (isObjectField(current)) {\n if (current.isList) {\n const index = parseInt(parts[i], 10);\n if (!isNaN(index)) {\n const item = current.items[index];\n if (item && i + 1 < parts.length) {\n current = item.children.get(parts[i + 1]);\n i++;\n } else {\n current = undefined;\n }\n continue;\n }\n }\n current = current.getChild(parts[i]);\n } else {\n current = undefined;\n }\n }\n if (current) {\n return current;\n }\n }\n\n throw new Error(`Field \"${name}\" not found.`);\n }\n\n focusField(name: string): void {\n if (this._lastFocusedField) {\n this._lastFocusedField.clearFocusRequest();\n this._lastFocusedField = null;\n }\n\n const activations = this._focusManager.buildFocusPath(name, this._layout);\n let field: IField | undefined;\n try {\n field = this.field(name);\n } catch {\n // Field not found — no-op.\n }\n\n runInAction(() => {\n if (activations) {\n for (const act of activations) {\n this._activeTabs.set(act.tabKey, act.tabId);\n }\n }\n if (field) {\n field.requestFocus();\n this._lastFocusedField = field;\n }\n });\n }\n\n fields(\n factory: (registry: IFieldBuilderRegistry) => Record<string, IFieldBuilder | undefined>\n ): void {\n const builders = factory(this._registry);\n\n for (const [name, builder] of Object.entries(builders)) {\n if (builder === undefined) {\n this._builders.delete(name);\n this.removeField(name);\n continue;\n }\n\n this._builders.set(name, builder);\n const fieldConfig = builder.build(name);\n const field = this._createField(fieldConfig);\n field.setForm(this);\n\n this._fields.set(name, field);\n }\n\n this._snapshotBaseline();\n this._propagateAncestorRules();\n }\n\n layout(factory: (layout: ILayoutModifier) => (LayoutNode | IPositionedLayoutNode)[]): void;\n layout(nodeId: string): ILayoutNodeAccessHandle;\n layout(\n factoryOrNodeId:\n | ((layout: ILayoutModifier) => (LayoutNode | IPositionedLayoutNode)[])\n | string\n ): void | ILayoutNodeAccessHandle {\n if (typeof factoryOrNodeId === \"string\") {\n return this._layoutMutator.accessNode(this._layout, factoryOrNodeId);\n }\n\n this._layout = this._layoutMutator.applyModifications(this._layout, factoryOrNodeId);\n this._registerObjectNodeLayouts(this._layout);\n this._propagateAncestorRules();\n }\n\n removeField(name: string): void {\n this._fields.delete(name);\n this._baseline.delete(name);\n this._layout = this._layoutMutator.removeFromLayout(this._layout, name);\n }\n\n getData(): Record<string, unknown> {\n const data: Record<string, unknown> = {};\n for (const [name, field] of this._fields) {\n if (isObjectField(field)) {\n data[name] = toJS(field.getData());\n } else {\n data[name] = toJS(field.getValue());\n }\n }\n return data;\n }\n\n setData(data: Record<string, unknown>): void {\n for (const [name, value] of Object.entries(data)) {\n const field = this._fields.get(name);\n if (field) {\n field.setValueSilent(value);\n }\n }\n this._snapshotBaseline();\n this._resetAllValidation();\n this._submitted = false;\n this._submitCount = 0;\n this._isValid = null;\n this._formRuleErrors = [];\n }\n\n reset(): void {\n for (const [name, field] of this._fields) {\n const baselineValue = this._baseline.get(name);\n field.setValueSilent(baselineValue ?? field.config.defaultValue ?? null);\n }\n this._resetAllValidation();\n this._submitted = false;\n this._submitCount = 0;\n this._isValid = null;\n this._formRuleErrors = [];\n }\n\n get isDirty(): boolean {\n for (const [name, field] of this._fields) {\n const baseline = this._baseline.get(name);\n const current = isObjectField(field) ? field.getData() : field.getValue();\n if (JSON.stringify(toJS(current)) !== JSON.stringify(toJS(baseline))) {\n return true;\n }\n }\n return false;\n }\n\n get isValid(): boolean | null {\n return this._isValid;\n }\n\n get submitted(): boolean {\n return this._submitted;\n }\n\n get submitCount(): number {\n return this._submitCount;\n }\n\n get errors(): IFormError[] {\n if (!this._submitted) {\n return [];\n }\n const ruleErrorPaths = new Set(this._formRuleErrors.filter(e => e.path).map(e => e.path));\n const errors: IFormError[] = [];\n\n const collectErrors = (\n fields: Map<string, IField>,\n pathPrefix: string,\n trail: string[]\n ) => {\n for (const [, field] of fields) {\n const path = pathPrefix ? `${pathPrefix}.${field.name}` : field.name;\n const segment = field.config.label || field.name;\n if (isObjectField(field)) {\n if (\n field.vm.validation.isValid === false &&\n field.vm.validation.message &&\n !ruleErrorPaths.has(path)\n ) {\n errors.push({\n path,\n label: field.config.label,\n breadcrumb: [...trail, segment],\n message: field.vm.validation.message\n });\n }\n if (field.config.isList) {\n for (const [index, item] of field.items.entries()) {\n collectErrors(item.children, `${path}.${index}`, [\n ...trail,\n `${segment} [${index + 1}]`\n ]);\n }\n } else {\n collectErrors(field.children, path, [...trail, segment]);\n }\n } else if (field.vm.validation.isValid === false && !ruleErrorPaths.has(path)) {\n errors.push({\n path,\n label: field.config.label,\n breadcrumb: [...trail, segment],\n message: field.vm.validation.message || \"Invalid value.\"\n });\n }\n }\n };\n\n collectErrors(this._fields, \"\", []);\n return [...errors, ...this._formRuleErrors];\n }\n\n addRule(rule: FormRule): void {\n this._formRules.push(rule);\n }\n\n setLayout(factory: (layout: ILayoutBuilder) => ILayoutNodeBuilder[]): void {\n this._layout = LayoutBuilderFactory.buildNodes(factory(LayoutBuilderFactory.create()));\n this._warnOrphanFields();\n this._registerObjectNodeLayouts(this._layout);\n this._propagateAncestorRules();\n }\n\n async validate(): Promise<boolean> {\n let allFieldsValid = true;\n\n for (const [, field] of this._fields) {\n const valid = await field.validate({ force: true });\n if (!valid) {\n allFieldsValid = false;\n }\n }\n\n const ruleErrors: IFormError[] = [];\n for (const rule of this._formRules) {\n const errors = await this._runFormRule(rule);\n for (const err of errors) {\n ruleErrors.push(err);\n if (err.path) {\n const target = this._tryGetField(err.path);\n if (target) {\n target.setValidation({ isValid: false, message: err.message });\n }\n }\n }\n }\n\n const isValid = allFieldsValid && ruleErrors.length === 0;\n runInAction(() => {\n this._formRuleErrors = ruleErrors;\n this._isValid = isValid;\n this._submitted = true;\n this._submitCount++;\n });\n return isValid;\n }\n\n async submit<T = Record<string, unknown>>(): Promise<T | false> {\n const valid = await this.validate();\n if (!valid) {\n return false;\n }\n return this.getData() as T;\n }\n\n get vm(): IFormVM {\n return {\n layout: this._layoutResolver.resolve(this._layout),\n errors: this.errors,\n isDirty: this.isDirty,\n isValid: this._isValid,\n submitCount: this._submitCount,\n focusField: (path: string) => this.focusField(path),\n getData: () => this.getData() as Record<string, unknown>,\n setData: (data: Record<string, unknown>) => this.setData(data)\n };\n }\n\n get registry(): IFieldBuilderRegistry {\n return this._registry;\n }\n\n public resolveChildLayout(layout: LayoutNode[], children: Map<string, IField>): LayoutNodeVM[] {\n return this._layoutResolver.resolveChildLayout(layout, children);\n }\n\n getField(name: string): IField | undefined {\n return this._fields.get(name);\n }\n\n getFields(): Map<string, IField> {\n return this._fields;\n }\n\n getFieldBuilders(predicate?: (builder: IFieldBuilder) => boolean): IFieldBuilder[] {\n const pred = predicate ?? (() => true);\n const result: IFieldBuilder[] = [];\n LayoutBuilderFactory.collectBuilders(this._fields, this._builders, pred, result);\n return result;\n }\n\n private async _runFormRule(rule: FormRule): Promise<IFormError[]> {\n if (typeof rule === \"function\") {\n const fn = rule as FormRuleFn;\n const result = await fn(this);\n return Array.isArray(result) ? result : [];\n }\n const data = this.getData();\n const result = await rule.safeParseAsync(data);\n if (result.success) {\n return [];\n }\n return result.error.issues.map(issue => {\n const path = issue.path.map(String).join(\".\");\n const field = path ? this._tryGetField(path) : undefined;\n return {\n path,\n label: field?.config.label,\n message: issue.message || \"Invalid value.\"\n };\n });\n }\n\n private _tryGetField(path: string): IField | undefined {\n try {\n return this.field(path);\n } catch {\n return undefined;\n }\n }\n\n private _registerObjectNodeLayouts(layout: LayoutNode[]): void {\n for (const node of layout) {\n if (node.type === \"object\") {\n const field = this._fields.get(node.fieldName);\n if (field && isObjectField(field)) {\n field.setInnerLayout(node.inner);\n }\n } else if (node.type === \"tabs\") {\n for (const tab of node.tabs) {\n this._registerObjectNodeLayouts(tab.layout);\n }\n }\n }\n }\n\n private _propagateAncestorRules(): void {\n const ancestry = new Map<string, IRule[]>();\n const walk = (nodes: LayoutNode[], rules: IRule[]) => {\n for (const node of nodes) {\n if (node.type === \"row\") {\n for (const id of node.fieldIds) {\n const existing = ancestry.get(id) ?? [];\n ancestry.set(id, [...existing, ...rules]);\n }\n } else if (node.type === \"tabs\") {\n const containerRules = [...rules, ...(node.rules ?? [])];\n for (const tab of node.tabs) {\n const tabRules = [...containerRules, ...(tab.rules ?? [])];\n walk(tab.layout, tabRules);\n }\n } else if (node.type === \"object\") {\n const existing = ancestry.get(node.fieldName) ?? [];\n ancestry.set(node.fieldName, [...existing, ...rules]);\n }\n }\n };\n\n walk(this._layout, []);\n\n for (const [, field] of this._fields) {\n field.setAncestorRules(ancestry.get(field.name) ?? []);\n }\n }\n\n private _generateDefaultLayout(): LayoutNode[] {\n const layout: LayoutNode[] = [];\n for (const [name, field] of this._fields) {\n if (field.visible) {\n layout.push({ type: \"row\", fieldIds: [name] });\n }\n }\n return layout;\n }\n\n private _warnOrphanFields(): void {\n const layoutFieldIds = new Set(LayoutBuilderFactory.collectFieldIds(this._layout));\n\n for (const [name, field] of this._fields) {\n if (field.visible && !layoutFieldIds.has(name)) {\n console.warn(\n `[FormModel] Field \"${name}\" is not in the layout and not marked as .hidden(). ` +\n `Add it to the layout or mark it as .hidden() to suppress this warning.`\n );\n }\n }\n }\n\n private _snapshotBaseline(): void {\n this._baseline.clear();\n for (const [name, field] of this._fields) {\n this._baseline.set(name, toJS(field.getValue()));\n }\n }\n\n private _resetAllValidation(): void {\n for (const [, field] of this._fields) {\n field.resetValidation();\n }\n }\n\n private _createField(config: any): IField {\n if (config.childBuilders) {\n return new ObjectField(config as IObjectFieldConfig);\n }\n return new Field(config);\n }\n}\n"],"names":["FormModel","config","registry","Map","observable","Set","LayoutMutator","builders","name","builder","Object","fieldConfig","field","LayoutBuilderFactory","makeAutoObservable","computed","LayoutResolver","FocusManager","rules","visible","disabled","rule","evaluator","e","process","console","matched","parts","current","i","isObjectField","index","parseInt","isNaN","item","undefined","Error","activations","runInAction","act","factory","factoryOrNodeId","data","toJS","value","baselineValue","baseline","JSON","ruleErrorPaths","errors","collectErrors","fields","pathPrefix","trail","path","segment","allFieldsValid","valid","ruleErrors","err","target","isValid","layout","children","predicate","pred","result","fn","Array","issue","String","node","tab","ancestry","walk","nodes","id","existing","containerRules","tabRules","layoutFieldIds","ObjectField","Field"],"mappings":"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"}
|
|
@@ -1246,7 +1246,9 @@ describe("FormModel", ()=>{
|
|
|
1246
1246
|
const valid = await form.validate();
|
|
1247
1247
|
expect(valid).toBe(false);
|
|
1248
1248
|
expect(form.errors.length).toBeGreaterThan(0);
|
|
1249
|
-
expect(form.errors.some((e)=>"address" === e.path)).toBe(
|
|
1249
|
+
expect(form.errors.some((e)=>"address" === e.path)).toBe(false);
|
|
1250
|
+
expect(form.errors.some((e)=>"address.street" === e.path)).toBe(true);
|
|
1251
|
+
expect(form.errors.some((e)=>"address.city" === e.path)).toBe(true);
|
|
1250
1252
|
});
|
|
1251
1253
|
it("should pass validation when children are valid", async ()=>{
|
|
1252
1254
|
const form = createFormWithObject();
|