@strapi/content-manager 5.60.0 → 5.61.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/constants/customOrder.js +14 -0
- package/dist/admin/constants/customOrder.js.map +1 -0
- package/dist/admin/constants/customOrder.mjs +10 -0
- package/dist/admin/constants/customOrder.mjs.map +1 -0
- package/dist/admin/hooks/useDocument.js +22 -11
- package/dist/admin/hooks/useDocument.js.map +1 -1
- package/dist/admin/hooks/useDocument.mjs +22 -11
- package/dist/admin/hooks/useDocument.mjs.map +1 -1
- package/dist/admin/hooks/useDocumentLayout.js.map +1 -1
- package/dist/admin/hooks/useDocumentLayout.mjs.map +1 -1
- package/dist/admin/hooks/useHasBeenNearViewport.js +70 -0
- package/dist/admin/hooks/useHasBeenNearViewport.js.map +1 -0
- package/dist/admin/hooks/useHasBeenNearViewport.mjs +46 -0
- package/dist/admin/hooks/useHasBeenNearViewport.mjs.map +1 -0
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/Image.js +102 -32
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/Image.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/Image.mjs +104 -35
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/Image.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/List.js +20 -17
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/List.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/List.mjs +20 -17
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/List.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksContent.js +15 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksContent.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksContent.mjs +17 -3
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksContent.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/plugins/withStrapiSchema.js +21 -0
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/plugins/withStrapiSchema.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/plugins/withStrapiSchema.mjs +22 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/plugins/withStrapiSchema.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.js +4 -7
- package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.mjs +4 -7
- package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.js +46 -10
- package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.mjs +47 -11
- package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormLayout.js +201 -51
- package/dist/admin/pages/EditView/components/FormLayout.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormLayout.mjs +202 -53
- package/dist/admin/pages/EditView/components/FormLayout.mjs.map +1 -1
- package/dist/admin/pages/ListConfiguration/components/Settings.js +31 -2
- package/dist/admin/pages/ListConfiguration/components/Settings.js.map +1 -1
- package/dist/admin/pages/ListConfiguration/components/Settings.mjs +31 -2
- package/dist/admin/pages/ListConfiguration/components/Settings.mjs.map +1 -1
- package/dist/admin/pages/ListView/ListViewPage.js +196 -132
- package/dist/admin/pages/ListView/ListViewPage.js.map +1 -1
- package/dist/admin/pages/ListView/ListViewPage.mjs +196 -132
- package/dist/admin/pages/ListView/ListViewPage.mjs.map +1 -1
- package/dist/admin/pages/ListView/components/CustomOrder.js +571 -0
- package/dist/admin/pages/ListView/components/CustomOrder.js.map +1 -0
- package/dist/admin/pages/ListView/components/CustomOrder.mjs +546 -0
- package/dist/admin/pages/ListView/components/CustomOrder.mjs.map +1 -0
- package/dist/admin/pages/ListView/components/TableActions.js +4 -1
- package/dist/admin/pages/ListView/components/TableActions.js.map +1 -1
- package/dist/admin/pages/ListView/components/TableActions.mjs +4 -1
- package/dist/admin/pages/ListView/components/TableActions.mjs.map +1 -1
- package/dist/admin/services/documents.js +22 -1
- package/dist/admin/services/documents.js.map +1 -1
- package/dist/admin/services/documents.mjs +21 -2
- package/dist/admin/services/documents.mjs.map +1 -1
- package/dist/admin/src/constants/customOrder.d.ts +8 -0
- package/dist/admin/src/exports.d.ts +1 -1
- package/dist/admin/src/hooks/useDocument.d.ts +4 -0
- package/dist/admin/src/hooks/useDocumentLayout.d.ts +6 -2
- package/dist/admin/src/hooks/useHasBeenNearViewport.d.ts +13 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/Image.d.ts +13 -1
- package/dist/admin/src/pages/EditView/components/FormLayout.d.ts +11 -1
- package/dist/admin/src/pages/ListView/components/CustomOrder.d.ts +72 -0
- package/dist/admin/src/services/documents.d.ts +10 -2
- package/dist/admin/translations/en.json.js +9 -0
- package/dist/admin/translations/en.json.js.map +1 -1
- package/dist/admin/translations/en.json.mjs +9 -0
- package/dist/admin/translations/en.json.mjs.map +1 -1
- package/dist/server/audit-logs.js +36 -0
- package/dist/server/audit-logs.js.map +1 -0
- package/dist/server/audit-logs.mjs +33 -0
- package/dist/server/audit-logs.mjs.map +1 -0
- package/dist/server/bootstrap.js +8 -0
- package/dist/server/bootstrap.js.map +1 -1
- package/dist/server/bootstrap.mjs +8 -0
- package/dist/server/bootstrap.mjs.map +1 -1
- package/dist/server/controllers/collection-types.js +8 -0
- package/dist/server/controllers/collection-types.js.map +1 -1
- package/dist/server/controllers/collection-types.mjs +8 -0
- package/dist/server/controllers/collection-types.mjs.map +1 -1
- package/dist/server/controllers/content-types.js +15 -0
- package/dist/server/controllers/content-types.js.map +1 -1
- package/dist/server/controllers/content-types.mjs +16 -1
- package/dist/server/controllers/content-types.mjs.map +1 -1
- package/dist/server/controllers/index.js +3 -1
- package/dist/server/controllers/index.js.map +1 -1
- package/dist/server/controllers/index.mjs +2 -0
- package/dist/server/controllers/index.mjs.map +1 -1
- package/dist/server/controllers/relations.js +5 -1
- package/dist/server/controllers/relations.js.map +1 -1
- package/dist/server/controllers/relations.mjs +5 -1
- package/dist/server/controllers/relations.mjs.map +1 -1
- package/dist/server/controllers/single-types.js +10 -1
- package/dist/server/controllers/single-types.js.map +1 -1
- package/dist/server/controllers/single-types.mjs +10 -1
- package/dist/server/controllers/single-types.mjs.map +1 -1
- package/dist/server/controllers/validation/model-configuration.js +2 -1
- package/dist/server/controllers/validation/model-configuration.js.map +1 -1
- package/dist/server/controllers/validation/model-configuration.mjs +2 -1
- package/dist/server/controllers/validation/model-configuration.mjs.map +1 -1
- package/dist/server/custom-order/constants.js +21 -0
- package/dist/server/custom-order/constants.js.map +1 -0
- package/dist/server/custom-order/constants.mjs +17 -0
- package/dist/server/custom-order/constants.mjs.map +1 -0
- package/dist/server/custom-order/controllers/custom-order.js +77 -0
- package/dist/server/custom-order/controllers/custom-order.js.map +1 -0
- package/dist/server/custom-order/controllers/custom-order.mjs +75 -0
- package/dist/server/custom-order/controllers/custom-order.mjs.map +1 -0
- package/dist/server/custom-order/controllers/index.js +10 -0
- package/dist/server/custom-order/controllers/index.js.map +1 -0
- package/dist/server/custom-order/controllers/index.mjs +8 -0
- package/dist/server/custom-order/controllers/index.mjs.map +1 -0
- package/dist/server/custom-order/index.js +71 -0
- package/dist/server/custom-order/index.js.map +1 -0
- package/dist/server/custom-order/index.mjs +69 -0
- package/dist/server/custom-order/index.mjs.map +1 -0
- package/dist/server/custom-order/routes/custom-order.js +38 -0
- package/dist/server/custom-order/routes/custom-order.js.map +1 -0
- package/dist/server/custom-order/routes/custom-order.mjs +36 -0
- package/dist/server/custom-order/routes/custom-order.mjs.map +1 -0
- package/dist/server/custom-order/routes/index.js +13 -0
- package/dist/server/custom-order/routes/index.js.map +1 -0
- package/dist/server/custom-order/routes/index.mjs +11 -0
- package/dist/server/custom-order/routes/index.mjs.map +1 -0
- package/dist/server/custom-order/services/custom-order.js +286 -0
- package/dist/server/custom-order/services/custom-order.js.map +1 -0
- package/dist/server/custom-order/services/custom-order.mjs +284 -0
- package/dist/server/custom-order/services/custom-order.mjs.map +1 -0
- package/dist/server/custom-order/services/document-middleware.js +83 -0
- package/dist/server/custom-order/services/document-middleware.js.map +1 -0
- package/dist/server/custom-order/services/document-middleware.mjs +81 -0
- package/dist/server/custom-order/services/document-middleware.mjs.map +1 -0
- package/dist/server/custom-order/services/index.js +10 -0
- package/dist/server/custom-order/services/index.js.map +1 -0
- package/dist/server/custom-order/services/index.mjs +8 -0
- package/dist/server/custom-order/services/index.mjs.map +1 -0
- package/dist/server/custom-order/services/utils.js +152 -0
- package/dist/server/custom-order/services/utils.js.map +1 -0
- package/dist/server/custom-order/services/utils.mjs +148 -0
- package/dist/server/custom-order/services/utils.mjs.map +1 -0
- package/dist/server/custom-order/utils.js +13 -0
- package/dist/server/custom-order/utils.js.map +1 -0
- package/dist/server/custom-order/utils.mjs +10 -0
- package/dist/server/custom-order/utils.mjs.map +1 -0
- package/dist/server/history/constants.js +2 -1
- package/dist/server/history/constants.js.map +1 -1
- package/dist/server/history/constants.mjs +2 -1
- package/dist/server/history/constants.mjs.map +1 -1
- package/dist/server/history/controllers/history-version.js +6 -2
- package/dist/server/history/controllers/history-version.js.map +1 -1
- package/dist/server/history/controllers/history-version.mjs +6 -2
- package/dist/server/history/controllers/history-version.mjs.map +1 -1
- package/dist/server/history/services/history.js +23 -6
- package/dist/server/history/services/history.js.map +1 -1
- package/dist/server/history/services/history.mjs +24 -7
- package/dist/server/history/services/history.mjs.map +1 -1
- package/dist/server/history/services/lifecycles.js +2 -16
- package/dist/server/history/services/lifecycles.js.map +1 -1
- package/dist/server/history/services/lifecycles.mjs +2 -16
- package/dist/server/history/services/lifecycles.mjs.map +1 -1
- package/dist/server/register.js +4 -0
- package/dist/server/register.js.map +1 -1
- package/dist/server/register.mjs +4 -0
- package/dist/server/register.mjs.map +1 -1
- package/dist/server/routes/index.js +3 -1
- package/dist/server/routes/index.js.map +1 -1
- package/dist/server/routes/index.mjs +2 -0
- package/dist/server/routes/index.mjs.map +1 -1
- package/dist/server/services/content-types.js +2 -2
- package/dist/server/services/content-types.js.map +1 -1
- package/dist/server/services/content-types.mjs +2 -2
- package/dist/server/services/content-types.mjs.map +1 -1
- package/dist/server/services/document-manager.js +13 -0
- package/dist/server/services/document-manager.js.map +1 -1
- package/dist/server/services/document-manager.mjs +14 -1
- package/dist/server/services/document-manager.mjs.map +1 -1
- package/dist/server/services/index.js +3 -1
- package/dist/server/services/index.js.map +1 -1
- package/dist/server/services/index.mjs +2 -0
- package/dist/server/services/index.mjs.map +1 -1
- package/dist/server/services/utils/configuration/settings.js +2 -1
- package/dist/server/services/utils/configuration/settings.js.map +1 -1
- package/dist/server/services/utils/configuration/settings.mjs +2 -1
- package/dist/server/services/utils/configuration/settings.mjs.map +1 -1
- package/dist/server/src/audit-logs.d.ts +40 -0
- package/dist/server/src/audit-logs.d.ts.map +1 -0
- package/dist/server/src/bootstrap.d.ts.map +1 -1
- package/dist/server/src/controllers/collection-types.d.ts +1 -1
- package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
- package/dist/server/src/controllers/content-types.d.ts.map +1 -1
- package/dist/server/src/controllers/index.d.ts +21 -3
- package/dist/server/src/controllers/index.d.ts.map +1 -1
- package/dist/server/src/controllers/relations.d.ts +19 -1
- package/dist/server/src/controllers/relations.d.ts.map +1 -1
- package/dist/server/src/controllers/single-types.d.ts +1 -1
- package/dist/server/src/controllers/single-types.d.ts.map +1 -1
- package/dist/server/src/custom-order/constants.d.ts +18 -0
- package/dist/server/src/custom-order/constants.d.ts.map +1 -0
- package/dist/server/src/custom-order/controllers/custom-order.d.ts +8 -0
- package/dist/server/src/custom-order/controllers/custom-order.d.ts.map +1 -0
- package/dist/server/src/custom-order/controllers/index.d.ts +3 -0
- package/dist/server/src/custom-order/controllers/index.d.ts.map +1 -0
- package/dist/server/src/custom-order/index.d.ts +8 -0
- package/dist/server/src/custom-order/index.d.ts.map +1 -0
- package/dist/server/src/custom-order/routes/custom-order.d.ts +4 -0
- package/dist/server/src/custom-order/routes/custom-order.d.ts.map +1 -0
- package/dist/server/src/custom-order/routes/index.d.ts +10 -0
- package/dist/server/src/custom-order/routes/index.d.ts.map +1 -0
- package/dist/server/src/custom-order/services/custom-order.d.ts +43 -0
- package/dist/server/src/custom-order/services/custom-order.d.ts.map +1 -0
- package/dist/server/src/custom-order/services/document-middleware.d.ts +16 -0
- package/dist/server/src/custom-order/services/document-middleware.d.ts.map +1 -0
- package/dist/server/src/custom-order/services/index.d.ts +24 -0
- package/dist/server/src/custom-order/services/index.d.ts.map +1 -0
- package/dist/server/src/custom-order/services/utils.d.ts +34 -0
- package/dist/server/src/custom-order/services/utils.d.ts.map +1 -0
- package/dist/server/src/custom-order/utils.d.ts +6 -0
- package/dist/server/src/custom-order/utils.d.ts.map +1 -0
- package/dist/server/src/history/constants.d.ts.map +1 -1
- package/dist/server/src/history/controllers/history-version.d.ts.map +1 -1
- package/dist/server/src/history/services/history.d.ts.map +1 -1
- package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +22 -6
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/register.d.ts.map +1 -1
- package/dist/server/src/routes/index.d.ts.map +1 -1
- package/dist/server/src/services/content-types.d.ts +1 -3
- package/dist/server/src/services/content-types.d.ts.map +1 -1
- package/dist/server/src/services/document-manager.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +1 -3
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/utils/configuration/settings.d.ts.map +1 -1
- package/dist/shared/contracts/content-types.d.ts +5 -0
- package/dist/shared/contracts/content-types.d.ts.map +1 -1
- package/dist/shared/contracts/custom-order.d.ts +33 -0
- package/dist/shared/contracts/custom-order.d.ts.map +1 -0
- package/dist/shared/contracts/custom-order.js +3 -0
- package/dist/shared/contracts/custom-order.js.map +1 -0
- package/dist/shared/contracts/custom-order.mjs +2 -0
- package/dist/shared/contracts/custom-order.mjs.map +1 -0
- package/dist/shared/contracts/history-versions.d.ts +0 -1
- package/dist/shared/contracts/history-versions.d.ts.map +1 -1
- package/dist/shared/contracts/index.d.ts +1 -0
- package/dist/shared/contracts/index.d.ts.map +1 -1
- package/dist/shared/contracts/index.js +2 -0
- package/dist/shared/contracts/index.js.map +1 -1
- package/dist/shared/contracts/index.mjs +2 -0
- package/dist/shared/contracts/index.mjs.map +1 -1
- package/package.json +8 -8
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
var jsxRuntime = require('react/jsx-runtime');
|
|
4
4
|
var React = require('react');
|
|
5
|
+
var strapiAdmin = require('@strapi/admin/strapi-admin');
|
|
5
6
|
var designSystem = require('@strapi/design-system');
|
|
6
7
|
var reactIntl = require('react-intl');
|
|
7
8
|
var styledComponents = require('styled-components');
|
|
9
|
+
var useHasBeenNearViewport = require('../../../hooks/useHasBeenNearViewport.js');
|
|
8
10
|
var InputRenderer = require('./InputRenderer.js');
|
|
9
11
|
|
|
10
12
|
function _interopNamespace(e) {
|
|
@@ -27,6 +29,139 @@ function _interopNamespace(e) {
|
|
|
27
29
|
|
|
28
30
|
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
29
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Rough rendered heights, only used to size placeholders so the scrollbar stays sensible.
|
|
34
|
+
*/ const ESTIMATED_HEIGHT = {
|
|
35
|
+
richtext: 320,
|
|
36
|
+
blocks: 320,
|
|
37
|
+
json: 240,
|
|
38
|
+
component: 240,
|
|
39
|
+
dynamiczone: 160,
|
|
40
|
+
relation: 120,
|
|
41
|
+
media: 160,
|
|
42
|
+
text: 120
|
|
43
|
+
};
|
|
44
|
+
const DEFAULT_ESTIMATED_HEIGHT = 80;
|
|
45
|
+
const requestIdle = (callback)=>typeof window.requestIdleCallback === 'function' ? window.requestIdleCallback(callback, {
|
|
46
|
+
timeout: 2000
|
|
47
|
+
}) : window.setTimeout(callback, 16);
|
|
48
|
+
const cancelIdle = (handle)=>typeof window.cancelIdleCallback === 'function' ? window.cancelIdleCallback(handle) : window.clearTimeout(handle);
|
|
49
|
+
/**
|
|
50
|
+
* Mounts the rows that weren't needed for the first paint, one per idle period, in the order
|
|
51
|
+
* they were scheduled (top to bottom). Rows are then already rendered when the user scrolls to
|
|
52
|
+
* them, and the browser search finds every field.
|
|
53
|
+
*/ const createIdleMountQueue = ()=>{
|
|
54
|
+
let queue = [];
|
|
55
|
+
let handle = null;
|
|
56
|
+
const flush = ()=>{
|
|
57
|
+
handle = null;
|
|
58
|
+
queue.shift()?.();
|
|
59
|
+
if (queue.length > 0) {
|
|
60
|
+
handle = requestIdle(flush);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
return {
|
|
64
|
+
schedule: (mount)=>{
|
|
65
|
+
queue.push(mount);
|
|
66
|
+
if (handle === null) {
|
|
67
|
+
handle = requestIdle(flush);
|
|
68
|
+
}
|
|
69
|
+
return ()=>{
|
|
70
|
+
queue = queue.filter((scheduled)=>scheduled !== mount);
|
|
71
|
+
};
|
|
72
|
+
},
|
|
73
|
+
dispose: ()=>{
|
|
74
|
+
queue = [];
|
|
75
|
+
if (handle !== null) {
|
|
76
|
+
cancelIdle(handle);
|
|
77
|
+
handle = null;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
const IdleMountContext = /*#__PURE__*/ React__namespace.createContext(null);
|
|
83
|
+
const useIdleMountQueue = ()=>{
|
|
84
|
+
const [queue] = React__namespace.useState(createIdleMountQueue);
|
|
85
|
+
React__namespace.useEffect(()=>queue.dispose, [
|
|
86
|
+
queue
|
|
87
|
+
]);
|
|
88
|
+
return queue.schedule;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Some inputs set a value when they mount: a required UID fetches its default value, and custom
|
|
92
|
+
* fields may set a default. Their rows are mounted with the page, as they always were, so that
|
|
93
|
+
* saving right after the page loads doesn't miss those values. Non-repeatable components are
|
|
94
|
+
* expanded by default, so the inputs they contain count too.
|
|
95
|
+
*/ const hasMountSideEffects = (attribute, components, depth = 0)=>{
|
|
96
|
+
if (attribute.type === 'uid' && attribute.required || 'customField' in attribute) {
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
if (attribute.type === 'component' && !attribute.repeatable && depth < 10) {
|
|
100
|
+
return Object.values(components[attribute.component]?.attributes ?? {}).some((nested)=>hasMountSideEffects(nested, components, depth + 1));
|
|
101
|
+
}
|
|
102
|
+
return false;
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Mounts its children once they get close to the viewport, or in the background when the
|
|
106
|
+
* browser is idle, then keeps them mounted. Rendering every field of a large content type
|
|
107
|
+
* upfront is what makes the edit view slow: the cost of the first render should depend on
|
|
108
|
+
* the screen, not on the size of the model.
|
|
109
|
+
*/ const LazyFormRow = ({ fields, mountImmediately = false, children })=>{
|
|
110
|
+
const scheduleMount = React__namespace.useContext(IdleMountContext);
|
|
111
|
+
const placeholderRef = React__namespace.useRef(null);
|
|
112
|
+
const [isVisible, setIsVisible] = React__namespace.useState(()=>mountImmediately || typeof IntersectionObserver === 'undefined');
|
|
113
|
+
// A field in error has to be mounted so the error is displayed and can receive the focus.
|
|
114
|
+
const hasError = strapiAdmin.useForm('LazyFormRow', (state)=>fields.some(({ name })=>name in state.errors));
|
|
115
|
+
// Once mounted for an error, the row stays mounted when the errors are cleared (every
|
|
116
|
+
// validation starts by clearing them), so its state (e.g. open blocks) is preserved.
|
|
117
|
+
React__namespace.useEffect(()=>{
|
|
118
|
+
if (hasError) {
|
|
119
|
+
setIsVisible(true);
|
|
120
|
+
}
|
|
121
|
+
}, [
|
|
122
|
+
hasError
|
|
123
|
+
]);
|
|
124
|
+
const shouldMount = isVisible || hasError;
|
|
125
|
+
React__namespace.useEffect(()=>{
|
|
126
|
+
const placeholder = placeholderRef.current;
|
|
127
|
+
if (shouldMount || !placeholder) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const observer = new IntersectionObserver((entries)=>{
|
|
131
|
+
if (entries.some((entry)=>entry.isIntersecting)) {
|
|
132
|
+
setIsVisible(true);
|
|
133
|
+
}
|
|
134
|
+
}, {
|
|
135
|
+
root: useHasBeenNearViewport.getScrollParent(placeholder),
|
|
136
|
+
rootMargin: useHasBeenNearViewport.NEAR_VIEWPORT_MARGIN
|
|
137
|
+
});
|
|
138
|
+
observer.observe(placeholder);
|
|
139
|
+
// Low priority: user input interrupts the render of a row mounted in the background.
|
|
140
|
+
const cancelIdleMount = scheduleMount?.(()=>React__namespace.startTransition(()=>{
|
|
141
|
+
setIsVisible(true);
|
|
142
|
+
}));
|
|
143
|
+
return ()=>{
|
|
144
|
+
observer.disconnect();
|
|
145
|
+
cancelIdleMount?.();
|
|
146
|
+
};
|
|
147
|
+
}, [
|
|
148
|
+
shouldMount,
|
|
149
|
+
scheduleMount
|
|
150
|
+
]);
|
|
151
|
+
if (shouldMount) {
|
|
152
|
+
return /*#__PURE__*/ jsxRuntime.jsx(jsxRuntime.Fragment, {
|
|
153
|
+
children: children
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
const height = Math.max(...fields.map(({ type })=>ESTIMATED_HEIGHT[type] ?? DEFAULT_ESTIMATED_HEIGHT));
|
|
157
|
+
return /*#__PURE__*/ jsxRuntime.jsx("div", {
|
|
158
|
+
ref: placeholderRef,
|
|
159
|
+
style: {
|
|
160
|
+
height
|
|
161
|
+
},
|
|
162
|
+
"aria-hidden": true
|
|
163
|
+
});
|
|
164
|
+
};
|
|
30
165
|
const ResponsiveGridRoot = styledComponents.styled(designSystem.Grid.Root)`
|
|
31
166
|
container-type: inline-size;
|
|
32
167
|
`;
|
|
@@ -55,6 +190,7 @@ const panelStyles = {
|
|
|
55
190
|
};
|
|
56
191
|
const FormLayout = /*#__PURE__*/ React__namespace.memo(({ layout, document, hasBackground = true })=>{
|
|
57
192
|
const { formatMessage } = reactIntl.useIntl();
|
|
193
|
+
const scheduleMount = useIdleMountQueue();
|
|
58
194
|
const modelUid = document.schema?.uid;
|
|
59
195
|
const getLabel = (name, label)=>{
|
|
60
196
|
return formatMessage({
|
|
@@ -62,61 +198,74 @@ const FormLayout = /*#__PURE__*/ React__namespace.memo(({ layout, document, hasB
|
|
|
62
198
|
defaultMessage: label
|
|
63
199
|
});
|
|
64
200
|
};
|
|
65
|
-
return /*#__PURE__*/ jsxRuntime.jsx(
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
201
|
+
return /*#__PURE__*/ jsxRuntime.jsx(IdleMountContext.Provider, {
|
|
202
|
+
value: scheduleMount,
|
|
203
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
|
|
204
|
+
direction: "column",
|
|
205
|
+
alignItems: "stretch",
|
|
206
|
+
gap: 6,
|
|
207
|
+
children: layout.map((panel)=>{
|
|
208
|
+
if (panel.some((row)=>row.some((field)=>field.type === 'dynamiczone'))) {
|
|
209
|
+
const [row] = panel;
|
|
210
|
+
const [field] = row;
|
|
211
|
+
return /*#__PURE__*/ jsxRuntime.jsx(LazyFormRow, {
|
|
212
|
+
fields: [
|
|
213
|
+
field
|
|
214
|
+
],
|
|
215
|
+
mountImmediately: hasMountSideEffects(field.attribute, document.components),
|
|
216
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Grid.Root, {
|
|
217
|
+
gap: 4,
|
|
218
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Grid.Item, {
|
|
219
|
+
col: 12,
|
|
220
|
+
s: 12,
|
|
221
|
+
xs: 12,
|
|
222
|
+
direction: "column",
|
|
223
|
+
alignItems: "stretch",
|
|
224
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(InputRenderer.InputRenderer, {
|
|
225
|
+
...field,
|
|
226
|
+
label: getLabel(field.name, field.label),
|
|
227
|
+
document: document
|
|
228
|
+
})
|
|
229
|
+
})
|
|
230
|
+
})
|
|
231
|
+
}, field.name);
|
|
232
|
+
}
|
|
233
|
+
return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
|
|
234
|
+
...hasBackground && panelStyles,
|
|
235
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
|
|
79
236
|
direction: "column",
|
|
80
237
|
alignItems: "stretch",
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
xs: 12,
|
|
106
|
-
direction: "column",
|
|
107
|
-
alignItems: "stretch",
|
|
108
|
-
children: /*#__PURE__*/ jsxRuntime.jsx(InputRenderer.InputRenderer, {
|
|
109
|
-
...field,
|
|
110
|
-
size: size,
|
|
111
|
-
label: getLabel(field.name, field.label),
|
|
112
|
-
document: document
|
|
238
|
+
gap: 6,
|
|
239
|
+
children: panel.map((row)=>{
|
|
240
|
+
return /*#__PURE__*/ jsxRuntime.jsx(LazyFormRow, {
|
|
241
|
+
fields: row,
|
|
242
|
+
mountImmediately: row.some((field)=>hasMountSideEffects(field.attribute, document.components)),
|
|
243
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(ResponsiveGridRoot, {
|
|
244
|
+
gap: {
|
|
245
|
+
initial: 6,
|
|
246
|
+
medium: 4
|
|
247
|
+
},
|
|
248
|
+
children: row.map(({ size, ...field })=>{
|
|
249
|
+
return /*#__PURE__*/ jsxRuntime.jsx(ResponsiveGridItem, {
|
|
250
|
+
col: size,
|
|
251
|
+
s: 12,
|
|
252
|
+
xs: 12,
|
|
253
|
+
direction: "column",
|
|
254
|
+
alignItems: "stretch",
|
|
255
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(InputRenderer.InputRenderer, {
|
|
256
|
+
...field,
|
|
257
|
+
size: size,
|
|
258
|
+
label: getLabel(field.name, field.label),
|
|
259
|
+
document: document
|
|
260
|
+
})
|
|
261
|
+
}, field.name);
|
|
113
262
|
})
|
|
114
|
-
}
|
|
115
|
-
})
|
|
116
|
-
}
|
|
263
|
+
})
|
|
264
|
+
}, row.map((field)=>field.name).join('.'));
|
|
265
|
+
})
|
|
117
266
|
})
|
|
118
|
-
})
|
|
119
|
-
}
|
|
267
|
+
}, panel.flatMap((row)=>row.map((field)=>field.name)).join('.'));
|
|
268
|
+
})
|
|
120
269
|
})
|
|
121
270
|
});
|
|
122
271
|
});
|
|
@@ -125,4 +274,5 @@ FormLayout.displayName = 'FormLayout';
|
|
|
125
274
|
exports.FormLayout = FormLayout;
|
|
126
275
|
exports.ResponsiveGridItem = ResponsiveGridItem;
|
|
127
276
|
exports.ResponsiveGridRoot = ResponsiveGridRoot;
|
|
277
|
+
exports.hasMountSideEffects = hasMountSideEffects;
|
|
128
278
|
//# sourceMappingURL=FormLayout.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormLayout.js","sources":["../../../../../admin/src/pages/EditView/components/FormLayout.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { Box, BoxProps, Flex, Grid } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { EditLayout } from '../../../hooks/useDocumentLayout';\n\nimport { InputRenderer } from './InputRenderer';\n\nimport type { UseDocument } from '../../../hooks/useDocument';\n\nexport const ResponsiveGridRoot = styled(Grid.Root)`\n container-type: inline-size;\n`;\n\nexport const ResponsiveGridItem =\n /**\n * TODO:\n * JSDOM cannot handle container queries.\n * This is a temporary workaround so that tests do not fail in the CI when jestdom throws an error\n * for failing to parse the stylesheet.\n */\n process.env.NODE_ENV !== 'test'\n ? styled(Grid.Item)<{ col: number }>`\n grid-column: span 12;\n ${({ theme }) => theme.breakpoints.medium} {\n ${({ col }) => col && `grid-column: span ${col};`}\n }\n `\n : styled(Grid.Item)<{ col: number }>`\n grid-column: span 12;\n `;\n\nconst panelStyles = {\n padding: {\n initial: 4,\n medium: 6,\n },\n borderColor: 'neutral150',\n background: 'neutral0',\n hasRadius: true,\n shadow: 'tableShadow',\n} satisfies BoxProps;\n\ninterface FormLayoutProps extends Pick<EditLayout, 'layout'> {\n hasBackground?: boolean;\n document: ReturnType<UseDocument>;\n}\n\nconst FormLayout = React.memo(({ layout, document, hasBackground = true }: FormLayoutProps) => {\n const { formatMessage } = useIntl();\n const modelUid = document.schema?.uid;\n\n const getLabel = (name: string, label: string) => {\n return formatMessage({\n id: `content-manager.content-types.${modelUid}.${name}`,\n defaultMessage: label,\n });\n };\n\n return (\n <Flex direction=\"column\" alignItems=\"stretch\" gap={6}>\n {layout.map((panel) => {\n if (panel.some((row) => row.some((field) => field.type === 'dynamiczone'))) {\n const [row] = panel;\n const [field] = row;\n\n return (\n <Grid.Root key={field.name} gap={4}>\n <Grid.Item col={12} s={12} xs={12} direction=\"column\" alignItems=\"stretch\">\n <InputRenderer\n {...field}\n label={getLabel(field.name, field.label)}\n document={document}\n />\n </Grid.Item>\n </Grid.Root>\n );\n }\n\n return (\n <Box\n key={panel.flatMap((row) => row.map((field) => field.name)).join('.')}\n {...(hasBackground && panelStyles)}\n >\n <Flex direction=\"column\" alignItems=\"stretch\" gap={6}>\n {panel.map((row) => {\n return (\n <ResponsiveGridRoot\n key={row.map((field) => field.name).join('.')}\n gap={{ initial: 6, medium: 4 }}\n >\n {row.map(({ size, ...field }) => {\n return (\n <ResponsiveGridItem\n col={size}\n key={field.name}\n s={12}\n xs={12}\n direction=\"column\"\n alignItems=\"stretch\"\n >\n <InputRenderer\n {...field}\n size={size}\n label={getLabel(field.name, field.label)}\n document={document}\n />\n </ResponsiveGridItem>\n );\n })}\n </ResponsiveGridRoot>\n );\n })}\n </Flex>\n </Box>\n );\n })}\n </Flex>\n );\n});\n\nFormLayout.displayName = 'FormLayout';\n\nexport { FormLayout, FormLayoutProps };\n"],"names":["ResponsiveGridRoot","styled","Grid","Root","ResponsiveGridItem","process","env","NODE_ENV","Item","theme","breakpoints","medium","col","panelStyles","padding","initial","borderColor","background","hasRadius","shadow","FormLayout","React","memo","layout","document","hasBackground","formatMessage","useIntl","modelUid","schema","uid","getLabel","name","label","id","defaultMessage","_jsx","Flex","direction","alignItems","gap","map","panel","some","row","field","type","s","xs","InputRenderer","Box","size","join","flatMap","displayName"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FormLayout.js","sources":["../../../../../admin/src/pages/EditView/components/FormLayout.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { useForm } from '@strapi/admin/strapi-admin';\nimport { Box, BoxProps, Flex, Grid } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { EditLayout } from '../../../hooks/useDocumentLayout';\nimport { NEAR_VIEWPORT_MARGIN, getScrollParent } from '../../../hooks/useHasBeenNearViewport';\n\nimport { InputRenderer } from './InputRenderer';\n\nimport type { UseDocument } from '../../../hooks/useDocument';\n\n/* -------------------------------------------------------------------------------------------------\n * LazyFormRow\n * -----------------------------------------------------------------------------------------------*/\n\ntype LayoutField = EditLayout['layout'][number][number][number];\n\n/**\n * Rough rendered heights, only used to size placeholders so the scrollbar stays sensible.\n */\nconst ESTIMATED_HEIGHT: Partial<Record<LayoutField['type'], number>> = {\n richtext: 320,\n blocks: 320,\n json: 240,\n component: 240,\n dynamiczone: 160,\n relation: 120,\n media: 160,\n text: 120,\n};\nconst DEFAULT_ESTIMATED_HEIGHT = 80;\n\n/* -------------------------------------------------------------------------------------------------\n * Idle mount queue\n * -----------------------------------------------------------------------------------------------*/\n\ntype ScheduleMount = (mount: () => void) => () => void;\n\ninterface IdleMountQueue {\n schedule: ScheduleMount;\n dispose: () => void;\n}\n\nconst requestIdle = (callback: () => void): number =>\n typeof window.requestIdleCallback === 'function'\n ? window.requestIdleCallback(callback, { timeout: 2000 })\n : window.setTimeout(callback, 16);\n\nconst cancelIdle = (handle: number) =>\n typeof window.cancelIdleCallback === 'function'\n ? window.cancelIdleCallback(handle)\n : window.clearTimeout(handle);\n\n/**\n * Mounts the rows that weren't needed for the first paint, one per idle period, in the order\n * they were scheduled (top to bottom). Rows are then already rendered when the user scrolls to\n * them, and the browser search finds every field.\n */\nconst createIdleMountQueue = (): IdleMountQueue => {\n let queue: Array<() => void> = [];\n let handle: number | null = null;\n\n const flush = () => {\n handle = null;\n queue.shift()?.();\n\n if (queue.length > 0) {\n handle = requestIdle(flush);\n }\n };\n\n return {\n schedule: (mount) => {\n queue.push(mount);\n\n if (handle === null) {\n handle = requestIdle(flush);\n }\n\n return () => {\n queue = queue.filter((scheduled) => scheduled !== mount);\n };\n },\n dispose: () => {\n queue = [];\n\n if (handle !== null) {\n cancelIdle(handle);\n handle = null;\n }\n },\n };\n};\n\nconst IdleMountContext = React.createContext<ScheduleMount | null>(null);\n\nconst useIdleMountQueue = () => {\n const [queue] = React.useState(createIdleMountQueue);\n\n React.useEffect(() => queue.dispose, [queue]);\n\n return queue.schedule;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * LazyFormRow\n * -----------------------------------------------------------------------------------------------*/\n\ntype Components = ReturnType<UseDocument>['components'];\ntype Attribute = LayoutField['attribute'];\n\n/**\n * Some inputs set a value when they mount: a required UID fetches its default value, and custom\n * fields may set a default. Their rows are mounted with the page, as they always were, so that\n * saving right after the page loads doesn't miss those values. Non-repeatable components are\n * expanded by default, so the inputs they contain count too.\n */\nconst hasMountSideEffects = (attribute: Attribute, components: Components, depth = 0): boolean => {\n if ((attribute.type === 'uid' && attribute.required) || 'customField' in attribute) {\n return true;\n }\n\n if (attribute.type === 'component' && !attribute.repeatable && depth < 10) {\n return Object.values(components[attribute.component]?.attributes ?? {}).some((nested) =>\n hasMountSideEffects(nested as Attribute, components, depth + 1)\n );\n }\n\n return false;\n};\n\ninterface LazyFormRowProps {\n fields: Pick<LayoutField, 'name' | 'type'>[];\n mountImmediately?: boolean;\n children: React.ReactNode;\n}\n\n/**\n * Mounts its children once they get close to the viewport, or in the background when the\n * browser is idle, then keeps them mounted. Rendering every field of a large content type\n * upfront is what makes the edit view slow: the cost of the first render should depend on\n * the screen, not on the size of the model.\n */\nconst LazyFormRow = ({ fields, mountImmediately = false, children }: LazyFormRowProps) => {\n const scheduleMount = React.useContext(IdleMountContext);\n const placeholderRef = React.useRef<HTMLDivElement>(null);\n const [isVisible, setIsVisible] = React.useState(\n () => mountImmediately || typeof IntersectionObserver === 'undefined'\n );\n\n // A field in error has to be mounted so the error is displayed and can receive the focus.\n const hasError = useForm('LazyFormRow', (state) =>\n fields.some(({ name }) => name in state.errors)\n );\n\n // Once mounted for an error, the row stays mounted when the errors are cleared (every\n // validation starts by clearing them), so its state (e.g. open blocks) is preserved.\n React.useEffect(() => {\n if (hasError) {\n setIsVisible(true);\n }\n }, [hasError]);\n\n const shouldMount = isVisible || hasError;\n\n React.useEffect(() => {\n const placeholder = placeholderRef.current;\n\n if (shouldMount || !placeholder) {\n return;\n }\n\n const observer = new IntersectionObserver(\n (entries) => {\n if (entries.some((entry) => entry.isIntersecting)) {\n setIsVisible(true);\n }\n },\n { root: getScrollParent(placeholder), rootMargin: NEAR_VIEWPORT_MARGIN }\n );\n\n observer.observe(placeholder);\n\n // Low priority: user input interrupts the render of a row mounted in the background.\n const cancelIdleMount = scheduleMount?.(() =>\n React.startTransition(() => {\n setIsVisible(true);\n })\n );\n\n return () => {\n observer.disconnect();\n cancelIdleMount?.();\n };\n }, [shouldMount, scheduleMount]);\n\n if (shouldMount) {\n return <>{children}</>;\n }\n\n const height = Math.max(\n ...fields.map(({ type }) => ESTIMATED_HEIGHT[type] ?? DEFAULT_ESTIMATED_HEIGHT)\n );\n\n return <div ref={placeholderRef} style={{ height }} aria-hidden />;\n};\n\nexport const ResponsiveGridRoot = styled(Grid.Root)`\n container-type: inline-size;\n`;\n\nexport const ResponsiveGridItem =\n /**\n * TODO:\n * JSDOM cannot handle container queries.\n * This is a temporary workaround so that tests do not fail in the CI when jestdom throws an error\n * for failing to parse the stylesheet.\n */\n process.env.NODE_ENV !== 'test'\n ? styled(Grid.Item)<{ col: number }>`\n grid-column: span 12;\n ${({ theme }) => theme.breakpoints.medium} {\n ${({ col }) => col && `grid-column: span ${col};`}\n }\n `\n : styled(Grid.Item)<{ col: number }>`\n grid-column: span 12;\n `;\n\nconst panelStyles = {\n padding: {\n initial: 4,\n medium: 6,\n },\n borderColor: 'neutral150',\n background: 'neutral0',\n hasRadius: true,\n shadow: 'tableShadow',\n} satisfies BoxProps;\n\ninterface FormLayoutProps extends Pick<EditLayout, 'layout'> {\n hasBackground?: boolean;\n document: ReturnType<UseDocument>;\n}\n\nconst FormLayout = React.memo(({ layout, document, hasBackground = true }: FormLayoutProps) => {\n const { formatMessage } = useIntl();\n const scheduleMount = useIdleMountQueue();\n const modelUid = document.schema?.uid;\n\n const getLabel = (name: string, label: string) => {\n return formatMessage({\n id: `content-manager.content-types.${modelUid}.${name}`,\n defaultMessage: label,\n });\n };\n\n return (\n <IdleMountContext.Provider value={scheduleMount}>\n <Flex direction=\"column\" alignItems=\"stretch\" gap={6}>\n {layout.map((panel) => {\n if (panel.some((row) => row.some((field) => field.type === 'dynamiczone'))) {\n const [row] = panel;\n const [field] = row;\n\n return (\n <LazyFormRow\n key={field.name}\n fields={[field]}\n mountImmediately={hasMountSideEffects(field.attribute, document.components)}\n >\n <Grid.Root gap={4}>\n <Grid.Item col={12} s={12} xs={12} direction=\"column\" alignItems=\"stretch\">\n <InputRenderer\n {...field}\n label={getLabel(field.name, field.label)}\n document={document}\n />\n </Grid.Item>\n </Grid.Root>\n </LazyFormRow>\n );\n }\n\n return (\n <Box\n key={panel.flatMap((row) => row.map((field) => field.name)).join('.')}\n {...(hasBackground && panelStyles)}\n >\n <Flex direction=\"column\" alignItems=\"stretch\" gap={6}>\n {panel.map((row) => {\n return (\n <LazyFormRow\n key={row.map((field) => field.name).join('.')}\n fields={row}\n mountImmediately={row.some((field) =>\n hasMountSideEffects(field.attribute, document.components)\n )}\n >\n <ResponsiveGridRoot gap={{ initial: 6, medium: 4 }}>\n {row.map(({ size, ...field }) => {\n return (\n <ResponsiveGridItem\n col={size}\n key={field.name}\n s={12}\n xs={12}\n direction=\"column\"\n alignItems=\"stretch\"\n >\n <InputRenderer\n {...field}\n size={size}\n label={getLabel(field.name, field.label)}\n document={document}\n />\n </ResponsiveGridItem>\n );\n })}\n </ResponsiveGridRoot>\n </LazyFormRow>\n );\n })}\n </Flex>\n </Box>\n );\n })}\n </Flex>\n </IdleMountContext.Provider>\n );\n});\n\nFormLayout.displayName = 'FormLayout';\n\nexport { FormLayout, FormLayoutProps, hasMountSideEffects };\n"],"names":["ESTIMATED_HEIGHT","richtext","blocks","json","component","dynamiczone","relation","media","text","DEFAULT_ESTIMATED_HEIGHT","requestIdle","callback","window","requestIdleCallback","timeout","setTimeout","cancelIdle","handle","cancelIdleCallback","clearTimeout","createIdleMountQueue","queue","flush","shift","length","schedule","mount","push","filter","scheduled","dispose","IdleMountContext","React","createContext","useIdleMountQueue","useState","useEffect","hasMountSideEffects","attribute","components","depth","type","required","repeatable","Object","values","attributes","some","nested","LazyFormRow","fields","mountImmediately","children","scheduleMount","useContext","placeholderRef","useRef","isVisible","setIsVisible","IntersectionObserver","hasError","useForm","state","name","errors","shouldMount","placeholder","current","observer","entries","entry","isIntersecting","root","getScrollParent","rootMargin","NEAR_VIEWPORT_MARGIN","observe","cancelIdleMount","startTransition","disconnect","_jsx","_Fragment","height","Math","max","map","div","ref","style","aria-hidden","ResponsiveGridRoot","styled","Grid","Root","ResponsiveGridItem","process","env","NODE_ENV","Item","theme","breakpoints","medium","col","panelStyles","padding","initial","borderColor","background","hasRadius","shadow","FormLayout","memo","layout","document","hasBackground","formatMessage","useIntl","modelUid","schema","uid","getLabel","label","id","defaultMessage","Provider","value","Flex","direction","alignItems","gap","panel","row","field","s","xs","InputRenderer","Box","size","join","flatMap","displayName"],"mappings":"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"}
|
|
@@ -1,10 +1,145 @@
|
|
|
1
|
-
import { jsx } from 'react/jsx-runtime';
|
|
1
|
+
import { jsx, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
+
import { useForm } from '@strapi/admin/strapi-admin';
|
|
3
4
|
import { Grid, Flex, Box } from '@strapi/design-system';
|
|
4
5
|
import { useIntl } from 'react-intl';
|
|
5
6
|
import { styled } from 'styled-components';
|
|
7
|
+
import { NEAR_VIEWPORT_MARGIN, getScrollParent } from '../../../hooks/useHasBeenNearViewport.mjs';
|
|
6
8
|
import { InputRenderer as MemoizedInputRenderer } from './InputRenderer.mjs';
|
|
7
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Rough rendered heights, only used to size placeholders so the scrollbar stays sensible.
|
|
12
|
+
*/ const ESTIMATED_HEIGHT = {
|
|
13
|
+
richtext: 320,
|
|
14
|
+
blocks: 320,
|
|
15
|
+
json: 240,
|
|
16
|
+
component: 240,
|
|
17
|
+
dynamiczone: 160,
|
|
18
|
+
relation: 120,
|
|
19
|
+
media: 160,
|
|
20
|
+
text: 120
|
|
21
|
+
};
|
|
22
|
+
const DEFAULT_ESTIMATED_HEIGHT = 80;
|
|
23
|
+
const requestIdle = (callback)=>typeof window.requestIdleCallback === 'function' ? window.requestIdleCallback(callback, {
|
|
24
|
+
timeout: 2000
|
|
25
|
+
}) : window.setTimeout(callback, 16);
|
|
26
|
+
const cancelIdle = (handle)=>typeof window.cancelIdleCallback === 'function' ? window.cancelIdleCallback(handle) : window.clearTimeout(handle);
|
|
27
|
+
/**
|
|
28
|
+
* Mounts the rows that weren't needed for the first paint, one per idle period, in the order
|
|
29
|
+
* they were scheduled (top to bottom). Rows are then already rendered when the user scrolls to
|
|
30
|
+
* them, and the browser search finds every field.
|
|
31
|
+
*/ const createIdleMountQueue = ()=>{
|
|
32
|
+
let queue = [];
|
|
33
|
+
let handle = null;
|
|
34
|
+
const flush = ()=>{
|
|
35
|
+
handle = null;
|
|
36
|
+
queue.shift()?.();
|
|
37
|
+
if (queue.length > 0) {
|
|
38
|
+
handle = requestIdle(flush);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
return {
|
|
42
|
+
schedule: (mount)=>{
|
|
43
|
+
queue.push(mount);
|
|
44
|
+
if (handle === null) {
|
|
45
|
+
handle = requestIdle(flush);
|
|
46
|
+
}
|
|
47
|
+
return ()=>{
|
|
48
|
+
queue = queue.filter((scheduled)=>scheduled !== mount);
|
|
49
|
+
};
|
|
50
|
+
},
|
|
51
|
+
dispose: ()=>{
|
|
52
|
+
queue = [];
|
|
53
|
+
if (handle !== null) {
|
|
54
|
+
cancelIdle(handle);
|
|
55
|
+
handle = null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
const IdleMountContext = /*#__PURE__*/ React.createContext(null);
|
|
61
|
+
const useIdleMountQueue = ()=>{
|
|
62
|
+
const [queue] = React.useState(createIdleMountQueue);
|
|
63
|
+
React.useEffect(()=>queue.dispose, [
|
|
64
|
+
queue
|
|
65
|
+
]);
|
|
66
|
+
return queue.schedule;
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Some inputs set a value when they mount: a required UID fetches its default value, and custom
|
|
70
|
+
* fields may set a default. Their rows are mounted with the page, as they always were, so that
|
|
71
|
+
* saving right after the page loads doesn't miss those values. Non-repeatable components are
|
|
72
|
+
* expanded by default, so the inputs they contain count too.
|
|
73
|
+
*/ const hasMountSideEffects = (attribute, components, depth = 0)=>{
|
|
74
|
+
if (attribute.type === 'uid' && attribute.required || 'customField' in attribute) {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
if (attribute.type === 'component' && !attribute.repeatable && depth < 10) {
|
|
78
|
+
return Object.values(components[attribute.component]?.attributes ?? {}).some((nested)=>hasMountSideEffects(nested, components, depth + 1));
|
|
79
|
+
}
|
|
80
|
+
return false;
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Mounts its children once they get close to the viewport, or in the background when the
|
|
84
|
+
* browser is idle, then keeps them mounted. Rendering every field of a large content type
|
|
85
|
+
* upfront is what makes the edit view slow: the cost of the first render should depend on
|
|
86
|
+
* the screen, not on the size of the model.
|
|
87
|
+
*/ const LazyFormRow = ({ fields, mountImmediately = false, children })=>{
|
|
88
|
+
const scheduleMount = React.useContext(IdleMountContext);
|
|
89
|
+
const placeholderRef = React.useRef(null);
|
|
90
|
+
const [isVisible, setIsVisible] = React.useState(()=>mountImmediately || typeof IntersectionObserver === 'undefined');
|
|
91
|
+
// A field in error has to be mounted so the error is displayed and can receive the focus.
|
|
92
|
+
const hasError = useForm('LazyFormRow', (state)=>fields.some(({ name })=>name in state.errors));
|
|
93
|
+
// Once mounted for an error, the row stays mounted when the errors are cleared (every
|
|
94
|
+
// validation starts by clearing them), so its state (e.g. open blocks) is preserved.
|
|
95
|
+
React.useEffect(()=>{
|
|
96
|
+
if (hasError) {
|
|
97
|
+
setIsVisible(true);
|
|
98
|
+
}
|
|
99
|
+
}, [
|
|
100
|
+
hasError
|
|
101
|
+
]);
|
|
102
|
+
const shouldMount = isVisible || hasError;
|
|
103
|
+
React.useEffect(()=>{
|
|
104
|
+
const placeholder = placeholderRef.current;
|
|
105
|
+
if (shouldMount || !placeholder) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const observer = new IntersectionObserver((entries)=>{
|
|
109
|
+
if (entries.some((entry)=>entry.isIntersecting)) {
|
|
110
|
+
setIsVisible(true);
|
|
111
|
+
}
|
|
112
|
+
}, {
|
|
113
|
+
root: getScrollParent(placeholder),
|
|
114
|
+
rootMargin: NEAR_VIEWPORT_MARGIN
|
|
115
|
+
});
|
|
116
|
+
observer.observe(placeholder);
|
|
117
|
+
// Low priority: user input interrupts the render of a row mounted in the background.
|
|
118
|
+
const cancelIdleMount = scheduleMount?.(()=>React.startTransition(()=>{
|
|
119
|
+
setIsVisible(true);
|
|
120
|
+
}));
|
|
121
|
+
return ()=>{
|
|
122
|
+
observer.disconnect();
|
|
123
|
+
cancelIdleMount?.();
|
|
124
|
+
};
|
|
125
|
+
}, [
|
|
126
|
+
shouldMount,
|
|
127
|
+
scheduleMount
|
|
128
|
+
]);
|
|
129
|
+
if (shouldMount) {
|
|
130
|
+
return /*#__PURE__*/ jsx(Fragment, {
|
|
131
|
+
children: children
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
const height = Math.max(...fields.map(({ type })=>ESTIMATED_HEIGHT[type] ?? DEFAULT_ESTIMATED_HEIGHT));
|
|
135
|
+
return /*#__PURE__*/ jsx("div", {
|
|
136
|
+
ref: placeholderRef,
|
|
137
|
+
style: {
|
|
138
|
+
height
|
|
139
|
+
},
|
|
140
|
+
"aria-hidden": true
|
|
141
|
+
});
|
|
142
|
+
};
|
|
8
143
|
const ResponsiveGridRoot = styled(Grid.Root)`
|
|
9
144
|
container-type: inline-size;
|
|
10
145
|
`;
|
|
@@ -33,6 +168,7 @@ const panelStyles = {
|
|
|
33
168
|
};
|
|
34
169
|
const FormLayout = /*#__PURE__*/ React.memo(({ layout, document, hasBackground = true })=>{
|
|
35
170
|
const { formatMessage } = useIntl();
|
|
171
|
+
const scheduleMount = useIdleMountQueue();
|
|
36
172
|
const modelUid = document.schema?.uid;
|
|
37
173
|
const getLabel = (name, label)=>{
|
|
38
174
|
return formatMessage({
|
|
@@ -40,65 +176,78 @@ const FormLayout = /*#__PURE__*/ React.memo(({ layout, document, hasBackground =
|
|
|
40
176
|
defaultMessage: label
|
|
41
177
|
});
|
|
42
178
|
};
|
|
43
|
-
return /*#__PURE__*/ jsx(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
179
|
+
return /*#__PURE__*/ jsx(IdleMountContext.Provider, {
|
|
180
|
+
value: scheduleMount,
|
|
181
|
+
children: /*#__PURE__*/ jsx(Flex, {
|
|
182
|
+
direction: "column",
|
|
183
|
+
alignItems: "stretch",
|
|
184
|
+
gap: 6,
|
|
185
|
+
children: layout.map((panel)=>{
|
|
186
|
+
if (panel.some((row)=>row.some((field)=>field.type === 'dynamiczone'))) {
|
|
187
|
+
const [row] = panel;
|
|
188
|
+
const [field] = row;
|
|
189
|
+
return /*#__PURE__*/ jsx(LazyFormRow, {
|
|
190
|
+
fields: [
|
|
191
|
+
field
|
|
192
|
+
],
|
|
193
|
+
mountImmediately: hasMountSideEffects(field.attribute, document.components),
|
|
194
|
+
children: /*#__PURE__*/ jsx(Grid.Root, {
|
|
195
|
+
gap: 4,
|
|
196
|
+
children: /*#__PURE__*/ jsx(Grid.Item, {
|
|
197
|
+
col: 12,
|
|
198
|
+
s: 12,
|
|
199
|
+
xs: 12,
|
|
200
|
+
direction: "column",
|
|
201
|
+
alignItems: "stretch",
|
|
202
|
+
children: /*#__PURE__*/ jsx(MemoizedInputRenderer, {
|
|
203
|
+
...field,
|
|
204
|
+
label: getLabel(field.name, field.label),
|
|
205
|
+
document: document
|
|
206
|
+
})
|
|
207
|
+
})
|
|
208
|
+
})
|
|
209
|
+
}, field.name);
|
|
210
|
+
}
|
|
211
|
+
return /*#__PURE__*/ jsx(Box, {
|
|
212
|
+
...hasBackground && panelStyles,
|
|
213
|
+
children: /*#__PURE__*/ jsx(Flex, {
|
|
57
214
|
direction: "column",
|
|
58
215
|
alignItems: "stretch",
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
xs: 12,
|
|
84
|
-
direction: "column",
|
|
85
|
-
alignItems: "stretch",
|
|
86
|
-
children: /*#__PURE__*/ jsx(MemoizedInputRenderer, {
|
|
87
|
-
...field,
|
|
88
|
-
size: size,
|
|
89
|
-
label: getLabel(field.name, field.label),
|
|
90
|
-
document: document
|
|
216
|
+
gap: 6,
|
|
217
|
+
children: panel.map((row)=>{
|
|
218
|
+
return /*#__PURE__*/ jsx(LazyFormRow, {
|
|
219
|
+
fields: row,
|
|
220
|
+
mountImmediately: row.some((field)=>hasMountSideEffects(field.attribute, document.components)),
|
|
221
|
+
children: /*#__PURE__*/ jsx(ResponsiveGridRoot, {
|
|
222
|
+
gap: {
|
|
223
|
+
initial: 6,
|
|
224
|
+
medium: 4
|
|
225
|
+
},
|
|
226
|
+
children: row.map(({ size, ...field })=>{
|
|
227
|
+
return /*#__PURE__*/ jsx(ResponsiveGridItem, {
|
|
228
|
+
col: size,
|
|
229
|
+
s: 12,
|
|
230
|
+
xs: 12,
|
|
231
|
+
direction: "column",
|
|
232
|
+
alignItems: "stretch",
|
|
233
|
+
children: /*#__PURE__*/ jsx(MemoizedInputRenderer, {
|
|
234
|
+
...field,
|
|
235
|
+
size: size,
|
|
236
|
+
label: getLabel(field.name, field.label),
|
|
237
|
+
document: document
|
|
238
|
+
})
|
|
239
|
+
}, field.name);
|
|
91
240
|
})
|
|
92
|
-
}
|
|
93
|
-
})
|
|
94
|
-
}
|
|
241
|
+
})
|
|
242
|
+
}, row.map((field)=>field.name).join('.'));
|
|
243
|
+
})
|
|
95
244
|
})
|
|
96
|
-
})
|
|
97
|
-
}
|
|
245
|
+
}, panel.flatMap((row)=>row.map((field)=>field.name)).join('.'));
|
|
246
|
+
})
|
|
98
247
|
})
|
|
99
248
|
});
|
|
100
249
|
});
|
|
101
250
|
FormLayout.displayName = 'FormLayout';
|
|
102
251
|
|
|
103
|
-
export { FormLayout, ResponsiveGridItem, ResponsiveGridRoot };
|
|
252
|
+
export { FormLayout, ResponsiveGridItem, ResponsiveGridRoot, hasMountSideEffects };
|
|
104
253
|
//# sourceMappingURL=FormLayout.mjs.map
|