@wordpress/dataviews 11.3.1-next.v.0 → 12.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 (444) hide show
  1. package/CHANGELOG.md +46 -1
  2. package/README.md +44 -2
  3. package/build/components/dataform-controls/adaptive-select.cjs +52 -0
  4. package/build/components/dataform-controls/adaptive-select.cjs.map +7 -0
  5. package/build/components/dataform-controls/array.cjs +2 -0
  6. package/build/components/dataform-controls/array.cjs.map +2 -2
  7. package/build/components/dataform-controls/checkbox.cjs +2 -0
  8. package/build/components/dataform-controls/checkbox.cjs.map +2 -2
  9. package/build/components/dataform-controls/color.cjs +21 -30
  10. package/build/components/dataform-controls/color.cjs.map +3 -3
  11. package/build/components/dataform-controls/combobox.cjs +80 -0
  12. package/build/components/dataform-controls/combobox.cjs.map +7 -0
  13. package/build/components/dataform-controls/date.cjs +58 -19
  14. package/build/components/dataform-controls/date.cjs.map +2 -2
  15. package/build/components/dataform-controls/datetime.cjs +11 -3
  16. package/build/components/dataform-controls/datetime.cjs.map +2 -2
  17. package/build/components/dataform-controls/email.cjs +2 -0
  18. package/build/components/dataform-controls/email.cjs.map +2 -2
  19. package/build/components/dataform-controls/index.cjs +5 -1
  20. package/build/components/dataform-controls/index.cjs.map +3 -3
  21. package/build/components/dataform-controls/password.cjs +2 -0
  22. package/build/components/dataform-controls/password.cjs.map +2 -2
  23. package/build/components/dataform-controls/radio.cjs +2 -0
  24. package/build/components/dataform-controls/radio.cjs.map +2 -2
  25. package/build/components/dataform-controls/select.cjs +2 -0
  26. package/build/components/dataform-controls/select.cjs.map +2 -2
  27. package/build/components/dataform-controls/telephone.cjs +2 -0
  28. package/build/components/dataform-controls/telephone.cjs.map +2 -2
  29. package/build/components/dataform-controls/text.cjs +2 -0
  30. package/build/components/dataform-controls/text.cjs.map +2 -2
  31. package/build/components/dataform-controls/textarea.cjs +2 -0
  32. package/build/components/dataform-controls/textarea.cjs.map +2 -2
  33. package/build/components/dataform-controls/toggle-group.cjs +2 -0
  34. package/build/components/dataform-controls/toggle-group.cjs.map +2 -2
  35. package/build/components/dataform-controls/toggle.cjs +2 -0
  36. package/build/components/dataform-controls/toggle.cjs.map +2 -2
  37. package/build/components/dataform-controls/url.cjs +2 -0
  38. package/build/components/dataform-controls/url.cjs.map +2 -2
  39. package/build/components/dataform-controls/utils/relative-date-control.cjs +1 -1
  40. package/build/components/dataform-controls/utils/relative-date-control.cjs.map +1 -1
  41. package/build/components/dataform-controls/utils/validated-input.cjs +2 -0
  42. package/build/components/dataform-controls/utils/validated-input.cjs.map +2 -2
  43. package/build/components/dataform-controls/utils/validated-number.cjs +2 -0
  44. package/build/components/dataform-controls/utils/validated-number.cjs.map +2 -2
  45. package/build/components/dataform-layouts/card/index.cjs +28 -3
  46. package/build/components/dataform-layouts/card/index.cjs.map +3 -3
  47. package/build/components/dataform-layouts/data-form-layout.cjs +11 -2
  48. package/build/components/dataform-layouts/data-form-layout.cjs.map +2 -2
  49. package/build/components/dataform-layouts/details/index.cjs +69 -12
  50. package/build/components/dataform-layouts/details/index.cjs.map +3 -3
  51. package/build/components/dataform-layouts/index.cjs +5 -5
  52. package/build/components/dataform-layouts/index.cjs.map +1 -1
  53. package/build/components/dataform-layouts/normalize-form.cjs +2 -1
  54. package/build/components/dataform-layouts/normalize-form.cjs.map +2 -2
  55. package/build/components/dataform-layouts/panel/dropdown.cjs +88 -63
  56. package/build/components/dataform-layouts/panel/dropdown.cjs.map +3 -3
  57. package/build/components/dataform-layouts/panel/index.cjs +13 -175
  58. package/build/components/dataform-layouts/panel/index.cjs.map +3 -3
  59. package/build/components/dataform-layouts/panel/modal.cjs +28 -18
  60. package/build/components/dataform-layouts/panel/modal.cjs.map +3 -3
  61. package/build/components/dataform-layouts/panel/summary-button.cjs +125 -56
  62. package/build/components/dataform-layouts/panel/summary-button.cjs.map +3 -3
  63. package/build/components/dataform-layouts/panel/utils/get-first-validation-error.cjs +59 -0
  64. package/build/components/dataform-layouts/panel/utils/get-first-validation-error.cjs.map +7 -0
  65. package/build/components/dataform-layouts/panel/utils/get-label-classname.cjs +45 -0
  66. package/build/components/dataform-layouts/panel/utils/get-label-classname.cjs.map +7 -0
  67. package/build/components/dataform-layouts/panel/utils/get-label-content.cjs +36 -0
  68. package/build/components/dataform-layouts/panel/utils/get-label-content.cjs.map +7 -0
  69. package/build/components/dataform-layouts/panel/utils/use-field-from-form-field.cjs +77 -0
  70. package/build/components/dataform-layouts/panel/utils/use-field-from-form-field.cjs.map +7 -0
  71. package/build/components/dataform-layouts/regular/index.cjs +6 -3
  72. package/build/components/dataform-layouts/regular/index.cjs.map +2 -2
  73. package/build/components/dataform-layouts/row/index.cjs +5 -2
  74. package/build/components/dataform-layouts/row/index.cjs.map +2 -2
  75. package/build/components/dataform-layouts/validation-badge.cjs +67 -0
  76. package/build/components/dataform-layouts/validation-badge.cjs.map +7 -0
  77. package/build/components/dataviews-bulk-actions/index.cjs +4 -4
  78. package/build/components/dataviews-bulk-actions/index.cjs.map +2 -2
  79. package/build/components/dataviews-context/index.cjs.map +2 -2
  80. package/build/components/dataviews-filters/filter.cjs +1 -1
  81. package/build/components/dataviews-filters/filter.cjs.map +1 -1
  82. package/build/components/dataviews-filters/filters.cjs +1 -1
  83. package/build/components/dataviews-filters/filters.cjs.map +1 -1
  84. package/build/components/dataviews-filters/search-widget.cjs +25 -11
  85. package/build/components/dataviews-filters/search-widget.cjs.map +2 -2
  86. package/build/components/dataviews-filters/toggle.cjs.map +1 -1
  87. package/build/components/dataviews-footer/index.cjs +1 -1
  88. package/build/components/dataviews-footer/index.cjs.map +1 -1
  89. package/build/components/dataviews-layouts/activity/activity-item.cjs +4 -4
  90. package/build/components/dataviews-layouts/activity/activity-item.cjs.map +1 -1
  91. package/build/components/dataviews-layouts/activity/index.cjs +1 -1
  92. package/build/components/dataviews-layouts/activity/index.cjs.map +1 -1
  93. package/build/components/dataviews-layouts/grid/composite-grid.cjs +27 -38
  94. package/build/components/dataviews-layouts/grid/composite-grid.cjs.map +2 -2
  95. package/build/components/dataviews-layouts/grid/index.cjs +2 -2
  96. package/build/components/dataviews-layouts/grid/index.cjs.map +1 -1
  97. package/build/components/dataviews-layouts/list/index.cjs +7 -8
  98. package/build/components/dataviews-layouts/list/index.cjs.map +2 -2
  99. package/build/components/dataviews-layouts/picker-grid/index.cjs +5 -5
  100. package/build/components/dataviews-layouts/picker-grid/index.cjs.map +2 -2
  101. package/build/components/dataviews-layouts/picker-table/index.cjs +1 -1
  102. package/build/components/dataviews-layouts/picker-table/index.cjs.map +2 -2
  103. package/build/components/dataviews-layouts/table/column-primary.cjs +1 -1
  104. package/build/components/dataviews-layouts/table/column-primary.cjs.map +1 -1
  105. package/build/components/dataviews-layouts/table/index.cjs +1 -1
  106. package/build/components/dataviews-layouts/table/index.cjs.map +2 -2
  107. package/build/components/dataviews-layouts/utils/item-click-wrapper.cjs.map +2 -2
  108. package/build/components/dataviews-pagination/index.cjs +3 -3
  109. package/build/components/dataviews-pagination/index.cjs.map +2 -2
  110. package/build/components/dataviews-picker-footer/index.cjs +3 -3
  111. package/build/components/dataviews-picker-footer/index.cjs.map +2 -2
  112. package/build/components/dataviews-view-config/index.cjs +74 -57
  113. package/build/components/dataviews-view-config/index.cjs.map +3 -3
  114. package/build/components/dataviews-view-config/properties-section.cjs +1 -1
  115. package/build/components/dataviews-view-config/properties-section.cjs.map +1 -1
  116. package/build/dataviews/index.cjs +7 -5
  117. package/build/dataviews/index.cjs.map +2 -2
  118. package/build/dataviews-picker/index.cjs +3 -3
  119. package/build/dataviews-picker/index.cjs.map +2 -2
  120. package/build/hooks/use-form-validity.cjs +61 -28
  121. package/build/hooks/use-form-validity.cjs.map +2 -2
  122. package/build/hooks/use-report-validity.cjs +39 -0
  123. package/build/hooks/use-report-validity.cjs.map +7 -0
  124. package/build/types/dataform.cjs.map +1 -1
  125. package/build/types/field-api.cjs.map +1 -1
  126. package/build-module/components/dataform-controls/adaptive-select.mjs +21 -0
  127. package/build-module/components/dataform-controls/adaptive-select.mjs.map +7 -0
  128. package/build-module/components/dataform-controls/array.mjs +2 -0
  129. package/build-module/components/dataform-controls/array.mjs.map +2 -2
  130. package/build-module/components/dataform-controls/checkbox.mjs +2 -0
  131. package/build-module/components/dataform-controls/checkbox.mjs.map +2 -2
  132. package/build-module/components/dataform-controls/color.mjs +26 -31
  133. package/build-module/components/dataform-controls/color.mjs.map +2 -2
  134. package/build-module/components/dataform-controls/combobox.mjs +49 -0
  135. package/build-module/components/dataform-controls/combobox.mjs.map +7 -0
  136. package/build-module/components/dataform-controls/date.mjs +58 -19
  137. package/build-module/components/dataform-controls/date.mjs.map +2 -2
  138. package/build-module/components/dataform-controls/datetime.mjs +11 -3
  139. package/build-module/components/dataform-controls/datetime.mjs.map +2 -2
  140. package/build-module/components/dataform-controls/email.mjs +2 -0
  141. package/build-module/components/dataform-controls/email.mjs.map +2 -2
  142. package/build-module/components/dataform-controls/index.mjs +5 -1
  143. package/build-module/components/dataform-controls/index.mjs.map +2 -2
  144. package/build-module/components/dataform-controls/password.mjs +2 -0
  145. package/build-module/components/dataform-controls/password.mjs.map +2 -2
  146. package/build-module/components/dataform-controls/radio.mjs +2 -0
  147. package/build-module/components/dataform-controls/radio.mjs.map +2 -2
  148. package/build-module/components/dataform-controls/select.mjs +2 -0
  149. package/build-module/components/dataform-controls/select.mjs.map +2 -2
  150. package/build-module/components/dataform-controls/telephone.mjs +2 -0
  151. package/build-module/components/dataform-controls/telephone.mjs.map +2 -2
  152. package/build-module/components/dataform-controls/text.mjs +2 -0
  153. package/build-module/components/dataform-controls/text.mjs.map +2 -2
  154. package/build-module/components/dataform-controls/textarea.mjs +2 -0
  155. package/build-module/components/dataform-controls/textarea.mjs.map +2 -2
  156. package/build-module/components/dataform-controls/toggle-group.mjs +2 -0
  157. package/build-module/components/dataform-controls/toggle-group.mjs.map +2 -2
  158. package/build-module/components/dataform-controls/toggle.mjs +2 -0
  159. package/build-module/components/dataform-controls/toggle.mjs.map +2 -2
  160. package/build-module/components/dataform-controls/url.mjs +2 -0
  161. package/build-module/components/dataform-controls/url.mjs.map +2 -2
  162. package/build-module/components/dataform-controls/utils/relative-date-control.mjs +1 -1
  163. package/build-module/components/dataform-controls/utils/relative-date-control.mjs.map +1 -1
  164. package/build-module/components/dataform-controls/utils/validated-input.mjs +2 -0
  165. package/build-module/components/dataform-controls/utils/validated-input.mjs.map +2 -2
  166. package/build-module/components/dataform-controls/utils/validated-number.mjs +2 -0
  167. package/build-module/components/dataform-controls/utils/validated-number.mjs.map +2 -2
  168. package/build-module/components/dataform-layouts/card/index.mjs +29 -3
  169. package/build-module/components/dataform-layouts/card/index.mjs.map +2 -2
  170. package/build-module/components/dataform-layouts/data-form-layout.mjs +12 -3
  171. package/build-module/components/dataform-layouts/data-form-layout.mjs.map +2 -2
  172. package/build-module/components/dataform-layouts/details/index.mjs +77 -13
  173. package/build-module/components/dataform-layouts/details/index.mjs.map +2 -2
  174. package/build-module/components/dataform-layouts/index.mjs +5 -5
  175. package/build-module/components/dataform-layouts/index.mjs.map +1 -1
  176. package/build-module/components/dataform-layouts/normalize-form.mjs +2 -1
  177. package/build-module/components/dataform-layouts/normalize-form.mjs.map +2 -2
  178. package/build-module/components/dataform-layouts/panel/dropdown.mjs +91 -66
  179. package/build-module/components/dataform-layouts/panel/dropdown.mjs.map +2 -2
  180. package/build-module/components/dataform-layouts/panel/index.mjs +14 -176
  181. package/build-module/components/dataform-layouts/panel/index.mjs.map +2 -2
  182. package/build-module/components/dataform-layouts/panel/modal.mjs +30 -20
  183. package/build-module/components/dataform-layouts/panel/modal.mjs.map +2 -2
  184. package/build-module/components/dataform-layouts/panel/summary-button.mjs +117 -58
  185. package/build-module/components/dataform-layouts/panel/summary-button.mjs.map +2 -2
  186. package/build-module/components/dataform-layouts/panel/utils/get-first-validation-error.mjs +38 -0
  187. package/build-module/components/dataform-layouts/panel/utils/get-first-validation-error.mjs.map +7 -0
  188. package/build-module/components/dataform-layouts/panel/utils/get-label-classname.mjs +14 -0
  189. package/build-module/components/dataform-layouts/panel/utils/get-label-classname.mjs.map +7 -0
  190. package/build-module/components/dataform-layouts/panel/utils/get-label-content.mjs +15 -0
  191. package/build-module/components/dataform-layouts/panel/utils/get-label-content.mjs.map +7 -0
  192. package/build-module/components/dataform-layouts/panel/utils/use-field-from-form-field.mjs +46 -0
  193. package/build-module/components/dataform-layouts/panel/utils/use-field-from-form-field.mjs.map +7 -0
  194. package/build-module/components/dataform-layouts/regular/index.mjs +6 -3
  195. package/build-module/components/dataform-layouts/regular/index.mjs.map +2 -2
  196. package/build-module/components/dataform-layouts/row/index.mjs +5 -2
  197. package/build-module/components/dataform-layouts/row/index.mjs.map +2 -2
  198. package/build-module/components/dataform-layouts/validation-badge.mjs +46 -0
  199. package/build-module/components/dataform-layouts/validation-badge.mjs.map +7 -0
  200. package/build-module/components/dataviews-bulk-actions/index.mjs +4 -4
  201. package/build-module/components/dataviews-bulk-actions/index.mjs.map +2 -2
  202. package/build-module/components/dataviews-context/index.mjs.map +2 -2
  203. package/build-module/components/dataviews-filters/filter.mjs +1 -1
  204. package/build-module/components/dataviews-filters/filter.mjs.map +1 -1
  205. package/build-module/components/dataviews-filters/filters.mjs +1 -1
  206. package/build-module/components/dataviews-filters/filters.mjs.map +1 -1
  207. package/build-module/components/dataviews-filters/search-widget.mjs +25 -11
  208. package/build-module/components/dataviews-filters/search-widget.mjs.map +2 -2
  209. package/build-module/components/dataviews-filters/toggle.mjs.map +1 -1
  210. package/build-module/components/dataviews-footer/index.mjs +1 -1
  211. package/build-module/components/dataviews-footer/index.mjs.map +1 -1
  212. package/build-module/components/dataviews-layouts/activity/activity-item.mjs +4 -4
  213. package/build-module/components/dataviews-layouts/activity/activity-item.mjs.map +1 -1
  214. package/build-module/components/dataviews-layouts/activity/index.mjs +1 -1
  215. package/build-module/components/dataviews-layouts/activity/index.mjs.map +1 -1
  216. package/build-module/components/dataviews-layouts/grid/composite-grid.mjs +27 -38
  217. package/build-module/components/dataviews-layouts/grid/composite-grid.mjs.map +2 -2
  218. package/build-module/components/dataviews-layouts/grid/index.mjs +2 -2
  219. package/build-module/components/dataviews-layouts/grid/index.mjs.map +1 -1
  220. package/build-module/components/dataviews-layouts/list/index.mjs +7 -8
  221. package/build-module/components/dataviews-layouts/list/index.mjs.map +2 -2
  222. package/build-module/components/dataviews-layouts/picker-grid/index.mjs +5 -5
  223. package/build-module/components/dataviews-layouts/picker-grid/index.mjs.map +2 -2
  224. package/build-module/components/dataviews-layouts/picker-table/index.mjs +1 -1
  225. package/build-module/components/dataviews-layouts/picker-table/index.mjs.map +2 -2
  226. package/build-module/components/dataviews-layouts/table/column-primary.mjs +1 -1
  227. package/build-module/components/dataviews-layouts/table/column-primary.mjs.map +1 -1
  228. package/build-module/components/dataviews-layouts/table/index.mjs +1 -1
  229. package/build-module/components/dataviews-layouts/table/index.mjs.map +2 -2
  230. package/build-module/components/dataviews-layouts/utils/item-click-wrapper.mjs.map +2 -2
  231. package/build-module/components/dataviews-pagination/index.mjs +3 -3
  232. package/build-module/components/dataviews-pagination/index.mjs.map +2 -2
  233. package/build-module/components/dataviews-picker-footer/index.mjs +3 -3
  234. package/build-module/components/dataviews-picker-footer/index.mjs.map +2 -2
  235. package/build-module/components/dataviews-view-config/index.mjs +74 -59
  236. package/build-module/components/dataviews-view-config/index.mjs.map +2 -2
  237. package/build-module/components/dataviews-view-config/properties-section.mjs +1 -1
  238. package/build-module/components/dataviews-view-config/properties-section.mjs.map +1 -1
  239. package/build-module/dataviews/index.mjs +7 -5
  240. package/build-module/dataviews/index.mjs.map +2 -2
  241. package/build-module/dataviews-picker/index.mjs +3 -3
  242. package/build-module/dataviews-picker/index.mjs.map +2 -2
  243. package/build-module/hooks/use-form-validity.mjs +61 -28
  244. package/build-module/hooks/use-form-validity.mjs.map +2 -2
  245. package/build-module/hooks/use-report-validity.mjs +18 -0
  246. package/build-module/hooks/use-report-validity.mjs.map +7 -0
  247. package/build-style/style-rtl.css +149 -217
  248. package/build-style/style.css +149 -217
  249. package/build-types/components/dataform-controls/adaptive-select.d.ts +6 -0
  250. package/build-types/components/dataform-controls/adaptive-select.d.ts.map +1 -0
  251. package/build-types/components/dataform-controls/array.d.ts +1 -1
  252. package/build-types/components/dataform-controls/array.d.ts.map +1 -1
  253. package/build-types/components/dataform-controls/checkbox.d.ts +1 -1
  254. package/build-types/components/dataform-controls/checkbox.d.ts.map +1 -1
  255. package/build-types/components/dataform-controls/color.d.ts +1 -1
  256. package/build-types/components/dataform-controls/color.d.ts.map +1 -1
  257. package/build-types/components/dataform-controls/combobox.d.ts +6 -0
  258. package/build-types/components/dataform-controls/combobox.d.ts.map +1 -0
  259. package/build-types/components/dataform-controls/date.d.ts +1 -1
  260. package/build-types/components/dataform-controls/date.d.ts.map +1 -1
  261. package/build-types/components/dataform-controls/datetime.d.ts +1 -1
  262. package/build-types/components/dataform-controls/datetime.d.ts.map +1 -1
  263. package/build-types/components/dataform-controls/email.d.ts +1 -1
  264. package/build-types/components/dataform-controls/email.d.ts.map +1 -1
  265. package/build-types/components/dataform-controls/index.d.ts.map +1 -1
  266. package/build-types/components/dataform-controls/password.d.ts +1 -1
  267. package/build-types/components/dataform-controls/password.d.ts.map +1 -1
  268. package/build-types/components/dataform-controls/radio.d.ts +1 -1
  269. package/build-types/components/dataform-controls/radio.d.ts.map +1 -1
  270. package/build-types/components/dataform-controls/select.d.ts +1 -1
  271. package/build-types/components/dataform-controls/select.d.ts.map +1 -1
  272. package/build-types/components/dataform-controls/telephone.d.ts +1 -1
  273. package/build-types/components/dataform-controls/telephone.d.ts.map +1 -1
  274. package/build-types/components/dataform-controls/text.d.ts +1 -1
  275. package/build-types/components/dataform-controls/text.d.ts.map +1 -1
  276. package/build-types/components/dataform-controls/textarea.d.ts +1 -1
  277. package/build-types/components/dataform-controls/textarea.d.ts.map +1 -1
  278. package/build-types/components/dataform-controls/toggle-group.d.ts +1 -1
  279. package/build-types/components/dataform-controls/toggle-group.d.ts.map +1 -1
  280. package/build-types/components/dataform-controls/toggle.d.ts +1 -1
  281. package/build-types/components/dataform-controls/toggle.d.ts.map +1 -1
  282. package/build-types/components/dataform-controls/url.d.ts +1 -1
  283. package/build-types/components/dataform-controls/url.d.ts.map +1 -1
  284. package/build-types/components/dataform-controls/utils/validated-input.d.ts +1 -1
  285. package/build-types/components/dataform-controls/utils/validated-input.d.ts.map +1 -1
  286. package/build-types/components/dataform-controls/utils/validated-number.d.ts +1 -1
  287. package/build-types/components/dataform-controls/utils/validated-number.d.ts.map +1 -1
  288. package/build-types/components/dataform-layouts/card/index.d.ts +3 -1
  289. package/build-types/components/dataform-layouts/card/index.d.ts.map +1 -1
  290. package/build-types/components/dataform-layouts/data-form-layout.d.ts +2 -1
  291. package/build-types/components/dataform-layouts/data-form-layout.d.ts.map +1 -1
  292. package/build-types/components/dataform-layouts/details/index.d.ts +1 -1
  293. package/build-types/components/dataform-layouts/details/index.d.ts.map +1 -1
  294. package/build-types/components/dataform-layouts/normalize-form.d.ts.map +1 -1
  295. package/build-types/components/dataform-layouts/panel/dropdown.d.ts +2 -12
  296. package/build-types/components/dataform-layouts/panel/dropdown.d.ts.map +1 -1
  297. package/build-types/components/dataform-layouts/panel/index.d.ts +1 -1
  298. package/build-types/components/dataform-layouts/panel/index.d.ts.map +1 -1
  299. package/build-types/components/dataform-layouts/panel/modal.d.ts +2 -10
  300. package/build-types/components/dataform-layouts/panel/modal.d.ts.map +1 -1
  301. package/build-types/components/dataform-layouts/panel/summary-button.d.ts +6 -5
  302. package/build-types/components/dataform-layouts/panel/summary-button.d.ts.map +1 -1
  303. package/build-types/components/dataform-layouts/panel/utils/get-first-validation-error.d.ts +4 -0
  304. package/build-types/components/dataform-layouts/panel/utils/get-first-validation-error.d.ts.map +1 -0
  305. package/build-types/components/dataform-layouts/panel/utils/get-label-classname.d.ts +4 -0
  306. package/build-types/components/dataform-layouts/panel/utils/get-label-classname.d.ts.map +1 -0
  307. package/build-types/components/dataform-layouts/panel/utils/get-label-content.d.ts +3 -0
  308. package/build-types/components/dataform-layouts/panel/utils/get-label-content.d.ts.map +1 -0
  309. package/build-types/components/dataform-layouts/panel/utils/use-field-from-form-field.d.ts +23 -0
  310. package/build-types/components/dataform-layouts/panel/utils/use-field-from-form-field.d.ts.map +1 -0
  311. package/build-types/components/dataform-layouts/regular/index.d.ts +1 -1
  312. package/build-types/components/dataform-layouts/regular/index.d.ts.map +1 -1
  313. package/build-types/components/dataform-layouts/row/index.d.ts +1 -1
  314. package/build-types/components/dataform-layouts/row/index.d.ts.map +1 -1
  315. package/build-types/components/dataform-layouts/validation-badge.d.ts +8 -0
  316. package/build-types/components/dataform-layouts/validation-badge.d.ts.map +1 -0
  317. package/build-types/components/dataviews-context/index.d.ts +1 -0
  318. package/build-types/components/dataviews-context/index.d.ts.map +1 -1
  319. package/build-types/components/dataviews-filters/filter.d.ts +1 -1
  320. package/build-types/components/dataviews-filters/filter.d.ts.map +1 -1
  321. package/build-types/components/dataviews-filters/search-widget.d.ts.map +1 -1
  322. package/build-types/components/dataviews-layouts/list/index.d.ts.map +1 -1
  323. package/build-types/components/dataviews-layouts/utils/item-click-wrapper.d.ts +1 -0
  324. package/build-types/components/dataviews-layouts/utils/item-click-wrapper.d.ts.map +1 -1
  325. package/build-types/components/dataviews-view-config/index.d.ts.map +1 -1
  326. package/build-types/dataform/stories/content.story.d.ts +14 -0
  327. package/build-types/dataform/stories/content.story.d.ts.map +1 -0
  328. package/build-types/dataform/stories/index.story.d.ts +10 -2
  329. package/build-types/dataform/stories/index.story.d.ts.map +1 -1
  330. package/build-types/dataform/stories/layout-panel.d.ts +3 -1
  331. package/build-types/dataform/stories/layout-panel.d.ts.map +1 -1
  332. package/build-types/dataform/stories/validation.d.ts +1 -1
  333. package/build-types/dataform/stories/validation.d.ts.map +1 -1
  334. package/build-types/dataviews/index.d.ts +2 -1
  335. package/build-types/dataviews/index.d.ts.map +1 -1
  336. package/build-types/dataviews/stories/fixtures.d.ts +1 -0
  337. package/build-types/dataviews/stories/fixtures.d.ts.map +1 -1
  338. package/build-types/dataviews/stories/index.story.d.ts +14 -2
  339. package/build-types/dataviews/stories/index.story.d.ts.map +1 -1
  340. package/build-types/dataviews/stories/layout-activity.d.ts +2 -1
  341. package/build-types/dataviews/stories/layout-activity.d.ts.map +1 -1
  342. package/build-types/dataviews/stories/layout-list.d.ts +2 -1
  343. package/build-types/dataviews/stories/layout-list.d.ts.map +1 -1
  344. package/build-types/field-types/stories/index.story.d.ts +42 -16
  345. package/build-types/field-types/stories/index.story.d.ts.map +1 -1
  346. package/build-types/hooks/use-form-validity.d.ts.map +1 -1
  347. package/build-types/hooks/use-report-validity.d.ts +14 -0
  348. package/build-types/hooks/use-report-validity.d.ts.map +1 -0
  349. package/build-types/types/dataform.d.ts +4 -0
  350. package/build-types/types/dataform.d.ts.map +1 -1
  351. package/build-types/types/field-api.d.ts +4 -0
  352. package/build-types/types/field-api.d.ts.map +1 -1
  353. package/build-wp/index.js +3749 -2632
  354. package/package.json +22 -21
  355. package/src/components/dataform-controls/adaptive-select.tsx +23 -0
  356. package/src/components/dataform-controls/array.tsx +2 -0
  357. package/src/components/dataform-controls/checkbox.tsx +2 -0
  358. package/src/components/dataform-controls/color.tsx +31 -36
  359. package/src/components/dataform-controls/combobox.tsx +58 -0
  360. package/src/components/dataform-controls/date.tsx +69 -26
  361. package/src/components/dataform-controls/datetime.tsx +16 -6
  362. package/src/components/dataform-controls/email.tsx +2 -0
  363. package/src/components/dataform-controls/index.tsx +5 -1
  364. package/src/components/dataform-controls/password.tsx +2 -0
  365. package/src/components/dataform-controls/radio.tsx +2 -0
  366. package/src/components/dataform-controls/select.tsx +2 -0
  367. package/src/components/dataform-controls/style.scss +4 -0
  368. package/src/components/dataform-controls/telephone.tsx +2 -0
  369. package/src/components/dataform-controls/text.tsx +2 -0
  370. package/src/components/dataform-controls/textarea.tsx +2 -0
  371. package/src/components/dataform-controls/toggle-group.tsx +2 -0
  372. package/src/components/dataform-controls/toggle.tsx +2 -0
  373. package/src/components/dataform-controls/url.tsx +2 -0
  374. package/src/components/dataform-controls/utils/relative-date-control.tsx +1 -1
  375. package/src/components/dataform-controls/utils/validated-input.tsx +2 -0
  376. package/src/components/dataform-controls/utils/validated-number.tsx +2 -0
  377. package/src/components/dataform-layouts/card/index.tsx +40 -3
  378. package/src/components/dataform-layouts/data-form-layout.tsx +18 -4
  379. package/src/components/dataform-layouts/details/index.tsx +66 -4
  380. package/src/components/dataform-layouts/details/style.scss +5 -0
  381. package/src/components/dataform-layouts/index.tsx +5 -5
  382. package/src/components/dataform-layouts/normalize-form.ts +1 -0
  383. package/src/components/dataform-layouts/panel/dropdown.tsx +110 -94
  384. package/src/components/dataform-layouts/panel/index.tsx +10 -243
  385. package/src/components/dataform-layouts/panel/modal.tsx +43 -29
  386. package/src/components/dataform-layouts/panel/style.scss +109 -27
  387. package/src/components/dataform-layouts/panel/summary-button.tsx +140 -62
  388. package/src/components/dataform-layouts/panel/utils/get-first-validation-error.ts +47 -0
  389. package/src/components/dataform-layouts/panel/utils/get-label-classname.ts +18 -0
  390. package/src/components/dataform-layouts/panel/utils/get-label-content.tsx +26 -0
  391. package/src/components/dataform-layouts/panel/utils/use-field-from-form-field.ts +78 -0
  392. package/src/components/dataform-layouts/regular/index.tsx +8 -3
  393. package/src/components/dataform-layouts/regular/style.scss +10 -0
  394. package/src/components/dataform-layouts/row/index.tsx +5 -2
  395. package/src/components/dataform-layouts/test/normalize-form.ts +5 -0
  396. package/src/components/dataform-layouts/validation-badge.tsx +63 -0
  397. package/src/components/dataviews-bulk-actions/index.tsx +4 -4
  398. package/src/components/dataviews-context/index.ts +1 -0
  399. package/src/components/dataviews-filters/filter.tsx +2 -2
  400. package/src/components/dataviews-filters/filters.tsx +1 -1
  401. package/src/components/dataviews-filters/search-widget.tsx +10 -2
  402. package/src/components/dataviews-filters/style.scss +8 -0
  403. package/src/components/dataviews-filters/toggle.tsx +1 -1
  404. package/src/components/dataviews-footer/index.tsx +1 -1
  405. package/src/components/dataviews-layouts/activity/activity-item.tsx +4 -4
  406. package/src/components/dataviews-layouts/activity/index.tsx +1 -1
  407. package/src/components/dataviews-layouts/grid/composite-grid.tsx +35 -35
  408. package/src/components/dataviews-layouts/grid/index.tsx +2 -2
  409. package/src/components/dataviews-layouts/grid/style.scss +15 -1
  410. package/src/components/dataviews-layouts/list/index.tsx +7 -8
  411. package/src/components/dataviews-layouts/list/style.scss +1 -0
  412. package/src/components/dataviews-layouts/picker-grid/index.tsx +5 -5
  413. package/src/components/dataviews-layouts/picker-table/index.tsx +1 -1
  414. package/src/components/dataviews-layouts/table/column-primary.tsx +1 -1
  415. package/src/components/dataviews-layouts/table/index.tsx +1 -1
  416. package/src/components/dataviews-layouts/utils/item-click-wrapper.tsx +1 -0
  417. package/src/components/dataviews-pagination/index.tsx +3 -3
  418. package/src/components/dataviews-picker-footer/index.tsx +3 -3
  419. package/src/components/dataviews-view-config/index.tsx +61 -50
  420. package/src/components/dataviews-view-config/properties-section.tsx +1 -1
  421. package/src/components/dataviews-view-config/style.scss +21 -0
  422. package/src/dataform/stories/content.story.mdx +159 -0
  423. package/src/dataform/stories/content.story.tsx +390 -0
  424. package/src/dataform/stories/index.story.tsx +14 -2
  425. package/src/dataform/stories/layout-panel.tsx +19 -2
  426. package/src/dataform/stories/validation.tsx +100 -7
  427. package/src/dataform/test/dataform.tsx +2 -2
  428. package/src/dataviews/index.tsx +7 -4
  429. package/src/dataviews/stories/empty.tsx +1 -1
  430. package/src/dataviews/stories/fixtures.tsx +93 -4
  431. package/src/dataviews/stories/free-composition.tsx +6 -6
  432. package/src/dataviews/stories/index.story.tsx +12 -0
  433. package/src/dataviews/stories/layout-activity.tsx +6 -3
  434. package/src/dataviews/stories/layout-list.tsx +3 -0
  435. package/src/dataviews-picker/index.tsx +4 -4
  436. package/src/dataviews-picker/stories/fixtures.tsx +2 -2
  437. package/src/dataviews-picker/stories/index.story.tsx +1 -1
  438. package/src/field-types/stories/index.story.tsx +101 -5
  439. package/src/hooks/test/use-form-validity.ts +303 -178
  440. package/src/hooks/use-form-validity.ts +85 -36
  441. package/src/hooks/use-report-validity.ts +32 -0
  442. package/src/style.scss +0 -2
  443. package/src/types/dataform.ts +5 -0
  444. package/src/types/field-api.ts +4 -0
@@ -18,6 +18,7 @@ export default function Telephone< Item >( {
18
18
  field,
19
19
  onChange,
20
20
  hideLabelFromVision,
21
+ markWhenOptional,
21
22
  validity,
22
23
  }: DataFormControlProps< Item > ) {
23
24
  return (
@@ -27,6 +28,7 @@ export default function Telephone< Item >( {
27
28
  field,
28
29
  onChange,
29
30
  hideLabelFromVision,
31
+ markWhenOptional,
30
32
  validity,
31
33
  type: 'tel',
32
34
  prefix: (
@@ -14,6 +14,7 @@ export default function Text< Item >( {
14
14
  field,
15
15
  onChange,
16
16
  hideLabelFromVision,
17
+ markWhenOptional,
17
18
  config,
18
19
  validity,
19
20
  }: DataFormControlProps< Item > ) {
@@ -26,6 +27,7 @@ export default function Text< Item >( {
26
27
  field,
27
28
  onChange,
28
29
  hideLabelFromVision,
30
+ markWhenOptional,
29
31
  validity,
30
32
  prefix: prefix ? createElement( prefix ) : undefined,
31
33
  suffix: suffix ? createElement( suffix ) : undefined,
@@ -18,6 +18,7 @@ export default function Textarea< Item >( {
18
18
  field,
19
19
  onChange,
20
20
  hideLabelFromVision,
21
+ markWhenOptional,
21
22
  config,
22
23
  validity,
23
24
  }: DataFormControlProps< Item > ) {
@@ -34,6 +35,7 @@ export default function Textarea< Item >( {
34
35
  return (
35
36
  <ValidatedTextareaControl
36
37
  required={ !! isValid.required }
38
+ markWhenOptional={ markWhenOptional }
37
39
  customValidity={ getCustomValidity( isValid, validity ) }
38
40
  label={ label }
39
41
  placeholder={ placeholder }
@@ -23,6 +23,7 @@ export default function ToggleGroup< Item >( {
23
23
  field,
24
24
  onChange,
25
25
  hideLabelFromVision,
26
+ markWhenOptional,
26
27
  validity,
27
28
  }: DataFormControlProps< Item > ) {
28
29
  const { getValue, setValue, isValid } = field;
@@ -51,6 +52,7 @@ export default function ToggleGroup< Item >( {
51
52
  return (
52
53
  <ValidatedToggleGroupControl
53
54
  required={ !! field.isValid?.required }
55
+ markWhenOptional={ markWhenOptional }
54
56
  customValidity={ getCustomValidity( isValid, validity ) }
55
57
  __next40pxDefaultSize
56
58
  isBlock
@@ -18,6 +18,7 @@ export default function Toggle< Item >( {
18
18
  onChange,
19
19
  data,
20
20
  hideLabelFromVision,
21
+ markWhenOptional,
21
22
  validity,
22
23
  }: DataFormControlProps< Item > ) {
23
24
  const { label, description, getValue, setValue, isValid } = field;
@@ -31,6 +32,7 @@ export default function Toggle< Item >( {
31
32
  return (
32
33
  <ValidatedToggleControl
33
34
  required={ !! isValid.required }
35
+ markWhenOptional={ markWhenOptional }
34
36
  customValidity={ getCustomValidity( isValid, validity ) }
35
37
  hidden={ hideLabelFromVision }
36
38
  label={ label }
@@ -18,6 +18,7 @@ export default function Url< Item >( {
18
18
  field,
19
19
  onChange,
20
20
  hideLabelFromVision,
21
+ markWhenOptional,
21
22
  validity,
22
23
  }: DataFormControlProps< Item > ) {
23
24
  return (
@@ -27,6 +28,7 @@ export default function Url< Item >( {
27
28
  field,
28
29
  onChange,
29
30
  hideLabelFromVision,
31
+ markWhenOptional,
30
32
  validity,
31
33
  type: 'url',
32
34
  prefix: (
@@ -92,7 +92,7 @@ export default function RelativeDateControl< Item >( {
92
92
  label={ label }
93
93
  hideLabelFromVision={ hideLabelFromVision }
94
94
  >
95
- <Stack direction="row" gap="xs">
95
+ <Stack direction="row" gap="sm">
96
96
  <NumberControl
97
97
  __next40pxDefaultSize
98
98
  className="dataviews-controls__relative-date-number"
@@ -34,6 +34,7 @@ export default function ValidatedText< Item >( {
34
34
  field,
35
35
  onChange,
36
36
  hideLabelFromVision,
37
+ markWhenOptional,
37
38
  type,
38
39
  prefix,
39
40
  suffix,
@@ -57,6 +58,7 @@ export default function ValidatedText< Item >( {
57
58
  return (
58
59
  <ValidatedInputControl
59
60
  required={ !! isValid.required }
61
+ markWhenOptional={ markWhenOptional }
60
62
  customValidity={ getCustomValidity( isValid, validity ) }
61
63
  label={ label }
62
64
  placeholder={ placeholder }
@@ -88,6 +88,7 @@ export default function ValidatedNumber< Item >( {
88
88
  field,
89
89
  onChange,
90
90
  hideLabelFromVision,
91
+ markWhenOptional,
91
92
  operator,
92
93
  validity,
93
94
  }: DataFormControlProps< Item > ) {
@@ -149,6 +150,7 @@ export default function ValidatedNumber< Item >( {
149
150
  return (
150
151
  <ValidatedNumberControl
151
152
  required={ !! isValid.required }
153
+ markWhenOptional={ markWhenOptional }
152
154
  customValidity={ getCustomValidity( isValid, validity ) }
153
155
  label={ label }
154
156
  help={ description }
@@ -12,6 +12,7 @@ import {
12
12
  useContext,
13
13
  useEffect,
14
14
  useMemo,
15
+ useRef,
15
16
  useState,
16
17
  } from '@wordpress/element';
17
18
  import { chevronDown, chevronUp } from '@wordpress/icons';
@@ -31,6 +32,8 @@ import type {
31
32
  import { DataFormLayout } from '../data-form-layout';
32
33
  import { DEFAULT_LAYOUT } from '../normalize-form';
33
34
  import { getSummaryFields } from '../get-summary-fields';
35
+ import useReportValidity from '../../../hooks/use-report-validity';
36
+ import ValidationBadge from '../validation-badge';
34
37
 
35
38
  const NonCollapsibleCardHeader = ( {
36
39
  children,
@@ -56,6 +59,7 @@ const NonCollapsibleCardHeader = ( {
56
59
  export function useCardHeader( layout: NormalizedCardLayout ) {
57
60
  const { isOpened, isCollapsible } = layout;
58
61
  const [ isOpen, setIsOpen ] = useState( isOpened );
62
+ const [ touched, setTouched ] = useState( false );
59
63
 
60
64
  // Sync internal state when the isOpened prop changes.
61
65
  // This is unlikely to happen in production, but it helps with storybook controls.
@@ -64,8 +68,12 @@ export function useCardHeader( layout: NormalizedCardLayout ) {
64
68
  }, [ isOpened ] );
65
69
 
66
70
  const toggle = useCallback( () => {
71
+ // Mark as touched when collapsing (going from open to closed)
72
+ if ( isOpen ) {
73
+ setTouched( true );
74
+ }
67
75
  setIsOpen( ( prev ) => ! prev );
68
- }, [] );
76
+ }, [ isOpen ] );
69
77
 
70
78
  const CollapsibleCardHeader = useCallback(
71
79
  ( {
@@ -111,7 +119,12 @@ export function useCardHeader( layout: NormalizedCardLayout ) {
111
119
  ? CollapsibleCardHeader
112
120
  : NonCollapsibleCardHeader;
113
121
 
114
- return { isOpen: effectiveIsOpen, CardHeader: CardHeaderComponent };
122
+ return {
123
+ isOpen: effectiveIsOpen,
124
+ CardHeader: CardHeaderComponent,
125
+ touched,
126
+ setTouched,
127
+ };
115
128
  }
116
129
 
117
130
  function isSummaryFieldVisible< Item >(
@@ -170,10 +183,12 @@ export default function FormCardField< Item >( {
170
183
  field,
171
184
  onChange,
172
185
  hideLabelFromVision,
186
+ markWhenOptional,
173
187
  validity,
174
188
  }: FieldLayoutProps< Item > ) {
175
189
  const { fields } = useContext( DataFormContext );
176
190
  const layout = field.layout as NormalizedCardLayout;
191
+ const cardBodyRef = useRef< HTMLDivElement >( null );
177
192
 
178
193
  const form: NormalizedForm = useMemo(
179
194
  () => ( {
@@ -183,7 +198,17 @@ export default function FormCardField< Item >( {
183
198
  [ field ]
184
199
  );
185
200
 
186
- const { isOpen, CardHeader } = useCardHeader( layout );
201
+ const { isOpen, CardHeader, touched, setTouched } = useCardHeader( layout );
202
+
203
+ // Mark the card as touched when any field inside it is blurred.
204
+ // This aligns with how validated controls show errors on blur.
205
+ const handleBlur = useCallback( () => {
206
+ setTouched( true );
207
+ }, [ setTouched ] );
208
+
209
+ // When the card is expanded after being touched (collapsed with errors),
210
+ // trigger reportValidity to show field-level errors.
211
+ useReportValidity( cardBodyRef, isOpen && touched );
187
212
 
188
213
  const summaryFields = getSummaryFields< Item >( layout.summary, fields );
189
214
 
@@ -191,6 +216,11 @@ export default function FormCardField< Item >( {
191
216
  isSummaryFieldVisible( summaryField, layout.summary, isOpen )
192
217
  );
193
218
 
219
+ const validationBadge =
220
+ touched && layout.isCollapsible ? (
221
+ <ValidationBadge validity={ validity } />
222
+ ) : null;
223
+
194
224
  const sizeCard = {
195
225
  blockStart: 'medium' as const,
196
226
  blockEnd: 'medium' as const,
@@ -217,6 +247,7 @@ export default function FormCardField< Item >( {
217
247
  <span className="dataforms-layouts-card__field-header-label">
218
248
  { field.label }
219
249
  </span>
250
+ { validationBadge }
220
251
  { visibleSummaryFields.length > 0 &&
221
252
  layout.withHeader && (
222
253
  <div className="dataforms-layouts-card__field-summary">
@@ -239,6 +270,8 @@ export default function FormCardField< Item >( {
239
270
  <CardBody
240
271
  size={ sizeCardBody }
241
272
  className="dataforms-layouts-card__field-control"
273
+ ref={ cardBodyRef }
274
+ onBlur={ handleBlur }
242
275
  >
243
276
  { field.description && (
244
277
  <div className="dataforms-layouts-card__field-description">
@@ -285,6 +318,7 @@ export default function FormCardField< Item >( {
285
318
  <span className="dataforms-layouts-card__field-header-label">
286
319
  { fieldDefinition.label }
287
320
  </span>
321
+ { validationBadge }
288
322
  { visibleSummaryFields.length > 0 && layout.withHeader && (
289
323
  <div className="dataforms-layouts-card__field-summary">
290
324
  { visibleSummaryFields.map( ( summaryField ) => (
@@ -304,6 +338,8 @@ export default function FormCardField< Item >( {
304
338
  <CardBody
305
339
  size={ sizeCardBody }
306
340
  className="dataforms-layouts-card__field-control"
341
+ ref={ cardBodyRef }
342
+ onBlur={ handleBlur }
307
343
  >
308
344
  <RegularLayout
309
345
  data={ data }
@@ -312,6 +348,7 @@ export default function FormCardField< Item >( {
312
348
  hideLabelFromVision={
313
349
  hideLabelFromVision || withHeader
314
350
  }
351
+ markWhenOptional={ markWhenOptional }
315
352
  validity={ validity }
316
353
  />
317
354
  </CardBody>
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { useContext } from '@wordpress/element';
4
+ import { useContext, useMemo } from '@wordpress/element';
5
5
  import { Stack } from '@wordpress/ui';
6
6
 
7
7
  /**
@@ -17,7 +17,7 @@ import { getFormFieldLayout } from './index';
17
17
  import DataFormContext from '../dataform-context';
18
18
 
19
19
  const DEFAULT_WRAPPER = ( { children }: { children: React.ReactNode } ) => (
20
- <Stack direction="column" className="dataforms-layouts__wrapper" gap="md">
20
+ <Stack direction="column" className="dataforms-layouts__wrapper" gap="lg">
21
21
  { children }
22
22
  </Stack>
23
23
  );
@@ -40,15 +40,27 @@ export function DataFormLayout< Item >( {
40
40
  field: NormalizedFormField;
41
41
  onChange: ( value: any ) => void;
42
42
  hideLabelFromVision?: boolean;
43
+ markWhenOptional?: boolean;
43
44
  validity?: FieldValidity;
44
45
  } ) => React.JSX.Element | null,
45
46
  childField: NormalizedFormField,
46
- childFieldValidity?: FieldValidity
47
+ childFieldValidity?: FieldValidity,
48
+ markWhenOptional?: boolean
47
49
  ) => React.JSX.Element;
48
50
  as?: React.ComponentType< { children: React.ReactNode } >;
49
51
  } ) {
50
52
  const { fields: fieldDefinitions } = useContext( DataFormContext );
51
53
 
54
+ // Auto-compute: mark the minority of fields
55
+ // When counts are equal, mark required fields
56
+ const markWhenOptional = useMemo( () => {
57
+ const requiredCount = fieldDefinitions.filter(
58
+ ( f ) => !! f.isValid?.required
59
+ ).length;
60
+ const optionalCount = fieldDefinitions.length - requiredCount;
61
+ return requiredCount > optionalCount;
62
+ }, [ fieldDefinitions ] );
63
+
52
64
  function getFieldDefinition( field: NormalizedFormField ) {
53
65
  return fieldDefinitions.find(
54
66
  ( fieldDefinition ) => fieldDefinition.id === field.id
@@ -86,7 +98,8 @@ export function DataFormLayout< Item >( {
86
98
  return children(
87
99
  FieldLayout,
88
100
  formField,
89
- validity?.[ formField.id ]
101
+ validity?.[ formField.id ],
102
+ markWhenOptional
90
103
  );
91
104
  }
92
105
 
@@ -96,6 +109,7 @@ export function DataFormLayout< Item >( {
96
109
  data={ data }
97
110
  field={ formField }
98
111
  onChange={ onChange }
112
+ markWhenOptional={ markWhenOptional }
99
113
  validity={ validity?.[ formField.id ] }
100
114
  />
101
115
  );
@@ -1,8 +1,16 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { useContext, useMemo } from '@wordpress/element';
4
+ import {
5
+ useCallback,
6
+ useContext,
7
+ useEffect,
8
+ useMemo,
9
+ useRef,
10
+ useState,
11
+ } from '@wordpress/element';
5
12
  import { __ } from '@wordpress/i18n';
13
+ import { Stack } from '@wordpress/ui';
6
14
 
7
15
  /**
8
16
  * Internal dependencies
@@ -15,13 +23,20 @@ import type {
15
23
  import DataFormContext from '../../dataform-context';
16
24
  import { DataFormLayout } from '../data-form-layout';
17
25
  import { DEFAULT_LAYOUT } from '../normalize-form';
26
+ import useReportValidity from '../../../hooks/use-report-validity';
27
+ import ValidationBadge from '../validation-badge';
18
28
 
19
29
  export default function FormDetailsField< Item >( {
20
30
  data,
21
31
  field,
22
32
  onChange,
33
+ validity,
23
34
  }: FieldLayoutProps< Item > ) {
24
35
  const { fields } = useContext( DataFormContext );
36
+ const detailsRef = useRef< HTMLDetailsElement >( null );
37
+ const contentRef = useRef< HTMLDivElement >( null );
38
+ const [ touched, setTouched ] = useState( false );
39
+ const [ isOpen, setIsOpen ] = useState( false );
25
40
 
26
41
  const form: NormalizedForm = useMemo(
27
42
  () => ( {
@@ -31,6 +46,37 @@ export default function FormDetailsField< Item >( {
31
46
  [ field ]
32
47
  );
33
48
 
49
+ // Track the open/close state of the native details element.
50
+ useEffect( () => {
51
+ const details = detailsRef.current;
52
+ if ( ! details ) {
53
+ return;
54
+ }
55
+
56
+ const handleToggle = () => {
57
+ const nowOpen = details.open;
58
+ // Mark as touched when collapsing (going from open to closed).
59
+ if ( ! nowOpen ) {
60
+ setTouched( true );
61
+ }
62
+ setIsOpen( nowOpen );
63
+ };
64
+
65
+ details.addEventListener( 'toggle', handleToggle );
66
+ return () => {
67
+ details.removeEventListener( 'toggle', handleToggle );
68
+ };
69
+ }, [] );
70
+
71
+ // When expanded after being touched, trigger reportValidity to show
72
+ // field-level errors.
73
+ useReportValidity( contentRef, isOpen && touched );
74
+
75
+ // Mark as touched when any field inside is blurred.
76
+ const handleBlur = useCallback( () => {
77
+ setTouched( true );
78
+ }, [] );
79
+
34
80
  if ( ! field.children ) {
35
81
  return null;
36
82
  }
@@ -55,15 +101,31 @@ export default function FormDetailsField< Item >( {
55
101
  }
56
102
 
57
103
  return (
58
- <details className="dataforms-layouts-details__details">
104
+ <details
105
+ ref={ detailsRef }
106
+ className="dataforms-layouts-details__details"
107
+ >
59
108
  <summary className="dataforms-layouts-details__summary">
60
- { summaryContent }
109
+ <Stack
110
+ direction="row"
111
+ align="center"
112
+ gap="md"
113
+ className="dataforms-layouts-details__summary-content"
114
+ >
115
+ { summaryContent }
116
+ { touched && <ValidationBadge validity={ validity } /> }
117
+ </Stack>
61
118
  </summary>
62
- <div className="dataforms-layouts-details__content">
119
+ <div
120
+ ref={ contentRef }
121
+ className="dataforms-layouts-details__content"
122
+ onBlur={ handleBlur }
123
+ >
63
124
  <DataFormLayout
64
125
  data={ data }
65
126
  form={ form }
66
127
  onChange={ onChange }
128
+ validity={ validity?.children }
67
129
  />
68
130
  </div>
69
131
  </details>
@@ -1,5 +1,10 @@
1
1
  @use "@wordpress/base-styles/variables" as *;
2
2
 
3
+ .dataforms-layouts-details__summary-content {
4
+ display: inline-flex;
5
+ min-height: $grid-unit-30;
6
+ }
7
+
3
8
  .dataforms-layouts-details__content {
4
9
  padding-top: $grid-unit-15;
5
10
  }
@@ -21,7 +21,7 @@ const FORM_FIELD_LAYOUTS = [
21
21
  <Stack
22
22
  direction="column"
23
23
  className="dataforms-layouts__wrapper"
24
- gap="md"
24
+ gap="lg"
25
25
  >
26
26
  { children }
27
27
  </Stack>
@@ -34,7 +34,7 @@ const FORM_FIELD_LAYOUTS = [
34
34
  <Stack
35
35
  direction="column"
36
36
  className="dataforms-layouts__wrapper"
37
- gap="xs"
37
+ gap="md"
38
38
  >
39
39
  { children }
40
40
  </Stack>
@@ -47,7 +47,7 @@ const FORM_FIELD_LAYOUTS = [
47
47
  <Stack
48
48
  direction="column"
49
49
  className="dataforms-layouts__wrapper"
50
- gap="lg"
50
+ gap="xl"
51
51
  >
52
52
  { children }
53
53
  </Stack>
@@ -66,12 +66,12 @@ const FORM_FIELD_LAYOUTS = [
66
66
  <Stack
67
67
  direction="column"
68
68
  className="dataforms-layouts__wrapper"
69
- gap="md"
69
+ gap="lg"
70
70
  >
71
71
  <div className="dataforms-layouts-row__field">
72
72
  <Stack
73
73
  direction="row"
74
- gap="md"
74
+ gap="lg"
75
75
  align={ ( layout as NormalizedRowLayout ).alignment }
76
76
  >
77
77
  { children }
@@ -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 ) {