@wordpress/dataviews 12.1.1-next.v.202602241322.0 → 13.0.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.
Files changed (132) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/README.md +132 -14
  3. package/build/components/dataform-layouts/card/index.cjs +12 -7
  4. package/build/components/dataform-layouts/card/index.cjs.map +2 -2
  5. package/build/components/dataform-layouts/panel/utils/get-label-content.cjs +2 -2
  6. package/build/components/dataform-layouts/panel/utils/get-label-content.cjs.map +2 -2
  7. package/build/components/dataviews-context/index.cjs +1 -0
  8. package/build/components/dataviews-context/index.cjs.map +2 -2
  9. package/build/components/dataviews-filters/toggle.cjs +6 -2
  10. package/build/components/dataviews-filters/toggle.cjs.map +2 -2
  11. package/build/components/dataviews-footer/index.cjs +28 -12
  12. package/build/components/dataviews-footer/index.cjs.map +3 -3
  13. package/build/components/dataviews-item-actions/index.cjs +0 -1
  14. package/build/components/dataviews-item-actions/index.cjs.map +2 -2
  15. package/build/components/dataviews-layout/index.cjs +4 -0
  16. package/build/components/dataviews-layout/index.cjs.map +2 -2
  17. package/build/components/dataviews-layouts/activity/index.cjs +41 -26
  18. package/build/components/dataviews-layouts/activity/index.cjs.map +3 -3
  19. package/build/components/dataviews-layouts/grid/composite-grid.cjs +2 -0
  20. package/build/components/dataviews-layouts/grid/composite-grid.cjs.map +2 -2
  21. package/build/components/dataviews-layouts/grid/index.cjs +19 -14
  22. package/build/components/dataviews-layouts/grid/index.cjs.map +3 -3
  23. package/build/components/dataviews-layouts/list/index.cjs +25 -12
  24. package/build/components/dataviews-layouts/list/index.cjs.map +2 -2
  25. package/build/components/dataviews-layouts/table/index.cjs +40 -19
  26. package/build/components/dataviews-layouts/table/index.cjs.map +2 -2
  27. package/build/dataviews/index.cjs +9 -2
  28. package/build/dataviews/index.cjs.map +3 -3
  29. package/build/dataviews-picker/index.cjs +1 -0
  30. package/build/dataviews-picker/index.cjs.map +2 -2
  31. package/build/hooks/use-data.cjs +46 -0
  32. package/build/hooks/use-data.cjs.map +7 -0
  33. package/build/hooks/use-delayed-loading.cjs +47 -0
  34. package/build/hooks/use-delayed-loading.cjs.map +7 -0
  35. package/build-module/components/dataform-layouts/card/index.mjs +12 -7
  36. package/build-module/components/dataform-layouts/card/index.mjs.map +2 -2
  37. package/build-module/components/dataform-layouts/panel/utils/get-label-content.mjs +3 -3
  38. package/build-module/components/dataform-layouts/panel/utils/get-label-content.mjs.map +2 -2
  39. package/build-module/components/dataviews-context/index.mjs +1 -0
  40. package/build-module/components/dataviews-context/index.mjs.map +2 -2
  41. package/build-module/components/dataviews-filters/toggle.mjs +6 -2
  42. package/build-module/components/dataviews-filters/toggle.mjs.map +2 -2
  43. package/build-module/components/dataviews-footer/index.mjs +28 -12
  44. package/build-module/components/dataviews-footer/index.mjs.map +2 -2
  45. package/build-module/components/dataviews-item-actions/index.mjs +0 -1
  46. package/build-module/components/dataviews-item-actions/index.mjs.map +2 -2
  47. package/build-module/components/dataviews-layout/index.mjs +4 -0
  48. package/build-module/components/dataviews-layout/index.mjs.map +2 -2
  49. package/build-module/components/dataviews-layouts/activity/index.mjs +41 -26
  50. package/build-module/components/dataviews-layouts/activity/index.mjs.map +2 -2
  51. package/build-module/components/dataviews-layouts/grid/composite-grid.mjs +2 -0
  52. package/build-module/components/dataviews-layouts/grid/composite-grid.mjs.map +2 -2
  53. package/build-module/components/dataviews-layouts/grid/index.mjs +19 -14
  54. package/build-module/components/dataviews-layouts/grid/index.mjs.map +2 -2
  55. package/build-module/components/dataviews-layouts/list/index.mjs +25 -12
  56. package/build-module/components/dataviews-layouts/list/index.mjs.map +2 -2
  57. package/build-module/components/dataviews-layouts/table/index.mjs +40 -19
  58. package/build-module/components/dataviews-layouts/table/index.mjs.map +2 -2
  59. package/build-module/dataviews/index.mjs +9 -2
  60. package/build-module/dataviews/index.mjs.map +2 -2
  61. package/build-module/dataviews-picker/index.mjs +1 -0
  62. package/build-module/dataviews-picker/index.mjs.map +2 -2
  63. package/build-module/hooks/use-data.mjs +25 -0
  64. package/build-module/hooks/use-data.mjs.map +7 -0
  65. package/build-module/hooks/use-delayed-loading.mjs +22 -0
  66. package/build-module/hooks/use-delayed-loading.mjs.map +7 -0
  67. package/build-style/style-rtl.css +91 -19
  68. package/build-style/style.css +91 -19
  69. package/build-types/components/dataform-layouts/card/index.d.ts.map +1 -1
  70. package/build-types/components/dataform-layouts/panel/utils/get-label-content.d.ts +1 -1
  71. package/build-types/components/dataform-layouts/panel/utils/get-label-content.d.ts.map +1 -1
  72. package/build-types/components/dataviews-context/index.d.ts +1 -0
  73. package/build-types/components/dataviews-context/index.d.ts.map +1 -1
  74. package/build-types/components/dataviews-filters/toggle.d.ts.map +1 -1
  75. package/build-types/components/dataviews-footer/index.d.ts +1 -1
  76. package/build-types/components/dataviews-footer/index.d.ts.map +1 -1
  77. package/build-types/components/dataviews-item-actions/index.d.ts.map +1 -1
  78. package/build-types/components/dataviews-layout/index.d.ts +1 -1
  79. package/build-types/components/dataviews-layout/index.d.ts.map +1 -1
  80. package/build-types/components/dataviews-layouts/activity/index.d.ts.map +1 -1
  81. package/build-types/components/dataviews-layouts/grid/composite-grid.d.ts +2 -1
  82. package/build-types/components/dataviews-layouts/grid/composite-grid.d.ts.map +1 -1
  83. package/build-types/components/dataviews-layouts/grid/index.d.ts.map +1 -1
  84. package/build-types/components/dataviews-layouts/list/index.d.ts.map +1 -1
  85. package/build-types/components/dataviews-layouts/table/index.d.ts.map +1 -1
  86. package/build-types/dataform/stories/layout-panel.d.ts.map +1 -1
  87. package/build-types/dataviews/index.d.ts.map +1 -1
  88. package/build-types/dataviews/stories/empty.d.ts.map +1 -1
  89. package/build-types/dataviews/stories/free-composition.d.ts.map +1 -1
  90. package/build-types/dataviews/stories/layout-table.d.ts.map +1 -1
  91. package/build-types/dataviews/stories/minimal-ui.d.ts.map +1 -1
  92. package/build-types/dataviews/stories/with-card.d.ts.map +1 -1
  93. package/build-types/dataviews-picker/index.d.ts.map +1 -1
  94. package/build-types/hooks/use-data.d.ts +12 -0
  95. package/build-types/hooks/use-data.d.ts.map +1 -0
  96. package/build-types/hooks/use-delayed-loading.d.ts +4 -0
  97. package/build-types/hooks/use-delayed-loading.d.ts.map +1 -0
  98. package/build-wp/index.js +263 -135
  99. package/package.json +16 -19
  100. package/src/components/dataform-layouts/card/index.tsx +8 -9
  101. package/src/components/dataform-layouts/card/style.scss +1 -0
  102. package/src/components/dataform-layouts/panel/style.scss +2 -0
  103. package/src/components/dataform-layouts/panel/utils/get-label-content.tsx +3 -5
  104. package/src/components/dataform-layouts/regular/style.scss +3 -2
  105. package/src/components/dataviews-context/index.ts +2 -0
  106. package/src/components/dataviews-filters/toggle.tsx +9 -2
  107. package/src/components/dataviews-footer/index.tsx +39 -12
  108. package/src/components/dataviews-footer/style.scss +6 -1
  109. package/src/components/dataviews-item-actions/index.tsx +0 -3
  110. package/src/components/dataviews-item-actions/style.scss +7 -0
  111. package/src/components/dataviews-layout/index.tsx +5 -0
  112. package/src/components/dataviews-layouts/activity/index.tsx +29 -22
  113. package/src/components/dataviews-layouts/activity/style.scss +5 -0
  114. package/src/components/dataviews-layouts/grid/composite-grid.tsx +4 -0
  115. package/src/components/dataviews-layouts/grid/index.tsx +19 -22
  116. package/src/components/dataviews-layouts/grid/style.scss +5 -0
  117. package/src/components/dataviews-layouts/list/index.tsx +39 -21
  118. package/src/components/dataviews-layouts/list/style.scss +5 -9
  119. package/src/components/dataviews-layouts/table/index.tsx +48 -22
  120. package/src/components/dataviews-layouts/table/style.scss +6 -0
  121. package/src/dataform/stories/layout-card.tsx +2 -2
  122. package/src/dataform/stories/layout-panel.tsx +5 -1
  123. package/src/dataviews/index.tsx +10 -2
  124. package/src/dataviews/stories/empty.tsx +1 -7
  125. package/src/dataviews/stories/free-composition.tsx +0 -5
  126. package/src/dataviews/stories/layout-table.tsx +1 -7
  127. package/src/dataviews/stories/minimal-ui.tsx +0 -5
  128. package/src/dataviews/stories/with-card.tsx +1 -7
  129. package/src/dataviews/style.scss +25 -0
  130. package/src/dataviews-picker/index.tsx +1 -0
  131. package/src/hooks/use-data.ts +45 -0
  132. package/src/hooks/use-delayed-loading.ts +21 -0
package/CHANGELOG.md CHANGED
@@ -2,17 +2,37 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
- ## 12.1.0-next.0 (2026-02-24)
5
+ ## 13.0.0 (2026-03-04)
6
+
7
+ ### Breaking Changes
8
+
9
+ - DataViews: Align to end integer and number field types. [#75917](https://github.com/WordPress/gutenberg/pull/75917)
6
10
 
7
11
  ### Bug Fixes
8
12
 
13
+ - DataForm: Fix label color of array control. [#75730](https://github.com/WordPress/gutenberg/pull/75730)
14
+ - DataForm: Fix text overflow for long unhyphenated text in panel layout. [#76073](https://github.com/WordPress/gutenberg/pull/76073)
15
+ - DataForm: Fix `card` layout's toggle button screen reader text. [#76039](https://github.com/WordPress/gutenberg/pull/76039)
16
+ - DataViews: Fix focus transfer while searching in `list` layout. [#75999](https://github.com/WordPress/gutenberg/pull/75999)
9
17
  - DataForm: Fix focus loss when collapsing in Card view. [#75689](https://github.com/WordPress/gutenberg/pull/75689)
18
+ - DataViews: Avoid flickering while refreshing. [#74572](https://github.com/WordPress/gutenberg/pull/74572)
10
19
  - DataViews: Fix spacing in first column. [#75693](https://github.com/WordPress/gutenberg/pull/75693)
20
+ - DataViews: Fix filter toggle flickering when there are locked or primary filters. [#75913](https://github.com/WordPress/gutenberg/pull/75913)
11
21
  - DataViews: Fix search input losing characters during debounce when externally synced. [#75810](https://github.com/WordPress/gutenberg/pull/75810)
22
+ - DataForm: Fix vertical alignment of summary fields in card layout. [#75864](https://github.com/WordPress/gutenberg/pull/75864)
23
+ - DataViews: Remove visual divider between quick and regular actions in the actions menu. [#75893](https://github.com/WordPress/gutenberg/pull/75893)
24
+ - DataForm: field label for panel layout are no longer uppercased. [#75944](https://github.com/WordPress/gutenberg/pull/75944)
12
25
 
13
26
  ### Enhancements
14
27
 
28
+ - Documentation: Update README.md. [#75881](https://github.com/WordPress/gutenberg/pull/75881)
29
+ - DataViews: Improve UI in `list` layout when we render only title and/or media fields. [#76042](https://github.com/WordPress/gutenberg/pull/76042)
15
30
  - DataViews: Adjust column spacing in table layout when no titleField is provided. [#75410](https://github.com/WordPress/gutenberg/pull/75410)
31
+ - DataViews: minimize padding for primary actions. [#75721](https://github.com/WordPress/gutenberg/pull/75721)
32
+
33
+ ### Code Quality
34
+
35
+ - Remove unused dependencies from `package.json`. [#76075](https://github.com/WordPress/gutenberg/pull/76075)
16
36
 
17
37
  ## 12.0.0 (2026-02-18)
18
38
 
@@ -42,6 +62,7 @@
42
62
  - DataViews: Consistent rendering of selection checkbox and actions in grid layout. [#75056](https://github.com/WordPress/gutenberg/pull/75056)
43
63
 
44
64
  ### Code Quality
65
+
45
66
  - DataForm: Style SummaryButton in panel layout with `is-disabled` classname. [#75470](https://github.com/WordPress/gutenberg/pull/75470)
46
67
 
47
68
  ### Internal
package/README.md CHANGED
@@ -207,7 +207,7 @@ const view = {
207
207
 
208
208
  Properties:
209
209
 
210
- - `type`: view type, one of `table`, `grid`, `list`. See "Layout types".
210
+ - `type`: view type, one of `table`, `grid`, `list`, `activity`, `pickerTable`, `pickerGrid`. See "Layout types".
211
211
  - `search`: the text search applied to the dataset.
212
212
  - `filters`: the filters applied to the dataset. Each item describes:
213
213
  - `field`: which field this filter is bound to.
@@ -230,7 +230,9 @@ Properties:
230
230
 
231
231
  - `field`: the field used for grouping the dataset.
232
232
  - `direction`: the direction to use for sorting the groups, one of `asc` or `desc`. Default `asc`.
233
+ - `showLabel`: whether to show the field label in the group header. `true` by default.
233
234
 
235
+ - `infiniteScrollEnabled`: whether infinite scroll is enabled. `false` by default.
234
236
  - `fields`: a list of remaining field `id` that are visible in the UI and the specific order in which they are displayed.
235
237
  - `layout`: config that is specific to a particular layout type.
236
238
 
@@ -238,7 +240,7 @@ Properties:
238
240
 
239
241
  | Props / Layout | `table` | `pickerTable` | `grid` | `pickerGrid` | `list` | `activity` |
240
242
  | -------------- | ------- | ------------- | ------ | ------------ | ------ | ---------- |
241
- | `density` | ✓ | ✓ | | | | ✓ |
243
+ | `density` | ✓ | ✓ | | || ✓ |
242
244
  | `enableMoving` | ✓ | ✓ | | | | |
243
245
  | `styles` | ✓ | ✓ | | | | |
244
246
  | `badgeFields` | | | ✓ | ✓ | | |
@@ -248,10 +250,10 @@ Properties:
248
250
 
249
251
  - `density`: one of `comfortable`, `balanced`, or `compact`. Configures the size and spacing of the layout.
250
252
  - `enableMoving`: whether the table columns should display moving controls.
251
- - `styles`: additional `width`, `maxWidth`, `minWidth`, `align` styles for each field column.
253
+ - `styles`: additional `width`, `maxWidth`, `minWidth`, `align` styles for each field column. The `align` property accepts `'start'`, `'center'`, or `'end'`.
252
254
 
253
255
  **For column alignment (`align` property), follow these guidelines:**
254
- Right-align whenever the cell value is fundamentally quantitative—numbers, decimals, currency, percentages—so that digits and decimal points line up, aiding comparison and calculation. Otherwise, default to left-alignment for all other types (text, codes, labels, dates).
256
+ Right-align (`'end'`) whenever the cell value is fundamentally quantitative—numbers, decimals, currency, percentages—so that digits and decimal points line up, aiding comparison and calculation. Otherwise, default to left-alignment (`'start'`) for all other types (text, codes, labels, dates).
255
257
 
256
258
  `grid` and `pickerGrid` layout:
257
259
 
@@ -260,7 +262,7 @@ Right-align whenever the cell value is fundamentally quantitative—numbers, dec
260
262
 
261
263
  `list` layout:
262
264
 
263
- - None
265
+ - `density`: one of `comfortable`, `balanced`, or `compact`. Configures the size and spacing of the layout.
264
266
 
265
267
  `activity` layout:
266
268
 
@@ -400,7 +402,7 @@ What text to show in the search input. "Search" by default.
400
402
 
401
403
  Whether the data is loading. `false` by default.
402
404
 
403
- #### `defaultLayouts`: `Record< string, view >`
405
+ #### `defaultLayouts`: `Object`
404
406
 
405
407
  This property limits the available layout and provides layout information about active view types. If empty, this enables all layout types (see "Layout Types") with empty layout data.
406
408
 
@@ -417,7 +419,7 @@ const defaultLayouts = {
417
419
  };
418
420
  ```
419
421
 
420
- The `defaultLayouts` property should be an object that includes properties named `table`, `grid`, `list`, and `activity`. These properties are applied to the view object each time the user switches to the corresponding layout.
422
+ The `defaultLayouts` property should be an object that includes properties named `table`, `grid`, `list`, `activity`, `pickerTable`, and `pickerGrid`. These properties are applied to the view object each time the user switches to the corresponding layout.
421
423
 
422
424
  #### `selection`: `string[]`
423
425
 
@@ -823,7 +825,7 @@ const fields = [
823
825
  ];
824
826
  ```
825
827
 
826
- #### `form`: `Object[]`
828
+ #### `form`: `Object`
827
829
 
828
830
  - `layout`: an object describing the layout used to render the top-level fields present in `fields`. See `layout` prop in "Form Field API".
829
831
  - `fields`: a list of fields ids that should be rendered. Field ids can also be defined as an object and allow you to define a `layout`, `labelPosition` or `children` if displaying combined fields. See "Form Field API" for a description of every property.
@@ -893,7 +895,9 @@ return (
893
895
 
894
896
  Object that determines the validation status of each field. There's a `useFormValidity` hook that can be used to create the validity object — see the utility below. This section documents the `validity` object in case you want to create it via other means.
895
897
 
896
- The top-level props of the `validity` object are the field IDs. Fields declare their validity status for each of the validation rules supported: `required`, `elements`, `custom`. If a rule is valid, it should not be present in the object; if a field is valid for all the rules, it should not be present in the object either.
898
+ The top-level props of the `validity` object are the field IDs. Fields declare their validity status for each of the validation rules supported: `required`, `elements`, `pattern`, `minLength`, `maxLength`, `min`, `max`, `custom`. If a rule is valid, it should not be present in the object; if a field is valid for all the rules, it should not be present in the object either.
899
+
900
+ A field's validity can also contain a `children` property (`Record<string, FieldValidity>`) for nested field validity when using combined fields.
897
901
 
898
902
  For example:
899
903
 
@@ -910,6 +914,32 @@ For example:
910
914
  "message": "Value must be one of the elements."
911
915
  }
912
916
  },
917
+ "slug": {
918
+ "pattern": {
919
+ "type": "invalid",
920
+ "message": "Must match the required pattern."
921
+ }
922
+ },
923
+ "description": {
924
+ "minLength": {
925
+ "type": "invalid",
926
+ "message": "Must be at least 10 characters."
927
+ },
928
+ "maxLength": {
929
+ "type": "invalid",
930
+ "message": "Must be at most 200 characters."
931
+ }
932
+ },
933
+ "price": {
934
+ "min": {
935
+ "type": "invalid",
936
+ "message": "Must be at least 0."
937
+ },
938
+ "max": {
939
+ "type": "invalid",
940
+ "message": "Must be at most 9999."
941
+ }
942
+ },
913
943
  "publisher": {
914
944
  "custom": {
915
945
  "type": "validating",
@@ -982,6 +1012,26 @@ Returns an object containing:
982
1012
  type: 'invalid',
983
1013
  message: 'Value must be one of the elements.' // Optional
984
1014
  },
1015
+ pattern: {
1016
+ type: 'invalid',
1017
+ message: 'Must match the required pattern.'
1018
+ },
1019
+ minLength: {
1020
+ type: 'invalid',
1021
+ message: 'Must be at least 10 characters.'
1022
+ },
1023
+ maxLength: {
1024
+ type: 'invalid',
1025
+ message: 'Must be at most 200 characters.'
1026
+ },
1027
+ min: {
1028
+ type: 'invalid',
1029
+ message: 'Must be at least 0.'
1030
+ },
1031
+ max: {
1032
+ type: 'invalid',
1033
+ message: 'Must be at most 9999.'
1034
+ },
985
1035
  custom: {
986
1036
  type: 'validating',
987
1037
  message: 'Validating...'
@@ -1084,7 +1134,7 @@ Function that performs the required action.
1084
1134
 
1085
1135
  ```js
1086
1136
  {
1087
- callback: ( items, { onActionPerformed } ) => {
1137
+ callback: ( items, { registry, onActionPerformed } ) => {
1088
1138
  // Perform action.
1089
1139
  onActionPerformed?.( items );
1090
1140
  };
@@ -1231,7 +1281,7 @@ Example:
1231
1281
 
1232
1282
  React element used by some layouts (table, grid) to display the field name — useful to add icons, etc.
1233
1283
 
1234
- - Type: React element.
1284
+ - Type: `string` | React element.
1235
1285
  - Optional.
1236
1286
  - Defaults to the `label` value.
1237
1287
 
@@ -1533,6 +1583,8 @@ Finally, the field author can always provide its own custom `Edit` control. It r
1533
1583
  - `field`: the field definition
1534
1584
  - `onChange`: the callback with the updates
1535
1585
  - `hideLabelFromVision`: boolean representing if the label should be hidden
1586
+ - `markWhenOptional`: boolean indicating whether to label the control as "optional" when the field is not required, instead of showing "required"
1587
+ - `operator`: the currently selected filter operator for this field. Used by DataViews filters to determine which control to render based on the operator type
1536
1588
  - `validity`: object representing the validity of the field's value (see validity section)
1537
1589
  - `config`: object representing extra config for the component:
1538
1590
  - `prefix`: a React component to be rendered as a prefix
@@ -1621,6 +1673,11 @@ Object that contains the validation rules for the field. If a rule is not met, t
1621
1673
 
1622
1674
  - `required`: boolean indicating whether the field is required or not. Disabled by default.
1623
1675
  - `elements`: boolean restricting selection to the provided list of elements only. Enabled by default. The `array` Edit control uses it to restrict the input values.
1676
+ - `pattern`: a regex pattern string that the field value must match.
1677
+ - `minLength`: minimum string length for the field value.
1678
+ - `maxLength`: maximum string length for the field value.
1679
+ - `min`: minimum numeric value for the field.
1680
+ - `max`: maximum numeric value for the field.
1624
1681
  - `custom`: a function that validates a field's value. If the value is invalid, the function should return a string explaining why the value is invalid. Otherwise, the function must return null.
1625
1682
 
1626
1683
  Fields that define a type come with default validation for the type. For example, the `integer` type ensures that the value is a valid integer:
@@ -1952,11 +2009,30 @@ Valid operators per field type:
1952
2009
 
1953
2010
  ### `format`
1954
2011
 
1955
- Display format configuration for fields. Supported for date, number, and integer fields. This configuration affects how the field is displayed in the `render` method, the `Edit` control, and filter controls.
2012
+ Display format configuration for fields. Supported for `datetime`, `date`, `number`, and `integer` fields. This configuration affects how the field is displayed in the `render` method, the `Edit` control, and filter controls.
1956
2013
 
1957
2014
  - Type: `object`.
1958
2015
  - Optional.
1959
2016
 
2017
+ For `datetime` fields:
2018
+ - Properties:
2019
+ - `datetime`: The format string using PHP date format (e.g., `'M j, Y g:i a'` for `'Jan 1, 2021 2:30 pm'`). Optional, defaults to WordPress date format settings.
2020
+ - `weekStartsOn`: Specifies the first day of the week for calendar controls. One of 0, 1, 2, 3, 4, 5, 6. Optional, defaults to WordPress "Week Starts On" setting, whose value is 0 (Sunday).
2021
+
2022
+ Example:
2023
+
2024
+ ```js
2025
+ {
2026
+ id: 'createdAt',
2027
+ type: 'datetime',
2028
+ label: 'Created At',
2029
+ format: {
2030
+ datetime: 'M j, Y g:i a',
2031
+ weekStartsOn: 1,
2032
+ },
2033
+ }
2034
+ ```
2035
+
1960
2036
  For `date` fields:
1961
2037
  - Properties:
1962
2038
  - `date`: The format string using PHP date format (e.g., 'F j, Y' for 'March 10, 2023'). Optional, defaults to WordPress "Date Format" setting.
@@ -2035,7 +2111,7 @@ Example:
2035
2111
 
2036
2112
  ### `layout`
2037
2113
 
2038
- Represents the type of layout used to render the field. It'll be one of Regular, Panel, Card, or Row. This prop is the same as the `form.layout` prop.
2114
+ Represents the type of layout used to render the field. It'll be one of Regular, Panel, Card, Row, or Details. This prop is the same as the `form.layout` prop.
2039
2115
 
2040
2116
  #### Regular
2041
2117
 
@@ -2116,6 +2192,7 @@ For example:
2116
2192
 
2117
2193
  - `type`: `row`. Required.
2118
2194
  - `alignment`: one of `start`, `center`, or `end`. Optional. `center` by default.
2195
+ - `styles`: an object mapping field IDs to style objects. Each style object supports a `flex` property (any valid CSS `flex` value) to control how the field sizes within the row. Optional.
2119
2196
 
2120
2197
  The Row layout displays fields horizontally in a single row. It's particularly useful for grouping related fields that should be displayed side by side. This layout can be used both as a top-level form layout and for individual field groups.
2121
2198
 
@@ -2126,7 +2203,30 @@ For example:
2126
2203
  id: 'field_id',
2127
2204
  layout: {
2128
2205
  type: 'row',
2129
- alignment: 'start'
2206
+ alignment: 'start',
2207
+ styles: {
2208
+ field1: { flex: '1 1 auto' },
2209
+ field2: { flex: '0 0 200px' },
2210
+ },
2211
+ },
2212
+ }
2213
+ ```
2214
+
2215
+ #### Details
2216
+
2217
+ - `type`: `details`. Required.
2218
+ - `summary`: Summary field configuration. Optional. Specifies which field to display in the details summary. A string (single field ID)
2219
+
2220
+ The Details layout renders the field inside a collapsible `<details>` HTML element. The `summary` property controls the text shown in the disclosure summary.
2221
+
2222
+ For example:
2223
+
2224
+ ```js
2225
+ {
2226
+ id: 'field_id',
2227
+ layout: {
2228
+ type: 'details',
2229
+ summary: 'summaryFieldId'
2130
2230
  },
2131
2231
  }
2132
2232
  ```
@@ -2147,6 +2247,24 @@ Example:
2147
2247
  }
2148
2248
  ```
2149
2249
 
2250
+ ### `description`
2251
+
2252
+ A string describing the form field's purpose or usage. Used to provide additional context.
2253
+
2254
+ - Type: `string`.
2255
+ - Optional.
2256
+
2257
+ Example:
2258
+
2259
+ ```js
2260
+ {
2261
+ id: 'field_id',
2262
+ label: 'Status & Visibility',
2263
+ description: 'Control the publish status and visibility of the post.',
2264
+ children: [ 'status', 'password' ],
2265
+ }
2266
+ ```
2267
+
2150
2268
  ### `children`
2151
2269
 
2152
2270
  Groups a set of fields defined within children. For example if you want to display multiple fields within the Panel dropdown you can use children ( see example ).
@@ -36,7 +36,6 @@ module.exports = __toCommonJS(card_exports);
36
36
  var import_components = require("@wordpress/components");
37
37
  var import_compose = require("@wordpress/compose");
38
38
  var import_element = require("@wordpress/element");
39
- var import_i18n = require("@wordpress/i18n");
40
39
  var import_icons = require("@wordpress/icons");
41
40
  var import__ = require("../index.cjs");
42
41
  var import_dataform_context = __toESM(require("../../dataform-context/index.cjs"));
@@ -82,10 +81,9 @@ function FormCardField({
82
81
  const { fields } = (0, import_element.useContext)(import_dataform_context.default);
83
82
  const layout = field.layout;
84
83
  const cardBodyRef = (0, import_element.useRef)(null);
85
- const bodyId = (0, import_compose.useInstanceId)(
86
- FormCardField,
87
- "dataforms-layouts-card-card-body"
88
- );
84
+ const instanceId = (0, import_compose.useInstanceId)(FormCardField);
85
+ const bodyId = `dataforms-layouts-card-card-body-${instanceId}`;
86
+ const titleId = `dataforms-layouts-card-card-title-${instanceId}`;
89
87
  const form = (0, import_element.useMemo)(
90
88
  () => ({
91
89
  layout: import_normalize_form.DEFAULT_LAYOUT,
@@ -195,7 +193,14 @@ function FormCardField({
195
193
  alignItems: "center"
196
194
  },
197
195
  children: [
198
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dataforms-layouts-card__field-header-label", children: label }),
196
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
197
+ "span",
198
+ {
199
+ id: titleId,
200
+ className: "dataforms-layouts-card__field-header-label",
201
+ children: label
202
+ }
203
+ ),
199
204
  validationBadge,
200
205
  visibleSummaryFields.length > 0 && layout.withHeader && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dataforms-layouts-card__field-summary", children: visibleSummaryFields.map(
201
206
  (summaryField) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -218,7 +223,7 @@ function FormCardField({
218
223
  icon: isOpen ? import_icons.chevronUp : import_icons.chevronDown,
219
224
  "aria-expanded": isOpen,
220
225
  "aria-controls": bodyId,
221
- "aria-label": isOpen ? (0, import_i18n.__)("Collapse") : (0, import_i18n.__)("Expand")
226
+ "aria-labelledby": titleId
222
227
  }
223
228
  )
224
229
  ]
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/components/dataform-layouts/card/index.tsx"],
4
- "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport {\n\tButton,\n\tCard,\n\tCardBody,\n\tCardHeader as OriginalCardHeader,\n} from '@wordpress/components';\nimport { useInstanceId } from '@wordpress/compose';\nimport {\n\tuseCallback,\n\tuseContext,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from '@wordpress/element';\nimport { __ } from '@wordpress/i18n';\nimport { chevronDown, chevronUp } from '@wordpress/icons';\n\n/**\n * Internal dependencies\n */\nimport { getFormFieldLayout } from '..';\nimport DataFormContext from '../../dataform-context';\nimport type {\n\tFieldLayoutProps,\n\tNormalizedCardLayout,\n\tNormalizedField,\n\tNormalizedForm,\n\tNormalizedLayout,\n} from '../../../types';\nimport { DataFormLayout } from '../data-form-layout';\nimport { DEFAULT_LAYOUT } from '../normalize-form';\nimport { getSummaryFields } from '../get-summary-fields';\nimport useReportValidity from '../../../hooks/use-report-validity';\nimport ValidationBadge from '../validation-badge';\n\nfunction isSummaryFieldVisible< Item >(\n\tsummaryField: NormalizedField< Item >,\n\tsummaryConfig: NormalizedCardLayout[ 'summary' ],\n\tisOpen: boolean\n) {\n\t// If no summary config, dont't show any fields\n\tif (\n\t\t! summaryConfig ||\n\t\t( Array.isArray( summaryConfig ) && summaryConfig.length === 0 )\n\t) {\n\t\treturn false;\n\t}\n\n\t// Convert to array for consistent handling\n\tconst summaryConfigArray = Array.isArray( summaryConfig )\n\t\t? summaryConfig\n\t\t: [ summaryConfig ];\n\n\t// Find the config for this specific field\n\tconst fieldConfig = summaryConfigArray.find( ( config ) => {\n\t\tif ( typeof config === 'string' ) {\n\t\t\treturn config === summaryField.id;\n\t\t}\n\t\tif ( typeof config === 'object' && 'id' in config ) {\n\t\t\treturn config.id === summaryField.id;\n\t\t}\n\t\treturn false;\n\t} );\n\n\t// If field is not in summary config, don't show it\n\tif ( ! fieldConfig ) {\n\t\treturn false;\n\t}\n\n\t// If it's a string, always show it\n\tif ( typeof fieldConfig === 'string' ) {\n\t\treturn true;\n\t}\n\n\t// If it has visibility rules, respect them\n\tif ( typeof fieldConfig === 'object' && 'visibility' in fieldConfig ) {\n\t\treturn (\n\t\t\tfieldConfig.visibility === 'always' ||\n\t\t\t( fieldConfig.visibility === 'when-collapsed' && ! isOpen )\n\t\t);\n\t}\n\n\t// Default to always show\n\treturn true;\n}\n\nexport default function FormCardField< Item >( {\n\tdata,\n\tfield,\n\tonChange,\n\thideLabelFromVision,\n\tmarkWhenOptional,\n\tvalidity,\n}: FieldLayoutProps< Item > ) {\n\tconst { fields } = useContext( DataFormContext );\n\tconst layout = field.layout as NormalizedCardLayout;\n\tconst cardBodyRef = useRef< HTMLDivElement >( null );\n\tconst bodyId = useInstanceId(\n\t\tFormCardField,\n\t\t'dataforms-layouts-card-card-body'\n\t);\n\n\tconst form: NormalizedForm = useMemo(\n\t\t() => ( {\n\t\t\tlayout: DEFAULT_LAYOUT as NormalizedLayout,\n\t\t\tfields: field.children ?? [],\n\t\t} ),\n\t\t[ field ]\n\t);\n\n\tconst { isOpened, isCollapsible } = layout;\n\tconst [ internalIsOpen, setIsOpen ] = useState( isOpened );\n\tconst [ touched, setTouched ] = useState( false );\n\n\t// Sync internal state when the isOpened prop changes.\n\t// This is unlikely to happen in production, but it helps with storybook controls.\n\tuseEffect( () => {\n\t\tsetIsOpen( isOpened );\n\t}, [ isOpened ] );\n\n\tconst toggle = useCallback( () => {\n\t\tsetIsOpen( ( prev ) => {\n\t\t\t// Mark as touched when collapsing (going from open to closed)\n\t\t\tif ( prev ) {\n\t\t\t\tsetTouched( true );\n\t\t\t}\n\t\t\treturn ! prev;\n\t\t} );\n\t}, [] );\n\n\tconst isOpen = isCollapsible ? internalIsOpen : true;\n\n\t// Mark the card as touched when any field inside it is blurred.\n\t// This aligns with how validated controls show errors on blur.\n\tconst handleBlur = useCallback( () => {\n\t\tsetTouched( true );\n\t}, [ setTouched ] );\n\n\t// When the card is expanded after being touched (collapsed with errors),\n\t// trigger reportValidity to show field-level errors.\n\tuseReportValidity( cardBodyRef, isOpen && touched );\n\n\tconst summaryFields = getSummaryFields< Item >( layout.summary, fields );\n\n\tconst visibleSummaryFields = summaryFields.filter( ( summaryField ) =>\n\t\tisSummaryFieldVisible( summaryField, layout.summary, isOpen )\n\t);\n\n\tconst validationBadge =\n\t\ttouched && layout.isCollapsible ? (\n\t\t\t<ValidationBadge validity={ validity } />\n\t\t) : null;\n\n\tconst sizeCard = {\n\t\tblockStart: 'medium' as const,\n\t\tblockEnd: 'medium' as const,\n\t\tinlineStart: 'medium' as const,\n\t\tinlineEnd: 'medium' as const,\n\t};\n\n\tlet label = field.label;\n\tlet withHeader: boolean;\n\tlet bodyContent: React.ReactNode;\n\n\tif ( field.children ) {\n\t\twithHeader = !! label && layout.withHeader;\n\t\tbodyContent = (\n\t\t\t<>\n\t\t\t\t{ field.description && (\n\t\t\t\t\t<div className=\"dataforms-layouts-card__field-description\">\n\t\t\t\t\t\t{ field.description }\n\t\t\t\t\t</div>\n\t\t\t\t) }\n\t\t\t\t<DataFormLayout\n\t\t\t\t\tdata={ data }\n\t\t\t\t\tform={ form }\n\t\t\t\t\tonChange={ onChange }\n\t\t\t\t\tvalidity={ validity?.children }\n\t\t\t\t/>\n\t\t\t</>\n\t\t);\n\t} else {\n\t\tconst fieldDefinition = fields.find(\n\t\t\t( fieldDef ) => fieldDef.id === field.id\n\t\t);\n\n\t\tif ( ! fieldDefinition || ! fieldDefinition.Edit ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst SingleFieldLayout = getFormFieldLayout( 'regular' )?.component;\n\t\tif ( ! SingleFieldLayout ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tlabel = fieldDefinition.label;\n\t\twithHeader = !! label && layout.withHeader;\n\t\tbodyContent = (\n\t\t\t<SingleFieldLayout\n\t\t\t\tdata={ data }\n\t\t\t\tfield={ field }\n\t\t\t\tonChange={ onChange }\n\t\t\t\thideLabelFromVision={ hideLabelFromVision || withHeader }\n\t\t\t\tmarkWhenOptional={ markWhenOptional }\n\t\t\t\tvalidity={ validity }\n\t\t\t/>\n\t\t);\n\t}\n\n\tconst sizeCardBody = {\n\t\tblockStart: withHeader ? ( 'none' as const ) : ( 'medium' as const ),\n\t\tblockEnd: 'medium' as const,\n\t\tinlineStart: 'medium' as const,\n\t\tinlineEnd: 'medium' as const,\n\t};\n\n\treturn (\n\t\t<Card className=\"dataforms-layouts-card__field\" size={ sizeCard }>\n\t\t\t{ withHeader && (\n\t\t\t\t<OriginalCardHeader\n\t\t\t\t\tclassName=\"dataforms-layouts-card__field-header\"\n\t\t\t\t\tonClick={ isCollapsible ? toggle : undefined }\n\t\t\t\t\tstyle={ {\n\t\t\t\t\t\tcursor: isCollapsible ? 'pointer' : undefined,\n\t\t\t\t\t} }\n\t\t\t\t\tisBorderless\n\t\t\t\t>\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={ {\n\t\t\t\t\t\t\t// Match the expand/collapse button's height to avoid layout\n\t\t\t\t\t\t\t// differences when that button is not displayed.\n\t\t\t\t\t\t\theight: isCollapsible ? undefined : '40px',\n\t\t\t\t\t\t\twidth: '100%',\n\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\tjustifyContent: 'space-between',\n\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t} }\n\t\t\t\t\t>\n\t\t\t\t\t\t<span className=\"dataforms-layouts-card__field-header-label\">\n\t\t\t\t\t\t\t{ label }\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t{ validationBadge }\n\t\t\t\t\t\t{ visibleSummaryFields.length > 0 &&\n\t\t\t\t\t\t\tlayout.withHeader && (\n\t\t\t\t\t\t\t\t<div className=\"dataforms-layouts-card__field-summary\">\n\t\t\t\t\t\t\t\t\t{ visibleSummaryFields.map(\n\t\t\t\t\t\t\t\t\t\t( summaryField ) => (\n\t\t\t\t\t\t\t\t\t\t\t<summaryField.render\n\t\t\t\t\t\t\t\t\t\t\t\tkey={ summaryField.id }\n\t\t\t\t\t\t\t\t\t\t\t\titem={ data }\n\t\t\t\t\t\t\t\t\t\t\t\tfield={ summaryField }\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t) }\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t) }\n\t\t\t\t\t</div>\n\t\t\t\t\t{ isCollapsible && (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t__next40pxDefaultSize\n\t\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t\ticon={ isOpen ? chevronUp : chevronDown }\n\t\t\t\t\t\t\taria-expanded={ isOpen }\n\t\t\t\t\t\t\taria-controls={ bodyId }\n\t\t\t\t\t\t\taria-label={\n\t\t\t\t\t\t\t\tisOpen ? __( 'Collapse' ) : __( 'Expand' )\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t) }\n\t\t\t\t</OriginalCardHeader>\n\t\t\t) }\n\t\t\t{ ( isOpen || ! withHeader ) && (\n\t\t\t\t// If it doesn't have a header, keep it open.\n\t\t\t\t// Otherwise, the card will not be visible.\n\t\t\t\t<CardBody\n\t\t\t\t\tid={ bodyId }\n\t\t\t\t\tsize={ sizeCardBody }\n\t\t\t\t\tclassName=\"dataforms-layouts-card__field-control\"\n\t\t\t\t\tref={ cardBodyRef }\n\t\t\t\t\tonBlur={ handleBlur }\n\t\t\t\t>\n\t\t\t\t\t{ bodyContent }\n\t\t\t\t</CardBody>\n\t\t\t) }\n\t\t</Card>\n\t);\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport {\n\tButton,\n\tCard,\n\tCardBody,\n\tCardHeader as OriginalCardHeader,\n} from '@wordpress/components';\nimport { useInstanceId } from '@wordpress/compose';\nimport {\n\tuseCallback,\n\tuseContext,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from '@wordpress/element';\nimport { chevronDown, chevronUp } from '@wordpress/icons';\n\n/**\n * Internal dependencies\n */\nimport { getFormFieldLayout } from '..';\nimport DataFormContext from '../../dataform-context';\nimport type {\n\tFieldLayoutProps,\n\tNormalizedCardLayout,\n\tNormalizedField,\n\tNormalizedForm,\n\tNormalizedLayout,\n} from '../../../types';\nimport { DataFormLayout } from '../data-form-layout';\nimport { DEFAULT_LAYOUT } from '../normalize-form';\nimport { getSummaryFields } from '../get-summary-fields';\nimport useReportValidity from '../../../hooks/use-report-validity';\nimport ValidationBadge from '../validation-badge';\n\nfunction isSummaryFieldVisible< Item >(\n\tsummaryField: NormalizedField< Item >,\n\tsummaryConfig: NormalizedCardLayout[ 'summary' ],\n\tisOpen: boolean\n) {\n\t// If no summary config, dont't show any fields\n\tif (\n\t\t! summaryConfig ||\n\t\t( Array.isArray( summaryConfig ) && summaryConfig.length === 0 )\n\t) {\n\t\treturn false;\n\t}\n\n\t// Convert to array for consistent handling\n\tconst summaryConfigArray = Array.isArray( summaryConfig )\n\t\t? summaryConfig\n\t\t: [ summaryConfig ];\n\n\t// Find the config for this specific field\n\tconst fieldConfig = summaryConfigArray.find( ( config ) => {\n\t\tif ( typeof config === 'string' ) {\n\t\t\treturn config === summaryField.id;\n\t\t}\n\t\tif ( typeof config === 'object' && 'id' in config ) {\n\t\t\treturn config.id === summaryField.id;\n\t\t}\n\t\treturn false;\n\t} );\n\n\t// If field is not in summary config, don't show it\n\tif ( ! fieldConfig ) {\n\t\treturn false;\n\t}\n\n\t// If it's a string, always show it\n\tif ( typeof fieldConfig === 'string' ) {\n\t\treturn true;\n\t}\n\n\t// If it has visibility rules, respect them\n\tif ( typeof fieldConfig === 'object' && 'visibility' in fieldConfig ) {\n\t\treturn (\n\t\t\tfieldConfig.visibility === 'always' ||\n\t\t\t( fieldConfig.visibility === 'when-collapsed' && ! isOpen )\n\t\t);\n\t}\n\n\t// Default to always show\n\treturn true;\n}\n\nexport default function FormCardField< Item >( {\n\tdata,\n\tfield,\n\tonChange,\n\thideLabelFromVision,\n\tmarkWhenOptional,\n\tvalidity,\n}: FieldLayoutProps< Item > ) {\n\tconst { fields } = useContext( DataFormContext );\n\tconst layout = field.layout as NormalizedCardLayout;\n\tconst cardBodyRef = useRef< HTMLDivElement >( null );\n\tconst instanceId = useInstanceId( FormCardField );\n\tconst bodyId = `dataforms-layouts-card-card-body-${ instanceId }`;\n\tconst titleId = `dataforms-layouts-card-card-title-${ instanceId }`;\n\n\tconst form: NormalizedForm = useMemo(\n\t\t() => ( {\n\t\t\tlayout: DEFAULT_LAYOUT as NormalizedLayout,\n\t\t\tfields: field.children ?? [],\n\t\t} ),\n\t\t[ field ]\n\t);\n\n\tconst { isOpened, isCollapsible } = layout;\n\tconst [ internalIsOpen, setIsOpen ] = useState( isOpened );\n\tconst [ touched, setTouched ] = useState( false );\n\n\t// Sync internal state when the isOpened prop changes.\n\t// This is unlikely to happen in production, but it helps with storybook controls.\n\tuseEffect( () => {\n\t\tsetIsOpen( isOpened );\n\t}, [ isOpened ] );\n\n\tconst toggle = useCallback( () => {\n\t\tsetIsOpen( ( prev ) => {\n\t\t\t// Mark as touched when collapsing (going from open to closed)\n\t\t\tif ( prev ) {\n\t\t\t\tsetTouched( true );\n\t\t\t}\n\t\t\treturn ! prev;\n\t\t} );\n\t}, [] );\n\n\tconst isOpen = isCollapsible ? internalIsOpen : true;\n\n\t// Mark the card as touched when any field inside it is blurred.\n\t// This aligns with how validated controls show errors on blur.\n\tconst handleBlur = useCallback( () => {\n\t\tsetTouched( true );\n\t}, [ setTouched ] );\n\n\t// When the card is expanded after being touched (collapsed with errors),\n\t// trigger reportValidity to show field-level errors.\n\tuseReportValidity( cardBodyRef, isOpen && touched );\n\n\tconst summaryFields = getSummaryFields< Item >( layout.summary, fields );\n\n\tconst visibleSummaryFields = summaryFields.filter( ( summaryField ) =>\n\t\tisSummaryFieldVisible( summaryField, layout.summary, isOpen )\n\t);\n\n\tconst validationBadge =\n\t\ttouched && layout.isCollapsible ? (\n\t\t\t<ValidationBadge validity={ validity } />\n\t\t) : null;\n\n\tconst sizeCard = {\n\t\tblockStart: 'medium' as const,\n\t\tblockEnd: 'medium' as const,\n\t\tinlineStart: 'medium' as const,\n\t\tinlineEnd: 'medium' as const,\n\t};\n\n\tlet label = field.label;\n\tlet withHeader: boolean;\n\tlet bodyContent: React.ReactNode;\n\n\tif ( field.children ) {\n\t\twithHeader = !! label && layout.withHeader;\n\t\tbodyContent = (\n\t\t\t<>\n\t\t\t\t{ field.description && (\n\t\t\t\t\t<div className=\"dataforms-layouts-card__field-description\">\n\t\t\t\t\t\t{ field.description }\n\t\t\t\t\t</div>\n\t\t\t\t) }\n\t\t\t\t<DataFormLayout\n\t\t\t\t\tdata={ data }\n\t\t\t\t\tform={ form }\n\t\t\t\t\tonChange={ onChange }\n\t\t\t\t\tvalidity={ validity?.children }\n\t\t\t\t/>\n\t\t\t</>\n\t\t);\n\t} else {\n\t\tconst fieldDefinition = fields.find(\n\t\t\t( fieldDef ) => fieldDef.id === field.id\n\t\t);\n\n\t\tif ( ! fieldDefinition || ! fieldDefinition.Edit ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst SingleFieldLayout = getFormFieldLayout( 'regular' )?.component;\n\t\tif ( ! SingleFieldLayout ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tlabel = fieldDefinition.label;\n\t\twithHeader = !! label && layout.withHeader;\n\t\tbodyContent = (\n\t\t\t<SingleFieldLayout\n\t\t\t\tdata={ data }\n\t\t\t\tfield={ field }\n\t\t\t\tonChange={ onChange }\n\t\t\t\thideLabelFromVision={ hideLabelFromVision || withHeader }\n\t\t\t\tmarkWhenOptional={ markWhenOptional }\n\t\t\t\tvalidity={ validity }\n\t\t\t/>\n\t\t);\n\t}\n\n\tconst sizeCardBody = {\n\t\tblockStart: withHeader ? ( 'none' as const ) : ( 'medium' as const ),\n\t\tblockEnd: 'medium' as const,\n\t\tinlineStart: 'medium' as const,\n\t\tinlineEnd: 'medium' as const,\n\t};\n\n\treturn (\n\t\t<Card className=\"dataforms-layouts-card__field\" size={ sizeCard }>\n\t\t\t{ withHeader && (\n\t\t\t\t<OriginalCardHeader\n\t\t\t\t\tclassName=\"dataforms-layouts-card__field-header\"\n\t\t\t\t\tonClick={ isCollapsible ? toggle : undefined }\n\t\t\t\t\tstyle={ {\n\t\t\t\t\t\tcursor: isCollapsible ? 'pointer' : undefined,\n\t\t\t\t\t} }\n\t\t\t\t\tisBorderless\n\t\t\t\t>\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={ {\n\t\t\t\t\t\t\t// Match the expand/collapse button's height to avoid layout\n\t\t\t\t\t\t\t// differences when that button is not displayed.\n\t\t\t\t\t\t\theight: isCollapsible ? undefined : '40px',\n\t\t\t\t\t\t\twidth: '100%',\n\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\tjustifyContent: 'space-between',\n\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t} }\n\t\t\t\t\t>\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tid={ titleId }\n\t\t\t\t\t\t\tclassName=\"dataforms-layouts-card__field-header-label\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{ label }\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t{ validationBadge }\n\t\t\t\t\t\t{ visibleSummaryFields.length > 0 &&\n\t\t\t\t\t\t\tlayout.withHeader && (\n\t\t\t\t\t\t\t\t<div className=\"dataforms-layouts-card__field-summary\">\n\t\t\t\t\t\t\t\t\t{ visibleSummaryFields.map(\n\t\t\t\t\t\t\t\t\t\t( summaryField ) => (\n\t\t\t\t\t\t\t\t\t\t\t<summaryField.render\n\t\t\t\t\t\t\t\t\t\t\t\tkey={ summaryField.id }\n\t\t\t\t\t\t\t\t\t\t\t\titem={ data }\n\t\t\t\t\t\t\t\t\t\t\t\tfield={ summaryField }\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t) }\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t) }\n\t\t\t\t\t</div>\n\t\t\t\t\t{ isCollapsible && (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t__next40pxDefaultSize\n\t\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t\ticon={ isOpen ? chevronUp : chevronDown }\n\t\t\t\t\t\t\taria-expanded={ isOpen }\n\t\t\t\t\t\t\taria-controls={ bodyId }\n\t\t\t\t\t\t\taria-labelledby={ titleId }\n\t\t\t\t\t\t/>\n\t\t\t\t\t) }\n\t\t\t\t</OriginalCardHeader>\n\t\t\t) }\n\t\t\t{ ( isOpen || ! withHeader ) && (\n\t\t\t\t// If it doesn't have a header, keep it open.\n\t\t\t\t// Otherwise, the card will not be visible.\n\t\t\t\t<CardBody\n\t\t\t\t\tid={ bodyId }\n\t\t\t\t\tsize={ sizeCardBody }\n\t\t\t\t\tclassName=\"dataforms-layouts-card__field-control\"\n\t\t\t\t\tref={ cardBodyRef }\n\t\t\t\t\tonBlur={ handleBlur }\n\t\t\t\t>\n\t\t\t\t\t{ bodyContent }\n\t\t\t\t</CardBody>\n\t\t\t) }\n\t\t</Card>\n\t);\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["DataFormContext", "useReportValidity", "ValidationBadge", "OriginalCardHeader"]
7
7
  }
@@ -29,8 +29,8 @@ var import_jsx_runtime = require("react/jsx-runtime");
29
29
  function getLabelContent(showError, errorMessage, fieldLabel) {
30
30
  return showError ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.Tooltip, { text: errorMessage, placement: "top", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dataforms-layouts-panel__field-label-error-content", children: [
31
31
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.Icon, { icon: import_icons.error, size: 16 }),
32
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.BaseControl.VisualLabel, { children: fieldLabel })
33
- ] }) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.BaseControl.VisualLabel, { children: fieldLabel });
32
+ fieldLabel
33
+ ] }) }) : fieldLabel;
34
34
  }
35
35
  var get_label_content_default = getLabelContent;
36
36
  //# sourceMappingURL=get-label-content.cjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/components/dataform-layouts/panel/utils/get-label-content.tsx"],
4
- "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { BaseControl, Icon, Tooltip } from '@wordpress/components';\nimport { error as errorIcon } from '@wordpress/icons';\n\nfunction getLabelContent(\n\tshowError?: boolean,\n\terrorMessage?: string,\n\tfieldLabel?: string\n) {\n\treturn showError ? (\n\t\t<Tooltip text={ errorMessage } placement=\"top\">\n\t\t\t<span className=\"dataforms-layouts-panel__field-label-error-content\">\n\t\t\t\t<Icon icon={ errorIcon } size={ 16 } />\n\t\t\t\t<BaseControl.VisualLabel>\n\t\t\t\t\t{ fieldLabel }\n\t\t\t\t</BaseControl.VisualLabel>\n\t\t\t</span>\n\t\t</Tooltip>\n\t) : (\n\t\t<BaseControl.VisualLabel>{ fieldLabel }</BaseControl.VisualLabel>\n\t);\n}\n\nexport default getLabelContent;\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,wBAA2C;AAC3C,mBAAmC;AAShC;AAPH,SAAS,gBACR,WACA,cACA,YACC;AACD,SAAO,YACN,4CAAC,6BAAQ,MAAO,cAAe,WAAU,OACxC,uDAAC,UAAK,WAAU,sDACf;AAAA,gDAAC,0BAAK,MAAO,aAAAA,OAAY,MAAO,IAAK;AAAA,IACrC,4CAAC,8BAAY,aAAZ,EACE,sBACH;AAAA,KACD,GACD,IAEA,4CAAC,8BAAY,aAAZ,EAA0B,sBAAY;AAEzC;AAEA,IAAO,4BAAQ;",
4
+ "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { Icon, Tooltip } from '@wordpress/components';\nimport { error as errorIcon } from '@wordpress/icons';\n\nfunction getLabelContent(\n\tshowError?: boolean,\n\terrorMessage?: string,\n\tfieldLabel?: string\n) {\n\treturn showError ? (\n\t\t<Tooltip text={ errorMessage } placement=\"top\">\n\t\t\t<span className=\"dataforms-layouts-panel__field-label-error-content\">\n\t\t\t\t<Icon icon={ errorIcon } size={ 16 } />\n\t\t\t\t{ fieldLabel }\n\t\t\t</span>\n\t\t</Tooltip>\n\t) : (\n\t\tfieldLabel\n\t);\n}\n\nexport default getLabelContent;\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,wBAA8B;AAC9B,mBAAmC;AAShC;AAPH,SAAS,gBACR,WACA,cACA,YACC;AACD,SAAO,YACN,4CAAC,6BAAQ,MAAO,cAAe,WAAU,OACxC,uDAAC,UAAK,WAAU,sDACf;AAAA,gDAAC,0BAAK,MAAO,aAAAA,OAAY,MAAO,IAAK;AAAA,IACnC;AAAA,KACH,GACD,IAEA;AAEF;AAEA,IAAO,4BAAQ;",
6
6
  "names": ["errorIcon"]
7
7
  }
@@ -53,6 +53,7 @@ var DataViewsContext = (0, import_element.createContext)({
53
53
  isShowingFilter: false,
54
54
  setIsShowingFilter: () => {
55
55
  },
56
+ hasInitiallyLoaded: false,
56
57
  hasInfiniteScrollHandler: false,
57
58
  config: {
58
59
  perPageSizes: []
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/components/dataviews-context/index.ts"],
4
- "sourcesContent": ["/**\n * External dependencies\n */\nimport type { ComponentProps, ReactElement, ReactNode } from 'react';\n\n/**\n * WordPress dependencies\n */\nimport { createContext, createRef } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport type {\n\tView,\n\tAction,\n\tNormalizedField,\n\tSupportedLayouts,\n\tNormalizedFilter,\n} from '../../types';\nimport type { SetSelection } from '../../types/private';\nimport { LAYOUT_TABLE } from '../../constants';\n\ntype DataViewsContextType< Item > = {\n\tview: View;\n\tonChangeView: ( view: View ) => void;\n\tfields: NormalizedField< Item >[];\n\tactions?: Action< Item >[];\n\tdata: Item[];\n\tisLoading?: boolean;\n\tpaginationInfo: {\n\t\ttotalItems: number;\n\t\ttotalPages: number;\n\t};\n\tselection: string[];\n\tonChangeSelection: SetSelection;\n\topenedFilter: string | null;\n\tsetOpenedFilter: ( openedFilter: string | null ) => void;\n\tgetItemId: ( item: Item ) => string;\n\tgetItemLevel?: ( item: Item ) => number;\n\tonClickItem?: ( item: Item ) => void;\n\trenderItemLink?: (\n\t\tprops: {\n\t\t\titem: Item;\n\t\t} & ComponentProps< 'a' >\n\t) => ReactElement;\n\tisItemClickable: ( item: Item ) => boolean;\n\tcontainerWidth: number;\n\tcontainerRef: React.MutableRefObject< HTMLDivElement | null >;\n\tresizeObserverRef:\n\t\t| ( ( element?: HTMLDivElement | null ) => void )\n\t\t| React.RefObject< HTMLDivElement >;\n\tdefaultLayouts: SupportedLayouts;\n\tfilters: NormalizedFilter[];\n\tisShowingFilter: boolean;\n\tsetIsShowingFilter: ( value: boolean ) => void;\n\tconfig: { perPageSizes: number[] };\n\tempty?: ReactNode;\n\thasInfiniteScrollHandler: boolean;\n\titemListLabel?: string;\n\tonReset?: ( () => void ) | false;\n};\n\nconst DataViewsContext = createContext< DataViewsContextType< any > >( {\n\tview: { type: LAYOUT_TABLE },\n\tonChangeView: () => {},\n\tfields: [],\n\tdata: [],\n\tpaginationInfo: {\n\t\ttotalItems: 0,\n\t\ttotalPages: 0,\n\t},\n\tselection: [],\n\tonChangeSelection: () => {},\n\tsetOpenedFilter: () => {},\n\topenedFilter: null,\n\tgetItemId: ( item ) => item.id,\n\tisItemClickable: () => true,\n\trenderItemLink: undefined,\n\tcontainerWidth: 0,\n\tcontainerRef: createRef(),\n\tresizeObserverRef: () => {},\n\tdefaultLayouts: { list: {}, grid: {}, table: {} },\n\tfilters: [],\n\tisShowingFilter: false,\n\tsetIsShowingFilter: () => {},\n\thasInfiniteScrollHandler: false,\n\tconfig: {\n\t\tperPageSizes: [],\n\t},\n} );\n\nDataViewsContext.displayName = 'DataViewsContext';\n\nexport default DataViewsContext;\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,qBAAyC;AAazC,uBAA6B;AA0C7B,IAAM,uBAAmB,8BAA8C;AAAA,EACtE,MAAM,EAAE,MAAM,8BAAa;AAAA,EAC3B,cAAc,MAAM;AAAA,EAAC;AAAA,EACrB,QAAQ,CAAC;AAAA,EACT,MAAM,CAAC;AAAA,EACP,gBAAgB;AAAA,IACf,YAAY;AAAA,IACZ,YAAY;AAAA,EACb;AAAA,EACA,WAAW,CAAC;AAAA,EACZ,mBAAmB,MAAM;AAAA,EAAC;AAAA,EAC1B,iBAAiB,MAAM;AAAA,EAAC;AAAA,EACxB,cAAc;AAAA,EACd,WAAW,CAAE,SAAU,KAAK;AAAA,EAC5B,iBAAiB,MAAM;AAAA,EACvB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,kBAAc,0BAAU;AAAA,EACxB,mBAAmB,MAAM;AAAA,EAAC;AAAA,EAC1B,gBAAgB,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,OAAO,CAAC,EAAE;AAAA,EAChD,SAAS,CAAC;AAAA,EACV,iBAAiB;AAAA,EACjB,oBAAoB,MAAM;AAAA,EAAC;AAAA,EAC3B,0BAA0B;AAAA,EAC1B,QAAQ;AAAA,IACP,cAAc,CAAC;AAAA,EAChB;AACD,CAAE;AAEF,iBAAiB,cAAc;AAE/B,IAAO,4BAAQ;",
4
+ "sourcesContent": ["/**\n * External dependencies\n */\nimport type { ComponentProps, ReactElement, ReactNode } from 'react';\n\n/**\n * WordPress dependencies\n */\nimport { createContext, createRef } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport type {\n\tView,\n\tAction,\n\tNormalizedField,\n\tSupportedLayouts,\n\tNormalizedFilter,\n} from '../../types';\nimport type { SetSelection } from '../../types/private';\nimport { LAYOUT_TABLE } from '../../constants';\n\ntype DataViewsContextType< Item > = {\n\tview: View;\n\tonChangeView: ( view: View ) => void;\n\tfields: NormalizedField< Item >[];\n\tactions?: Action< Item >[];\n\tdata: Item[];\n\tisLoading?: boolean;\n\tpaginationInfo: {\n\t\ttotalItems: number;\n\t\ttotalPages: number;\n\t};\n\tselection: string[];\n\tonChangeSelection: SetSelection;\n\topenedFilter: string | null;\n\tsetOpenedFilter: ( openedFilter: string | null ) => void;\n\tgetItemId: ( item: Item ) => string;\n\tgetItemLevel?: ( item: Item ) => number;\n\tonClickItem?: ( item: Item ) => void;\n\trenderItemLink?: (\n\t\tprops: {\n\t\t\titem: Item;\n\t\t} & ComponentProps< 'a' >\n\t) => ReactElement;\n\tisItemClickable: ( item: Item ) => boolean;\n\tcontainerWidth: number;\n\tcontainerRef: React.MutableRefObject< HTMLDivElement | null >;\n\tresizeObserverRef:\n\t\t| ( ( element?: HTMLDivElement | null ) => void )\n\t\t| React.RefObject< HTMLDivElement >;\n\tdefaultLayouts: SupportedLayouts;\n\tfilters: NormalizedFilter[];\n\tisShowingFilter: boolean;\n\tsetIsShowingFilter: ( value: boolean ) => void;\n\tconfig: { perPageSizes: number[] };\n\tempty?: ReactNode;\n\thasInitiallyLoaded?: boolean;\n\thasInfiniteScrollHandler: boolean;\n\titemListLabel?: string;\n\tonReset?: ( () => void ) | false;\n};\n\nconst DataViewsContext = createContext< DataViewsContextType< any > >( {\n\tview: { type: LAYOUT_TABLE },\n\tonChangeView: () => {},\n\tfields: [],\n\tdata: [],\n\tpaginationInfo: {\n\t\ttotalItems: 0,\n\t\ttotalPages: 0,\n\t},\n\tselection: [],\n\tonChangeSelection: () => {},\n\tsetOpenedFilter: () => {},\n\topenedFilter: null,\n\tgetItemId: ( item ) => item.id,\n\tisItemClickable: () => true,\n\trenderItemLink: undefined,\n\tcontainerWidth: 0,\n\tcontainerRef: createRef(),\n\tresizeObserverRef: () => {},\n\tdefaultLayouts: { list: {}, grid: {}, table: {} },\n\tfilters: [],\n\tisShowingFilter: false,\n\tsetIsShowingFilter: () => {},\n\thasInitiallyLoaded: false,\n\thasInfiniteScrollHandler: false,\n\tconfig: {\n\t\tperPageSizes: [],\n\t},\n} );\n\nDataViewsContext.displayName = 'DataViewsContext';\n\nexport default DataViewsContext;\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,qBAAyC;AAazC,uBAA6B;AA2C7B,IAAM,uBAAmB,8BAA8C;AAAA,EACtE,MAAM,EAAE,MAAM,8BAAa;AAAA,EAC3B,cAAc,MAAM;AAAA,EAAC;AAAA,EACrB,QAAQ,CAAC;AAAA,EACT,MAAM,CAAC;AAAA,EACP,gBAAgB;AAAA,IACf,YAAY;AAAA,IACZ,YAAY;AAAA,EACb;AAAA,EACA,WAAW,CAAC;AAAA,EACZ,mBAAmB,MAAM;AAAA,EAAC;AAAA,EAC1B,iBAAiB,MAAM;AAAA,EAAC;AAAA,EACxB,cAAc;AAAA,EACd,WAAW,CAAE,SAAU,KAAK;AAAA,EAC5B,iBAAiB,MAAM;AAAA,EACvB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,kBAAc,0BAAU;AAAA,EACxB,mBAAmB,MAAM;AAAA,EAAC;AAAA,EAC1B,gBAAgB,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,OAAO,CAAC,EAAE;AAAA,EAChD,SAAS,CAAC;AAAA,EACV,iBAAiB;AAAA,EACjB,oBAAoB,MAAM;AAAA,EAAC;AAAA,EAC3B,oBAAoB;AAAA,EACpB,0BAA0B;AAAA,EAC1B,QAAQ;AAAA,IACP,cAAc,CAAC;AAAA,EAChB;AACD,CAAE;AAEF,iBAAiB,cAAc;AAE/B,IAAO,4BAAQ;",
6
6
  "names": []
7
7
  }
@@ -57,11 +57,10 @@ function FiltersToggle() {
57
57
  },
58
58
  [onChangeView, setIsShowingFilter]
59
59
  );
60
- const visibleFilters = filters.filter((filter) => filter.isVisible);
61
- const hasVisibleFilters = !!visibleFilters.length;
62
60
  if (filters.length === 0) {
63
61
  return null;
64
62
  }
63
+ const hasVisibleFilters = filters.some((filter) => filter.isVisible);
65
64
  const addFilterButtonProps = {
66
65
  label: (0, import_i18n.__)("Add filter"),
67
66
  "aria-expanded": false,
@@ -78,6 +77,9 @@ function FiltersToggle() {
78
77
  setIsShowingFilter(!isShowingFilter);
79
78
  }
80
79
  };
80
+ const hasPrimaryOrLockedFilters = filters.some(
81
+ (filter) => filter.isPrimary || filter.isLocked
82
+ );
81
83
  const buttonComponent = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
82
84
  import_components.Button,
83
85
  {
@@ -85,6 +87,8 @@ function FiltersToggle() {
85
87
  className: "dataviews-filters__visibility-toggle",
86
88
  size: "compact",
87
89
  icon: import_icons.funnel,
90
+ disabled: hasPrimaryOrLockedFilters,
91
+ accessibleWhenDisabled: true,
88
92
  ...hasVisibleFilters ? toggleFiltersButtonProps : addFilterButtonProps
89
93
  }
90
94
  );
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/components/dataviews-filters/toggle.tsx"],
4
- "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { useContext, useRef, useCallback, useEffect } from '@wordpress/element';\nimport { Button } from '@wordpress/components';\nimport { funnel } from '@wordpress/icons';\nimport { __, _x } from '@wordpress/i18n';\n\n/**\n * Internal dependencies\n */\nimport { AddFilterMenu } from './add-filter';\nimport DataViewsContext from '../dataviews-context';\nimport type { View } from '../../types';\n\nfunction FiltersToggle() {\n\tconst {\n\t\tfilters,\n\t\tview,\n\t\tonChangeView,\n\t\tsetOpenedFilter,\n\t\tisShowingFilter,\n\t\tsetIsShowingFilter,\n\t} = useContext( DataViewsContext );\n\n\tconst buttonRef = useRef< HTMLButtonElement >( null );\n\tconst onChangeViewWithFilterVisibility = useCallback(\n\t\t( _view: View ) => {\n\t\t\tonChangeView( _view );\n\t\t\tsetIsShowingFilter( true );\n\t\t},\n\t\t[ onChangeView, setIsShowingFilter ]\n\t);\n\tconst visibleFilters = filters.filter( ( filter ) => filter.isVisible );\n\n\tconst hasVisibleFilters = !! visibleFilters.length;\n\tif ( filters.length === 0 ) {\n\t\treturn null;\n\t}\n\n\tconst addFilterButtonProps = {\n\t\tlabel: __( 'Add filter' ),\n\t\t'aria-expanded': false,\n\t\tisPressed: false,\n\t};\n\tconst toggleFiltersButtonProps = {\n\t\tlabel: _x( 'Filter', 'verb' ),\n\t\t'aria-expanded': isShowingFilter,\n\t\tisPressed: isShowingFilter,\n\t\tonClick: () => {\n\t\t\tif ( ! isShowingFilter ) {\n\t\t\t\tsetOpenedFilter( null );\n\t\t\t}\n\t\t\tsetIsShowingFilter( ! isShowingFilter );\n\t\t},\n\t};\n\tconst buttonComponent = (\n\t\t<Button\n\t\t\tref={ buttonRef }\n\t\t\tclassName=\"dataviews-filters__visibility-toggle\"\n\t\t\tsize=\"compact\"\n\t\t\ticon={ funnel }\n\t\t\t{ ...( hasVisibleFilters\n\t\t\t\t? toggleFiltersButtonProps\n\t\t\t\t: addFilterButtonProps ) }\n\t\t/>\n\t);\n\treturn (\n\t\t<div className=\"dataviews-filters__container-visibility-toggle\">\n\t\t\t{ ! hasVisibleFilters ? (\n\t\t\t\t<AddFilterMenu\n\t\t\t\t\tfilters={ filters }\n\t\t\t\t\tview={ view }\n\t\t\t\t\tonChangeView={ onChangeViewWithFilterVisibility }\n\t\t\t\t\tsetOpenedFilter={ setOpenedFilter }\n\t\t\t\t\ttriggerProps={ { render: buttonComponent } }\n\t\t\t\t/>\n\t\t\t) : (\n\t\t\t\t<FilterVisibilityToggle\n\t\t\t\t\tbuttonRef={ buttonRef }\n\t\t\t\t\tfiltersCount={ view.filters?.length }\n\t\t\t\t>\n\t\t\t\t\t{ buttonComponent }\n\t\t\t\t</FilterVisibilityToggle>\n\t\t\t) }\n\t\t</div>\n\t);\n}\n\nfunction FilterVisibilityToggle( {\n\tbuttonRef,\n\tfiltersCount,\n\tchildren,\n}: {\n\tbuttonRef: React.RefObject< HTMLButtonElement | null >;\n\tfiltersCount?: number;\n\tchildren: React.ReactNode;\n} ) {\n\t// Focus the `add filter` button when unmounts.\n\tuseEffect(\n\t\t() => () => {\n\t\t\tbuttonRef.current?.focus();\n\t\t},\n\t\t[ buttonRef ]\n\t);\n\treturn (\n\t\t<>\n\t\t\t{ children }\n\t\t\t{ !! filtersCount && (\n\t\t\t\t<span className=\"dataviews-filters-toggle__count\">\n\t\t\t\t\t{ filtersCount }\n\t\t\t\t</span>\n\t\t\t) }\n\t\t</>\n\t);\n}\n\nexport default FiltersToggle;\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,qBAA2D;AAC3D,wBAAuB;AACvB,mBAAuB;AACvB,kBAAuB;AAKvB,wBAA8B;AAC9B,+BAA6B;AA6C3B;AA1CF,SAAS,gBAAgB;AACxB,QAAM;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,QAAI,2BAAY,yBAAAA,OAAiB;AAEjC,QAAM,gBAAY,uBAA6B,IAAK;AACpD,QAAM,uCAAmC;AAAA,IACxC,CAAE,UAAiB;AAClB,mBAAc,KAAM;AACpB,yBAAoB,IAAK;AAAA,IAC1B;AAAA,IACA,CAAE,cAAc,kBAAmB;AAAA,EACpC;AACA,QAAM,iBAAiB,QAAQ,OAAQ,CAAE,WAAY,OAAO,SAAU;AAEtE,QAAM,oBAAoB,CAAC,CAAE,eAAe;AAC5C,MAAK,QAAQ,WAAW,GAAI;AAC3B,WAAO;AAAA,EACR;AAEA,QAAM,uBAAuB;AAAA,IAC5B,WAAO,gBAAI,YAAa;AAAA,IACxB,iBAAiB;AAAA,IACjB,WAAW;AAAA,EACZ;AACA,QAAM,2BAA2B;AAAA,IAChC,WAAO,gBAAI,UAAU,MAAO;AAAA,IAC5B,iBAAiB;AAAA,IACjB,WAAW;AAAA,IACX,SAAS,MAAM;AACd,UAAK,CAAE,iBAAkB;AACxB,wBAAiB,IAAK;AAAA,MACvB;AACA,yBAAoB,CAAE,eAAgB;AAAA,IACvC;AAAA,EACD;AACA,QAAM,kBACL;AAAA,IAAC;AAAA;AAAA,MACA,KAAM;AAAA,MACN,WAAU;AAAA,MACV,MAAK;AAAA,MACL,MAAO;AAAA,MACL,GAAK,oBACJ,2BACA;AAAA;AAAA,EACJ;AAED,SACC,4CAAC,SAAI,WAAU,kDACZ,WAAE,oBACH;AAAA,IAAC;AAAA;AAAA,MACA;AAAA,MACA;AAAA,MACA,cAAe;AAAA,MACf;AAAA,MACA,cAAe,EAAE,QAAQ,gBAAgB;AAAA;AAAA,EAC1C,IAEA;AAAA,IAAC;AAAA;AAAA,MACA;AAAA,MACA,cAAe,KAAK,SAAS;AAAA,MAE3B;AAAA;AAAA,EACH,GAEF;AAEF;AAEA,SAAS,uBAAwB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AACD,GAII;AAEH;AAAA,IACC,MAAM,MAAM;AACX,gBAAU,SAAS,MAAM;AAAA,IAC1B;AAAA,IACA,CAAE,SAAU;AAAA,EACb;AACA,SACC,4EACG;AAAA;AAAA,IACA,CAAC,CAAE,gBACJ,4CAAC,UAAK,WAAU,mCACb,wBACH;AAAA,KAEF;AAEF;AAEA,IAAO,iBAAQ;",
4
+ "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { useContext, useRef, useCallback, useEffect } from '@wordpress/element';\nimport { Button } from '@wordpress/components';\nimport { funnel } from '@wordpress/icons';\nimport { __, _x } from '@wordpress/i18n';\n\n/**\n * Internal dependencies\n */\nimport { AddFilterMenu } from './add-filter';\nimport DataViewsContext from '../dataviews-context';\nimport type { View } from '../../types';\n\nfunction FiltersToggle() {\n\tconst {\n\t\tfilters,\n\t\tview,\n\t\tonChangeView,\n\t\tsetOpenedFilter,\n\t\tisShowingFilter,\n\t\tsetIsShowingFilter,\n\t} = useContext( DataViewsContext );\n\n\tconst buttonRef = useRef< HTMLButtonElement >( null );\n\tconst onChangeViewWithFilterVisibility = useCallback(\n\t\t( _view: View ) => {\n\t\t\tonChangeView( _view );\n\t\t\tsetIsShowingFilter( true );\n\t\t},\n\t\t[ onChangeView, setIsShowingFilter ]\n\t);\n\n\tif ( filters.length === 0 ) {\n\t\treturn null;\n\t}\n\n\tconst hasVisibleFilters = filters.some( ( filter ) => filter.isVisible );\n\n\tconst addFilterButtonProps = {\n\t\tlabel: __( 'Add filter' ),\n\t\t'aria-expanded': false,\n\t\tisPressed: false,\n\t};\n\tconst toggleFiltersButtonProps = {\n\t\tlabel: _x( 'Filter', 'verb' ),\n\t\t'aria-expanded': isShowingFilter,\n\t\tisPressed: isShowingFilter,\n\t\tonClick: () => {\n\t\t\tif ( ! isShowingFilter ) {\n\t\t\t\tsetOpenedFilter( null );\n\t\t\t}\n\t\t\tsetIsShowingFilter( ! isShowingFilter );\n\t\t},\n\t};\n\t// When there are primary or locked filters, the filter bar is always\n\t// visible and cannot be hidden, so the toggle button should be disabled.\n\tconst hasPrimaryOrLockedFilters = filters.some(\n\t\t( filter ) => filter.isPrimary || filter.isLocked\n\t);\n\tconst buttonComponent = (\n\t\t<Button\n\t\t\tref={ buttonRef }\n\t\t\tclassName=\"dataviews-filters__visibility-toggle\"\n\t\t\tsize=\"compact\"\n\t\t\ticon={ funnel }\n\t\t\tdisabled={ hasPrimaryOrLockedFilters }\n\t\t\taccessibleWhenDisabled\n\t\t\t{ ...( hasVisibleFilters\n\t\t\t\t? toggleFiltersButtonProps\n\t\t\t\t: addFilterButtonProps ) }\n\t\t/>\n\t);\n\treturn (\n\t\t<div className=\"dataviews-filters__container-visibility-toggle\">\n\t\t\t{ ! hasVisibleFilters ? (\n\t\t\t\t<AddFilterMenu\n\t\t\t\t\tfilters={ filters }\n\t\t\t\t\tview={ view }\n\t\t\t\t\tonChangeView={ onChangeViewWithFilterVisibility }\n\t\t\t\t\tsetOpenedFilter={ setOpenedFilter }\n\t\t\t\t\ttriggerProps={ { render: buttonComponent } }\n\t\t\t\t/>\n\t\t\t) : (\n\t\t\t\t<FilterVisibilityToggle\n\t\t\t\t\tbuttonRef={ buttonRef }\n\t\t\t\t\tfiltersCount={ view.filters?.length }\n\t\t\t\t>\n\t\t\t\t\t{ buttonComponent }\n\t\t\t\t</FilterVisibilityToggle>\n\t\t\t) }\n\t\t</div>\n\t);\n}\n\nfunction FilterVisibilityToggle( {\n\tbuttonRef,\n\tfiltersCount,\n\tchildren,\n}: {\n\tbuttonRef: React.RefObject< HTMLButtonElement | null >;\n\tfiltersCount?: number;\n\tchildren: React.ReactNode;\n} ) {\n\t// Focus the `add filter` button when unmounts.\n\tuseEffect(\n\t\t() => () => {\n\t\t\tbuttonRef.current?.focus();\n\t\t},\n\t\t[ buttonRef ]\n\t);\n\treturn (\n\t\t<>\n\t\t\t{ children }\n\t\t\t{ !! filtersCount && (\n\t\t\t\t<span className=\"dataviews-filters-toggle__count\">\n\t\t\t\t\t{ filtersCount }\n\t\t\t\t</span>\n\t\t\t) }\n\t\t</>\n\t);\n}\n\nexport default FiltersToggle;\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,qBAA2D;AAC3D,wBAAuB;AACvB,mBAAuB;AACvB,kBAAuB;AAKvB,wBAA8B;AAC9B,+BAA6B;AAkD3B;AA/CF,SAAS,gBAAgB;AACxB,QAAM;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,QAAI,2BAAY,yBAAAA,OAAiB;AAEjC,QAAM,gBAAY,uBAA6B,IAAK;AACpD,QAAM,uCAAmC;AAAA,IACxC,CAAE,UAAiB;AAClB,mBAAc,KAAM;AACpB,yBAAoB,IAAK;AAAA,IAC1B;AAAA,IACA,CAAE,cAAc,kBAAmB;AAAA,EACpC;AAEA,MAAK,QAAQ,WAAW,GAAI;AAC3B,WAAO;AAAA,EACR;AAEA,QAAM,oBAAoB,QAAQ,KAAM,CAAE,WAAY,OAAO,SAAU;AAEvE,QAAM,uBAAuB;AAAA,IAC5B,WAAO,gBAAI,YAAa;AAAA,IACxB,iBAAiB;AAAA,IACjB,WAAW;AAAA,EACZ;AACA,QAAM,2BAA2B;AAAA,IAChC,WAAO,gBAAI,UAAU,MAAO;AAAA,IAC5B,iBAAiB;AAAA,IACjB,WAAW;AAAA,IACX,SAAS,MAAM;AACd,UAAK,CAAE,iBAAkB;AACxB,wBAAiB,IAAK;AAAA,MACvB;AACA,yBAAoB,CAAE,eAAgB;AAAA,IACvC;AAAA,EACD;AAGA,QAAM,4BAA4B,QAAQ;AAAA,IACzC,CAAE,WAAY,OAAO,aAAa,OAAO;AAAA,EAC1C;AACA,QAAM,kBACL;AAAA,IAAC;AAAA;AAAA,MACA,KAAM;AAAA,MACN,WAAU;AAAA,MACV,MAAK;AAAA,MACL,MAAO;AAAA,MACP,UAAW;AAAA,MACX,wBAAsB;AAAA,MACpB,GAAK,oBACJ,2BACA;AAAA;AAAA,EACJ;AAED,SACC,4CAAC,SAAI,WAAU,kDACZ,WAAE,oBACH;AAAA,IAAC;AAAA;AAAA,MACA;AAAA,MACA;AAAA,MACA,cAAe;AAAA,MACf;AAAA,MACA,cAAe,EAAE,QAAQ,gBAAgB;AAAA;AAAA,EAC1C,IAEA;AAAA,IAAC;AAAA;AAAA,MACA;AAAA,MACA,cAAe,KAAK,SAAS;AAAA,MAE3B;AAAA;AAAA,EACH,GAEF;AAEF;AAEA,SAAS,uBAAwB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AACD,GAII;AAEH;AAAA,IACC,MAAM,MAAM;AACX,gBAAU,SAAS,MAAM;AAAA,IAC1B;AAAA,IACA,CAAE,SAAU;AAAA,EACb;AACA,SACC,4EACG;AAAA;AAAA,IACA,CAAC,CAAE,gBACJ,4CAAC,UAAK,WAAU,mCACb,wBACH;AAAA,KAEF;AAEF;AAEA,IAAO,iBAAQ;",
6
6
  "names": ["DataViewsContext"]
7
7
  }
@@ -33,12 +33,14 @@ __export(dataviews_footer_exports, {
33
33
  default: () => DataViewsFooter
34
34
  });
35
35
  module.exports = __toCommonJS(dataviews_footer_exports);
36
+ var import_clsx = __toESM(require("clsx"));
36
37
  var import_element = require("@wordpress/element");
37
38
  var import_ui = require("@wordpress/ui");
38
39
  var import_dataviews_context = __toESM(require("../dataviews-context/index.cjs"));
39
40
  var import_dataviews_pagination = __toESM(require("../dataviews-pagination/index.cjs"));
40
41
  var import_dataviews_bulk_actions = require("../dataviews-bulk-actions/index.cjs");
41
42
  var import_constants = require("../../constants.cjs");
43
+ var import_use_delayed_loading = require("../../hooks/use-delayed-loading.cjs");
42
44
  var import_jsx_runtime = require("react/jsx-runtime");
43
45
  var EMPTY_ARRAY = [];
44
46
  function DataViewsFooter() {
@@ -46,24 +48,38 @@ function DataViewsFooter() {
46
48
  view,
47
49
  paginationInfo: { totalItems = 0, totalPages },
48
50
  data,
49
- actions = EMPTY_ARRAY
51
+ actions = EMPTY_ARRAY,
52
+ isLoading,
53
+ hasInitiallyLoaded,
54
+ hasInfiniteScrollHandler
50
55
  } = (0, import_element.useContext)(import_dataviews_context.default);
56
+ const isRefreshing = !!isLoading && hasInitiallyLoaded && !hasInfiniteScrollHandler && !!data?.length;
57
+ const isDelayedRefreshing = (0, import_use_delayed_loading.useDelayedLoading)(!!isRefreshing);
51
58
  const hasBulkActions = (0, import_dataviews_bulk_actions.useSomeItemHasAPossibleBulkAction)(actions, data) && [import_constants.LAYOUT_TABLE, import_constants.LAYOUT_GRID].includes(view.type);
52
- if (!totalItems || !totalPages || totalPages <= 1 && !hasBulkActions) {
59
+ if (!isRefreshing && (!totalItems || !totalPages || totalPages <= 1 && !hasBulkActions)) {
53
60
  return null;
54
61
  }
55
- return !!totalItems && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
56
- import_ui.Stack,
62
+ return (!!totalItems || isRefreshing) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
63
+ "div",
57
64
  {
58
- direction: "row",
59
- justify: "end",
60
- align: "center",
61
65
  className: "dataviews-footer",
62
- gap: "sm",
63
- children: [
64
- hasBulkActions && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dataviews_bulk_actions.BulkActionsFooter, {}),
65
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dataviews_pagination.default, {})
66
- ]
66
+ inert: isRefreshing ? "true" : void 0,
67
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
68
+ import_ui.Stack,
69
+ {
70
+ direction: "row",
71
+ justify: "end",
72
+ align: "center",
73
+ className: (0, import_clsx.default)("dataviews-footer__content", {
74
+ "is-refreshing": isDelayedRefreshing
75
+ }),
76
+ gap: "sm",
77
+ children: [
78
+ hasBulkActions && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dataviews_bulk_actions.BulkActionsFooter, {}),
79
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dataviews_pagination.default, {})
80
+ ]
81
+ }
82
+ )
67
83
  }
68
84
  );
69
85
  }