@webiny/app-headless-cms-common 6.0.0-rc.3 → 6.0.0-rc.5
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/Fields/Fields.js +7 -7
- package/Fields/Fields.js.map +1 -1
- package/Fields/LayoutDescriptorCell.d.ts +3 -3
- package/Fields/LayoutDescriptorCell.js +7 -7
- package/Fields/LayoutDescriptorCell.js.map +1 -1
- package/Fields/fieldOptions.d.ts +3 -3
- package/Fields/fieldOptions.js +3 -3
- package/Fields/fieldOptions.js.map +1 -1
- package/Fields/layoutFieldRenderers/AlertFieldRenderer.d.ts +3 -3
- package/Fields/layoutFieldRenderers/AlertFieldRenderer.js +3 -3
- package/Fields/layoutFieldRenderers/AlertFieldRenderer.js.map +1 -1
- package/Fields/layoutFieldRenderers/SeparatorFieldRenderer.d.ts +3 -3
- package/Fields/layoutFieldRenderers/SeparatorFieldRenderer.js +3 -3
- package/Fields/layoutFieldRenderers/SeparatorFieldRenderer.js.map +1 -1
- package/Fields/layoutFieldRenderers/TabsFieldRenderer.d.ts +3 -3
- package/Fields/layoutFieldRenderers/TabsFieldRenderer.js +10 -10
- package/Fields/layoutFieldRenderers/TabsFieldRenderer.js.map +1 -1
- package/Fields/useFieldRules.d.ts +1 -1
- package/Fields/useFieldRules.js +1 -1
- package/Fields/useFieldRules.js.map +1 -1
- package/Fields/useRenderPlugins.d.ts +2 -1
- package/Fields/useRenderPlugins.js.map +1 -1
- package/exports/admin/cms/model.d.ts +1 -2
- package/exports/admin/cms/model.js +1 -1
- package/exports/admin/cms/model.js.map +1 -1
- package/exports/admin/cms.d.ts +1 -1
- package/exports/admin/cms.js.map +1 -1
- package/package.json +10 -10
- package/types/index.d.ts +20 -32
- package/types/index.js +1 -13
- package/types/index.js.map +1 -1
- package/types/model.d.ts +14 -14
- package/types/model.js +9 -8
- package/types/model.js.map +1 -1
package/Fields/Fields.js
CHANGED
|
@@ -2,11 +2,11 @@ import React from "react";
|
|
|
2
2
|
import { Alert, Grid } from "@webiny/admin-ui";
|
|
3
3
|
import { FieldElement } from "./FieldElement.js";
|
|
4
4
|
import { FieldElementError } from "./FieldElementError.js";
|
|
5
|
-
import {
|
|
5
|
+
import { isLayoutField } from "../types/model.js";
|
|
6
6
|
import { LayoutDescriptorCell } from "./LayoutDescriptorCell.js";
|
|
7
7
|
import { useAuthentication } from "@webiny/app-admin";
|
|
8
8
|
import { FieldRulesProvider, useParentRules } from "./FieldRulesProvider.js";
|
|
9
|
-
import { evaluateAccessControlRules,
|
|
9
|
+
import { evaluateAccessControlRules, useFieldEffectiveRules } from "./useFieldRules.js";
|
|
10
10
|
const getFieldById = (fields, id) => {
|
|
11
11
|
return fields.find(field => field.id === id) || null;
|
|
12
12
|
};
|
|
@@ -27,8 +27,8 @@ const LayoutCell = ({
|
|
|
27
27
|
contentModel,
|
|
28
28
|
gridClassName
|
|
29
29
|
}) => {
|
|
30
|
-
const isLayout =
|
|
31
|
-
const rules =
|
|
30
|
+
const isLayout = isLayoutField(cell);
|
|
31
|
+
const rules = useFieldEffectiveRules(isLayout ? cell : {});
|
|
32
32
|
if (!isLayout) {
|
|
33
33
|
return null;
|
|
34
34
|
}
|
|
@@ -38,7 +38,7 @@ const LayoutCell = ({
|
|
|
38
38
|
return /*#__PURE__*/React.createElement(FieldRulesProvider, {
|
|
39
39
|
rules: rules
|
|
40
40
|
}, /*#__PURE__*/React.createElement(LayoutDescriptorCell, {
|
|
41
|
-
|
|
41
|
+
field: cell,
|
|
42
42
|
Bind: Bind,
|
|
43
43
|
fields: fields,
|
|
44
44
|
contentModel: contentModel,
|
|
@@ -57,7 +57,7 @@ const FieldCell = ({
|
|
|
57
57
|
Bind,
|
|
58
58
|
contentModel
|
|
59
59
|
}) => {
|
|
60
|
-
const rules =
|
|
60
|
+
const rules = useFieldEffectiveRules(field ?? {});
|
|
61
61
|
if (!rules.canView || rules.hidden) {
|
|
62
62
|
return null;
|
|
63
63
|
}
|
|
@@ -108,7 +108,7 @@ const RowRenderer = ({
|
|
|
108
108
|
});
|
|
109
109
|
const span = visibleStringCells.length > 0 ? Math.floor(12 / visibleStringCells.length) : 12;
|
|
110
110
|
return /*#__PURE__*/React.createElement(React.Fragment, null, row.map(cell => {
|
|
111
|
-
if (
|
|
111
|
+
if (isLayoutField(cell)) {
|
|
112
112
|
return /*#__PURE__*/React.createElement(LayoutCell, {
|
|
113
113
|
key: cell.id,
|
|
114
114
|
cell: cell,
|
package/Fields/Fields.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","Alert","Grid","FieldElement","FieldElementError","isLayoutDescriptor","LayoutDescriptorCell","useAuthentication","FieldRulesProvider","useParentRules","evaluateAccessControlRules","useEffectiveRules","getFieldById","fields","id","find","field","LayoutNotDefined","createElement","type","LayoutCell","cell","Bind","contentModel","gridClassName","isLayout","rules","canView","hidden","descriptor","FieldCell","span","Column","title","description","RowRenderer","row","identity","parentRules","visibleStringCells","filter","c","f","acPerms","length","Math","floor","Fragment","map","key","Fields","layout","plugin","className","rowIndex"],"sources":["Fields.tsx"],"sourcesContent":["import React from \"react\";\nimport { Alert, type ColumnProps, Grid } from \"@webiny/admin-ui\";\nimport { FieldElement } from \"./FieldElement.js\";\nimport { FieldElementError } from \"./FieldElementError.js\";\nimport type {\n BindComponent,\n CmsEditorContentModel,\n CmsEditorFieldsLayout,\n CmsModelField\n} from \"~/types/index.js\";\nimport type { CmsEditorLayoutCell } from \"~/types/model.js\";\nimport { isLayoutDescriptor } from \"~/types/model.js\";\nimport { LayoutDescriptorCell } from \"./LayoutDescriptorCell.js\";\nimport { useAuthentication } from \"@webiny/app-admin\";\nimport { FieldRulesProvider, useParentRules } from \"./FieldRulesProvider.js\";\nimport { evaluateAccessControlRules, useEffectiveRules } from \"./useFieldRules.js\";\n\ninterface FieldsProps {\n Bind: BindComponent;\n contentModel: CmsEditorContentModel;\n fields: CmsModelField[];\n layout: CmsEditorFieldsLayout;\n gridClassName?: string;\n}\n\nconst getFieldById = (fields: CmsModelField[], id: string): CmsModelField | null => {\n return fields.find(field => field.id === id) || null;\n};\n\nconst LayoutNotDefined = () => {\n return (\n <Alert type={\"warning\"}>\n You are missing the layout definition in your code content model. Please ensure you have\n the layout property correctly defined.\n </Alert>\n );\n};\n\n/**\n * Renders a single layout descriptor cell with rules + permissions.\n */\ninterface LayoutCellProps {\n cell: CmsEditorLayoutCell;\n Bind: BindComponent;\n fields: CmsModelField[];\n contentModel: CmsEditorContentModel;\n gridClassName?: string;\n}\n\nconst LayoutCell = ({ cell, Bind, fields, contentModel, gridClassName }: LayoutCellProps) => {\n const isLayout = isLayoutDescriptor(cell);\n const rules = useEffectiveRules(isLayout ? cell : {});\n\n if (!isLayout) {\n return null;\n }\n\n if (!rules.canView || rules.hidden) {\n return null;\n }\n\n return (\n <FieldRulesProvider rules={rules}>\n <LayoutDescriptorCell\n descriptor={cell}\n Bind={Bind}\n fields={fields}\n contentModel={contentModel}\n gridClassName={gridClassName}\n />\n </FieldRulesProvider>\n );\n};\n\n/**\n * Renders a single data field cell with rules + permissions.\n */\ninterface FieldCellProps {\n id: string;\n field: CmsModelField | null;\n span: ColumnProps[\"span\"];\n Bind: BindComponent;\n contentModel: CmsEditorContentModel;\n}\n\nconst FieldCell = ({ id, field, span, Bind, contentModel }: FieldCellProps) => {\n const rules = useEffectiveRules(field ?? {});\n\n if (!rules.canView || rules.hidden) {\n return null;\n }\n\n return (\n <Grid.Column span={span}>\n {field ? (\n <FieldRulesProvider rules={rules}>\n <FieldElement field={field} Bind={Bind} contentModel={contentModel} />\n </FieldRulesProvider>\n ) : (\n <FieldElementError\n title={`Missing field with id \"${id}\"!`}\n description={\n \"Make sure field layout contains the correct field ids (hint: check for typos).\"\n }\n />\n )}\n </Grid.Column>\n );\n};\n\n/**\n * Renders a single row, delegating each cell to FieldCell or LayoutCell.\n */\ninterface RowRendererProps {\n row: CmsEditorLayoutCell[];\n fields: CmsModelField[];\n Bind: BindComponent;\n contentModel: CmsEditorContentModel;\n gridClassName?: string;\n}\n\nconst RowRenderer = ({ row, fields, Bind, contentModel, gridClassName }: RowRendererProps) => {\n const { identity } = useAuthentication();\n const parentRules = useParentRules();\n\n // Count visible string cells for column span calculation.\n // This count is approximate based on access control rules only (not entry value rules),\n // because entry value rules require per-field hooks and we can't call them in a filter.\n // The actual visibility is enforced in FieldCell.\n const visibleStringCells = row.filter(c => {\n if (typeof c !== \"string\") {\n return false;\n }\n const f = getFieldById(fields, c);\n if (!f) {\n return true;\n }\n const acPerms = evaluateAccessControlRules(f, identity);\n return parentRules.canView && acPerms.canView;\n });\n\n const span =\n visibleStringCells.length > 0\n ? (Math.floor(12 / visibleStringCells.length) as ColumnProps[\"span\"])\n : (12 as ColumnProps[\"span\"]);\n\n return (\n <>\n {row.map(cell => {\n if (isLayoutDescriptor(cell)) {\n return (\n <LayoutCell\n key={cell.id}\n cell={cell}\n Bind={Bind}\n fields={fields}\n contentModel={contentModel}\n gridClassName={gridClassName}\n />\n );\n }\n\n const id = cell as string;\n const field = getFieldById(fields, id);\n\n return (\n <FieldCell\n key={id}\n id={id}\n field={field}\n span={span}\n Bind={Bind}\n contentModel={contentModel}\n />\n );\n })}\n </>\n );\n};\n\nexport const Fields = ({ Bind, fields, layout, contentModel, gridClassName }: FieldsProps) => {\n if (contentModel.plugin && fields.length > 0 && layout.length === 0) {\n return <LayoutNotDefined />;\n }\n\n return (\n <Grid className={gridClassName}>\n {layout.map((row, rowIndex) => (\n <React.Fragment key={rowIndex}>\n <RowRenderer\n row={row}\n fields={fields}\n Bind={Bind}\n contentModel={contentModel}\n gridClassName={gridClassName}\n />\n </React.Fragment>\n ))}\n </Grid>\n );\n};\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["React","Alert","Grid","FieldElement","FieldElementError","isLayoutField","LayoutDescriptorCell","useAuthentication","FieldRulesProvider","useParentRules","evaluateAccessControlRules","useFieldEffectiveRules","getFieldById","fields","id","find","field","LayoutNotDefined","createElement","type","LayoutCell","cell","Bind","contentModel","gridClassName","isLayout","rules","canView","hidden","FieldCell","span","Column","title","description","RowRenderer","row","identity","parentRules","visibleStringCells","filter","c","f","acPerms","length","Math","floor","Fragment","map","key","Fields","layout","plugin","className","rowIndex"],"sources":["Fields.tsx"],"sourcesContent":["import React from \"react\";\nimport { Alert, type ColumnProps, Grid } from \"@webiny/admin-ui\";\nimport { FieldElement } from \"./FieldElement.js\";\nimport { FieldElementError } from \"./FieldElementError.js\";\nimport type {\n BindComponent,\n CmsEditorContentModel,\n CmsEditorFieldsLayout,\n CmsModelField\n} from \"~/types/index.js\";\nimport type { CmsEditorLayoutCell } from \"~/types/model.js\";\nimport { isLayoutField } from \"~/types/model.js\";\nimport { LayoutDescriptorCell } from \"./LayoutDescriptorCell.js\";\nimport { useAuthentication } from \"@webiny/app-admin\";\nimport { FieldRulesProvider, useParentRules } from \"./FieldRulesProvider.js\";\nimport { evaluateAccessControlRules, useFieldEffectiveRules } from \"./useFieldRules.js\";\n\ninterface FieldsProps {\n Bind: BindComponent;\n contentModel: CmsEditorContentModel;\n fields: CmsModelField[];\n layout: CmsEditorFieldsLayout;\n gridClassName?: string;\n}\n\nconst getFieldById = (fields: CmsModelField[], id: string): CmsModelField | null => {\n return fields.find(field => field.id === id) || null;\n};\n\nconst LayoutNotDefined = () => {\n return (\n <Alert type={\"warning\"}>\n You are missing the layout definition in your code content model. Please ensure you have\n the layout property correctly defined.\n </Alert>\n );\n};\n\n/**\n * Renders a single layout descriptor cell with rules + permissions.\n */\ninterface LayoutCellProps {\n cell: CmsEditorLayoutCell;\n Bind: BindComponent;\n fields: CmsModelField[];\n contentModel: CmsEditorContentModel;\n gridClassName?: string;\n}\n\nconst LayoutCell = ({ cell, Bind, fields, contentModel, gridClassName }: LayoutCellProps) => {\n const isLayout = isLayoutField(cell);\n const rules = useFieldEffectiveRules(isLayout ? cell : {});\n\n if (!isLayout) {\n return null;\n }\n\n if (!rules.canView || rules.hidden) {\n return null;\n }\n\n return (\n <FieldRulesProvider rules={rules}>\n <LayoutDescriptorCell\n field={cell}\n Bind={Bind}\n fields={fields}\n contentModel={contentModel}\n gridClassName={gridClassName}\n />\n </FieldRulesProvider>\n );\n};\n\n/**\n * Renders a single data field cell with rules + permissions.\n */\ninterface FieldCellProps {\n id: string;\n field: CmsModelField | null;\n span: ColumnProps[\"span\"];\n Bind: BindComponent;\n contentModel: CmsEditorContentModel;\n}\n\nconst FieldCell = ({ id, field, span, Bind, contentModel }: FieldCellProps) => {\n const rules = useFieldEffectiveRules(field ?? {});\n\n if (!rules.canView || rules.hidden) {\n return null;\n }\n\n return (\n <Grid.Column span={span}>\n {field ? (\n <FieldRulesProvider rules={rules}>\n <FieldElement field={field} Bind={Bind} contentModel={contentModel} />\n </FieldRulesProvider>\n ) : (\n <FieldElementError\n title={`Missing field with id \"${id}\"!`}\n description={\n \"Make sure field layout contains the correct field ids (hint: check for typos).\"\n }\n />\n )}\n </Grid.Column>\n );\n};\n\n/**\n * Renders a single row, delegating each cell to FieldCell or LayoutCell.\n */\ninterface RowRendererProps {\n row: CmsEditorLayoutCell[];\n fields: CmsModelField[];\n Bind: BindComponent;\n contentModel: CmsEditorContentModel;\n gridClassName?: string;\n}\n\nconst RowRenderer = ({ row, fields, Bind, contentModel, gridClassName }: RowRendererProps) => {\n const { identity } = useAuthentication();\n const parentRules = useParentRules();\n\n // Count visible string cells for column span calculation.\n // This count is approximate based on access control rules only (not entry value rules),\n // because entry value rules require per-field hooks and we can't call them in a filter.\n // The actual visibility is enforced in FieldCell.\n const visibleStringCells = row.filter(c => {\n if (typeof c !== \"string\") {\n return false;\n }\n const f = getFieldById(fields, c);\n if (!f) {\n return true;\n }\n const acPerms = evaluateAccessControlRules(f, identity);\n return parentRules.canView && acPerms.canView;\n });\n\n const span =\n visibleStringCells.length > 0\n ? (Math.floor(12 / visibleStringCells.length) as ColumnProps[\"span\"])\n : (12 as ColumnProps[\"span\"]);\n\n return (\n <>\n {row.map(cell => {\n if (isLayoutField(cell)) {\n return (\n <LayoutCell\n key={cell.id}\n cell={cell}\n Bind={Bind}\n fields={fields}\n contentModel={contentModel}\n gridClassName={gridClassName}\n />\n );\n }\n\n const id = cell as string;\n const field = getFieldById(fields, id);\n\n return (\n <FieldCell\n key={id}\n id={id}\n field={field}\n span={span}\n Bind={Bind}\n contentModel={contentModel}\n />\n );\n })}\n </>\n );\n};\n\nexport const Fields = ({ Bind, fields, layout, contentModel, gridClassName }: FieldsProps) => {\n if (contentModel.plugin && fields.length > 0 && layout.length === 0) {\n return <LayoutNotDefined />;\n }\n\n return (\n <Grid className={gridClassName}>\n {layout.map((row, rowIndex) => (\n <React.Fragment key={rowIndex}>\n <RowRenderer\n row={row}\n fields={fields}\n Bind={Bind}\n contentModel={contentModel}\n gridClassName={gridClassName}\n />\n </React.Fragment>\n ))}\n </Grid>\n );\n};\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import type {
|
|
2
|
+
import type { CmsLayoutField } from "../types/model.js";
|
|
3
3
|
import type { BindComponent, CmsEditorContentModel, CmsModelField } from "../types/index.js";
|
|
4
4
|
interface LayoutDescriptorCellProps {
|
|
5
|
-
|
|
5
|
+
field: CmsLayoutField;
|
|
6
6
|
Bind: BindComponent;
|
|
7
7
|
fields: CmsModelField[];
|
|
8
8
|
contentModel: CmsEditorContentModel;
|
|
9
9
|
gridClassName?: string;
|
|
10
10
|
}
|
|
11
|
-
export declare const LayoutDescriptorCell: ({
|
|
11
|
+
export declare const LayoutDescriptorCell: ({ field, Bind, fields, contentModel, gridClassName }: LayoutDescriptorCellProps) => React.JSX.Element | null;
|
|
12
12
|
export {};
|
|
@@ -4,24 +4,24 @@ import { SeparatorFieldRenderer } from "./layoutFieldRenderers/SeparatorFieldRen
|
|
|
4
4
|
import { AlertFieldRenderer } from "./layoutFieldRenderers/AlertFieldRenderer.js";
|
|
5
5
|
import { TabsFieldRenderer } from "./layoutFieldRenderers/TabsFieldRenderer.js";
|
|
6
6
|
export const LayoutDescriptorCell = ({
|
|
7
|
-
|
|
7
|
+
field,
|
|
8
8
|
Bind,
|
|
9
9
|
fields,
|
|
10
10
|
contentModel,
|
|
11
11
|
gridClassName
|
|
12
12
|
}) => {
|
|
13
|
-
switch (
|
|
13
|
+
switch (field.type) {
|
|
14
14
|
case "separator":
|
|
15
15
|
return /*#__PURE__*/React.createElement(SeparatorFieldRenderer, {
|
|
16
|
-
|
|
16
|
+
field: field
|
|
17
17
|
});
|
|
18
18
|
case "alert":
|
|
19
19
|
return /*#__PURE__*/React.createElement(AlertFieldRenderer, {
|
|
20
|
-
|
|
20
|
+
field: field
|
|
21
21
|
});
|
|
22
22
|
case "tabs":
|
|
23
23
|
return /*#__PURE__*/React.createElement(TabsFieldRenderer, {
|
|
24
|
-
|
|
24
|
+
field: field,
|
|
25
25
|
Bind: Bind,
|
|
26
26
|
fields: fields,
|
|
27
27
|
contentModel: contentModel,
|
|
@@ -29,10 +29,10 @@ export const LayoutDescriptorCell = ({
|
|
|
29
29
|
});
|
|
30
30
|
default:
|
|
31
31
|
{
|
|
32
|
-
const rendererPlugin = plugins.byType("cms-layout-
|
|
32
|
+
const rendererPlugin = plugins.byType("cms-layout-field-renderer").find(p => p.fieldType === field.type);
|
|
33
33
|
if (rendererPlugin) {
|
|
34
34
|
return rendererPlugin.render({
|
|
35
|
-
|
|
35
|
+
field,
|
|
36
36
|
Bind,
|
|
37
37
|
fields,
|
|
38
38
|
contentModel,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","plugins","SeparatorFieldRenderer","AlertFieldRenderer","TabsFieldRenderer","LayoutDescriptorCell","
|
|
1
|
+
{"version":3,"names":["React","plugins","SeparatorFieldRenderer","AlertFieldRenderer","TabsFieldRenderer","LayoutDescriptorCell","field","Bind","fields","contentModel","gridClassName","type","createElement","rendererPlugin","byType","find","p","fieldType","render"],"sources":["LayoutDescriptorCell.tsx"],"sourcesContent":["import React from \"react\";\nimport type {\n CmsAlertLayoutField,\n CmsLayoutField,\n CmsSeparatorLayoutField,\n CmsTabLayoutField\n} from \"~/types/model.js\";\nimport type {\n BindComponent,\n CmsEditorContentModel,\n CmsModelLayoutFieldRendererPlugin,\n CmsModelField\n} from \"~/types/index.js\";\nimport { plugins } from \"@webiny/plugins\";\nimport { SeparatorFieldRenderer } from \"./layoutFieldRenderers/SeparatorFieldRenderer.js\";\nimport { AlertFieldRenderer } from \"./layoutFieldRenderers/AlertFieldRenderer.js\";\nimport { TabsFieldRenderer } from \"./layoutFieldRenderers/TabsFieldRenderer.js\";\n\ninterface LayoutDescriptorCellProps {\n field: CmsLayoutField;\n Bind: BindComponent;\n fields: CmsModelField[];\n contentModel: CmsEditorContentModel;\n gridClassName?: string;\n}\n\nexport const LayoutDescriptorCell = ({\n field,\n Bind,\n fields,\n contentModel,\n gridClassName\n}: LayoutDescriptorCellProps) => {\n switch (field.type) {\n case \"separator\":\n return <SeparatorFieldRenderer field={field as CmsSeparatorLayoutField} />;\n case \"alert\":\n return <AlertFieldRenderer field={field as CmsAlertLayoutField} />;\n case \"tabs\":\n return (\n <TabsFieldRenderer\n field={field as CmsTabLayoutField}\n Bind={Bind}\n fields={fields}\n contentModel={contentModel}\n gridClassName={gridClassName}\n />\n );\n default: {\n const rendererPlugin = plugins\n .byType<CmsModelLayoutFieldRendererPlugin>(\"cms-layout-field-renderer\")\n .find(p => p.fieldType === field.type);\n if (rendererPlugin) {\n return rendererPlugin.render({\n field,\n Bind,\n fields,\n contentModel,\n gridClassName\n });\n }\n return null;\n }\n }\n};\n"],"mappings":"AAAA,OAAOA,KAAK,MAAM,OAAO;AAazB,SAASC,OAAO,QAAQ,iBAAiB;AACzC,SAASC,sBAAsB;AAC/B,SAASC,kBAAkB;AAC3B,SAASC,iBAAiB;AAU1B,OAAO,MAAMC,oBAAoB,GAAGA,CAAC;EACjCC,KAAK;EACLC,IAAI;EACJC,MAAM;EACNC,YAAY;EACZC;AACuB,CAAC,KAAK;EAC7B,QAAQJ,KAAK,CAACK,IAAI;IACd,KAAK,WAAW;MACZ,oBAAOX,KAAA,CAAAY,aAAA,CAACV,sBAAsB;QAACI,KAAK,EAAEA;MAAiC,CAAE,CAAC;IAC9E,KAAK,OAAO;MACR,oBAAON,KAAA,CAAAY,aAAA,CAACT,kBAAkB;QAACG,KAAK,EAAEA;MAA6B,CAAE,CAAC;IACtE,KAAK,MAAM;MACP,oBACIN,KAAA,CAAAY,aAAA,CAACR,iBAAiB;QACdE,KAAK,EAAEA,KAA2B;QAClCC,IAAI,EAAEA,IAAK;QACXC,MAAM,EAAEA,MAAO;QACfC,YAAY,EAAEA,YAAa;QAC3BC,aAAa,EAAEA;MAAc,CAChC,CAAC;IAEV;MAAS;QACL,MAAMG,cAAc,GAAGZ,OAAO,CACzBa,MAAM,CAAoC,2BAA2B,CAAC,CACtEC,IAAI,CAACC,CAAC,IAAIA,CAAC,CAACC,SAAS,KAAKX,KAAK,CAACK,IAAI,CAAC;QAC1C,IAAIE,cAAc,EAAE;UAChB,OAAOA,cAAc,CAACK,MAAM,CAAC;YACzBZ,KAAK;YACLC,IAAI;YACJC,MAAM;YACNC,YAAY;YACZC;UACJ,CAAC,CAAC;QACN;QACA,OAAO,IAAI;MACf;EACJ;AACJ,CAAC","ignoreList":[]}
|
package/Fields/fieldOptions.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CmsModelField, CmsEditorFieldsLayout } from "../types/model.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type { CmsModelLayoutFieldTypePlugin } from "../types/index.js";
|
|
3
3
|
export interface FieldOption {
|
|
4
4
|
label: string;
|
|
5
5
|
value: string;
|
|
@@ -12,7 +12,7 @@ export interface FieldOption {
|
|
|
12
12
|
* Returns a map from fieldId to its label prefix string
|
|
13
13
|
* (e.g., `"metaTitle" → "My Tabs › SEO"`).
|
|
14
14
|
*/
|
|
15
|
-
export declare function buildFieldLabelPrefixes(layout: CmsEditorFieldsLayout, plugins:
|
|
15
|
+
export declare function buildFieldLabelPrefixes(layout: CmsEditorFieldsLayout, plugins: CmsModelLayoutFieldTypePlugin[]): Map<string, string>;
|
|
16
16
|
/**
|
|
17
17
|
* Build a flat list of field options from the model's field tree.
|
|
18
18
|
* Paths are absolute using fieldId segments, with `$` for list-object children
|
|
@@ -33,4 +33,4 @@ export declare function buildFieldLabelPrefixes(layout: CmsEditorFieldsLayout, p
|
|
|
33
33
|
* - dynamicZone: skip
|
|
34
34
|
* - ref: emit for isEmpty checks, skip children
|
|
35
35
|
*/
|
|
36
|
-
export declare function buildFieldOptions(fields: CmsModelField[], prefix?: string, labelPrefix?: string, fieldLabelPrefixes?: Map<string, string>, layoutPlugins?:
|
|
36
|
+
export declare function buildFieldOptions(fields: CmsModelField[], prefix?: string, labelPrefix?: string, fieldLabelPrefixes?: Map<string, string>, layoutPlugins?: CmsModelLayoutFieldTypePlugin[]): FieldOption[];
|
package/Fields/fieldOptions.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isLayoutField } from "../types/model.js";
|
|
2
2
|
/**
|
|
3
3
|
* Walk a model layout and collect label prefixes for each field ID by delegating
|
|
4
4
|
* to `getFieldLabelPrefixes` on the matching layout-field-type plugin.
|
|
@@ -11,7 +11,7 @@ export function buildFieldLabelPrefixes(layout, plugins) {
|
|
|
11
11
|
const pluginByType = new Map(plugins.map(p => [p.field.type, p]));
|
|
12
12
|
for (const row of layout) {
|
|
13
13
|
for (const cell of row) {
|
|
14
|
-
if (!
|
|
14
|
+
if (!isLayoutField(cell)) {
|
|
15
15
|
continue;
|
|
16
16
|
}
|
|
17
17
|
const plugin = pluginByType.get(cell.type);
|
|
@@ -19,7 +19,7 @@ export function buildFieldLabelPrefixes(layout, plugins) {
|
|
|
19
19
|
continue;
|
|
20
20
|
}
|
|
21
21
|
const prefixes = plugin.field.getFieldLabelPrefixes({
|
|
22
|
-
|
|
22
|
+
field: cell
|
|
23
23
|
});
|
|
24
24
|
for (const [fieldId, prefix] of Object.entries(prefixes)) {
|
|
25
25
|
map.set(fieldId, prefix);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["
|
|
1
|
+
{"version":3,"names":["isLayoutField","buildFieldLabelPrefixes","layout","plugins","map","Map","pluginByType","p","field","type","row","cell","plugin","get","getFieldLabelPrefixes","prefixes","fieldId","prefix","Object","entries","set","buildFieldOptions","fields","labelPrefix","fieldLabelPrefixes","layoutPlugins","options","path","layoutPrefix","id","label","push","value","fieldType","childFields","settings","length","childPrefixes","list"],"sources":["fieldOptions.ts"],"sourcesContent":["import type { CmsModelField, CmsEditorFieldsLayout } from \"~/types/model.js\";\nimport type { CmsModelLayoutFieldTypePlugin } from \"~/types/index.js\";\nimport { isLayoutField } from \"~/types/model.js\";\n\nexport interface FieldOption {\n label: string;\n value: string;\n fieldType: string;\n}\n\n/**\n * Walk a model layout and collect label prefixes for each field ID by delegating\n * to `getFieldLabelPrefixes` on the matching layout-field-type plugin.\n *\n * Returns a map from fieldId to its label prefix string\n * (e.g., `\"metaTitle\" → \"My Tabs › SEO\"`).\n */\nexport function buildFieldLabelPrefixes(\n layout: CmsEditorFieldsLayout,\n plugins: CmsModelLayoutFieldTypePlugin[]\n): Map<string, string> {\n const map = new Map<string, string>();\n const pluginByType = new Map(plugins.map(p => [p.field.type, p]));\n\n for (const row of layout) {\n for (const cell of row) {\n if (!isLayoutField(cell)) {\n continue;\n }\n\n const plugin = pluginByType.get(cell.type);\n if (!plugin?.field.getFieldLabelPrefixes) {\n continue;\n }\n\n const prefixes = plugin.field.getFieldLabelPrefixes({ field: cell });\n for (const [fieldId, prefix] of Object.entries(prefixes)) {\n map.set(fieldId, prefix);\n }\n }\n }\n\n return map;\n}\n\n/**\n * Build a flat list of field options from the model's field tree.\n * Paths are absolute using fieldId segments, with `$` for list-object children\n * (e.g., `panorama.hotspots.$.title`).\n *\n * When `fieldLabelPrefixes` is provided, fields whose IDs appear in the map will\n * have the layout hierarchy prepended to their labels\n * (e.g., `\"My Tabs › SEO › Meta Title\"`).\n *\n * When `layoutPlugins` is provided, nested layouts inside object fields\n * (e.g., tabs inside an object field) are also scanned for label prefixes.\n *\n * Recursion rules:\n * - Leaf field (no settings.fields): emit option\n * - Object field (settings.fields, not list): recurse with prefix\n * - List object field (settings.fields, list: true): emit `.length` pseudo-option,\n * then recurse children with `.$` segment\n * - dynamicZone: skip\n * - ref: emit for isEmpty checks, skip children\n */\nexport function buildFieldOptions(\n fields: CmsModelField[],\n prefix = \"\",\n labelPrefix = \"\",\n fieldLabelPrefixes?: Map<string, string>,\n layoutPlugins?: CmsModelLayoutFieldTypePlugin[]\n): FieldOption[] {\n const options: FieldOption[] = [];\n\n for (const field of fields) {\n const path = prefix + field.fieldId;\n const layoutPrefix = fieldLabelPrefixes?.get(field.id);\n const label = layoutPrefix\n ? `${labelPrefix}${layoutPrefix} › ${field.label}`\n : labelPrefix + field.label;\n\n // Dynamic zone: emit .length pseudo-option only, skip children\n if (field.type === \"dynamicZone\") {\n options.push({\n label: `${label} › Length`,\n value: `${path}.length`,\n fieldType: \"number\"\n });\n continue;\n }\n\n const childFields = field.settings?.fields;\n\n // Ref field: include for isEmpty checks, skip children\n if (field.type === \"ref\") {\n options.push({ label, value: path, fieldType: field.type });\n continue;\n }\n\n // Object with child fields\n if (childFields && childFields.length > 0) {\n // Build label prefixes from the object field's own layout (e.g., tabs inside an object).\n let childPrefixes: Map<string, string> | undefined;\n if (layoutPlugins && field.settings?.layout) {\n childPrefixes = buildFieldLabelPrefixes(field.settings.layout, layoutPlugins);\n }\n\n if (field.list) {\n // List object: emit .length pseudo-option\n options.push({\n label: `${label} › Length`,\n value: `${path}.length`,\n fieldType: \"number\"\n });\n // Recurse children with $ segment\n options.push(\n ...buildFieldOptions(\n childFields,\n `${path}.$.`,\n `${label} › `,\n childPrefixes,\n layoutPlugins\n )\n );\n } else {\n // Non-list object: recurse into children\n options.push(\n ...buildFieldOptions(\n childFields,\n `${path}.`,\n `${label} › `,\n childPrefixes,\n layoutPlugins\n )\n );\n }\n continue;\n }\n\n // Leaf field\n options.push({ label, value: path, fieldType: field.type });\n }\n\n return options;\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import type {
|
|
2
|
+
import type { CmsAlertLayoutField } from "../../types/model.js";
|
|
3
3
|
interface AlertFieldRendererProps {
|
|
4
|
-
|
|
4
|
+
field: CmsAlertLayoutField;
|
|
5
5
|
}
|
|
6
|
-
export declare const AlertFieldRenderer: ({
|
|
6
|
+
export declare const AlertFieldRenderer: ({ field }: AlertFieldRendererProps) => React.JSX.Element;
|
|
7
7
|
export {};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { Alert, Grid } from "@webiny/admin-ui";
|
|
3
3
|
export const AlertFieldRenderer = ({
|
|
4
|
-
|
|
4
|
+
field
|
|
5
5
|
}) => {
|
|
6
6
|
return /*#__PURE__*/React.createElement(Grid.Column, {
|
|
7
7
|
span: 12
|
|
8
8
|
}, /*#__PURE__*/React.createElement(Alert, {
|
|
9
|
-
type:
|
|
10
|
-
},
|
|
9
|
+
type: field.alertType
|
|
10
|
+
}, field.label));
|
|
11
11
|
};
|
|
12
12
|
|
|
13
13
|
//# sourceMappingURL=AlertFieldRenderer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","Alert","Grid","AlertFieldRenderer","
|
|
1
|
+
{"version":3,"names":["React","Alert","Grid","AlertFieldRenderer","field","createElement","Column","span","type","alertType","label"],"sources":["AlertFieldRenderer.tsx"],"sourcesContent":["import React from \"react\";\nimport { Alert, Grid } from \"@webiny/admin-ui\";\nimport type { CmsAlertLayoutField } from \"~/types/model.js\";\n\ninterface AlertFieldRendererProps {\n field: CmsAlertLayoutField;\n}\n\nexport const AlertFieldRenderer = ({ field }: AlertFieldRendererProps) => {\n return (\n <Grid.Column span={12}>\n <Alert type={field.alertType}>{field.label}</Alert>\n </Grid.Column>\n );\n};\n"],"mappings":"AAAA,OAAOA,KAAK,MAAM,OAAO;AACzB,SAASC,KAAK,EAAEC,IAAI,QAAQ,kBAAkB;AAO9C,OAAO,MAAMC,kBAAkB,GAAGA,CAAC;EAAEC;AAA+B,CAAC,KAAK;EACtE,oBACIJ,KAAA,CAAAK,aAAA,CAACH,IAAI,CAACI,MAAM;IAACC,IAAI,EAAE;EAAG,gBAClBP,KAAA,CAAAK,aAAA,CAACJ,KAAK;IAACO,IAAI,EAAEJ,KAAK,CAACK;EAAU,GAAEL,KAAK,CAACM,KAAa,CACzC,CAAC;AAEtB,CAAC","ignoreList":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import type {
|
|
2
|
+
import type { CmsSeparatorLayoutField } from "../../types/model.js";
|
|
3
3
|
interface SeparatorFieldRendererProps {
|
|
4
|
-
|
|
4
|
+
field: CmsSeparatorLayoutField;
|
|
5
5
|
}
|
|
6
|
-
export declare const SeparatorFieldRenderer: ({
|
|
6
|
+
export declare const SeparatorFieldRenderer: ({ field }: SeparatorFieldRendererProps) => React.JSX.Element;
|
|
7
7
|
export {};
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { Grid, Separator, Text } from "@webiny/admin-ui";
|
|
3
3
|
export const SeparatorFieldRenderer = ({
|
|
4
|
-
|
|
4
|
+
field
|
|
5
5
|
}) => {
|
|
6
6
|
return /*#__PURE__*/React.createElement(Grid.Column, {
|
|
7
7
|
span: 12
|
|
8
8
|
}, /*#__PURE__*/React.createElement(Separator, {
|
|
9
9
|
variant: "accent",
|
|
10
10
|
labelPosition: "start"
|
|
11
|
-
},
|
|
11
|
+
}, field.label), field.description && /*#__PURE__*/React.createElement(Text, {
|
|
12
12
|
as: "div",
|
|
13
13
|
size: "sm",
|
|
14
14
|
className: "text-neutral-strong mt-sm"
|
|
15
|
-
},
|
|
15
|
+
}, field.description));
|
|
16
16
|
};
|
|
17
17
|
|
|
18
18
|
//# sourceMappingURL=SeparatorFieldRenderer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","Grid","Separator","Text","SeparatorFieldRenderer","
|
|
1
|
+
{"version":3,"names":["React","Grid","Separator","Text","SeparatorFieldRenderer","field","createElement","Column","span","variant","labelPosition","label","description","as","size","className"],"sources":["SeparatorFieldRenderer.tsx"],"sourcesContent":["import React from \"react\";\nimport { Grid, Separator, Text } from \"@webiny/admin-ui\";\nimport type { CmsSeparatorLayoutField } from \"~/types/model.js\";\n\ninterface SeparatorFieldRendererProps {\n field: CmsSeparatorLayoutField;\n}\n\nexport const SeparatorFieldRenderer = ({ field }: SeparatorFieldRendererProps) => {\n return (\n <Grid.Column span={12}>\n <Separator variant={\"accent\"} labelPosition={\"start\"}>\n {field.label}\n </Separator>\n {field.description && (\n <Text as={\"div\"} size={\"sm\"} className={\"text-neutral-strong mt-sm\"}>\n {field.description}\n </Text>\n )}\n </Grid.Column>\n );\n};\n"],"mappings":"AAAA,OAAOA,KAAK,MAAM,OAAO;AACzB,SAASC,IAAI,EAAEC,SAAS,EAAEC,IAAI,QAAQ,kBAAkB;AAOxD,OAAO,MAAMC,sBAAsB,GAAGA,CAAC;EAAEC;AAAmC,CAAC,KAAK;EAC9E,oBACIL,KAAA,CAAAM,aAAA,CAACL,IAAI,CAACM,MAAM;IAACC,IAAI,EAAE;EAAG,gBAClBR,KAAA,CAAAM,aAAA,CAACJ,SAAS;IAACO,OAAO,EAAE,QAAS;IAACC,aAAa,EAAE;EAAQ,GAChDL,KAAK,CAACM,KACA,CAAC,EACXN,KAAK,CAACO,WAAW,iBACdZ,KAAA,CAAAM,aAAA,CAACH,IAAI;IAACU,EAAE,EAAE,KAAM;IAACC,IAAI,EAAE,IAAK;IAACC,SAAS,EAAE;EAA4B,GAC/DV,KAAK,CAACO,WACL,CAED,CAAC;AAEtB,CAAC","ignoreList":[]}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import type {
|
|
2
|
+
import type { CmsTabLayoutField } from "../../types/model.js";
|
|
3
3
|
import type { BindComponent, CmsEditorContentModel, CmsModelField } from "../../types/index.js";
|
|
4
4
|
interface TabsFieldRendererProps {
|
|
5
|
-
|
|
5
|
+
field: CmsTabLayoutField;
|
|
6
6
|
Bind: BindComponent;
|
|
7
7
|
fields: CmsModelField[];
|
|
8
8
|
contentModel: CmsEditorContentModel;
|
|
9
9
|
gridClassName?: string;
|
|
10
10
|
}
|
|
11
|
-
export declare const TabsFieldRenderer: ({
|
|
11
|
+
export declare const TabsFieldRenderer: ({ field, Bind, fields, contentModel, gridClassName }: TabsFieldRendererProps) => React.JSX.Element;
|
|
12
12
|
export {};
|
|
@@ -4,7 +4,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
|
4
4
|
import { normalizeIcon } from "../../normalizeIcon.js";
|
|
5
5
|
import { Fields } from "../index.js";
|
|
6
6
|
import { FieldRulesProvider } from "../FieldRulesProvider.js";
|
|
7
|
-
import {
|
|
7
|
+
import { useFieldEffectiveRules } from "../useFieldRules.js";
|
|
8
8
|
const TabPanel = ({
|
|
9
9
|
tab,
|
|
10
10
|
Bind,
|
|
@@ -12,7 +12,7 @@ const TabPanel = ({
|
|
|
12
12
|
contentModel,
|
|
13
13
|
gridClassName
|
|
14
14
|
}) => {
|
|
15
|
-
const rules =
|
|
15
|
+
const rules = useFieldEffectiveRules(tab);
|
|
16
16
|
const icon = normalizeIcon(tab.icon);
|
|
17
17
|
return /*#__PURE__*/React.createElement(Tabs.Tab, {
|
|
18
18
|
disabled: rules.disabled,
|
|
@@ -36,13 +36,13 @@ const TabPanel = ({
|
|
|
36
36
|
};
|
|
37
37
|
const tabsWrapperClassName = ["bg-white!", "opacity-100!", "border-neutral-muted", "text-neutral-strong", "fill-neutral-xstrong", "w-full", "border-sm", "rounded-md"].join(" ");
|
|
38
38
|
export const TabsFieldRenderer = ({
|
|
39
|
-
|
|
39
|
+
field,
|
|
40
40
|
Bind,
|
|
41
41
|
fields,
|
|
42
42
|
contentModel,
|
|
43
43
|
gridClassName
|
|
44
44
|
}) => {
|
|
45
|
-
const tabElements =
|
|
45
|
+
const tabElements = field.tabs.map(tab => /*#__PURE__*/React.createElement(TabPanel, {
|
|
46
46
|
key: tab.id,
|
|
47
47
|
tab: tab,
|
|
48
48
|
Bind: Bind,
|
|
@@ -50,14 +50,14 @@ export const TabsFieldRenderer = ({
|
|
|
50
50
|
contentModel: contentModel,
|
|
51
51
|
gridClassName: gridClassName
|
|
52
52
|
}));
|
|
53
|
-
const firstTab =
|
|
53
|
+
const firstTab = field.tabs[0];
|
|
54
54
|
return /*#__PURE__*/React.createElement(Grid.Column, {
|
|
55
55
|
span: 12
|
|
56
|
-
},
|
|
57
|
-
text:
|
|
58
|
-
hint:
|
|
59
|
-
}) : null,
|
|
60
|
-
text:
|
|
56
|
+
}, field.label ? /*#__PURE__*/React.createElement(FormComponentLabel, {
|
|
57
|
+
text: field.label,
|
|
58
|
+
hint: field.help
|
|
59
|
+
}) : null, field.description ? /*#__PURE__*/React.createElement(FormComponentDescription, {
|
|
60
|
+
text: field.description
|
|
61
61
|
}) : null, /*#__PURE__*/React.createElement("div", {
|
|
62
62
|
className: tabsWrapperClassName
|
|
63
63
|
}, /*#__PURE__*/React.createElement(Tabs, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","Grid","FormComponentLabel","FormComponentDescription","Tabs","FontAwesomeIcon","normalizeIcon","Fields","FieldRulesProvider","
|
|
1
|
+
{"version":3,"names":["React","Grid","FormComponentLabel","FormComponentDescription","Tabs","FontAwesomeIcon","normalizeIcon","Fields","FieldRulesProvider","useFieldEffectiveRules","TabPanel","tab","Bind","fields","contentModel","gridClassName","rules","icon","createElement","Tab","disabled","visible","canView","hidden","value","id","trigger","label","size","undefined","content","layout","tabsWrapperClassName","join","TabsFieldRenderer","field","tabElements","tabs","map","key","firstTab","Column","span","text","hint","help","description","className","spacing","separator","defaultValue"],"sources":["TabsFieldRenderer.tsx"],"sourcesContent":["import React from \"react\";\nimport { Grid, FormComponentLabel, FormComponentDescription, Tabs } from \"@webiny/admin-ui\";\nimport { FontAwesomeIcon } from \"@fortawesome/react-fontawesome\";\nimport type { CmsTabLayoutField, CmsTabLayoutTab } from \"~/types/model.js\";\nimport type { BindComponent, CmsEditorContentModel, CmsModelField } from \"~/types/index.js\";\nimport { normalizeIcon } from \"~/normalizeIcon.js\";\nimport { Fields } from \"~/Fields/index.js\";\nimport { FieldRulesProvider } from \"~/Fields/FieldRulesProvider.js\";\nimport { useFieldEffectiveRules } from \"~/Fields/useFieldRules.js\";\n\ninterface TabsFieldRendererProps {\n field: CmsTabLayoutField;\n Bind: BindComponent;\n fields: CmsModelField[];\n contentModel: CmsEditorContentModel;\n gridClassName?: string;\n}\n\ninterface TabPanelProps {\n tab: CmsTabLayoutTab;\n Bind: BindComponent;\n fields: CmsModelField[];\n contentModel: CmsEditorContentModel;\n gridClassName?: string;\n}\n\nconst TabPanel = ({ tab, Bind, fields, contentModel, gridClassName }: TabPanelProps) => {\n const rules = useFieldEffectiveRules(tab);\n\n const icon = normalizeIcon(tab.icon);\n\n return (\n <Tabs.Tab\n disabled={rules.disabled}\n visible={rules.canView && !rules.hidden}\n value={tab.id}\n trigger={tab.label}\n icon={icon ? <FontAwesomeIcon icon={icon} size={\"sm\"} /> : undefined}\n content={\n <FieldRulesProvider rules={rules}>\n <Fields\n Bind={Bind}\n fields={fields}\n layout={tab.layout}\n contentModel={contentModel}\n gridClassName={gridClassName}\n />\n </FieldRulesProvider>\n }\n />\n );\n};\n\nconst tabsWrapperClassName = [\n \"bg-white!\",\n \"opacity-100!\",\n \"border-neutral-muted\",\n \"text-neutral-strong\",\n \"fill-neutral-xstrong\",\n \"w-full\",\n \"border-sm\",\n \"rounded-md\"\n].join(\" \");\n\nexport const TabsFieldRenderer = ({\n field,\n Bind,\n fields,\n contentModel,\n gridClassName\n}: TabsFieldRendererProps) => {\n const tabElements = field.tabs.map(tab => (\n <TabPanel\n key={tab.id}\n tab={tab}\n Bind={Bind}\n fields={fields}\n contentModel={contentModel}\n gridClassName={gridClassName}\n />\n ));\n\n const firstTab = field.tabs[0];\n\n return (\n <Grid.Column span={12}>\n {field.label ? <FormComponentLabel text={field.label} hint={field.help} /> : null}\n {field.description ? <FormComponentDescription text={field.description} /> : null}\n <div className={tabsWrapperClassName}>\n <Tabs\n size=\"md\"\n spacing=\"md\"\n separator={true}\n tabs={tabElements}\n defaultValue={firstTab?.id}\n />\n </div>\n </Grid.Column>\n );\n};\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -28,5 +28,5 @@ export declare function evaluateAccessControlRules(item: HasRules, identity: Ide
|
|
|
28
28
|
* Composes useParentRules and useFieldRules into a single hook
|
|
29
29
|
* that returns the effective (intersected) rules.
|
|
30
30
|
*/
|
|
31
|
-
export declare function
|
|
31
|
+
export declare function useFieldEffectiveRules(item: HasRules): EffectiveFieldRules;
|
|
32
32
|
export {};
|
package/Fields/useFieldRules.js
CHANGED
|
@@ -139,7 +139,7 @@ function useFieldRules(item) {
|
|
|
139
139
|
* Composes useParentRules and useFieldRules into a single hook
|
|
140
140
|
* that returns the effective (intersected) rules.
|
|
141
141
|
*/
|
|
142
|
-
export function
|
|
142
|
+
export function useFieldEffectiveRules(item) {
|
|
143
143
|
const parentRules = useParentRules();
|
|
144
144
|
const itemRules = useFieldRules(item);
|
|
145
145
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useForm","useAuthentication","evaluateExpression","resolveFieldPath","useParentRules","useBindParentName","evaluateAccessControlRulesForIdentity","rules","identity","userTargets","Set","add","id","team","teams","slug","canView","canEdit","rule","type","value","operator","has","String","action","useFieldAccessControlRules","item","length","evaluateAccessControlRules","hidden","disabled","useFieldRules","form","bindParentName","target","resolvedPath","matches","name","getValue","
|
|
1
|
+
{"version":3,"names":["useForm","useAuthentication","evaluateExpression","resolveFieldPath","useParentRules","useBindParentName","evaluateAccessControlRulesForIdentity","rules","identity","userTargets","Set","add","id","team","teams","slug","canView","canEdit","rule","type","value","operator","has","String","action","useFieldAccessControlRules","item","length","evaluateAccessControlRules","hidden","disabled","useFieldRules","form","bindParentName","target","resolvedPath","matches","name","getValue","useFieldEffectiveRules","parentRules","itemRules"],"sources":["useFieldRules.ts"],"sourcesContent":["import { useForm } from \"@webiny/form\";\nimport { useAuthentication } from \"@webiny/app-admin\";\nimport type { FieldRule } from \"~/types/model.js\";\nimport { evaluateExpression, resolveFieldPath } from \"./evaluateExpression.js\";\nimport { useParentRules } from \"./FieldRulesProvider.js\";\nimport { useBindParentName } from \"./useBind.js\";\n\nexport interface EffectiveFieldRules {\n canView: boolean;\n canEdit: boolean;\n hidden: boolean;\n disabled: boolean;\n}\n\ninterface HasRules {\n rules?: FieldRule[];\n}\n\ninterface IdentityLike {\n id: string;\n teams: { slug: string }[];\n}\n\n/**\n * Evaluate access control rules against an identity.\n * Pure function — no hooks, can be called anywhere.\n */\nfunction evaluateAccessControlRulesForIdentity(\n rules: FieldRule[],\n identity: IdentityLike\n): Pick<EffectiveFieldRules, \"canView\" | \"canEdit\"> {\n const userTargets = new Set<string>();\n userTargets.add(`admin:${identity.id}`);\n for (const team of identity.teams) {\n userTargets.add(`team:${team.slug}`);\n }\n\n let canView = true;\n let canEdit = true;\n\n for (const rule of rules) {\n if (rule.type !== \"accessControl\") {\n continue;\n }\n if (!rule.value || !rule.operator) {\n continue;\n }\n if (!userTargets.has(String(rule.value))) {\n continue;\n }\n if (rule.action === \"hide\") {\n canView = false;\n } else if (rule.action === \"disable\") {\n canEdit = false;\n }\n }\n\n return { canView, canEdit };\n}\n\n/**\n * Hook that evaluates access control rules for the current identity.\n * Does not require `bindParentName` — only identity-based permissions.\n */\nexport function useFieldAccessControlRules(\n item: HasRules\n): Pick<EffectiveFieldRules, \"canView\" | \"canEdit\"> {\n const { identity } = useAuthentication();\n\n const rules = item.rules;\n if (!rules || rules.length === 0) {\n return { canView: true, canEdit: true };\n }\n\n return evaluateAccessControlRulesForIdentity(rules, identity);\n}\n\n/**\n * Evaluate access control rules statically (without hooks).\n * Used in RowRenderer for the visibility approximation where hooks can't be called.\n */\nexport function evaluateAccessControlRules(\n item: HasRules,\n identity: IdentityLike\n): EffectiveFieldRules {\n const rules = item.rules;\n if (!rules || rules.length === 0) {\n return { canView: true, canEdit: true, hidden: false, disabled: false };\n }\n\n const { canView, canEdit } = evaluateAccessControlRulesForIdentity(rules, identity);\n return { canView, canEdit, hidden: false, disabled: false };\n}\n\n/**\n * Internal hook that evaluates all rules (access control + entry value).\n */\nfunction useFieldRules(item: HasRules): EffectiveFieldRules {\n const { identity } = useAuthentication();\n const form = useForm();\n const bindParentName = useBindParentName();\n\n const rules = item.rules;\n if (!rules || rules.length === 0) {\n return { canView: true, canEdit: true, hidden: false, disabled: false };\n }\n\n const { canView, canEdit } = evaluateAccessControlRulesForIdentity(rules, identity);\n\n let hidden = false;\n let disabled = false;\n\n for (const rule of rules) {\n if (rule.type !== \"condition\") {\n continue;\n }\n if (!rule.target || !rule.operator) {\n continue;\n }\n const resolvedPath = resolveFieldPath(rule.target, bindParentName);\n const matches = evaluateExpression(\n { target: resolvedPath, operator: rule.operator as any, value: rule.value },\n name => form.getValue(name)\n );\n if (!matches) {\n continue;\n }\n if (rule.action === \"hide\") {\n hidden = true;\n } else if (rule.action === \"disable\") {\n disabled = true;\n }\n }\n\n return { canView, canEdit, hidden, disabled };\n}\n\n/**\n * Composes useParentRules and useFieldRules into a single hook\n * that returns the effective (intersected) rules.\n */\nexport function useFieldEffectiveRules(item: HasRules): EffectiveFieldRules {\n const parentRules = useParentRules();\n const itemRules = useFieldRules(item);\n return {\n canView: parentRules.canView && itemRules.canView,\n canEdit: parentRules.canEdit && itemRules.canEdit,\n hidden: parentRules.hidden || itemRules.hidden,\n disabled: parentRules.disabled || itemRules.disabled\n };\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import type { CmsModelFieldRendererPlugin } from "../types/index.js";
|
|
2
|
+
export declare function useRenderPlugins(): import("@webiny/plugins/PluginsContainer").WithName<CmsModelFieldRendererPlugin>[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["plugins","useMemo","useRenderPlugins","byType"],"sources":["useRenderPlugins.ts"],"sourcesContent":["import { plugins } from \"@webiny/plugins\";\nimport { useMemo } from \"react\";\nimport type {
|
|
1
|
+
{"version":3,"names":["plugins","useMemo","useRenderPlugins","byType"],"sources":["useRenderPlugins.ts"],"sourcesContent":["import { plugins } from \"@webiny/plugins\";\nimport { useMemo } from \"react\";\nimport type { CmsModelFieldRendererPlugin } from \"~/types/index.js\";\n\nexport function useRenderPlugins() {\n return useMemo(\n () => plugins.byType<CmsModelFieldRendererPlugin>(\"cms-editor-field-renderer\"),\n []\n );\n}\n"],"mappings":"AAAA,SAASA,OAAO,QAAQ,iBAAiB;AACzC,SAASC,OAAO,QAAQ,OAAO;AAG/B,OAAO,SAASC,gBAAgBA,CAAA,EAAG;EAC/B,OAAOD,OAAO,CACV,MAAMD,OAAO,CAACG,MAAM,CAA8B,2BAA2B,CAAC,EAC9E,EACJ,CAAC;AACL","ignoreList":[]}
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export { useFieldAccessControlRules,
|
|
2
|
-
export type { CmsLayoutFieldTypePlugin, CmsLayoutDescriptorRendererPlugin, CmsBaseLayoutDescriptor, CmsLayoutDescriptor } from "../../../types/index.ts";
|
|
1
|
+
export { useFieldAccessControlRules, useFieldEffectiveRules } from "../../../Fields/index.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useFieldAccessControlRules","
|
|
1
|
+
{"version":3,"names":["useFieldAccessControlRules","useFieldEffectiveRules"],"sources":["model.ts"],"sourcesContent":["export { useFieldAccessControlRules, useFieldEffectiveRules } from \"~/Fields/index.js\";\n"],"mappings":"AAAA,SAASA,0BAA0B,EAAEC,sBAAsB","ignoreList":[]}
|
package/exports/admin/cms.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export type { CmsContentEntry, CmsModel, CmsModelField,
|
|
1
|
+
export type { CmsContentEntry, CmsModel, CmsModelField, CmsModelLayoutField, CmsIdentity } from "../../types/index.ts";
|
package/exports/admin/cms.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["cms.ts"],"sourcesContent":["export type {\n CmsContentEntry,\n CmsModel,\n CmsModelField,\n
|
|
1
|
+
{"version":3,"names":[],"sources":["cms.ts"],"sourcesContent":["export type {\n CmsContentEntry,\n CmsModel,\n CmsModelField,\n CmsModelLayoutField,\n CmsIdentity\n} from \"~/types/index.ts\";\n"],"mappings":"","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webiny/app-headless-cms-common",
|
|
3
|
-
"version": "6.0.0-rc.
|
|
3
|
+
"version": "6.0.0-rc.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
@@ -18,13 +18,13 @@
|
|
|
18
18
|
"@emotion/styled": "11.10.6",
|
|
19
19
|
"@fortawesome/fontawesome-svg-core": "1.3.0",
|
|
20
20
|
"@fortawesome/react-fontawesome": "0.1.19",
|
|
21
|
-
"@webiny/admin-ui": "6.0.0-rc.
|
|
22
|
-
"@webiny/app": "6.0.0-rc.
|
|
23
|
-
"@webiny/app-admin": "6.0.0-rc.
|
|
24
|
-
"@webiny/form": "6.0.0-rc.
|
|
25
|
-
"@webiny/plugins": "6.0.0-rc.
|
|
26
|
-
"@webiny/react-composition": "6.0.0-rc.
|
|
27
|
-
"@webiny/validation": "6.0.0-rc.
|
|
21
|
+
"@webiny/admin-ui": "6.0.0-rc.5",
|
|
22
|
+
"@webiny/app": "6.0.0-rc.5",
|
|
23
|
+
"@webiny/app-admin": "6.0.0-rc.5",
|
|
24
|
+
"@webiny/form": "6.0.0-rc.5",
|
|
25
|
+
"@webiny/plugins": "6.0.0-rc.5",
|
|
26
|
+
"@webiny/react-composition": "6.0.0-rc.5",
|
|
27
|
+
"@webiny/validation": "6.0.0-rc.5",
|
|
28
28
|
"dnd-core": "16.0.1",
|
|
29
29
|
"graphql": "16.13.0",
|
|
30
30
|
"graphql-tag": "2.12.6",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@emotion/babel-plugin": "11.13.5",
|
|
37
37
|
"@types/react": "18.2.79",
|
|
38
|
-
"@webiny/build-tools": "6.0.0-rc.
|
|
38
|
+
"@webiny/build-tools": "6.0.0-rc.5",
|
|
39
39
|
"babel-plugin-module-resolver": "5.0.2",
|
|
40
40
|
"rimraf": "6.1.3",
|
|
41
41
|
"typescript": "5.9.3"
|
|
@@ -44,5 +44,5 @@
|
|
|
44
44
|
"access": "public",
|
|
45
45
|
"directory": "dist"
|
|
46
46
|
},
|
|
47
|
-
"gitHead": "
|
|
47
|
+
"gitHead": "8f9b60f1193682a21e037e6f771b19f1dfd65045"
|
|
48
48
|
}
|
package/types/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type { Plugin } from "@webiny/plugins/types.js";
|
|
|
4
4
|
import type { BindComponent as BaseBindComponent, BindComponentProps as BaseBindComponentProps, BindComponentRenderProp as BaseBindComponentRenderProp, FormAPI } from "@webiny/form";
|
|
5
5
|
import type { IconName, IconPrefix } from "@fortawesome/fontawesome-svg-core";
|
|
6
6
|
import type { CmsModelFieldValidator, CmsModelFieldValidatorsFactory, CmsModelFieldValidatorsGroup } from "./validation.js";
|
|
7
|
-
import type {
|
|
7
|
+
import type { CmsModelLayoutField, CmsEditorFieldsLayout, CmsLayoutField, CmsModel, CmsModelField } from "./model.js";
|
|
8
8
|
import type { CmsIdentity } from "../types/shared.js";
|
|
9
9
|
import type { SourceType } from "dnd-core";
|
|
10
10
|
import type { IconPickerIconDto } from "@webiny/admin-ui";
|
|
@@ -15,7 +15,7 @@ export type DragObjectWithType = {
|
|
|
15
15
|
};
|
|
16
16
|
export type * from "./validation.js";
|
|
17
17
|
export type * from "./model.js";
|
|
18
|
-
export { isLayoutDescriptor } from "./model.js";
|
|
18
|
+
export { isLayoutField, isLayoutDescriptor } from "./model.js";
|
|
19
19
|
export type * from "./shared.js";
|
|
20
20
|
interface QueryFieldParams {
|
|
21
21
|
model: CmsModel;
|
|
@@ -37,12 +37,8 @@ export interface DragSource extends DragObjectWithType {
|
|
|
37
37
|
layoutFieldType?: string;
|
|
38
38
|
field?: CmsModelField | null;
|
|
39
39
|
fields?: CmsModelField[];
|
|
40
|
-
|
|
40
|
+
layoutField?: CmsLayoutField;
|
|
41
41
|
}
|
|
42
|
-
/**
|
|
43
|
-
* @deprecated Use `CmsModelFieldTypePlugin`.
|
|
44
|
-
*/
|
|
45
|
-
export type CmsEditorFieldTypePlugin = CmsModelFieldTypePlugin;
|
|
46
42
|
export interface CmsModelFieldTypePlugin extends Plugin {
|
|
47
43
|
/**
|
|
48
44
|
* a plugin type
|
|
@@ -222,53 +218,53 @@ export interface CmsModelFieldTypePlugin extends Plugin {
|
|
|
222
218
|
}) => React.ReactElement;
|
|
223
219
|
};
|
|
224
220
|
}
|
|
225
|
-
export interface
|
|
221
|
+
export interface CmsModelLayoutFieldTypePlugin<T extends CmsModelLayoutField = CmsModelLayoutField> extends Plugin {
|
|
226
222
|
type: "cms-editor-layout-field-type";
|
|
227
223
|
field: {
|
|
228
|
-
type:
|
|
224
|
+
type: T["type"];
|
|
229
225
|
label: string;
|
|
230
226
|
description: string;
|
|
231
227
|
icon: React.ReactElement;
|
|
232
|
-
|
|
228
|
+
createField(): Omit<T, "id">;
|
|
233
229
|
canEditSettings?: boolean;
|
|
234
230
|
renderSettings?(): React.ReactNode;
|
|
235
231
|
/**
|
|
236
|
-
* Collect all model fields embedded inside a layout
|
|
237
|
-
* Used during drag-and-drop to move embedded fields along with the
|
|
238
|
-
* across parent boundaries. Return `[]` or omit for
|
|
232
|
+
* Collect all model fields embedded inside a layout field's nested layout.
|
|
233
|
+
* Used during drag-and-drop to move embedded fields along with the layout field
|
|
234
|
+
* across parent boundaries. Return `[]` or omit for layout fields with no nested fields.
|
|
239
235
|
*/
|
|
240
236
|
collectFields?(params: {
|
|
241
|
-
|
|
237
|
+
field: T;
|
|
242
238
|
getField: (id: string) => CmsModelField | undefined;
|
|
243
239
|
}): CmsModelField[];
|
|
244
240
|
/**
|
|
245
|
-
* Return a label prefix for each field ID nested inside this layout
|
|
241
|
+
* Return a label prefix for each field ID nested inside this layout field.
|
|
246
242
|
* Used by `buildFieldOptions` to include layout hierarchy in field labels.
|
|
247
243
|
*
|
|
248
|
-
* For example, a tabs
|
|
244
|
+
* For example, a tabs layout field with label "My Tabs" containing a tab "SEO"
|
|
249
245
|
* with field "metaTitle" would return: `{ "metaTitle": "My Tabs › SEO" }`.
|
|
250
246
|
*
|
|
251
|
-
* Omit or return `{}` for
|
|
247
|
+
* Omit or return `{}` for layout fields that don't group fields.
|
|
252
248
|
*/
|
|
253
249
|
getFieldLabelPrefixes?(params: {
|
|
254
|
-
|
|
250
|
+
field: T;
|
|
255
251
|
}): Record<string, string>;
|
|
256
252
|
/**
|
|
257
253
|
* Controls how this layout field looks on the model editor canvas.
|
|
258
254
|
* Each plugin fully owns its visual representation.
|
|
259
255
|
*/
|
|
260
256
|
render(params: {
|
|
261
|
-
|
|
262
|
-
onUpdate: (d:
|
|
257
|
+
field: T;
|
|
258
|
+
onUpdate: (d: T) => void;
|
|
263
259
|
onDelete: () => void;
|
|
264
260
|
}): React.ReactElement;
|
|
265
261
|
};
|
|
266
262
|
}
|
|
267
|
-
export interface
|
|
268
|
-
type: "cms-layout-
|
|
269
|
-
|
|
263
|
+
export interface CmsModelLayoutFieldRendererPlugin<T extends CmsModelLayoutField = CmsModelLayoutField> extends Plugin {
|
|
264
|
+
type: "cms-layout-field-renderer";
|
|
265
|
+
fieldType: string;
|
|
270
266
|
render(props: {
|
|
271
|
-
|
|
267
|
+
field: T;
|
|
272
268
|
Bind: BindComponent;
|
|
273
269
|
fields: CmsModelField[];
|
|
274
270
|
contentModel: CmsModel;
|
|
@@ -284,14 +280,6 @@ export interface CmsModelFieldRendererProps {
|
|
|
284
280
|
getBind: <T = any>(index?: number, key?: string) => BindComponent<T>;
|
|
285
281
|
contentModel: CmsModel;
|
|
286
282
|
}
|
|
287
|
-
/**
|
|
288
|
-
* @deprecated Use `CmsModelFieldRendererProps`.
|
|
289
|
-
*/
|
|
290
|
-
export type CmsEditorFieldRendererProps = CmsModelFieldRendererProps;
|
|
291
|
-
/**
|
|
292
|
-
* @deprecated Use `CmsModelFieldRendererPlugin`.
|
|
293
|
-
*/
|
|
294
|
-
export type CmsEditorFieldRendererPlugin = CmsModelFieldRendererPlugin;
|
|
295
283
|
export interface CmsModelFieldRendererPlugin extends Plugin {
|
|
296
284
|
/**
|
|
297
285
|
* a plugin type
|
package/types/index.js
CHANGED
|
@@ -1,16 +1,4 @@
|
|
|
1
|
-
export { isLayoutDescriptor } from "./model.js";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @deprecated Use `CmsModelFieldTypePlugin`.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @deprecated Use `CmsModelFieldRendererProps`.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* @deprecated Use `CmsModelFieldRendererPlugin`.
|
|
13
|
-
*/
|
|
1
|
+
export { isLayoutField, isLayoutDescriptor } from "./model.js";
|
|
14
2
|
|
|
15
3
|
/**
|
|
16
4
|
* @deprecated Use `CmsContentEntry`.
|
package/types/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["isLayoutDescriptor"],"sources":["index.ts"],"sourcesContent":["import type * as React from \"react\";\nimport type { ReactElement, ReactNode } from \"react\";\nimport type { Plugin } from \"@webiny/plugins/types.js\";\nimport type {\n BindComponent as BaseBindComponent,\n BindComponentProps as BaseBindComponentProps,\n BindComponentRenderProp as BaseBindComponentRenderProp,\n FormAPI\n} from \"@webiny/form\";\nimport type { IconName, IconPrefix } from \"@fortawesome/fontawesome-svg-core\";\nimport type {\n CmsModelFieldValidator,\n CmsModelFieldValidatorsFactory,\n CmsModelFieldValidatorsGroup\n} from \"./validation.js\";\nimport type {\n CmsBaseLayoutDescriptor,\n CmsEditorFieldsLayout,\n CmsLayoutDescriptor,\n CmsModel,\n CmsModelField\n} from \"./model.js\";\nimport type { CmsIdentity } from \"~/types/shared.js\";\nimport type { SourceType } from \"dnd-core\";\nimport type { IconPickerIconDto } from \"@webiny/admin-ui\";\nimport { GenericRecord } from \"@webiny/app/types.js\";\nimport { Identity } from \"@webiny/app-admin/domain/Identity.js\";\n\nexport type DragObjectWithType = {\n type: SourceType;\n};\n\nexport type * from \"./validation.js\";\nexport type * from \"./model.js\";\nexport { isLayoutDescriptor } from \"./model.js\";\nexport type * from \"./shared.js\";\n\ninterface QueryFieldParams {\n model: CmsModel;\n field: CmsModelField;\n graphQLTypePrefix: string;\n}\n\ninterface Position {\n row: number;\n index: number;\n}\n\ninterface Location {\n folderId: string;\n}\n\nexport interface DragSource extends DragObjectWithType {\n parent?: string;\n pos?: Partial<Position>;\n type: \"row\" | \"field\" | \"newField\" | \"newLayoutField\" | \"layoutField\";\n fieldType?: string;\n layoutFieldType?: string;\n field?: CmsModelField | null;\n fields?: CmsModelField[];\n descriptor?: CmsLayoutDescriptor;\n}\n\n/**\n * @deprecated Use `CmsModelFieldTypePlugin`.\n */\nexport type CmsEditorFieldTypePlugin = CmsModelFieldTypePlugin;\n\nexport interface CmsModelFieldTypePlugin extends Plugin {\n /**\n * a plugin type\n */\n type: \"cms-editor-field-type\";\n field: {\n /**\n * A unique identifier of the field type (text, number, json, myField, ...).\n *\n * ```ts\n * type: \"myField\"\n * ```\n */\n type: string;\n /**\n * A display name for the field.\n *\n * ```ts\n * label: \"Field name\"\n * ```\n */\n label: string;\n /**\n * A list of available validators for the model field.\n *\n * ```ts\n * validators: [\n * \"required\",\n * \"gte\",\n * \"lte\"\n * ]\n * ```\n */\n validators?: string[] | CmsModelFieldValidatorsGroup | CmsModelFieldValidatorsFactory;\n /**\n * A list of available validators when a model field accepts a list (array) of values.\n *\n * ```ts\n * listValidators: [\n * \"minLength\",\n * \"maxLength\"\n * ]\n * ```\n */\n listValidators?: string[] | CmsModelFieldValidatorsGroup | CmsModelFieldValidatorsFactory;\n /**\n * An explanation of the field displayed beneath the label.\n *\n * ```ts\n * description: \"A short description of the field\"\n * ```\n */\n description: string;\n /**\n * A ReactNode to display the icon for the field.\n *\n * ```tsx\n * icon: <MyIconComponent />\n * ```\n */\n icon: React.ReactNode;\n /**\n * Is it allowed to have multiple values in this field?\n *\n * ```ts\n * allowList: true\n * ```\n */\n allowList?: boolean;\n /**\n * Does this field type have a fixed list of values that can be selected?\n *\n * ```ts\n * allowPredefinedValues: false\n * ```\n */\n allowPredefinedValues?: boolean;\n /**\n * A ReactNode label when multiple values are enabled.\n */\n listLabel?: React.ReactNode;\n /**\n * Determines if this field type should be hidden from the admin UI.\n * If set to `true`, the field type will not be visible or selectable in the admin interface.\n */\n hideInAdmin?: boolean;\n /**\n * These are default values when the field is first created. This is a representation of the field that is stored in the database.\n *\n * ```ts\n * createField: () => ({\n * type: \"fieldType\",\n * validation: [],\n * renderer: {\n * name: \"fieldTypeRenderer\"\n * }\n * })\n * ```\n */\n createField: () => Pick<CmsModelField, \"type\" | \"validation\" | \"renderer\" | \"settings\">;\n /**\n * If `true` (default), this field will be configurable via a settings dialog.\n * If `false`, a user will not be able to open the settings dialog, not will the dialog be opened on field drop.\n */\n canEditSettings?: boolean;\n /**\n * Determine if a `draggable` can be dropped into this field.\n * NOTE: This is only applicable to nested field types.\n */\n canAccept?(field: CmsModelField, draggable: DragSource): boolean;\n /**\n * If `true` (default), will allow fields to be laid out into columns (next to each other).\n * If `false`, horizontal layout will not be allowed.\n * NOTE: This is only applicable to nested field types.\n */\n allowLayout?: boolean;\n /**\n * A ReactNode that you can add in the section below the help text when creating/editing field.\n *\n * ```tsx\n * renderSettings: (params) => {\n * return <FieldSettingsComponent />;\n * }\n * ```\n */\n renderSettings?: (params: {\n afterChangeLabel: (value: string) => void;\n uniqueFieldIdValidator: (fieldId: string) => void;\n contentModel: CmsModel;\n }) => React.ReactNode;\n /**\n * A ReactNode that renders in the Predefined values tab.\n *\n * ```tsx\n * renderPredefinedValues: (params) => {\n * const {form: {Bind}} = params;\n * return (\n * <Bind name=\"fieldProperty\">\n * <InputComponent />\n * </Bind>\n * );\n * }\n * ```\n */\n renderPredefinedValues?: (params: {\n getBind: (index?: number) => any;\n }) => React.ReactElement;\n /**\n * Object wrapper for GraphQL stuff\n */\n graphql?: {\n /**\n * Define field selection.\n *\n * ```ts\n * graphql: {\n * queryField: `\n * {\n * id\n * title\n * createdOn\n * }\n * `,\n * }\n * ```\n */\n queryField?: string | ((params: QueryFieldParams) => string | null);\n };\n render?(params: any): React.ReactElement;\n tags?: string[];\n /**\n * Render additional information in the Admin UI Model edit view\n */\n renderInfo?: (params: { field: CmsModelField; model: CmsModel }) => React.ReactElement;\n };\n}\n\nexport interface CmsLayoutFieldTypePlugin extends Plugin {\n type: \"cms-editor-layout-field-type\";\n field: {\n type: CmsLayoutDescriptor[\"type\"];\n label: string;\n description: string;\n icon: React.ReactElement;\n createDescriptor(): Omit<CmsLayoutDescriptor, \"id\">;\n canEditSettings?: boolean;\n renderSettings?(): React.ReactNode;\n /**\n * Collect all model fields embedded inside a layout descriptor's nested layout.\n * Used during drag-and-drop to move embedded fields along with the descriptor\n * across parent boundaries. Return `[]` or omit for descriptors with no nested fields.\n */\n collectFields?(params: {\n descriptor: CmsLayoutDescriptor;\n getField: (id: string) => CmsModelField | undefined;\n }): CmsModelField[];\n /**\n * Return a label prefix for each field ID nested inside this layout descriptor.\n * Used by `buildFieldOptions` to include layout hierarchy in field labels.\n *\n * For example, a tabs descriptor with label \"My Tabs\" containing a tab \"SEO\"\n * with field \"metaTitle\" would return: `{ \"metaTitle\": \"My Tabs › SEO\" }`.\n *\n * Omit or return `{}` for descriptors that don't group fields.\n */\n getFieldLabelPrefixes?(params: { descriptor: CmsLayoutDescriptor }): Record<string, string>;\n /**\n * Controls how this layout field looks on the model editor canvas.\n * Each plugin fully owns its visual representation.\n */\n render(params: {\n descriptor: CmsLayoutDescriptor;\n onUpdate: (d: CmsLayoutDescriptor) => void;\n onDelete: () => void;\n }): React.ReactElement;\n };\n}\n\nexport interface CmsLayoutDescriptorRendererPlugin extends Plugin {\n type: \"cms-layout-descriptor-renderer\";\n descriptorType: string;\n render(props: {\n descriptor: CmsBaseLayoutDescriptor;\n Bind: BindComponent;\n fields: CmsModelField[];\n contentModel: CmsModel;\n gridClassName?: string;\n }): React.ReactElement | null;\n}\n\nexport interface CmsModelFieldRendererSettingsProps {\n field: CmsModelField;\n}\n\nexport interface CmsModelFieldRendererProps {\n field: CmsModelField;\n Label: React.ComponentType<React.PropsWithChildren>;\n getBind: <T = any>(index?: number, key?: string) => BindComponent<T>;\n contentModel: CmsModel;\n}\n\n/**\n * @deprecated Use `CmsModelFieldRendererProps`.\n */\nexport type CmsEditorFieldRendererProps = CmsModelFieldRendererProps;\n\n/**\n * @deprecated Use `CmsModelFieldRendererPlugin`.\n */\nexport type CmsEditorFieldRendererPlugin = CmsModelFieldRendererPlugin;\n\nexport interface CmsModelFieldRendererPlugin extends Plugin {\n /**\n * a plugin type\n */\n type: \"cms-editor-field-renderer\";\n renderer: {\n /**\n * Name of the renderer to match the one from `createField()` method in `CmsModelFieldTypePlugin`.\n *\n * ```ts\n * renderName: \"myFieldTypeRenderer\"\n * ```\n */\n rendererName: string;\n /**\n * A display name for the field in the UI. It is a `ReactNode` type, so you can use a JSX element.\n *\n * ```tsx\n * name: <MyFieldNameComponent />\n * ```\n */\n name: React.ReactNode;\n /**\n * A description for the field in the UI. Works exactly like the `name` property.\n *\n * ```tsx\n * name: <MyFieldDescriptionComponent />\n * ```\n */\n description: React.ReactNode;\n /**\n * A method that determines if the field can be rendered by this plugin.\n *\n * ```ts\n * canUse({ field }) {\n * return (\n * field.type === \"myType\" && !field.list\n * );\n * }\n * ```\n */\n canUse(props: {\n field: CmsModelField;\n fieldPlugin: CmsModelFieldTypePlugin;\n model: CmsModel;\n }): boolean;\n /**\n * Renders a field in the UI.\n *\n * ```tsx\n * render({ field, getBind }) {\n * const Bind = getBind();\n *\n * return (\n * <Bind>\n * {bind => {\n * return (\n * <Input\n * value={bind.value}\n * onChange={bind.onChange}\n * />\n * )\n * }}\n * </Bind>\n * );\n * }\n * ```\n */\n render(props: CmsModelFieldRendererProps): React.ReactNode;\n renderSettings?: (props: CmsModelFieldRendererSettingsProps) => React.ReactNode;\n };\n}\n\nexport interface CmsEditorFieldPredefinedValuesEntry {\n label: string;\n value: string;\n selected?: boolean;\n}\n\nexport interface CmsEditorFieldPredefinedValues {\n enabled: boolean;\n values: CmsEditorFieldPredefinedValuesEntry[];\n}\n\nexport interface CmsDynamicZoneTemplate {\n id: string;\n name: string;\n gqlTypeName: string;\n description: string;\n icon: string;\n fields: CmsModelField[];\n layout: CmsEditorFieldsLayout;\n validation: CmsModelFieldValidator[];\n tags?: string[];\n}\n\nexport interface CmsDynamicZoneTemplateWithTypename extends CmsDynamicZoneTemplate {\n __typename: string;\n}\n\nexport type CmsContentEntryStatusType = \"draft\" | \"published\" | \"unpublished\";\n\n/**\n * @deprecated Use `CmsContentEntry`.\n */\nexport type CmsEditorContentEntry = CmsContentEntry;\n\nexport interface CmsContentEntryLive {\n version: number;\n}\n\nexport interface CmsContentEntrySystem {\n // to be extended\n}\n\nexport interface CmsContentEntry<TValues extends GenericRecord = GenericRecord> {\n id: string;\n entryId: string;\n modelId: string;\n createdOn: string;\n createdBy: CmsIdentity;\n savedOn: string;\n savedBy: CmsIdentity;\n modifiedOn: string | null;\n modifiedBy: CmsIdentity | null;\n deletedOn: string | null;\n deletedBy: CmsIdentity | null;\n firstPublishedOn: string | null;\n firstPublishedBy: CmsIdentity | null;\n lastPublishedOn: string | null;\n lastPublishedBy: CmsIdentity | null;\n revisionCreatedOn: string;\n revisionCreatedBy: CmsIdentity;\n revisionSavedOn: string;\n revisionSavedBy: CmsIdentity;\n revisionModifiedOn: string | null;\n revisionModifiedBy: CmsIdentity | null;\n revisionDeletedOn: string | null;\n revisionDeletedBy: CmsIdentity | null;\n revisionFirstPublishedOn: string | null;\n revisionFirstPublishedBy: CmsIdentity | null;\n revisionLastPublishedOn: string | null;\n revisionLastPublishedBy: CmsIdentity | null;\n wbyAco_location: Location;\n live: CmsContentEntryLive | null;\n system: CmsContentEntrySystem | null;\n meta: {\n title: string;\n description?: string;\n image?: string;\n locked: boolean;\n status: CmsContentEntryStatusType;\n version: number;\n };\n values?: TValues;\n}\n\nexport interface CmsContentEntryRevision {\n id: string;\n modelId: string;\n savedOn: string;\n deletedOn: string | null;\n firstPublishedOn: string | null;\n lastPublishedOn: string | null;\n createdBy: CmsIdentity;\n deletedBy: CmsIdentity | null;\n revisionCreatedOn: string;\n revisionSavedOn: string;\n revisionModifiedOn: string | null;\n revisionDeletedOn: string | null;\n revisionFirstPublishedOn: string | null;\n revisionLastPublishedOn: string | null;\n revisionCreatedBy: CmsIdentity;\n revisionSavedBy: CmsIdentity;\n revisionModifiedBy: CmsIdentity | null;\n revisionDeletedBy: CmsIdentity | null;\n revisionFirstPublishedBy: CmsIdentity | null;\n revisionLastPublishedBy: CmsIdentity | null;\n wbyAco_location: Location;\n meta: {\n title: string;\n locked: boolean;\n status: CmsContentEntryStatusType;\n version: number;\n };\n}\n\nexport type CmsEditorContentTab = React.ComponentType<{ activeTab: boolean }>;\n\n// ------------------------------------------------------------------------------------------------------------\nexport interface CmsEditorFieldOptionPlugin extends Plugin {\n type: \"cms-editor-field-option\";\n render(): ReactElement;\n}\n\nexport interface CmsContentDetailsPlugin extends Plugin {\n render: (params: any) => ReactNode;\n}\n\nexport interface FieldLayoutPosition {\n row: number;\n index: number | null;\n}\n\nexport interface CmsEditorFormSettingsPlugin<T = GenericRecord> extends Plugin {\n type: \"cms-editor-form-settings\";\n title: string;\n description: string;\n icon: React.ReactElement;\n showSave?: boolean;\n render(props: { Bind: BaseBindComponent; form: FormAPI<T>; formData: T }): React.ReactNode;\n renderHeaderActions?(props: {\n Bind: BaseBindComponent;\n form: FormAPI<T>;\n formData: T;\n }): React.ReactNode;\n}\n\nexport interface CmsIcon {\n /**\n * [ pack, icon ], ex: [\"fab\", \"cog\"]\n */\n id: [IconPrefix, IconName];\n /**\n * Icon name\n */\n name: string;\n /**\n * SVG element\n */\n svg: ReactElement;\n}\n\nexport interface CmsIconsPlugin extends Plugin {\n type: \"cms-icons\";\n getIcons(): IconPickerIconDto[];\n}\n\n/**\n * Transform field value when sending data to the API.\n */\nexport interface CmsFieldValueTransformer<TField extends CmsModelField = CmsModelField>\n extends Plugin {\n /**\n * A plugin type.\n */\n type: \"cms-field-value-transformer\";\n /**\n * A field type for the value transformer. Or a list of field types.\n */\n fieldType: string | string[];\n /**\n * A transformer function that takes a value and returns a new one.\n */\n transform: (value: any, field: TField) => any;\n}\n\n/**\n * Define a custom form layout renderer for a specific content model.\n */\nexport interface CmsContentFormRendererPlugin extends Plugin {\n /**\n * A plugin type.\n */\n type: \"cms-content-form-renderer\";\n /**\n * Content model ID that will use this renderer.\n */\n modelId: string;\n\n /**\n * A function that will render a custom form layout.\n */\n render(props: {\n /**\n * Content model that is being rendered.\n */\n contentModel: CmsModel;\n /**\n * Content entry data handled by the Form element.\n */\n data: Record<string, any>;\n /**\n * A component to bind data to the Form.\n */\n Bind: BindComponent;\n /**\n * Content model fields to render.\n */\n fields: Record<string, React.ReactElement>;\n }): React.ReactNode;\n}\n/**\n * #########################\n * Data types\n * #########################\n */\nexport interface CmsSecurityPermission extends Identity.Permission {\n accessLevel?: \"full\" | \"no\" | \"custom\";\n models?: string[];\n groups?: string[];\n endpoints?: string[];\n rwd?: string;\n own?: boolean;\n pw?: string;\n}\n\n/**\n * @category GraphQL\n * @category Error\n */\nexport interface CmsErrorResponse {\n message: string;\n code: string;\n data?: Record<string, any> | null;\n}\n/**\n * @category GraphQL\n * @category Meta\n */\nexport interface CmsMetaResponse {\n totalCount: number;\n cursor: string | null;\n hasMoreItems: boolean;\n}\n\n/***\n * ###### FORM ########\n */\nexport interface BindComponentRenderProp<T = any> extends BaseBindComponentRenderProp<T> {\n parentName: string;\n appendValue: (value: any, index?: number) => void;\n prependValue: (value: any) => void;\n appendValues: (values: any[]) => void;\n removeValue: (index: number) => void;\n moveValueUp: (index: number) => void;\n moveValueDown: (index: number) => void;\n}\n\ninterface BindComponentProps<T = any> extends Omit<BaseBindComponentProps, \"children\" | \"name\"> {\n name?: string;\n children?: ((props: BindComponentRenderProp<T>) => React.ReactElement) | React.ReactElement;\n}\n\nexport type BindComponent<T = any> = React.ComponentType<BindComponentProps<T>> & {\n parentName: string;\n ValidationContainer: React.ComponentType<{ children: React.ReactNode }>;\n};\n\n/**\n * After RequestReview and RequestChanges was removed, we need an option to add new status filters\n */\nexport interface CmsEntryFilterStatusPlugin extends Plugin {\n type: \"cms.entry.filter.status\";\n label: string;\n value: string;\n}\n"],"mappings":"AAkCA,SAASA,kBAAkB;;AA6B3B;AACA;AACA;;AAoPA;AACA;AACA;;AAGA;AACA;AACA;;AAyGA;AACA;AACA;;AAqFA;;AAiDA;AACA;AACA;;AAiBA;AACA;AACA;;AAiCA;AACA;AACA;AACA;AACA;;AAWA;AACA;AACA;AACA;;AAMA;AACA;AACA;AACA;;AAOA;AACA;AACA;;AAqBA;AACA;AACA","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["isLayoutField","isLayoutDescriptor"],"sources":["index.ts"],"sourcesContent":["import type * as React from \"react\";\nimport type { ReactElement, ReactNode } from \"react\";\nimport type { Plugin } from \"@webiny/plugins/types.js\";\nimport type {\n BindComponent as BaseBindComponent,\n BindComponentProps as BaseBindComponentProps,\n BindComponentRenderProp as BaseBindComponentRenderProp,\n FormAPI\n} from \"@webiny/form\";\nimport type { IconName, IconPrefix } from \"@fortawesome/fontawesome-svg-core\";\nimport type {\n CmsModelFieldValidator,\n CmsModelFieldValidatorsFactory,\n CmsModelFieldValidatorsGroup\n} from \"./validation.js\";\nimport type {\n CmsModelLayoutField,\n CmsEditorFieldsLayout,\n CmsLayoutField,\n CmsModel,\n CmsModelField\n} from \"./model.js\";\nimport type { CmsIdentity } from \"~/types/shared.js\";\nimport type { SourceType } from \"dnd-core\";\nimport type { IconPickerIconDto } from \"@webiny/admin-ui\";\nimport { GenericRecord } from \"@webiny/app/types.js\";\nimport { Identity } from \"@webiny/app-admin/domain/Identity.js\";\n\nexport type DragObjectWithType = {\n type: SourceType;\n};\n\nexport type * from \"./validation.js\";\nexport type * from \"./model.js\";\nexport { isLayoutField, isLayoutDescriptor } from \"./model.js\";\nexport type * from \"./shared.js\";\n\ninterface QueryFieldParams {\n model: CmsModel;\n field: CmsModelField;\n graphQLTypePrefix: string;\n}\n\ninterface Position {\n row: number;\n index: number;\n}\n\ninterface Location {\n folderId: string;\n}\n\nexport interface DragSource extends DragObjectWithType {\n parent?: string;\n pos?: Partial<Position>;\n type: \"row\" | \"field\" | \"newField\" | \"newLayoutField\" | \"layoutField\";\n fieldType?: string;\n layoutFieldType?: string;\n field?: CmsModelField | null;\n fields?: CmsModelField[];\n layoutField?: CmsLayoutField;\n}\n\nexport interface CmsModelFieldTypePlugin extends Plugin {\n /**\n * a plugin type\n */\n type: \"cms-editor-field-type\";\n field: {\n /**\n * A unique identifier of the field type (text, number, json, myField, ...).\n *\n * ```ts\n * type: \"myField\"\n * ```\n */\n type: string;\n /**\n * A display name for the field.\n *\n * ```ts\n * label: \"Field name\"\n * ```\n */\n label: string;\n /**\n * A list of available validators for the model field.\n *\n * ```ts\n * validators: [\n * \"required\",\n * \"gte\",\n * \"lte\"\n * ]\n * ```\n */\n validators?: string[] | CmsModelFieldValidatorsGroup | CmsModelFieldValidatorsFactory;\n /**\n * A list of available validators when a model field accepts a list (array) of values.\n *\n * ```ts\n * listValidators: [\n * \"minLength\",\n * \"maxLength\"\n * ]\n * ```\n */\n listValidators?: string[] | CmsModelFieldValidatorsGroup | CmsModelFieldValidatorsFactory;\n /**\n * An explanation of the field displayed beneath the label.\n *\n * ```ts\n * description: \"A short description of the field\"\n * ```\n */\n description: string;\n /**\n * A ReactNode to display the icon for the field.\n *\n * ```tsx\n * icon: <MyIconComponent />\n * ```\n */\n icon: React.ReactNode;\n /**\n * Is it allowed to have multiple values in this field?\n *\n * ```ts\n * allowList: true\n * ```\n */\n allowList?: boolean;\n /**\n * Does this field type have a fixed list of values that can be selected?\n *\n * ```ts\n * allowPredefinedValues: false\n * ```\n */\n allowPredefinedValues?: boolean;\n /**\n * A ReactNode label when multiple values are enabled.\n */\n listLabel?: React.ReactNode;\n /**\n * Determines if this field type should be hidden from the admin UI.\n * If set to `true`, the field type will not be visible or selectable in the admin interface.\n */\n hideInAdmin?: boolean;\n /**\n * These are default values when the field is first created. This is a representation of the field that is stored in the database.\n *\n * ```ts\n * createField: () => ({\n * type: \"fieldType\",\n * validation: [],\n * renderer: {\n * name: \"fieldTypeRenderer\"\n * }\n * })\n * ```\n */\n createField: () => Pick<CmsModelField, \"type\" | \"validation\" | \"renderer\" | \"settings\">;\n /**\n * If `true` (default), this field will be configurable via a settings dialog.\n * If `false`, a user will not be able to open the settings dialog, not will the dialog be opened on field drop.\n */\n canEditSettings?: boolean;\n /**\n * Determine if a `draggable` can be dropped into this field.\n * NOTE: This is only applicable to nested field types.\n */\n canAccept?(field: CmsModelField, draggable: DragSource): boolean;\n /**\n * If `true` (default), will allow fields to be laid out into columns (next to each other).\n * If `false`, horizontal layout will not be allowed.\n * NOTE: This is only applicable to nested field types.\n */\n allowLayout?: boolean;\n /**\n * A ReactNode that you can add in the section below the help text when creating/editing field.\n *\n * ```tsx\n * renderSettings: (params) => {\n * return <FieldSettingsComponent />;\n * }\n * ```\n */\n renderSettings?: (params: {\n afterChangeLabel: (value: string) => void;\n uniqueFieldIdValidator: (fieldId: string) => void;\n contentModel: CmsModel;\n }) => React.ReactNode;\n /**\n * A ReactNode that renders in the Predefined values tab.\n *\n * ```tsx\n * renderPredefinedValues: (params) => {\n * const {form: {Bind}} = params;\n * return (\n * <Bind name=\"fieldProperty\">\n * <InputComponent />\n * </Bind>\n * );\n * }\n * ```\n */\n renderPredefinedValues?: (params: {\n getBind: (index?: number) => any;\n }) => React.ReactElement;\n /**\n * Object wrapper for GraphQL stuff\n */\n graphql?: {\n /**\n * Define field selection.\n *\n * ```ts\n * graphql: {\n * queryField: `\n * {\n * id\n * title\n * createdOn\n * }\n * `,\n * }\n * ```\n */\n queryField?: string | ((params: QueryFieldParams) => string | null);\n };\n render?(params: any): React.ReactElement;\n tags?: string[];\n /**\n * Render additional information in the Admin UI Model edit view\n */\n renderInfo?: (params: { field: CmsModelField; model: CmsModel }) => React.ReactElement;\n };\n}\n\nexport interface CmsModelLayoutFieldTypePlugin<T extends CmsModelLayoutField = CmsModelLayoutField>\n extends Plugin {\n type: \"cms-editor-layout-field-type\";\n field: {\n type: T[\"type\"];\n label: string;\n description: string;\n icon: React.ReactElement;\n createField(): Omit<T, \"id\">;\n canEditSettings?: boolean;\n renderSettings?(): React.ReactNode;\n /**\n * Collect all model fields embedded inside a layout field's nested layout.\n * Used during drag-and-drop to move embedded fields along with the layout field\n * across parent boundaries. Return `[]` or omit for layout fields with no nested fields.\n */\n collectFields?(params: {\n field: T;\n getField: (id: string) => CmsModelField | undefined;\n }): CmsModelField[];\n /**\n * Return a label prefix for each field ID nested inside this layout field.\n * Used by `buildFieldOptions` to include layout hierarchy in field labels.\n *\n * For example, a tabs layout field with label \"My Tabs\" containing a tab \"SEO\"\n * with field \"metaTitle\" would return: `{ \"metaTitle\": \"My Tabs › SEO\" }`.\n *\n * Omit or return `{}` for layout fields that don't group fields.\n */\n getFieldLabelPrefixes?(params: { field: T }): Record<string, string>;\n /**\n * Controls how this layout field looks on the model editor canvas.\n * Each plugin fully owns its visual representation.\n */\n render(params: {\n field: T;\n onUpdate: (d: T) => void;\n onDelete: () => void;\n }): React.ReactElement;\n };\n}\n\nexport interface CmsModelLayoutFieldRendererPlugin<\n T extends CmsModelLayoutField = CmsModelLayoutField\n> extends Plugin {\n type: \"cms-layout-field-renderer\";\n fieldType: string;\n render(props: {\n field: T;\n Bind: BindComponent;\n fields: CmsModelField[];\n contentModel: CmsModel;\n gridClassName?: string;\n }): React.ReactElement | null;\n}\n\nexport interface CmsModelFieldRendererSettingsProps {\n field: CmsModelField;\n}\n\nexport interface CmsModelFieldRendererProps {\n field: CmsModelField;\n Label: React.ComponentType<React.PropsWithChildren>;\n getBind: <T = any>(index?: number, key?: string) => BindComponent<T>;\n contentModel: CmsModel;\n}\n\nexport interface CmsModelFieldRendererPlugin extends Plugin {\n /**\n * a plugin type\n */\n type: \"cms-editor-field-renderer\";\n renderer: {\n /**\n * Name of the renderer to match the one from `createField()` method in `CmsModelFieldTypePlugin`.\n *\n * ```ts\n * renderName: \"myFieldTypeRenderer\"\n * ```\n */\n rendererName: string;\n /**\n * A display name for the field in the UI. It is a `ReactNode` type, so you can use a JSX element.\n *\n * ```tsx\n * name: <MyFieldNameComponent />\n * ```\n */\n name: React.ReactNode;\n /**\n * A description for the field in the UI. Works exactly like the `name` property.\n *\n * ```tsx\n * name: <MyFieldDescriptionComponent />\n * ```\n */\n description: React.ReactNode;\n /**\n * A method that determines if the field can be rendered by this plugin.\n *\n * ```ts\n * canUse({ field }) {\n * return (\n * field.type === \"myType\" && !field.list\n * );\n * }\n * ```\n */\n canUse(props: {\n field: CmsModelField;\n fieldPlugin: CmsModelFieldTypePlugin;\n model: CmsModel;\n }): boolean;\n /**\n * Renders a field in the UI.\n *\n * ```tsx\n * render({ field, getBind }) {\n * const Bind = getBind();\n *\n * return (\n * <Bind>\n * {bind => {\n * return (\n * <Input\n * value={bind.value}\n * onChange={bind.onChange}\n * />\n * )\n * }}\n * </Bind>\n * );\n * }\n * ```\n */\n render(props: CmsModelFieldRendererProps): React.ReactNode;\n renderSettings?: (props: CmsModelFieldRendererSettingsProps) => React.ReactNode;\n };\n}\n\nexport interface CmsEditorFieldPredefinedValuesEntry {\n label: string;\n value: string;\n selected?: boolean;\n}\n\nexport interface CmsEditorFieldPredefinedValues {\n enabled: boolean;\n values: CmsEditorFieldPredefinedValuesEntry[];\n}\n\nexport interface CmsDynamicZoneTemplate {\n id: string;\n name: string;\n gqlTypeName: string;\n description: string;\n icon: string;\n fields: CmsModelField[];\n layout: CmsEditorFieldsLayout;\n validation: CmsModelFieldValidator[];\n tags?: string[];\n}\n\nexport interface CmsDynamicZoneTemplateWithTypename extends CmsDynamicZoneTemplate {\n __typename: string;\n}\n\nexport type CmsContentEntryStatusType = \"draft\" | \"published\" | \"unpublished\";\n\n/**\n * @deprecated Use `CmsContentEntry`.\n */\nexport type CmsEditorContentEntry = CmsContentEntry;\n\nexport interface CmsContentEntryLive {\n version: number;\n}\n\nexport interface CmsContentEntrySystem {\n // to be extended\n}\n\nexport interface CmsContentEntry<TValues extends GenericRecord = GenericRecord> {\n id: string;\n entryId: string;\n modelId: string;\n createdOn: string;\n createdBy: CmsIdentity;\n savedOn: string;\n savedBy: CmsIdentity;\n modifiedOn: string | null;\n modifiedBy: CmsIdentity | null;\n deletedOn: string | null;\n deletedBy: CmsIdentity | null;\n firstPublishedOn: string | null;\n firstPublishedBy: CmsIdentity | null;\n lastPublishedOn: string | null;\n lastPublishedBy: CmsIdentity | null;\n revisionCreatedOn: string;\n revisionCreatedBy: CmsIdentity;\n revisionSavedOn: string;\n revisionSavedBy: CmsIdentity;\n revisionModifiedOn: string | null;\n revisionModifiedBy: CmsIdentity | null;\n revisionDeletedOn: string | null;\n revisionDeletedBy: CmsIdentity | null;\n revisionFirstPublishedOn: string | null;\n revisionFirstPublishedBy: CmsIdentity | null;\n revisionLastPublishedOn: string | null;\n revisionLastPublishedBy: CmsIdentity | null;\n wbyAco_location: Location;\n live: CmsContentEntryLive | null;\n system: CmsContentEntrySystem | null;\n meta: {\n title: string;\n description?: string;\n image?: string;\n locked: boolean;\n status: CmsContentEntryStatusType;\n version: number;\n };\n values?: TValues;\n}\n\nexport interface CmsContentEntryRevision {\n id: string;\n modelId: string;\n savedOn: string;\n deletedOn: string | null;\n firstPublishedOn: string | null;\n lastPublishedOn: string | null;\n createdBy: CmsIdentity;\n deletedBy: CmsIdentity | null;\n revisionCreatedOn: string;\n revisionSavedOn: string;\n revisionModifiedOn: string | null;\n revisionDeletedOn: string | null;\n revisionFirstPublishedOn: string | null;\n revisionLastPublishedOn: string | null;\n revisionCreatedBy: CmsIdentity;\n revisionSavedBy: CmsIdentity;\n revisionModifiedBy: CmsIdentity | null;\n revisionDeletedBy: CmsIdentity | null;\n revisionFirstPublishedBy: CmsIdentity | null;\n revisionLastPublishedBy: CmsIdentity | null;\n wbyAco_location: Location;\n meta: {\n title: string;\n locked: boolean;\n status: CmsContentEntryStatusType;\n version: number;\n };\n}\n\nexport type CmsEditorContentTab = React.ComponentType<{ activeTab: boolean }>;\n\n// ------------------------------------------------------------------------------------------------------------\nexport interface CmsEditorFieldOptionPlugin extends Plugin {\n type: \"cms-editor-field-option\";\n render(): ReactElement;\n}\n\nexport interface CmsContentDetailsPlugin extends Plugin {\n render: (params: any) => ReactNode;\n}\n\nexport interface FieldLayoutPosition {\n row: number;\n index: number | null;\n}\n\nexport interface CmsEditorFormSettingsPlugin<T = GenericRecord> extends Plugin {\n type: \"cms-editor-form-settings\";\n title: string;\n description: string;\n icon: React.ReactElement;\n showSave?: boolean;\n render(props: { Bind: BaseBindComponent; form: FormAPI<T>; formData: T }): React.ReactNode;\n renderHeaderActions?(props: {\n Bind: BaseBindComponent;\n form: FormAPI<T>;\n formData: T;\n }): React.ReactNode;\n}\n\nexport interface CmsIcon {\n /**\n * [ pack, icon ], ex: [\"fab\", \"cog\"]\n */\n id: [IconPrefix, IconName];\n /**\n * Icon name\n */\n name: string;\n /**\n * SVG element\n */\n svg: ReactElement;\n}\n\nexport interface CmsIconsPlugin extends Plugin {\n type: \"cms-icons\";\n getIcons(): IconPickerIconDto[];\n}\n\n/**\n * Transform field value when sending data to the API.\n */\nexport interface CmsFieldValueTransformer<TField extends CmsModelField = CmsModelField>\n extends Plugin {\n /**\n * A plugin type.\n */\n type: \"cms-field-value-transformer\";\n /**\n * A field type for the value transformer. Or a list of field types.\n */\n fieldType: string | string[];\n /**\n * A transformer function that takes a value and returns a new one.\n */\n transform: (value: any, field: TField) => any;\n}\n\n/**\n * Define a custom form layout renderer for a specific content model.\n */\nexport interface CmsContentFormRendererPlugin extends Plugin {\n /**\n * A plugin type.\n */\n type: \"cms-content-form-renderer\";\n /**\n * Content model ID that will use this renderer.\n */\n modelId: string;\n\n /**\n * A function that will render a custom form layout.\n */\n render(props: {\n /**\n * Content model that is being rendered.\n */\n contentModel: CmsModel;\n /**\n * Content entry data handled by the Form element.\n */\n data: Record<string, any>;\n /**\n * A component to bind data to the Form.\n */\n Bind: BindComponent;\n /**\n * Content model fields to render.\n */\n fields: Record<string, React.ReactElement>;\n }): React.ReactNode;\n}\n/**\n * #########################\n * Data types\n * #########################\n */\nexport interface CmsSecurityPermission extends Identity.Permission {\n accessLevel?: \"full\" | \"no\" | \"custom\";\n models?: string[];\n groups?: string[];\n endpoints?: string[];\n rwd?: string;\n own?: boolean;\n pw?: string;\n}\n\n/**\n * @category GraphQL\n * @category Error\n */\nexport interface CmsErrorResponse {\n message: string;\n code: string;\n data?: Record<string, any> | null;\n}\n/**\n * @category GraphQL\n * @category Meta\n */\nexport interface CmsMetaResponse {\n totalCount: number;\n cursor: string | null;\n hasMoreItems: boolean;\n}\n\n/***\n * ###### FORM ########\n */\nexport interface BindComponentRenderProp<T = any> extends BaseBindComponentRenderProp<T> {\n parentName: string;\n appendValue: (value: any, index?: number) => void;\n prependValue: (value: any) => void;\n appendValues: (values: any[]) => void;\n removeValue: (index: number) => void;\n moveValueUp: (index: number) => void;\n moveValueDown: (index: number) => void;\n}\n\ninterface BindComponentProps<T = any> extends Omit<BaseBindComponentProps, \"children\" | \"name\"> {\n name?: string;\n children?: ((props: BindComponentRenderProp<T>) => React.ReactElement) | React.ReactElement;\n}\n\nexport type BindComponent<T = any> = React.ComponentType<BindComponentProps<T>> & {\n parentName: string;\n ValidationContainer: React.ComponentType<{ children: React.ReactNode }>;\n};\n\n/**\n * After RequestReview and RequestChanges was removed, we need an option to add new status filters\n */\nexport interface CmsEntryFilterStatusPlugin extends Plugin {\n type: \"cms.entry.filter.status\";\n label: string;\n value: string;\n}\n"],"mappings":"AAkCA,SAASA,aAAa,EAAEC,kBAAkB;;AAuX1C;AACA;AACA;;AAqFA;;AAiDA;AACA;AACA;;AAiBA;AACA;AACA;;AAiCA;AACA;AACA;AACA;AACA;;AAWA;AACA;AACA;AACA;;AAMA;AACA;AACA;AACA;;AAOA;AACA;AACA;;AAqBA;AACA;AACA","ignoreList":[]}
|
package/types/model.d.ts
CHANGED
|
@@ -3,10 +3,6 @@ import type { CmsModelFieldValidator } from "../types/validation.js";
|
|
|
3
3
|
import type { CmsDynamicZoneTemplate, CmsEditorFieldPredefinedValues, CmsModelFieldRendererPlugin } from "../types/index.js";
|
|
4
4
|
import type { CmsIdentity } from "../types/shared.js";
|
|
5
5
|
import type React from "react";
|
|
6
|
-
/**
|
|
7
|
-
* @deprecated Use `CmsModelField` instead.
|
|
8
|
-
*/
|
|
9
|
-
export type CmsEditorField<T = unknown> = CmsModelField<T>;
|
|
10
6
|
export interface CmsModelFieldSettings<T = unknown> {
|
|
11
7
|
defaultValue?: string | boolean | number | null | undefined;
|
|
12
8
|
defaultSetValue?: string;
|
|
@@ -54,17 +50,17 @@ export type CmsModelField<T = unknown> = T & {
|
|
|
54
50
|
rules?: FieldRule[];
|
|
55
51
|
};
|
|
56
52
|
export type CmsEditorFieldId = string;
|
|
57
|
-
export interface
|
|
53
|
+
export interface CmsModelLayoutField {
|
|
58
54
|
id: string;
|
|
59
55
|
type: string;
|
|
60
56
|
rules?: FieldRule[];
|
|
61
57
|
}
|
|
62
|
-
export interface
|
|
58
|
+
export interface CmsSeparatorLayoutField extends CmsModelLayoutField {
|
|
63
59
|
type: "separator";
|
|
64
60
|
label: string;
|
|
65
61
|
description?: string;
|
|
66
62
|
}
|
|
67
|
-
export interface
|
|
63
|
+
export interface CmsAlertLayoutField extends CmsModelLayoutField {
|
|
68
64
|
type: "alert";
|
|
69
65
|
label: string;
|
|
70
66
|
alertType: "info" | "success" | "warning" | "danger";
|
|
@@ -76,27 +72,31 @@ export interface CmsTabLayoutTab {
|
|
|
76
72
|
layout: CmsEditorFieldsLayout;
|
|
77
73
|
rules?: FieldRule[];
|
|
78
74
|
}
|
|
79
|
-
export interface
|
|
75
|
+
export interface CmsTabLayoutField extends CmsModelLayoutField {
|
|
80
76
|
type: "tabs";
|
|
81
77
|
label: string;
|
|
82
78
|
description?: string | null;
|
|
83
79
|
help?: string | null;
|
|
84
80
|
tabs: CmsTabLayoutTab[];
|
|
85
81
|
}
|
|
86
|
-
export type
|
|
87
|
-
export type CmsEditorLayoutCell = CmsEditorFieldId |
|
|
82
|
+
export type CmsLayoutField = CmsSeparatorLayoutField | CmsAlertLayoutField | CmsTabLayoutField | CmsModelLayoutField;
|
|
83
|
+
export type CmsEditorLayoutCell = CmsEditorFieldId | CmsLayoutField;
|
|
88
84
|
export type CmsEditorFieldsLayout = CmsEditorLayoutCell[][];
|
|
89
85
|
/**
|
|
90
|
-
* Distinguish layout
|
|
86
|
+
* Distinguish layout fields from field IDs (strings) and CmsModelField objects.
|
|
91
87
|
*
|
|
92
88
|
* In raw layout data (`CmsEditorFieldsLayout`), cells are either strings (field IDs)
|
|
93
|
-
* or layout
|
|
89
|
+
* or layout field objects — the `typeof` check handles that.
|
|
94
90
|
*
|
|
95
91
|
* In resolved layout data (after `getFieldsInLayout`), cells are either `CmsModelField`
|
|
96
|
-
* or layout
|
|
92
|
+
* or layout field objects — both have `{ id, type }`, but only `CmsModelField`
|
|
97
93
|
* has `fieldId`, so we use its absence as the discriminator.
|
|
98
94
|
*/
|
|
99
|
-
export declare function
|
|
95
|
+
export declare function isLayoutField(cell: unknown): cell is CmsLayoutField;
|
|
96
|
+
/**
|
|
97
|
+
* @deprecated Use `isLayoutField` instead.
|
|
98
|
+
*/
|
|
99
|
+
export declare const isLayoutDescriptor: typeof isLayoutField;
|
|
100
100
|
/**
|
|
101
101
|
* @category GraphQL
|
|
102
102
|
* @category Model
|
package/types/model.js
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Distinguish layout descriptors from field IDs (strings) and CmsModelField objects.
|
|
2
|
+
* Distinguish layout fields from field IDs (strings) and CmsModelField objects.
|
|
7
3
|
*
|
|
8
4
|
* In raw layout data (`CmsEditorFieldsLayout`), cells are either strings (field IDs)
|
|
9
|
-
* or layout
|
|
5
|
+
* or layout field objects — the `typeof` check handles that.
|
|
10
6
|
*
|
|
11
7
|
* In resolved layout data (after `getFieldsInLayout`), cells are either `CmsModelField`
|
|
12
|
-
* or layout
|
|
8
|
+
* or layout field objects — both have `{ id, type }`, but only `CmsModelField`
|
|
13
9
|
* has `fieldId`, so we use its absence as the discriminator.
|
|
14
10
|
*/
|
|
15
|
-
export function
|
|
11
|
+
export function isLayoutField(cell) {
|
|
16
12
|
return typeof cell === "object" && cell !== null && "type" in cell && typeof cell.type === "string" && !("fieldId" in cell);
|
|
17
13
|
}
|
|
18
14
|
|
|
15
|
+
/**
|
|
16
|
+
* @deprecated Use `isLayoutField` instead.
|
|
17
|
+
*/
|
|
18
|
+
export const isLayoutDescriptor = isLayoutField;
|
|
19
|
+
|
|
19
20
|
/**
|
|
20
21
|
* @category GraphQL
|
|
21
22
|
* @category Model
|
package/types/model.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["
|
|
1
|
+
{"version":3,"names":["isLayoutField","cell","type","isLayoutDescriptor"],"sources":["model.ts"],"sourcesContent":["import type { Validator } from \"@webiny/validation/types.js\";\nimport type { CmsModelFieldValidator } from \"~/types/validation.js\";\nimport type {\n CmsDynamicZoneTemplate,\n CmsEditorFieldPredefinedValues,\n CmsModelFieldRendererPlugin\n} from \"~/types/index.js\";\nimport type { CmsIdentity } from \"~/types/shared.js\";\nimport type React from \"react\";\n\nexport interface CmsModelFieldSettings<T = unknown> {\n defaultValue?: string | boolean | number | null | undefined;\n defaultSetValue?: string;\n type?: string;\n fields?: CmsModelField<T>[];\n layout?: CmsEditorFieldsLayout;\n models?: Pick<CmsModel, \"modelId\">[];\n templates?: CmsDynamicZoneTemplate[];\n imagesOnly?: boolean;\n [key: string]: any;\n}\n\nexport type FieldRuleAction = \"hide\" | \"disable\" | string;\n\nexport interface FieldRule {\n type: \"accessControl\" | \"condition\";\n target: string;\n operator: string;\n value: string | number | boolean | null;\n action: FieldRuleAction;\n}\n\nexport type CmsModelField<T = unknown> = T & {\n id: string;\n type: string;\n fieldId: CmsEditorFieldId;\n storageId?: string;\n label: string;\n help?: string | React.ReactNode;\n description?: string | React.ReactNode;\n note?: string | React.ReactNode;\n placeholder?: string;\n validation?: (CmsModelFieldValidator | Validator)[];\n listValidation?: CmsModelFieldValidator[];\n list?: boolean;\n predefinedValues?: CmsEditorFieldPredefinedValues;\n settings?: CmsModelFieldSettings<T>;\n renderer:\n | {\n name: string;\n settings?: Record<string, any>;\n }\n /**\n * Use this only for programmatic assignment of renderers.\n * Since functions cannot be serialized, this can only work via code.\n */\n | CmsModelFieldRendererPlugin[\"renderer\"][\"render\"];\n tags?: string[];\n rules?: FieldRule[];\n};\n\nexport type CmsEditorFieldId = string;\n\nexport interface CmsModelLayoutField {\n id: string;\n type: string;\n rules?: FieldRule[];\n}\n\nexport interface CmsSeparatorLayoutField extends CmsModelLayoutField {\n type: \"separator\";\n label: string;\n description?: string;\n}\n\nexport interface CmsAlertLayoutField extends CmsModelLayoutField {\n type: \"alert\";\n label: string;\n alertType: \"info\" | \"success\" | \"warning\" | \"danger\";\n}\n\nexport interface CmsTabLayoutTab {\n id: string;\n label: string;\n icon?: string;\n layout: CmsEditorFieldsLayout;\n rules?: FieldRule[];\n}\n\nexport interface CmsTabLayoutField extends CmsModelLayoutField {\n type: \"tabs\";\n label: string;\n description?: string | null;\n help?: string | null;\n tabs: CmsTabLayoutTab[];\n}\n\nexport type CmsLayoutField =\n | CmsSeparatorLayoutField\n | CmsAlertLayoutField\n | CmsTabLayoutField\n | CmsModelLayoutField;\n\nexport type CmsEditorLayoutCell = CmsEditorFieldId | CmsLayoutField;\nexport type CmsEditorFieldsLayout = CmsEditorLayoutCell[][];\n\n/**\n * Distinguish layout fields from field IDs (strings) and CmsModelField objects.\n *\n * In raw layout data (`CmsEditorFieldsLayout`), cells are either strings (field IDs)\n * or layout field objects — the `typeof` check handles that.\n *\n * In resolved layout data (after `getFieldsInLayout`), cells are either `CmsModelField`\n * or layout field objects — both have `{ id, type }`, but only `CmsModelField`\n * has `fieldId`, so we use its absence as the discriminator.\n */\nexport function isLayoutField(cell: unknown): cell is CmsLayoutField {\n return (\n typeof cell === \"object\" &&\n cell !== null &&\n \"type\" in cell &&\n typeof (cell as any).type === \"string\" &&\n !(\"fieldId\" in cell)\n );\n}\n\n/**\n * @deprecated Use `isLayoutField` instead.\n */\nexport const isLayoutDescriptor = isLayoutField;\n\n/**\n * @category GraphQL\n * @category Model\n */\nexport type CmsEditorContentModel = CmsModel;\n\n/**\n * @category GraphQL\n * @category Group\n */\nexport interface CmsGroup {\n id: string;\n name: string;\n slug: string;\n icon: string;\n description?: string;\n contentModels: CmsModel[];\n createdBy: CmsIdentity;\n /**\n * Tells if this group is a plugin one (cannot be changed/deleted)\n */\n plugin?: boolean;\n}\n\nexport interface CmsModel {\n id: string;\n group: string;\n description?: string;\n version: number;\n layout?: CmsEditorFieldsLayout;\n fields: CmsModelField[];\n icon: string;\n name: string;\n modelId: string;\n singularApiName: string;\n pluralApiName: string;\n titleFieldId: string | null;\n descriptionFieldId: string | null;\n imageFieldId: string | null;\n status: string;\n savedOn: string;\n meta: any;\n createdBy: CmsIdentity;\n tags: string[];\n /**\n * If model is a plugin one (it cannot be changed/deleted)\n */\n plugin?: boolean;\n /**\n * Is model currently being deleted?\n */\n isBeingDeleted?: boolean;\n settings: {\n [key: string]: any;\n };\n}\n"],"mappings":"AA0GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASA,aAAaA,CAACC,IAAa,EAA0B;EACjE,OACI,OAAOA,IAAI,KAAK,QAAQ,IACxBA,IAAI,KAAK,IAAI,IACb,MAAM,IAAIA,IAAI,IACd,OAAQA,IAAI,CAASC,IAAI,KAAK,QAAQ,IACtC,EAAE,SAAS,IAAID,IAAI,CAAC;AAE5B;;AAEA;AACA;AACA;AACA,OAAO,MAAME,kBAAkB,GAAGH,aAAa;;AAE/C;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA","ignoreList":[]}
|