@wordpress/dataviews 12.0.1-next.v.202602111440.0 → 12.0.1
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/CHANGELOG.md +37 -1
- package/README.md +3 -1
- package/build/components/dataform-controls/color.cjs +19 -30
- package/build/components/dataform-controls/color.cjs.map +3 -3
- package/build/components/dataform-controls/date.cjs.map +1 -1
- package/build/components/dataform-controls/datetime.cjs +12 -21
- package/build/components/dataform-controls/datetime.cjs.map +2 -2
- package/build/components/dataform-layouts/card/index.cjs +112 -164
- package/build/components/dataform-layouts/card/index.cjs.map +3 -3
- package/build/components/dataform-layouts/normalize-form.cjs +2 -1
- package/build/components/dataform-layouts/normalize-form.cjs.map +2 -2
- package/build/components/dataform-layouts/panel/summary-button.cjs +77 -49
- package/build/components/dataform-layouts/panel/summary-button.cjs.map +2 -2
- package/build/components/dataform-layouts/panel/utils/get-label-content.cjs +2 -2
- package/build/components/dataform-layouts/panel/utils/get-label-content.cjs.map +2 -2
- package/build/components/dataviews-bulk-actions/index.cjs +2 -2
- package/build/components/dataviews-bulk-actions/index.cjs.map +2 -2
- package/build/components/dataviews-context/index.cjs +1 -0
- package/build/components/dataviews-context/index.cjs.map +2 -2
- package/build/components/dataviews-filters/filter.cjs.map +1 -1
- package/build/components/dataviews-filters/toggle.cjs +6 -2
- package/build/components/dataviews-filters/toggle.cjs.map +2 -2
- package/build/components/dataviews-footer/index.cjs +28 -12
- package/build/components/dataviews-footer/index.cjs.map +3 -3
- package/build/components/dataviews-item-actions/index.cjs +0 -1
- package/build/components/dataviews-item-actions/index.cjs.map +2 -2
- package/build/components/dataviews-layout/index.cjs +12 -0
- package/build/components/dataviews-layout/index.cjs.map +2 -2
- package/build/components/dataviews-layouts/activity/index.cjs +41 -26
- package/build/components/dataviews-layouts/activity/index.cjs.map +3 -3
- package/build/components/dataviews-layouts/grid/composite-grid.cjs +2 -0
- package/build/components/dataviews-layouts/grid/composite-grid.cjs.map +2 -2
- package/build/components/dataviews-layouts/grid/index.cjs +19 -14
- package/build/components/dataviews-layouts/grid/index.cjs.map +3 -3
- package/build/components/dataviews-layouts/list/index.cjs +13 -9
- package/build/components/dataviews-layouts/list/index.cjs.map +2 -2
- package/build/components/dataviews-layouts/picker-table/index.cjs +1 -1
- package/build/components/dataviews-layouts/picker-table/index.cjs.map +2 -2
- package/build/components/dataviews-layouts/table/index.cjs +40 -19
- package/build/components/dataviews-layouts/table/index.cjs.map +2 -2
- package/build/dataviews/index.cjs +9 -2
- package/build/dataviews/index.cjs.map +3 -3
- package/build/dataviews-picker/index.cjs +1 -0
- package/build/dataviews-picker/index.cjs.map +2 -2
- package/build/hooks/use-data.cjs +46 -0
- package/build/hooks/use-data.cjs.map +7 -0
- package/build/hooks/use-delayed-loading.cjs +47 -0
- package/build/hooks/use-delayed-loading.cjs.map +7 -0
- package/build/types/dataform.cjs.map +1 -1
- package/build-module/components/dataform-controls/color.mjs +24 -31
- package/build-module/components/dataform-controls/color.mjs.map +2 -2
- package/build-module/components/dataform-controls/date.mjs.map +1 -1
- package/build-module/components/dataform-controls/datetime.mjs +13 -22
- package/build-module/components/dataform-controls/datetime.mjs.map +2 -2
- package/build-module/components/dataform-layouts/card/index.mjs +113 -161
- package/build-module/components/dataform-layouts/card/index.mjs.map +3 -3
- package/build-module/components/dataform-layouts/normalize-form.mjs +2 -1
- package/build-module/components/dataform-layouts/normalize-form.mjs.map +2 -2
- package/build-module/components/dataform-layouts/panel/summary-button.mjs +78 -50
- package/build-module/components/dataform-layouts/panel/summary-button.mjs.map +2 -2
- package/build-module/components/dataform-layouts/panel/utils/get-label-content.mjs +3 -3
- package/build-module/components/dataform-layouts/panel/utils/get-label-content.mjs.map +2 -2
- package/build-module/components/dataviews-bulk-actions/index.mjs +2 -2
- package/build-module/components/dataviews-bulk-actions/index.mjs.map +2 -2
- package/build-module/components/dataviews-context/index.mjs +1 -0
- package/build-module/components/dataviews-context/index.mjs.map +2 -2
- package/build-module/components/dataviews-filters/filter.mjs.map +1 -1
- package/build-module/components/dataviews-filters/toggle.mjs +6 -2
- package/build-module/components/dataviews-filters/toggle.mjs.map +2 -2
- package/build-module/components/dataviews-footer/index.mjs +28 -12
- package/build-module/components/dataviews-footer/index.mjs.map +2 -2
- package/build-module/components/dataviews-item-actions/index.mjs +0 -1
- package/build-module/components/dataviews-item-actions/index.mjs.map +2 -2
- package/build-module/components/dataviews-layout/index.mjs +12 -0
- package/build-module/components/dataviews-layout/index.mjs.map +2 -2
- package/build-module/components/dataviews-layouts/activity/index.mjs +41 -26
- package/build-module/components/dataviews-layouts/activity/index.mjs.map +2 -2
- package/build-module/components/dataviews-layouts/grid/composite-grid.mjs +2 -0
- package/build-module/components/dataviews-layouts/grid/composite-grid.mjs.map +2 -2
- package/build-module/components/dataviews-layouts/grid/index.mjs +19 -14
- package/build-module/components/dataviews-layouts/grid/index.mjs.map +2 -2
- package/build-module/components/dataviews-layouts/list/index.mjs +13 -9
- package/build-module/components/dataviews-layouts/list/index.mjs.map +2 -2
- package/build-module/components/dataviews-layouts/picker-table/index.mjs +1 -1
- package/build-module/components/dataviews-layouts/picker-table/index.mjs.map +2 -2
- package/build-module/components/dataviews-layouts/table/index.mjs +40 -19
- package/build-module/components/dataviews-layouts/table/index.mjs.map +2 -2
- package/build-module/dataviews/index.mjs +9 -2
- package/build-module/dataviews/index.mjs.map +2 -2
- package/build-module/dataviews-picker/index.mjs +1 -0
- package/build-module/dataviews-picker/index.mjs.map +2 -2
- package/build-module/hooks/use-data.mjs +25 -0
- package/build-module/hooks/use-data.mjs.map +7 -0
- package/build-module/hooks/use-delayed-loading.mjs +22 -0
- package/build-module/hooks/use-delayed-loading.mjs.map +7 -0
- package/build-style/style-rtl.css +109 -32
- package/build-style/style.css +109 -32
- package/build-types/components/dataform-controls/color.d.ts.map +1 -1
- package/build-types/components/dataform-controls/datetime.d.ts.map +1 -1
- package/build-types/components/dataform-controls/utils/use-disabled-date-matchers.d.ts +16 -0
- package/build-types/components/dataform-controls/utils/use-disabled-date-matchers.d.ts.map +1 -0
- package/build-types/components/dataform-layouts/card/index.d.ts +1 -10
- package/build-types/components/dataform-layouts/card/index.d.ts.map +1 -1
- package/build-types/components/dataform-layouts/normalize-form.d.ts.map +1 -1
- package/build-types/components/dataform-layouts/panel/summary-button.d.ts.map +1 -1
- package/build-types/components/dataform-layouts/panel/utils/get-label-content.d.ts +1 -1
- package/build-types/components/dataform-layouts/panel/utils/get-label-content.d.ts.map +1 -1
- package/build-types/components/dataviews-context/index.d.ts +1 -0
- package/build-types/components/dataviews-context/index.d.ts.map +1 -1
- package/build-types/components/dataviews-filters/filter.d.ts +1 -1
- package/build-types/components/dataviews-filters/filter.d.ts.map +1 -1
- package/build-types/components/dataviews-filters/toggle.d.ts.map +1 -1
- package/build-types/components/dataviews-footer/index.d.ts +1 -1
- package/build-types/components/dataviews-footer/index.d.ts.map +1 -1
- package/build-types/components/dataviews-item-actions/index.d.ts.map +1 -1
- package/build-types/components/dataviews-layout/index.d.ts +1 -1
- package/build-types/components/dataviews-layout/index.d.ts.map +1 -1
- package/build-types/components/dataviews-layouts/activity/index.d.ts.map +1 -1
- package/build-types/components/dataviews-layouts/grid/composite-grid.d.ts +2 -1
- package/build-types/components/dataviews-layouts/grid/composite-grid.d.ts.map +1 -1
- package/build-types/components/dataviews-layouts/grid/index.d.ts.map +1 -1
- package/build-types/components/dataviews-layouts/list/index.d.ts.map +1 -1
- package/build-types/components/dataviews-layouts/picker-activity/index.d.ts +3 -0
- package/build-types/components/dataviews-layouts/picker-activity/index.d.ts.map +1 -0
- package/build-types/components/dataviews-layouts/table/index.d.ts.map +1 -1
- package/build-types/components/dataviews-layouts/table/use-scroll-state.d.ts +25 -0
- package/build-types/components/dataviews-layouts/table/use-scroll-state.d.ts.map +1 -0
- package/build-types/components/dataviews-layouts/utils/grid-config-options.d.ts +2 -0
- package/build-types/components/dataviews-layouts/utils/grid-config-options.d.ts.map +1 -0
- package/build-types/components/dataviews-layouts/utils/use-infinite-scroll.d.ts +22 -0
- package/build-types/components/dataviews-layouts/utils/use-infinite-scroll.d.ts.map +1 -0
- package/build-types/dataform/stories/index.story.d.ts +9 -1
- package/build-types/dataform/stories/index.story.d.ts.map +1 -1
- package/build-types/dataform/stories/layout-panel.d.ts +3 -1
- package/build-types/dataform/stories/layout-panel.d.ts.map +1 -1
- package/build-types/dataviews/index.d.ts.map +1 -1
- package/build-types/dataviews/stories/empty.d.ts.map +1 -1
- package/build-types/dataviews/stories/free-composition.d.ts.map +1 -1
- package/build-types/dataviews/stories/layout-table.d.ts.map +1 -1
- package/build-types/dataviews/stories/minimal-ui.d.ts.map +1 -1
- package/build-types/dataviews/stories/with-card.d.ts.map +1 -1
- package/build-types/dataviews-picker/index.d.ts.map +1 -1
- package/build-types/field-types/utils/is-valid-date-boundary.d.ts +7 -0
- package/build-types/field-types/utils/is-valid-date-boundary.d.ts.map +1 -0
- package/build-types/hooks/test/use-data.d.ts +2 -0
- package/build-types/hooks/test/use-data.d.ts.map +1 -0
- package/build-types/hooks/use-data.d.ts +12 -0
- package/build-types/hooks/use-data.d.ts.map +1 -0
- package/build-types/hooks/use-delayed-loading.d.ts +4 -0
- package/build-types/hooks/use-delayed-loading.d.ts.map +1 -0
- package/build-types/hooks/use-infinite-scroll.d.ts +21 -0
- package/build-types/hooks/use-infinite-scroll.d.ts.map +1 -0
- package/build-types/hooks/use-selected-items.d.ts +19 -0
- package/build-types/hooks/use-selected-items.d.ts.map +1 -0
- package/build-types/types/dataform.d.ts +3 -0
- package/build-types/types/dataform.d.ts.map +1 -1
- package/build-wp/index.js +2568 -1864
- package/package.json +21 -21
- package/src/components/dataform-controls/color.tsx +29 -36
- package/src/components/dataform-controls/date.tsx +2 -2
- package/src/components/dataform-controls/datetime.tsx +19 -34
- package/src/components/dataform-controls/style.scss +4 -0
- package/src/components/dataform-layouts/card/index.tsx +118 -185
- package/src/components/dataform-layouts/normalize-form.ts +1 -0
- package/src/components/dataform-layouts/panel/style.scss +24 -20
- package/src/components/dataform-layouts/panel/summary-button.tsx +43 -12
- package/src/components/dataform-layouts/panel/utils/get-label-content.tsx +3 -5
- package/src/components/dataform-layouts/regular/style.scss +3 -2
- package/src/components/dataform-layouts/test/normalize-form.ts +5 -0
- package/src/components/dataviews-bulk-actions/index.tsx +2 -2
- package/src/components/dataviews-context/index.ts +2 -0
- package/src/components/dataviews-filters/filter.tsx +1 -1
- package/src/components/dataviews-filters/toggle.tsx +10 -3
- package/src/components/dataviews-footer/index.tsx +39 -12
- package/src/components/dataviews-footer/style.scss +6 -1
- package/src/components/dataviews-item-actions/index.tsx +0 -3
- package/src/components/dataviews-item-actions/style.scss +7 -0
- package/src/components/dataviews-layout/index.tsx +24 -0
- package/src/components/dataviews-layouts/activity/index.tsx +29 -22
- package/src/components/dataviews-layouts/activity/style.scss +5 -0
- package/src/components/dataviews-layouts/grid/composite-grid.tsx +5 -1
- package/src/components/dataviews-layouts/grid/index.tsx +19 -22
- package/src/components/dataviews-layouts/grid/style.scss +5 -0
- package/src/components/dataviews-layouts/list/index.tsx +18 -18
- package/src/components/dataviews-layouts/list/style.scss +5 -0
- package/src/components/dataviews-layouts/picker-table/index.tsx +1 -1
- package/src/components/dataviews-layouts/table/index.tsx +48 -22
- package/src/components/dataviews-layouts/table/style.scss +8 -2
- package/src/dataform/stories/index.story.tsx +5 -0
- package/src/dataform/stories/layout-panel.tsx +19 -2
- package/src/dataviews/index.tsx +11 -3
- package/src/dataviews/stories/empty.tsx +1 -7
- package/src/dataviews/stories/free-composition.tsx +0 -5
- package/src/dataviews/stories/layout-table.tsx +1 -7
- package/src/dataviews/stories/minimal-ui.tsx +0 -5
- package/src/dataviews/stories/with-card.tsx +1 -7
- package/src/dataviews/style.scss +25 -0
- package/src/dataviews-picker/index.tsx +2 -1
- package/src/hooks/use-data.ts +45 -0
- package/src/hooks/use-delayed-loading.ts +21 -0
- package/src/types/dataform.ts +4 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wordpress/dataviews",
|
|
3
|
-
"version": "12.0.1
|
|
3
|
+
"version": "12.0.1",
|
|
4
4
|
"description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).",
|
|
5
5
|
"author": "The WordPress Contributors",
|
|
6
6
|
"license": "GPL-2.0-or-later",
|
|
@@ -52,24 +52,24 @@
|
|
|
52
52
|
"types": "build-types",
|
|
53
53
|
"sideEffects": false,
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@ariakit/react": "^0.4.
|
|
56
|
-
"@wordpress/base-styles": "^6.
|
|
57
|
-
"@wordpress/components": "^32.2.1
|
|
58
|
-
"@wordpress/compose": "^7.
|
|
59
|
-
"@wordpress/data": "^10.
|
|
60
|
-
"@wordpress/date": "^5.
|
|
61
|
-
"@wordpress/deprecated": "^4.
|
|
62
|
-
"@wordpress/dom": "^4.
|
|
63
|
-
"@wordpress/element": "^6.
|
|
64
|
-
"@wordpress/i18n": "^6.
|
|
65
|
-
"@wordpress/icons": "^11.
|
|
66
|
-
"@wordpress/keycodes": "^4.
|
|
67
|
-
"@wordpress/primitives": "^4.
|
|
68
|
-
"@wordpress/private-apis": "^1.
|
|
69
|
-
"@wordpress/theme": "^0.7.1
|
|
70
|
-
"@wordpress/ui": "^0.7.1
|
|
71
|
-
"@wordpress/url": "^4.
|
|
72
|
-
"@wordpress/warning": "^3.
|
|
55
|
+
"@ariakit/react": "^0.4.21",
|
|
56
|
+
"@wordpress/base-styles": "^6.16.1",
|
|
57
|
+
"@wordpress/components": "^32.2.1",
|
|
58
|
+
"@wordpress/compose": "^7.40.1",
|
|
59
|
+
"@wordpress/data": "^10.40.1",
|
|
60
|
+
"@wordpress/date": "^5.40.1",
|
|
61
|
+
"@wordpress/deprecated": "^4.40.1",
|
|
62
|
+
"@wordpress/dom": "^4.40.1",
|
|
63
|
+
"@wordpress/element": "^6.40.1",
|
|
64
|
+
"@wordpress/i18n": "^6.13.1",
|
|
65
|
+
"@wordpress/icons": "^11.7.1",
|
|
66
|
+
"@wordpress/keycodes": "^4.40.1",
|
|
67
|
+
"@wordpress/primitives": "^4.40.1",
|
|
68
|
+
"@wordpress/private-apis": "^1.40.1",
|
|
69
|
+
"@wordpress/theme": "^0.7.1",
|
|
70
|
+
"@wordpress/ui": "^0.7.1",
|
|
71
|
+
"@wordpress/url": "^4.40.1",
|
|
72
|
+
"@wordpress/warning": "^3.40.1",
|
|
73
73
|
"clsx": "^2.1.1",
|
|
74
74
|
"colord": "^2.7.0",
|
|
75
75
|
"date-fns": "^4.1.0",
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
"devDependencies": {
|
|
81
81
|
"@storybook/addon-docs": "^10.1.11",
|
|
82
82
|
"@storybook/react-vite": "^10.1.11",
|
|
83
|
-
"@testing-library/jest-dom": "^6.
|
|
83
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
84
84
|
"@types/jest": "^29.5.14",
|
|
85
85
|
"esbuild": "^0.27.2",
|
|
86
86
|
"storybook": "^10.1.11"
|
|
@@ -95,5 +95,5 @@
|
|
|
95
95
|
"scripts": {
|
|
96
96
|
"build:wp": "node build.cjs"
|
|
97
97
|
},
|
|
98
|
-
"gitHead": "
|
|
98
|
+
"gitHead": "adb6623c9f32490cfc73c7ac7f122578c1f10c65"
|
|
99
99
|
}
|
|
@@ -7,11 +7,16 @@ import { colord } from 'colord';
|
|
|
7
7
|
* WordPress dependencies
|
|
8
8
|
*/
|
|
9
9
|
import {
|
|
10
|
+
Button,
|
|
11
|
+
ColorIndicator,
|
|
12
|
+
ColorPicker,
|
|
10
13
|
Dropdown,
|
|
11
14
|
privateApis,
|
|
12
15
|
__experimentalInputControlPrefixWrapper as InputControlPrefixWrapper,
|
|
16
|
+
__experimentalDropdownContentWrapper as DropdownContentWrapper,
|
|
13
17
|
} from '@wordpress/components';
|
|
14
18
|
import { useCallback } from '@wordpress/element';
|
|
19
|
+
import { __ } from '@wordpress/i18n';
|
|
15
20
|
|
|
16
21
|
/**
|
|
17
22
|
* Internal dependencies
|
|
@@ -20,51 +25,37 @@ import type { DataFormControlProps } from '../../types';
|
|
|
20
25
|
import { unlock } from '../../lock-unlock';
|
|
21
26
|
import getCustomValidity from './utils/get-custom-validity';
|
|
22
27
|
|
|
23
|
-
const { ValidatedInputControl
|
|
28
|
+
const { ValidatedInputControl } = unlock( privateApis );
|
|
24
29
|
|
|
25
|
-
const
|
|
30
|
+
const ColorPickerDropdown = ( {
|
|
26
31
|
color,
|
|
27
32
|
onColorChange,
|
|
28
33
|
}: {
|
|
29
34
|
color: string;
|
|
30
|
-
onColorChange: (
|
|
35
|
+
onColorChange: ( newColor: string ) => void;
|
|
31
36
|
} ) => {
|
|
32
37
|
const validColor = color && colord( color ).isValid() ? color : '#ffffff';
|
|
33
38
|
|
|
34
39
|
return (
|
|
35
40
|
<Dropdown
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
backgroundColor: validColor,
|
|
46
|
-
border: '1px solid #ddd',
|
|
47
|
-
cursor: 'pointer',
|
|
48
|
-
outline: isOpen ? '2px solid #007cba' : 'none',
|
|
49
|
-
outlineOffset: '2px',
|
|
50
|
-
display: 'flex',
|
|
51
|
-
alignItems: 'center',
|
|
52
|
-
justifyContent: 'center',
|
|
53
|
-
padding: 0,
|
|
54
|
-
margin: 0,
|
|
55
|
-
} }
|
|
56
|
-
aria-label="Open color picker"
|
|
57
|
-
/>
|
|
58
|
-
</InputControlPrefixWrapper>
|
|
41
|
+
className="dataviews-controls__color-picker-dropdown"
|
|
42
|
+
popoverProps={ { resize: false } }
|
|
43
|
+
renderToggle={ ( { onToggle } ) => (
|
|
44
|
+
<Button
|
|
45
|
+
onClick={ onToggle }
|
|
46
|
+
aria-label={ __( 'Open color picker' ) }
|
|
47
|
+
size="small"
|
|
48
|
+
icon={ () => <ColorIndicator colorValue={ validColor } /> }
|
|
49
|
+
/>
|
|
59
50
|
) }
|
|
60
51
|
renderContent={ () => (
|
|
61
|
-
<
|
|
62
|
-
<
|
|
63
|
-
color={
|
|
52
|
+
<DropdownContentWrapper paddingSize="none">
|
|
53
|
+
<ColorPicker
|
|
54
|
+
color={ validColor }
|
|
64
55
|
onChange={ onColorChange }
|
|
65
56
|
enableAlpha
|
|
66
57
|
/>
|
|
67
|
-
</
|
|
58
|
+
</DropdownContentWrapper>
|
|
68
59
|
) }
|
|
69
60
|
/>
|
|
70
61
|
);
|
|
@@ -82,8 +73,8 @@ export default function Color< Item >( {
|
|
|
82
73
|
const value = field.getValue( { item: data } ) || '';
|
|
83
74
|
|
|
84
75
|
const handleColorChange = useCallback(
|
|
85
|
-
(
|
|
86
|
-
onChange( setValue( { item: data, value:
|
|
76
|
+
( newColor: string ) => {
|
|
77
|
+
onChange( setValue( { item: data, value: newColor } ) );
|
|
87
78
|
},
|
|
88
79
|
[ data, onChange, setValue ]
|
|
89
80
|
);
|
|
@@ -108,10 +99,12 @@ export default function Color< Item >( {
|
|
|
108
99
|
hideLabelFromVision={ hideLabelFromVision }
|
|
109
100
|
type="text"
|
|
110
101
|
prefix={
|
|
111
|
-
<
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
102
|
+
<InputControlPrefixWrapper variant="control">
|
|
103
|
+
<ColorPickerDropdown
|
|
104
|
+
color={ value }
|
|
105
|
+
onColorChange={ handleColorChange }
|
|
106
|
+
/>
|
|
107
|
+
</InputControlPrefixWrapper>
|
|
115
108
|
}
|
|
116
109
|
/>
|
|
117
110
|
);
|
|
@@ -161,8 +161,8 @@ function ValidatedDateControl< Item >( {
|
|
|
161
161
|
field: NormalizedField< Item >;
|
|
162
162
|
validity?: FieldValidity;
|
|
163
163
|
inputRefs:
|
|
164
|
-
| React.RefObject< HTMLInputElement >
|
|
165
|
-
| React.RefObject< HTMLInputElement >[];
|
|
164
|
+
| React.RefObject< HTMLInputElement | null >
|
|
165
|
+
| React.RefObject< HTMLInputElement | null >[];
|
|
166
166
|
isTouched: boolean;
|
|
167
167
|
setIsTouched: ( touched: boolean ) => void;
|
|
168
168
|
children: React.ReactNode;
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* External dependencies
|
|
3
|
-
*/
|
|
4
|
-
import { format } from 'date-fns';
|
|
5
|
-
|
|
6
1
|
/**
|
|
7
2
|
* WordPress dependencies
|
|
8
3
|
*/
|
|
@@ -12,7 +7,7 @@ import {
|
|
|
12
7
|
} from '@wordpress/components';
|
|
13
8
|
import { useCallback, useEffect, useRef, useState } from '@wordpress/element';
|
|
14
9
|
import { __ } from '@wordpress/i18n';
|
|
15
|
-
import { getSettings } from '@wordpress/date';
|
|
10
|
+
import { dateI18n, getDate, getSettings } from '@wordpress/date';
|
|
16
11
|
import { Stack } from '@wordpress/ui';
|
|
17
12
|
|
|
18
13
|
/**
|
|
@@ -27,15 +22,12 @@ import { unlock } from '../../lock-unlock';
|
|
|
27
22
|
|
|
28
23
|
const { DateCalendar, ValidatedInputControl } = unlock( componentsPrivateApis );
|
|
29
24
|
|
|
30
|
-
const formatDateTime = (
|
|
31
|
-
if ( !
|
|
25
|
+
const formatDateTime = ( value?: string ): string => {
|
|
26
|
+
if ( ! value ) {
|
|
32
27
|
return '';
|
|
33
28
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
// Format as datetime-local input expects: YYYY-MM-DDTHH:mm
|
|
38
|
-
return format( date, "yyyy-MM-dd'T'HH:mm" );
|
|
29
|
+
// Format in WordPress timezone for datetime-local input: YYYY-MM-DDTHH:mm
|
|
30
|
+
return dateI18n( 'Y-m-d\\TH:i', getDate( value ) );
|
|
39
31
|
};
|
|
40
32
|
|
|
41
33
|
function CalendarDateTimeControl< Item >( {
|
|
@@ -56,7 +48,8 @@ function CalendarDateTimeControl< Item >( {
|
|
|
56
48
|
} );
|
|
57
49
|
|
|
58
50
|
const inputControlRef = useRef< HTMLInputElement >( null );
|
|
59
|
-
const validationTimeoutRef =
|
|
51
|
+
const validationTimeoutRef =
|
|
52
|
+
useRef< ReturnType< typeof setTimeout > >( undefined );
|
|
60
53
|
const previousFocusRef = useRef< Element | null >( null );
|
|
61
54
|
|
|
62
55
|
const onChangeCallback = useCallback(
|
|
@@ -78,21 +71,19 @@ function CalendarDateTimeControl< Item >( {
|
|
|
78
71
|
( newDate: Date | undefined | null ) => {
|
|
79
72
|
let dateTimeValue: string | undefined;
|
|
80
73
|
if ( newDate ) {
|
|
81
|
-
//
|
|
82
|
-
|
|
74
|
+
// Extract the date part in WP timezone from the calendar selection
|
|
75
|
+
const wpDate = dateI18n( 'Y-m-d', newDate );
|
|
83
76
|
|
|
77
|
+
// Preserve time if it exists in current value, otherwise use current time
|
|
78
|
+
let wpTime: string;
|
|
84
79
|
if ( value ) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
finalDateTime = new Date( newDate );
|
|
89
|
-
finalDateTime.setHours( currentDateTime.getHours() );
|
|
90
|
-
finalDateTime.setMinutes(
|
|
91
|
-
currentDateTime.getMinutes()
|
|
92
|
-
);
|
|
93
|
-
}
|
|
80
|
+
wpTime = dateI18n( 'H:i', getDate( value ) );
|
|
81
|
+
} else {
|
|
82
|
+
wpTime = dateI18n( 'H:i', newDate );
|
|
94
83
|
}
|
|
95
84
|
|
|
85
|
+
// Combine date and time in WP timezone and convert to ISO
|
|
86
|
+
const finalDateTime = getDate( `${ wpDate }T${ wpTime }` );
|
|
96
87
|
dateTimeValue = finalDateTime.toISOString();
|
|
97
88
|
onChangeCallback( dateTimeValue );
|
|
98
89
|
|
|
@@ -132,8 +123,8 @@ function CalendarDateTimeControl< Item >( {
|
|
|
132
123
|
const handleManualDateTimeChange = useCallback(
|
|
133
124
|
( newValue?: string ) => {
|
|
134
125
|
if ( newValue ) {
|
|
135
|
-
//
|
|
136
|
-
const dateTime =
|
|
126
|
+
// Interpret the datetime-local value in WordPress timezone
|
|
127
|
+
const dateTime = getDate( newValue );
|
|
137
128
|
onChangeCallback( dateTime.toISOString() );
|
|
138
129
|
|
|
139
130
|
// Update calendar month to match
|
|
@@ -196,13 +187,7 @@ function CalendarDateTimeControl< Item >( {
|
|
|
196
187
|
type="datetime-local"
|
|
197
188
|
label={ __( 'Date time' ) }
|
|
198
189
|
hideLabelFromVision
|
|
199
|
-
value={
|
|
200
|
-
value
|
|
201
|
-
? formatDateTime(
|
|
202
|
-
parseDateTime( value ) || undefined
|
|
203
|
-
)
|
|
204
|
-
: ''
|
|
205
|
-
}
|
|
190
|
+
value={ formatDateTime( value ) }
|
|
206
191
|
onChange={ handleManualDateTimeChange }
|
|
207
192
|
/>
|
|
208
193
|
</Stack>
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
CardBody,
|
|
8
8
|
CardHeader as OriginalCardHeader,
|
|
9
9
|
} from '@wordpress/components';
|
|
10
|
+
import { useInstanceId } from '@wordpress/compose';
|
|
10
11
|
import {
|
|
11
12
|
useCallback,
|
|
12
13
|
useContext,
|
|
@@ -15,6 +16,7 @@ import {
|
|
|
15
16
|
useRef,
|
|
16
17
|
useState,
|
|
17
18
|
} from '@wordpress/element';
|
|
19
|
+
import { __ } from '@wordpress/i18n';
|
|
18
20
|
import { chevronDown, chevronUp } from '@wordpress/icons';
|
|
19
21
|
|
|
20
22
|
/**
|
|
@@ -35,98 +37,6 @@ import { getSummaryFields } from '../get-summary-fields';
|
|
|
35
37
|
import useReportValidity from '../../../hooks/use-report-validity';
|
|
36
38
|
import ValidationBadge from '../validation-badge';
|
|
37
39
|
|
|
38
|
-
const NonCollapsibleCardHeader = ( {
|
|
39
|
-
children,
|
|
40
|
-
...props
|
|
41
|
-
}: {
|
|
42
|
-
children: React.ReactNode;
|
|
43
|
-
} ) => (
|
|
44
|
-
<OriginalCardHeader isBorderless { ...props }>
|
|
45
|
-
<div
|
|
46
|
-
style={ {
|
|
47
|
-
height: '40px', // This is to match the chevron's __next40pxDefaultSize
|
|
48
|
-
width: '100%',
|
|
49
|
-
display: 'flex',
|
|
50
|
-
justifyContent: 'space-between',
|
|
51
|
-
alignItems: 'center',
|
|
52
|
-
} }
|
|
53
|
-
>
|
|
54
|
-
{ children }
|
|
55
|
-
</div>
|
|
56
|
-
</OriginalCardHeader>
|
|
57
|
-
);
|
|
58
|
-
|
|
59
|
-
export function useCardHeader( layout: NormalizedCardLayout ) {
|
|
60
|
-
const { isOpened, isCollapsible } = layout;
|
|
61
|
-
const [ isOpen, setIsOpen ] = useState( isOpened );
|
|
62
|
-
const [ touched, setTouched ] = useState( false );
|
|
63
|
-
|
|
64
|
-
// Sync internal state when the isOpened prop changes.
|
|
65
|
-
// This is unlikely to happen in production, but it helps with storybook controls.
|
|
66
|
-
useEffect( () => {
|
|
67
|
-
setIsOpen( isOpened );
|
|
68
|
-
}, [ isOpened ] );
|
|
69
|
-
|
|
70
|
-
const toggle = useCallback( () => {
|
|
71
|
-
// Mark as touched when collapsing (going from open to closed)
|
|
72
|
-
if ( isOpen ) {
|
|
73
|
-
setTouched( true );
|
|
74
|
-
}
|
|
75
|
-
setIsOpen( ( prev ) => ! prev );
|
|
76
|
-
}, [ isOpen ] );
|
|
77
|
-
|
|
78
|
-
const CollapsibleCardHeader = useCallback(
|
|
79
|
-
( {
|
|
80
|
-
children,
|
|
81
|
-
...props
|
|
82
|
-
}: {
|
|
83
|
-
children: React.ReactNode;
|
|
84
|
-
[ key: string ]: any;
|
|
85
|
-
} ) => (
|
|
86
|
-
<OriginalCardHeader
|
|
87
|
-
{ ...props }
|
|
88
|
-
onClick={ toggle }
|
|
89
|
-
style={ {
|
|
90
|
-
cursor: 'pointer',
|
|
91
|
-
...props.style,
|
|
92
|
-
} }
|
|
93
|
-
isBorderless
|
|
94
|
-
>
|
|
95
|
-
<div
|
|
96
|
-
style={ {
|
|
97
|
-
width: '100%',
|
|
98
|
-
display: 'flex',
|
|
99
|
-
justifyContent: 'space-between',
|
|
100
|
-
alignItems: 'center',
|
|
101
|
-
} }
|
|
102
|
-
>
|
|
103
|
-
{ children }
|
|
104
|
-
</div>
|
|
105
|
-
<Button
|
|
106
|
-
__next40pxDefaultSize
|
|
107
|
-
variant="tertiary"
|
|
108
|
-
icon={ isOpen ? chevronUp : chevronDown }
|
|
109
|
-
aria-expanded={ isOpen }
|
|
110
|
-
aria-label={ isOpen ? 'Collapse' : 'Expand' }
|
|
111
|
-
/>
|
|
112
|
-
</OriginalCardHeader>
|
|
113
|
-
),
|
|
114
|
-
[ toggle, isOpen ]
|
|
115
|
-
);
|
|
116
|
-
|
|
117
|
-
const effectiveIsOpen = isCollapsible ? isOpen : true;
|
|
118
|
-
const CardHeaderComponent = isCollapsible
|
|
119
|
-
? CollapsibleCardHeader
|
|
120
|
-
: NonCollapsibleCardHeader;
|
|
121
|
-
|
|
122
|
-
return {
|
|
123
|
-
isOpen: effectiveIsOpen,
|
|
124
|
-
CardHeader: CardHeaderComponent,
|
|
125
|
-
touched,
|
|
126
|
-
setTouched,
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
|
|
130
40
|
function isSummaryFieldVisible< Item >(
|
|
131
41
|
summaryField: NormalizedField< Item >,
|
|
132
42
|
summaryConfig: NormalizedCardLayout[ 'summary' ],
|
|
@@ -189,6 +99,10 @@ export default function FormCardField< Item >( {
|
|
|
189
99
|
const { fields } = useContext( DataFormContext );
|
|
190
100
|
const layout = field.layout as NormalizedCardLayout;
|
|
191
101
|
const cardBodyRef = useRef< HTMLDivElement >( null );
|
|
102
|
+
const bodyId = useInstanceId(
|
|
103
|
+
FormCardField,
|
|
104
|
+
'dataforms-layouts-card-card-body'
|
|
105
|
+
);
|
|
192
106
|
|
|
193
107
|
const form: NormalizedForm = useMemo(
|
|
194
108
|
() => ( {
|
|
@@ -198,7 +112,27 @@ export default function FormCardField< Item >( {
|
|
|
198
112
|
[ field ]
|
|
199
113
|
);
|
|
200
114
|
|
|
201
|
-
const {
|
|
115
|
+
const { isOpened, isCollapsible } = layout;
|
|
116
|
+
const [ internalIsOpen, setIsOpen ] = useState( isOpened );
|
|
117
|
+
const [ touched, setTouched ] = useState( false );
|
|
118
|
+
|
|
119
|
+
// Sync internal state when the isOpened prop changes.
|
|
120
|
+
// This is unlikely to happen in production, but it helps with storybook controls.
|
|
121
|
+
useEffect( () => {
|
|
122
|
+
setIsOpen( isOpened );
|
|
123
|
+
}, [ isOpened ] );
|
|
124
|
+
|
|
125
|
+
const toggle = useCallback( () => {
|
|
126
|
+
setIsOpen( ( prev ) => {
|
|
127
|
+
// Mark as touched when collapsing (going from open to closed)
|
|
128
|
+
if ( prev ) {
|
|
129
|
+
setTouched( true );
|
|
130
|
+
}
|
|
131
|
+
return ! prev;
|
|
132
|
+
} );
|
|
133
|
+
}, [] );
|
|
134
|
+
|
|
135
|
+
const isOpen = isCollapsible ? internalIsOpen : true;
|
|
202
136
|
|
|
203
137
|
// Mark the card as touched when any field inside it is blurred.
|
|
204
138
|
// This aligns with how validated controls show errors on blur.
|
|
@@ -228,24 +162,86 @@ export default function FormCardField< Item >( {
|
|
|
228
162
|
inlineEnd: 'medium' as const,
|
|
229
163
|
};
|
|
230
164
|
|
|
231
|
-
|
|
232
|
-
|
|
165
|
+
let label = field.label;
|
|
166
|
+
let withHeader: boolean;
|
|
167
|
+
let bodyContent: React.ReactNode;
|
|
168
|
+
|
|
169
|
+
if ( field.children ) {
|
|
170
|
+
withHeader = !! label && layout.withHeader;
|
|
171
|
+
bodyContent = (
|
|
172
|
+
<>
|
|
173
|
+
{ field.description && (
|
|
174
|
+
<div className="dataforms-layouts-card__field-description">
|
|
175
|
+
{ field.description }
|
|
176
|
+
</div>
|
|
177
|
+
) }
|
|
178
|
+
<DataFormLayout
|
|
179
|
+
data={ data }
|
|
180
|
+
form={ form }
|
|
181
|
+
onChange={ onChange }
|
|
182
|
+
validity={ validity?.children }
|
|
183
|
+
/>
|
|
184
|
+
</>
|
|
185
|
+
);
|
|
186
|
+
} else {
|
|
187
|
+
const fieldDefinition = fields.find(
|
|
188
|
+
( fieldDef ) => fieldDef.id === field.id
|
|
189
|
+
);
|
|
233
190
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
: ( 'medium' as const ),
|
|
238
|
-
blockEnd: 'medium' as const,
|
|
239
|
-
inlineStart: 'medium' as const,
|
|
240
|
-
inlineEnd: 'medium' as const,
|
|
241
|
-
};
|
|
191
|
+
if ( ! fieldDefinition || ! fieldDefinition.Edit ) {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
242
194
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
195
|
+
const SingleFieldLayout = getFormFieldLayout( 'regular' )?.component;
|
|
196
|
+
if ( ! SingleFieldLayout ) {
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
label = fieldDefinition.label;
|
|
201
|
+
withHeader = !! label && layout.withHeader;
|
|
202
|
+
bodyContent = (
|
|
203
|
+
<SingleFieldLayout
|
|
204
|
+
data={ data }
|
|
205
|
+
field={ field }
|
|
206
|
+
onChange={ onChange }
|
|
207
|
+
hideLabelFromVision={ hideLabelFromVision || withHeader }
|
|
208
|
+
markWhenOptional={ markWhenOptional }
|
|
209
|
+
validity={ validity }
|
|
210
|
+
/>
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const sizeCardBody = {
|
|
215
|
+
blockStart: withHeader ? ( 'none' as const ) : ( 'medium' as const ),
|
|
216
|
+
blockEnd: 'medium' as const,
|
|
217
|
+
inlineStart: 'medium' as const,
|
|
218
|
+
inlineEnd: 'medium' as const,
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
return (
|
|
222
|
+
<Card className="dataforms-layouts-card__field" size={ sizeCard }>
|
|
223
|
+
{ withHeader && (
|
|
224
|
+
<OriginalCardHeader
|
|
225
|
+
className="dataforms-layouts-card__field-header"
|
|
226
|
+
onClick={ isCollapsible ? toggle : undefined }
|
|
227
|
+
style={ {
|
|
228
|
+
cursor: isCollapsible ? 'pointer' : undefined,
|
|
229
|
+
} }
|
|
230
|
+
isBorderless
|
|
231
|
+
>
|
|
232
|
+
<div
|
|
233
|
+
style={ {
|
|
234
|
+
// Match the expand/collapse button's height to avoid layout
|
|
235
|
+
// differences when that button is not displayed.
|
|
236
|
+
height: isCollapsible ? undefined : '40px',
|
|
237
|
+
width: '100%',
|
|
238
|
+
display: 'flex',
|
|
239
|
+
justifyContent: 'space-between',
|
|
240
|
+
alignItems: 'center',
|
|
241
|
+
} }
|
|
242
|
+
>
|
|
247
243
|
<span className="dataforms-layouts-card__field-header-label">
|
|
248
|
-
{
|
|
244
|
+
{ label }
|
|
249
245
|
</span>
|
|
250
246
|
{ validationBadge }
|
|
251
247
|
{ visibleSummaryFields.length > 0 &&
|
|
@@ -262,95 +258,32 @@ export default function FormCardField< Item >( {
|
|
|
262
258
|
) }
|
|
263
259
|
</div>
|
|
264
260
|
) }
|
|
265
|
-
</
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
{ field.description && (
|
|
277
|
-
<div className="dataforms-layouts-card__field-description">
|
|
278
|
-
{ field.description }
|
|
279
|
-
</div>
|
|
280
|
-
) }
|
|
281
|
-
<DataFormLayout
|
|
282
|
-
data={ data }
|
|
283
|
-
form={ form }
|
|
284
|
-
onChange={ onChange }
|
|
285
|
-
validity={ validity?.children }
|
|
261
|
+
</div>
|
|
262
|
+
{ isCollapsible && (
|
|
263
|
+
<Button
|
|
264
|
+
__next40pxDefaultSize
|
|
265
|
+
variant="tertiary"
|
|
266
|
+
icon={ isOpen ? chevronUp : chevronDown }
|
|
267
|
+
aria-expanded={ isOpen }
|
|
268
|
+
aria-controls={ bodyId }
|
|
269
|
+
aria-label={
|
|
270
|
+
isOpen ? __( 'Collapse' ) : __( 'Expand' )
|
|
271
|
+
}
|
|
286
272
|
/>
|
|
287
|
-
</CardBody>
|
|
288
|
-
) }
|
|
289
|
-
</Card>
|
|
290
|
-
);
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
const fieldDefinition = fields.find(
|
|
294
|
-
( fieldDef ) => fieldDef.id === field.id
|
|
295
|
-
);
|
|
296
|
-
|
|
297
|
-
if ( ! fieldDefinition || ! fieldDefinition.Edit ) {
|
|
298
|
-
return null;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
const RegularLayout = getFormFieldLayout( 'regular' )?.component;
|
|
302
|
-
if ( ! RegularLayout ) {
|
|
303
|
-
return null;
|
|
304
|
-
}
|
|
305
|
-
const withHeader = !! fieldDefinition.label && layout.withHeader;
|
|
306
|
-
|
|
307
|
-
const sizeCardBody = {
|
|
308
|
-
blockStart: withHeader ? ( 'none' as const ) : ( 'medium' as const ),
|
|
309
|
-
blockEnd: 'medium' as const,
|
|
310
|
-
inlineStart: 'medium' as const,
|
|
311
|
-
inlineEnd: 'medium' as const,
|
|
312
|
-
};
|
|
313
|
-
|
|
314
|
-
return (
|
|
315
|
-
<Card className="dataforms-layouts-card__field" size={ sizeCard }>
|
|
316
|
-
{ withHeader && (
|
|
317
|
-
<CardHeader className="dataforms-layouts-card__field-header">
|
|
318
|
-
<span className="dataforms-layouts-card__field-header-label">
|
|
319
|
-
{ fieldDefinition.label }
|
|
320
|
-
</span>
|
|
321
|
-
{ validationBadge }
|
|
322
|
-
{ visibleSummaryFields.length > 0 && layout.withHeader && (
|
|
323
|
-
<div className="dataforms-layouts-card__field-summary">
|
|
324
|
-
{ visibleSummaryFields.map( ( summaryField ) => (
|
|
325
|
-
<summaryField.render
|
|
326
|
-
key={ summaryField.id }
|
|
327
|
-
item={ data }
|
|
328
|
-
field={ summaryField }
|
|
329
|
-
/>
|
|
330
|
-
) ) }
|
|
331
|
-
</div>
|
|
332
273
|
) }
|
|
333
|
-
</
|
|
274
|
+
</OriginalCardHeader>
|
|
334
275
|
) }
|
|
335
276
|
{ ( isOpen || ! withHeader ) && (
|
|
336
277
|
// If it doesn't have a header, keep it open.
|
|
337
278
|
// Otherwise, the card will not be visible.
|
|
338
279
|
<CardBody
|
|
280
|
+
id={ bodyId }
|
|
339
281
|
size={ sizeCardBody }
|
|
340
282
|
className="dataforms-layouts-card__field-control"
|
|
341
283
|
ref={ cardBodyRef }
|
|
342
284
|
onBlur={ handleBlur }
|
|
343
285
|
>
|
|
344
|
-
|
|
345
|
-
data={ data }
|
|
346
|
-
field={ field }
|
|
347
|
-
onChange={ onChange }
|
|
348
|
-
hideLabelFromVision={
|
|
349
|
-
hideLabelFromVision || withHeader
|
|
350
|
-
}
|
|
351
|
-
markWhenOptional={ markWhenOptional }
|
|
352
|
-
validity={ validity }
|
|
353
|
-
/>
|
|
286
|
+
{ bodyContent }
|
|
354
287
|
</CardBody>
|
|
355
288
|
) }
|
|
356
289
|
</Card>
|
|
@@ -60,6 +60,7 @@ function normalizeLayout( layout?: Layout ): NormalizedLayout {
|
|
|
60
60
|
labelPosition: layout?.labelPosition ?? 'side',
|
|
61
61
|
openAs: layout?.openAs ?? 'dropdown',
|
|
62
62
|
summary: normalizedSummary,
|
|
63
|
+
editVisibility: layout?.editVisibility ?? 'on-hover',
|
|
63
64
|
} satisfies NormalizedPanelLayout;
|
|
64
65
|
} else if ( layout?.type === 'card' ) {
|
|
65
66
|
if ( layout.withHeader === false ) {
|