@wordpress/dataviews 8.0.1-next.e256d081a.0 → 9.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 (415) hide show
  1. package/CHANGELOG.md +40 -1
  2. package/README.md +203 -13
  3. package/build/components/dataform-context/index.js +1 -0
  4. package/build/components/dataform-context/index.js.map +1 -1
  5. package/build/components/dataviews/index.js +11 -1
  6. package/build/components/dataviews/index.js.map +1 -1
  7. package/build/components/dataviews-context/index.js +1 -0
  8. package/build/components/dataviews-context/index.js.map +1 -1
  9. package/build/components/dataviews-filters/input-widget.js +48 -4
  10. package/build/components/dataviews-filters/input-widget.js.map +1 -1
  11. package/build/components/dataviews-layout/index.js +5 -2
  12. package/build/components/dataviews-layout/index.js.map +1 -1
  13. package/build/components/dataviews-picker/footer.js +145 -0
  14. package/build/components/dataviews-picker/footer.js.map +1 -0
  15. package/build/components/dataviews-picker/index.js +201 -0
  16. package/build/components/dataviews-picker/index.js.map +1 -0
  17. package/build/components/dataviews-selection-checkbox/index.js +4 -2
  18. package/build/components/dataviews-selection-checkbox/index.js.map +1 -1
  19. package/build/components/dataviews-view-config/index.js +1 -0
  20. package/build/components/dataviews-view-config/index.js.map +1 -1
  21. package/build/constants.js +4 -1
  22. package/build/constants.js.map +1 -1
  23. package/build/dataform-controls/array.js +9 -7
  24. package/build/dataform-controls/array.js.map +1 -1
  25. package/build/dataform-controls/checkbox.js +40 -8
  26. package/build/dataform-controls/checkbox.js.map +1 -1
  27. package/build/dataform-controls/color.js +133 -0
  28. package/build/dataform-controls/color.js.map +1 -0
  29. package/build/dataform-controls/date.js +32 -24
  30. package/build/dataform-controls/date.js.map +1 -1
  31. package/build/dataform-controls/datetime.js +133 -19
  32. package/build/dataform-controls/datetime.js.map +1 -1
  33. package/build/dataform-controls/email.js +15 -44
  34. package/build/dataform-controls/email.js.map +1 -1
  35. package/build/dataform-controls/index.js +35 -2
  36. package/build/dataform-controls/index.js.map +1 -1
  37. package/build/dataform-controls/integer.js +47 -34
  38. package/build/dataform-controls/integer.js.map +1 -1
  39. package/build/dataform-controls/password.js +47 -0
  40. package/build/dataform-controls/password.js.map +1 -0
  41. package/build/dataform-controls/radio.js +42 -9
  42. package/build/dataform-controls/radio.js.map +1 -1
  43. package/build/dataform-controls/relative-date-control.js +6 -10
  44. package/build/dataform-controls/relative-date-control.js.map +1 -1
  45. package/build/dataform-controls/select.js +41 -10
  46. package/build/dataform-controls/select.js.map +1 -1
  47. package/build/dataform-controls/telephone.js +40 -0
  48. package/build/dataform-controls/telephone.js.map +1 -0
  49. package/build/dataform-controls/text.js +14 -43
  50. package/build/dataform-controls/text.js.map +1 -1
  51. package/build/dataform-controls/textarea.js +81 -0
  52. package/build/dataform-controls/textarea.js.map +1 -0
  53. package/build/dataform-controls/toggle-group.js +36 -6
  54. package/build/dataform-controls/toggle-group.js.map +1 -1
  55. package/build/dataform-controls/toggle.js +77 -0
  56. package/build/dataform-controls/toggle.js.map +1 -0
  57. package/build/dataform-controls/url.js +40 -0
  58. package/build/dataform-controls/url.js.map +1 -0
  59. package/build/dataform-controls/utils/validated-input.js +83 -0
  60. package/build/dataform-controls/utils/validated-input.js.map +1 -0
  61. package/build/dataforms-layouts/card/index.js +6 -7
  62. package/build/dataforms-layouts/card/index.js.map +1 -1
  63. package/build/dataforms-layouts/data-form-layout.js +16 -4
  64. package/build/dataforms-layouts/data-form-layout.js.map +1 -1
  65. package/build/dataforms-layouts/index.js +31 -1
  66. package/build/dataforms-layouts/index.js.map +1 -1
  67. package/build/dataforms-layouts/panel/dropdown.js +10 -14
  68. package/build/dataforms-layouts/panel/dropdown.js.map +1 -1
  69. package/build/dataforms-layouts/panel/index.js +24 -11
  70. package/build/dataforms-layouts/panel/index.js.map +1 -1
  71. package/build/dataforms-layouts/panel/modal.js +22 -27
  72. package/build/dataforms-layouts/panel/modal.js.map +1 -1
  73. package/build/dataforms-layouts/panel/summary-button.js +67 -0
  74. package/build/dataforms-layouts/panel/summary-button.js.map +1 -0
  75. package/build/dataforms-layouts/regular/index.js +7 -9
  76. package/build/dataforms-layouts/regular/index.js.map +1 -1
  77. package/build/dataforms-layouts/row/index.js +113 -0
  78. package/build/dataforms-layouts/row/index.js.map +1 -0
  79. package/build/dataviews-layouts/grid/index.js +21 -26
  80. package/build/dataviews-layouts/grid/index.js.map +1 -1
  81. package/build/dataviews-layouts/index.js +9 -1
  82. package/build/dataviews-layouts/index.js.map +1 -1
  83. package/build/dataviews-layouts/list/index.js +47 -2
  84. package/build/dataviews-layouts/list/index.js.map +1 -1
  85. package/build/dataviews-layouts/picker-grid/index.js +347 -0
  86. package/build/dataviews-layouts/picker-grid/index.js.map +1 -0
  87. package/build/dataviews-layouts/table/index.js +5 -17
  88. package/build/dataviews-layouts/table/index.js.map +1 -1
  89. package/build/dataviews-layouts/utils/get-data-by-group.js +23 -0
  90. package/build/dataviews-layouts/utils/get-data-by-group.js.map +1 -0
  91. package/build/dataviews-layouts/utils/grid-items.js +37 -0
  92. package/build/dataviews-layouts/utils/grid-items.js.map +1 -0
  93. package/build/dataviews-layouts/utils/preview-size-picker.js +81 -0
  94. package/build/dataviews-layouts/utils/preview-size-picker.js.map +1 -0
  95. package/build/field-types/boolean.js +1 -1
  96. package/build/field-types/boolean.js.map +1 -1
  97. package/build/field-types/color.js +113 -0
  98. package/build/field-types/color.js.map +1 -0
  99. package/build/field-types/index.js +16 -0
  100. package/build/field-types/index.js.map +1 -1
  101. package/build/field-types/password.js +51 -0
  102. package/build/field-types/password.js.map +1 -0
  103. package/build/field-types/telephone.js +57 -0
  104. package/build/field-types/telephone.js.map +1 -0
  105. package/build/field-types/url.js +57 -0
  106. package/build/field-types/url.js.map +1 -0
  107. package/build/normalize-fields.js +17 -0
  108. package/build/normalize-fields.js.map +1 -1
  109. package/build/normalize-form-fields.js +6 -0
  110. package/build/normalize-form-fields.js.map +1 -1
  111. package/build/types.js.map +1 -1
  112. package/build/validation.js +1 -1
  113. package/build/validation.js.map +1 -1
  114. package/build-module/components/dataform-context/index.js +1 -0
  115. package/build-module/components/dataform-context/index.js.map +1 -1
  116. package/build-module/components/dataviews/index.js +11 -1
  117. package/build-module/components/dataviews/index.js.map +1 -1
  118. package/build-module/components/dataviews-context/index.js +1 -0
  119. package/build-module/components/dataviews-context/index.js.map +1 -1
  120. package/build-module/components/dataviews-filters/input-widget.js +48 -4
  121. package/build-module/components/dataviews-filters/input-widget.js.map +1 -1
  122. package/build-module/components/dataviews-layout/index.js +5 -2
  123. package/build-module/components/dataviews-layout/index.js.map +1 -1
  124. package/build-module/components/dataviews-picker/footer.js +136 -0
  125. package/build-module/components/dataviews-picker/footer.js.map +1 -0
  126. package/build-module/components/dataviews-picker/index.js +191 -0
  127. package/build-module/components/dataviews-picker/index.js.map +1 -0
  128. package/build-module/components/dataviews-selection-checkbox/index.js +4 -2
  129. package/build-module/components/dataviews-selection-checkbox/index.js.map +1 -1
  130. package/build-module/components/dataviews-view-config/index.js +1 -0
  131. package/build-module/components/dataviews-view-config/index.js.map +1 -1
  132. package/build-module/constants.js +3 -0
  133. package/build-module/constants.js.map +1 -1
  134. package/build-module/dataform-controls/array.js +9 -7
  135. package/build-module/dataform-controls/array.js.map +1 -1
  136. package/build-module/dataform-controls/checkbox.js +41 -9
  137. package/build-module/dataform-controls/checkbox.js.map +1 -1
  138. package/build-module/dataform-controls/color.js +126 -0
  139. package/build-module/dataform-controls/color.js.map +1 -0
  140. package/build-module/dataform-controls/date.js +32 -24
  141. package/build-module/dataform-controls/date.js.map +1 -1
  142. package/build-module/dataform-controls/datetime.js +135 -21
  143. package/build-module/dataform-controls/datetime.js.map +1 -1
  144. package/build-module/dataform-controls/email.js +15 -45
  145. package/build-module/dataform-controls/email.js.map +1 -1
  146. package/build-module/dataform-controls/index.js +35 -2
  147. package/build-module/dataform-controls/index.js.map +1 -1
  148. package/build-module/dataform-controls/integer.js +46 -34
  149. package/build-module/dataform-controls/integer.js.map +1 -1
  150. package/build-module/dataform-controls/password.js +38 -0
  151. package/build-module/dataform-controls/password.js.map +1 -0
  152. package/build-module/dataform-controls/radio.js +44 -11
  153. package/build-module/dataform-controls/radio.js.map +1 -1
  154. package/build-module/dataform-controls/relative-date-control.js +6 -10
  155. package/build-module/dataform-controls/relative-date-control.js.map +1 -1
  156. package/build-module/dataform-controls/select.js +43 -12
  157. package/build-module/dataform-controls/select.js.map +1 -1
  158. package/build-module/dataform-controls/telephone.js +33 -0
  159. package/build-module/dataform-controls/telephone.js.map +1 -0
  160. package/build-module/dataform-controls/text.js +14 -44
  161. package/build-module/dataform-controls/text.js.map +1 -1
  162. package/build-module/dataform-controls/textarea.js +74 -0
  163. package/build-module/dataform-controls/textarea.js.map +1 -0
  164. package/build-module/dataform-controls/toggle-group.js +38 -8
  165. package/build-module/dataform-controls/toggle-group.js.map +1 -1
  166. package/build-module/dataform-controls/toggle.js +70 -0
  167. package/build-module/dataform-controls/toggle.js.map +1 -0
  168. package/build-module/dataform-controls/url.js +33 -0
  169. package/build-module/dataform-controls/url.js.map +1 -0
  170. package/build-module/dataform-controls/utils/validated-input.js +76 -0
  171. package/build-module/dataform-controls/utils/validated-input.js.map +1 -0
  172. package/build-module/dataforms-layouts/card/index.js +6 -7
  173. package/build-module/dataforms-layouts/card/index.js.map +1 -1
  174. package/build-module/dataforms-layouts/data-form-layout.js +14 -4
  175. package/build-module/dataforms-layouts/data-form-layout.js.map +1 -1
  176. package/build-module/dataforms-layouts/index.js +32 -1
  177. package/build-module/dataforms-layouts/index.js.map +1 -1
  178. package/build-module/dataforms-layouts/panel/dropdown.js +10 -15
  179. package/build-module/dataforms-layouts/panel/dropdown.js.map +1 -1
  180. package/build-module/dataforms-layouts/panel/index.js +24 -11
  181. package/build-module/dataforms-layouts/panel/index.js.map +1 -1
  182. package/build-module/dataforms-layouts/panel/modal.js +22 -28
  183. package/build-module/dataforms-layouts/panel/modal.js.map +1 -1
  184. package/build-module/dataforms-layouts/panel/summary-button.js +60 -0
  185. package/build-module/dataforms-layouts/panel/summary-button.js.map +1 -0
  186. package/build-module/dataforms-layouts/regular/index.js +8 -10
  187. package/build-module/dataforms-layouts/regular/index.js.map +1 -1
  188. package/build-module/dataforms-layouts/row/index.js +106 -0
  189. package/build-module/dataforms-layouts/row/index.js.map +1 -0
  190. package/build-module/dataviews-layouts/grid/index.js +22 -27
  191. package/build-module/dataviews-layouts/grid/index.js.map +1 -1
  192. package/build-module/dataviews-layouts/index.js +10 -2
  193. package/build-module/dataviews-layouts/index.js.map +1 -1
  194. package/build-module/dataviews-layouts/list/index.js +48 -3
  195. package/build-module/dataviews-layouts/list/index.js.map +1 -1
  196. package/build-module/dataviews-layouts/picker-grid/index.js +338 -0
  197. package/build-module/dataviews-layouts/picker-grid/index.js.map +1 -0
  198. package/build-module/dataviews-layouts/table/index.js +5 -17
  199. package/build-module/dataviews-layouts/table/index.js.map +1 -1
  200. package/build-module/dataviews-layouts/utils/get-data-by-group.js +17 -0
  201. package/build-module/dataviews-layouts/utils/get-data-by-group.js.map +1 -0
  202. package/build-module/dataviews-layouts/utils/grid-items.js +29 -0
  203. package/build-module/dataviews-layouts/utils/grid-items.js.map +1 -0
  204. package/build-module/dataviews-layouts/utils/preview-size-picker.js +73 -0
  205. package/build-module/dataviews-layouts/utils/preview-size-picker.js.map +1 -0
  206. package/build-module/field-types/boolean.js +1 -1
  207. package/build-module/field-types/boolean.js.map +1 -1
  208. package/build-module/field-types/color.js +107 -0
  209. package/build-module/field-types/color.js.map +1 -0
  210. package/build-module/field-types/index.js +16 -0
  211. package/build-module/field-types/index.js.map +1 -1
  212. package/build-module/field-types/password.js +46 -0
  213. package/build-module/field-types/password.js.map +1 -0
  214. package/build-module/field-types/telephone.js +51 -0
  215. package/build-module/field-types/telephone.js.map +1 -0
  216. package/build-module/field-types/url.js +51 -0
  217. package/build-module/field-types/url.js.map +1 -0
  218. package/build-module/normalize-fields.js +15 -0
  219. package/build-module/normalize-fields.js.map +1 -1
  220. package/build-module/normalize-form-fields.js +6 -0
  221. package/build-module/normalize-form-fields.js.map +1 -1
  222. package/build-module/types.js.map +1 -1
  223. package/build-module/validation.js +1 -1
  224. package/build-module/validation.js.map +1 -1
  225. package/build-style/style-rtl.css +261 -18
  226. package/build-style/style.css +261 -18
  227. package/build-types/components/dataform/stories/index.story.d.ts +21 -17
  228. package/build-types/components/dataform/stories/index.story.d.ts.map +1 -1
  229. package/build-types/components/dataform-context/index.d.ts.map +1 -1
  230. package/build-types/components/dataviews/index.d.ts +1 -1
  231. package/build-types/components/dataviews/index.d.ts.map +1 -1
  232. package/build-types/components/dataviews/stories/fixtures.d.ts +4 -2
  233. package/build-types/components/dataviews/stories/fixtures.d.ts.map +1 -1
  234. package/build-types/components/dataviews/stories/index.story.d.ts.map +1 -1
  235. package/build-types/components/dataviews-context/index.d.ts +1 -0
  236. package/build-types/components/dataviews-context/index.d.ts.map +1 -1
  237. package/build-types/components/dataviews-filters/input-widget.d.ts.map +1 -1
  238. package/build-types/components/dataviews-layout/index.d.ts.map +1 -1
  239. package/build-types/components/dataviews-picker/footer.d.ts +4 -0
  240. package/build-types/components/dataviews-picker/footer.d.ts.map +1 -0
  241. package/build-types/components/dataviews-picker/index.d.ts +55 -0
  242. package/build-types/components/dataviews-picker/index.d.ts.map +1 -0
  243. package/build-types/components/dataviews-picker/stories/index.story.d.ts +42 -0
  244. package/build-types/components/dataviews-picker/stories/index.story.d.ts.map +1 -0
  245. package/build-types/components/dataviews-selection-checkbox/index.d.ts +2 -1
  246. package/build-types/components/dataviews-selection-checkbox/index.d.ts.map +1 -1
  247. package/build-types/components/dataviews-view-config/index.d.ts.map +1 -1
  248. package/build-types/constants.d.ts +1 -0
  249. package/build-types/constants.d.ts.map +1 -1
  250. package/build-types/dataform-controls/array.d.ts.map +1 -1
  251. package/build-types/dataform-controls/checkbox.d.ts.map +1 -1
  252. package/build-types/dataform-controls/color.d.ts +6 -0
  253. package/build-types/dataform-controls/color.d.ts.map +1 -0
  254. package/build-types/dataform-controls/date.d.ts.map +1 -1
  255. package/build-types/dataform-controls/datetime.d.ts.map +1 -1
  256. package/build-types/dataform-controls/email.d.ts.map +1 -1
  257. package/build-types/dataform-controls/index.d.ts +1 -1
  258. package/build-types/dataform-controls/index.d.ts.map +1 -1
  259. package/build-types/dataform-controls/integer.d.ts.map +1 -1
  260. package/build-types/dataform-controls/password.d.ts +3 -0
  261. package/build-types/dataform-controls/password.d.ts.map +1 -0
  262. package/build-types/dataform-controls/radio.d.ts.map +1 -1
  263. package/build-types/dataform-controls/relative-date-control.d.ts +6 -5
  264. package/build-types/dataform-controls/relative-date-control.d.ts.map +1 -1
  265. package/build-types/dataform-controls/select.d.ts.map +1 -1
  266. package/build-types/dataform-controls/telephone.d.ts +6 -0
  267. package/build-types/dataform-controls/telephone.d.ts.map +1 -0
  268. package/build-types/dataform-controls/text.d.ts +1 -1
  269. package/build-types/dataform-controls/text.d.ts.map +1 -1
  270. package/build-types/dataform-controls/textarea.d.ts +6 -0
  271. package/build-types/dataform-controls/textarea.d.ts.map +1 -0
  272. package/build-types/dataform-controls/toggle-group.d.ts.map +1 -1
  273. package/build-types/dataform-controls/toggle.d.ts +6 -0
  274. package/build-types/dataform-controls/toggle.d.ts.map +1 -0
  275. package/build-types/dataform-controls/url.d.ts +6 -0
  276. package/build-types/dataform-controls/url.d.ts.map +1 -0
  277. package/build-types/dataform-controls/utils/validated-input.d.ts +20 -0
  278. package/build-types/dataform-controls/utils/validated-input.d.ts.map +1 -0
  279. package/build-types/dataforms-layouts/card/index.d.ts +0 -3
  280. package/build-types/dataforms-layouts/card/index.d.ts.map +1 -1
  281. package/build-types/dataforms-layouts/data-form-layout.d.ts +4 -1
  282. package/build-types/dataforms-layouts/data-form-layout.d.ts.map +1 -1
  283. package/build-types/dataforms-layouts/index.d.ts +10 -0
  284. package/build-types/dataforms-layouts/index.d.ts.map +1 -1
  285. package/build-types/dataforms-layouts/panel/dropdown.d.ts +2 -1
  286. package/build-types/dataforms-layouts/panel/dropdown.d.ts.map +1 -1
  287. package/build-types/dataforms-layouts/panel/index.d.ts.map +1 -1
  288. package/build-types/dataforms-layouts/panel/modal.d.ts +2 -1
  289. package/build-types/dataforms-layouts/panel/modal.d.ts.map +1 -1
  290. package/build-types/dataforms-layouts/panel/summary-button.d.ts +15 -0
  291. package/build-types/dataforms-layouts/panel/summary-button.d.ts.map +1 -0
  292. package/build-types/dataforms-layouts/regular/index.d.ts.map +1 -1
  293. package/build-types/dataforms-layouts/row/index.d.ts +6 -0
  294. package/build-types/dataforms-layouts/row/index.d.ts.map +1 -0
  295. package/build-types/dataviews-layouts/grid/index.d.ts.map +1 -1
  296. package/build-types/dataviews-layouts/index.d.ts +12 -1
  297. package/build-types/dataviews-layouts/index.d.ts.map +1 -1
  298. package/build-types/dataviews-layouts/list/index.d.ts.map +1 -1
  299. package/build-types/dataviews-layouts/picker-grid/index.d.ts +4 -0
  300. package/build-types/dataviews-layouts/picker-grid/index.d.ts.map +1 -0
  301. package/build-types/dataviews-layouts/table/index.d.ts.map +1 -1
  302. package/build-types/dataviews-layouts/utils/get-data-by-group.d.ts +6 -0
  303. package/build-types/dataviews-layouts/utils/get-data-by-group.d.ts.map +1 -0
  304. package/build-types/dataviews-layouts/utils/grid-items.d.ts +5 -0
  305. package/build-types/dataviews-layouts/utils/grid-items.d.ts.map +1 -0
  306. package/build-types/dataviews-layouts/utils/preview-size-picker.d.ts +2 -0
  307. package/build-types/dataviews-layouts/utils/preview-size-picker.d.ts.map +1 -0
  308. package/build-types/field-types/color.d.ts +20 -0
  309. package/build-types/field-types/color.d.ts.map +1 -0
  310. package/build-types/field-types/index.d.ts.map +1 -1
  311. package/build-types/field-types/password.d.ts +17 -0
  312. package/build-types/field-types/password.d.ts.map +1 -0
  313. package/build-types/field-types/stories/index.story.d.ts +85 -0
  314. package/build-types/field-types/stories/index.story.d.ts.map +1 -0
  315. package/build-types/field-types/telephone.d.ts +20 -0
  316. package/build-types/field-types/telephone.d.ts.map +1 -0
  317. package/build-types/field-types/url.d.ts +20 -0
  318. package/build-types/field-types/url.d.ts.map +1 -0
  319. package/build-types/normalize-fields.d.ts +3 -0
  320. package/build-types/normalize-fields.d.ts.map +1 -1
  321. package/build-types/normalize-form-fields.d.ts.map +1 -1
  322. package/build-types/test/dataviews-picker.d.ts +2 -0
  323. package/build-types/test/dataviews-picker.d.ts.map +1 -0
  324. package/build-types/types.d.ts +102 -8
  325. package/build-types/types.d.ts.map +1 -1
  326. package/build-types/validation.d.ts.map +1 -1
  327. package/build-wp/index.js +6380 -5012
  328. package/package.json +17 -15
  329. package/src/components/dataform/stories/index.story.tsx +822 -28
  330. package/src/components/dataform-context/index.tsx +1 -0
  331. package/src/components/dataviews/index.tsx +25 -1
  332. package/src/components/dataviews/stories/fixtures.tsx +100 -42
  333. package/src/components/dataviews/stories/index.story.tsx +16 -2
  334. package/src/components/dataviews/style.scss +4 -2
  335. package/src/components/dataviews-context/index.ts +3 -0
  336. package/src/components/dataviews-filters/input-widget.tsx +44 -5
  337. package/src/components/dataviews-layout/index.tsx +5 -3
  338. package/src/components/dataviews-picker/footer.tsx +207 -0
  339. package/src/components/dataviews-picker/index.tsx +284 -0
  340. package/src/components/dataviews-picker/stories/index.story.tsx +251 -0
  341. package/src/components/dataviews-picker/style.scss +10 -0
  342. package/src/components/dataviews-selection-checkbox/index.tsx +3 -0
  343. package/src/components/dataviews-view-config/index.tsx +1 -0
  344. package/src/constants.ts +3 -0
  345. package/src/dataform-controls/array.tsx +4 -6
  346. package/src/dataform-controls/checkbox.tsx +54 -7
  347. package/src/dataform-controls/color.tsx +148 -0
  348. package/src/dataform-controls/date.tsx +47 -21
  349. package/src/dataform-controls/datetime.tsx +171 -23
  350. package/src/dataform-controls/email.tsx +18 -52
  351. package/src/dataform-controls/index.tsx +38 -2
  352. package/src/dataform-controls/integer.tsx +82 -49
  353. package/src/dataform-controls/password.tsx +50 -0
  354. package/src/dataform-controls/radio.tsx +53 -11
  355. package/src/dataform-controls/relative-date-control.tsx +11 -10
  356. package/src/dataform-controls/select.tsx +53 -10
  357. package/src/dataform-controls/telephone.tsx +38 -0
  358. package/src/dataform-controls/text.tsx +12 -50
  359. package/src/dataform-controls/textarea.tsx +85 -0
  360. package/src/dataform-controls/toggle-group.tsx +50 -10
  361. package/src/dataform-controls/toggle.tsx +79 -0
  362. package/src/dataform-controls/url.tsx +38 -0
  363. package/src/dataform-controls/utils/validated-input.tsx +109 -0
  364. package/src/dataforms-layouts/card/index.tsx +5 -4
  365. package/src/dataforms-layouts/card/style.scss +7 -0
  366. package/src/dataforms-layouts/data-form-layout.tsx +15 -3
  367. package/src/dataforms-layouts/index.tsx +35 -0
  368. package/src/dataforms-layouts/panel/dropdown.tsx +12 -23
  369. package/src/dataforms-layouts/panel/index.tsx +39 -16
  370. package/src/dataforms-layouts/panel/modal.tsx +24 -30
  371. package/src/dataforms-layouts/panel/summary-button.tsx +92 -0
  372. package/src/dataforms-layouts/regular/index.tsx +9 -7
  373. package/src/dataforms-layouts/regular/style.scss +0 -6
  374. package/src/dataforms-layouts/row/index.tsx +115 -0
  375. package/src/dataforms-layouts/row/style.scss +3 -0
  376. package/src/dataviews-layouts/grid/index.tsx +47 -47
  377. package/src/dataviews-layouts/grid/style.scss +43 -20
  378. package/src/dataviews-layouts/index.ts +16 -2
  379. package/src/dataviews-layouts/list/index.tsx +74 -2
  380. package/src/dataviews-layouts/list/style.scss +8 -0
  381. package/src/dataviews-layouts/picker-grid/index.tsx +486 -0
  382. package/src/dataviews-layouts/picker-grid/style.scss +171 -0
  383. package/src/dataviews-layouts/table/index.tsx +10 -14
  384. package/src/dataviews-layouts/utils/get-data-by-group.ts +18 -0
  385. package/src/dataviews-layouts/utils/grid-items.scss +21 -0
  386. package/src/dataviews-layouts/utils/grid-items.tsx +35 -0
  387. package/src/dataviews-layouts/utils/preview-size-picker.tsx +87 -0
  388. package/src/field-types/boolean.tsx +1 -1
  389. package/src/field-types/color.tsx +115 -0
  390. package/src/field-types/index.tsx +20 -0
  391. package/src/field-types/password.tsx +46 -0
  392. package/src/field-types/stories/index.story.tsx +856 -0
  393. package/src/field-types/telephone.tsx +71 -0
  394. package/src/field-types/url.tsx +71 -0
  395. package/src/normalize-fields.ts +18 -0
  396. package/src/normalize-form-fields.ts +6 -0
  397. package/src/style.scss +4 -0
  398. package/src/test/dataform.tsx +2 -2
  399. package/src/test/dataviews-picker.tsx +478 -0
  400. package/src/test/dataviews.tsx +86 -0
  401. package/src/test/filter-and-sort-data-view.js +148 -138
  402. package/src/test/normalize-fields.ts +114 -0
  403. package/src/types.ts +130 -7
  404. package/src/validation.ts +5 -0
  405. package/tsconfig.tsbuildinfo +1 -1
  406. package/build/dataform-controls/boolean.js +0 -64
  407. package/build/dataform-controls/boolean.js.map +0 -1
  408. package/build-module/dataform-controls/boolean.js +0 -58
  409. package/build-module/dataform-controls/boolean.js.map +0 -1
  410. package/build-types/components/stories/index.story.d.ts +0 -63
  411. package/build-types/components/stories/index.story.d.ts.map +0 -1
  412. package/build-types/dataform-controls/boolean.d.ts +0 -6
  413. package/build-types/dataform-controls/boolean.d.ts.map +0 -1
  414. package/src/components/stories/index.story.tsx +0 -372
  415. package/src/dataform-controls/boolean.tsx +0 -61
@@ -1,3 +1,8 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import deepMerge from 'deepmerge';
5
+
1
6
  /**
2
7
  * WordPress dependencies
3
8
  */
@@ -41,6 +46,14 @@ type SamplePost = {
41
46
  address1?: string;
42
47
  address2?: string;
43
48
  city?: string;
49
+ comment_status?: string;
50
+ ping_status?: boolean;
51
+ longDescription?: string;
52
+ origin?: string;
53
+ destination?: string;
54
+ flight_status?: string;
55
+ gate?: string;
56
+ seat?: string;
44
57
  };
45
58
 
46
59
  const fields: Field< SamplePost >[] = [
@@ -79,6 +92,9 @@ const fields: Field< SamplePost >[] = [
79
92
  { value: 3, label: 'Alice' },
80
93
  { value: 4, label: 'Bob' },
81
94
  ],
95
+ setValue: ( { value } ) => ( {
96
+ author: Number( value ),
97
+ } ),
82
98
  },
83
99
  {
84
100
  id: 'reviewer',
@@ -168,13 +184,91 @@ const fields: Field< SamplePost >[] = [
168
184
  label: 'City',
169
185
  type: 'text',
170
186
  },
187
+ {
188
+ id: 'description',
189
+ label: 'Description',
190
+ type: 'text',
191
+ Edit: 'textarea',
192
+ },
193
+ {
194
+ id: 'longDescription',
195
+ label: 'Long Description',
196
+ type: 'text',
197
+ Edit: {
198
+ control: 'textarea',
199
+ rows: 5,
200
+ },
201
+ },
202
+ {
203
+ id: 'comment_status',
204
+ label: 'Comment Status',
205
+ type: 'text',
206
+ Edit: 'radio',
207
+ elements: [
208
+ { value: 'open', label: 'Allow comments' },
209
+ { value: 'closed', label: 'Comments closed' },
210
+ ],
211
+ },
212
+ {
213
+ id: 'ping_status',
214
+ label: 'Allow Pings/Trackbacks',
215
+ type: 'boolean',
216
+ },
217
+ {
218
+ id: 'discussion',
219
+ label: 'Discussion',
220
+ type: 'text',
221
+ render: ( { item } ) => {
222
+ const commentLabel =
223
+ item.comment_status === 'open'
224
+ ? 'Allow comments'
225
+ : 'Comments closed';
226
+ const pingLabel = item.ping_status
227
+ ? 'Pings enabled'
228
+ : 'Pings disabled';
229
+ return (
230
+ <span>
231
+ { commentLabel }, { pingLabel }
232
+ </span>
233
+ );
234
+ },
235
+ },
236
+ {
237
+ id: 'origin',
238
+ label: 'Origin',
239
+ type: 'text',
240
+ },
241
+ {
242
+ id: 'destination',
243
+ label: 'Destination',
244
+ type: 'text',
245
+ },
246
+ {
247
+ id: 'flight_status',
248
+ label: 'Flight Status',
249
+ type: 'text',
250
+ Edit: 'radio',
251
+ elements: [
252
+ { value: 'on-time', label: 'On Time' },
253
+ { value: 'delayed', label: 'Delayed' },
254
+ { value: 'cancelled', label: 'Cancelled' },
255
+ ],
256
+ },
257
+ {
258
+ id: 'gate',
259
+ label: 'Gate',
260
+ type: 'text',
261
+ },
262
+ {
263
+ id: 'seat',
264
+ label: 'Seat',
265
+ type: 'text',
266
+ },
171
267
  ];
172
268
 
173
269
  const LayoutRegularComponent = ( {
174
- type = 'default',
175
270
  labelPosition,
176
271
  }: {
177
- type?: 'default' | 'regular' | 'panel' | 'card';
178
272
  labelPosition: 'default' | 'top' | 'side' | 'none';
179
273
  } ) => {
180
274
  const [ post, setPost ] = useState( {
@@ -191,12 +285,13 @@ const LayoutRegularComponent = ( {
191
285
  filesize: 1024,
192
286
  dimensions: '1920x1080',
193
287
  tags: [ 'photography' ],
288
+ description: 'This is a sample description.',
194
289
  } );
195
290
 
196
291
  const form: Form = useMemo(
197
292
  () => ( {
198
293
  layout: getLayoutFromStoryArgs( {
199
- type,
294
+ type: 'regular',
200
295
  labelPosition,
201
296
  } ),
202
297
  fields: [
@@ -214,9 +309,11 @@ const LayoutRegularComponent = ( {
214
309
  'filesize',
215
310
  'dimensions',
216
311
  'tags',
312
+ 'description',
313
+ 'longDescription',
217
314
  ],
218
315
  } ),
219
- [ type, labelPosition ]
316
+ [ labelPosition ]
220
317
  );
221
318
 
222
319
  return (
@@ -240,7 +337,7 @@ const getLayoutFromStoryArgs = ( {
240
337
  openAs,
241
338
  withHeader,
242
339
  }: {
243
- type: 'default' | 'regular' | 'panel' | 'card';
340
+ type: 'default' | 'regular' | 'panel' | 'card' | 'row';
244
341
  labelPosition?: 'default' | 'top' | 'side' | 'none';
245
342
  openAs?: 'default' | 'dropdown' | 'modal';
246
343
  withHeader?: boolean;
@@ -302,6 +399,13 @@ const LayoutPanelComponent = ( {
302
399
  address1: '123 Main St',
303
400
  address2: 'Apt 4B',
304
401
  city: 'New York',
402
+ comment_status: 'open',
403
+ ping_status: true,
404
+ origin: 'New York (JFK)',
405
+ destination: 'Los Angeles (LAX)',
406
+ flight_status: 'on-time',
407
+ gate: 'A12',
408
+ seat: '14F',
305
409
  } );
306
410
 
307
411
  const form: Form = useMemo( () => {
@@ -323,11 +427,34 @@ const LayoutPanelComponent = ( {
323
427
  'filesize',
324
428
  'dimensions',
325
429
  'tags',
430
+ {
431
+ id: 'discussion',
432
+ label: 'Discussion',
433
+ children: [ 'comment_status', 'ping_status' ],
434
+ summary: 'discussion',
435
+ },
326
436
  {
327
437
  id: 'address1',
328
438
  label: 'Combined Address',
329
439
  children: [ 'address1', 'address2', 'city' ],
330
440
  },
441
+ {
442
+ id: 'flight_info',
443
+ label: 'Flight Information',
444
+ children: [
445
+ 'origin',
446
+ 'destination',
447
+ 'flight_status',
448
+ 'gate',
449
+ ],
450
+ summary: [ 'origin', 'destination', 'flight_status' ],
451
+ },
452
+ {
453
+ id: 'passenger_details',
454
+ label: 'Passenger Details',
455
+ children: [ 'author', 'seat' ],
456
+ summary: [ 'author', 'seat' ],
457
+ },
331
458
  ],
332
459
  };
333
460
  }, [ labelPosition, openAs ] );
@@ -353,15 +480,13 @@ function CustomEditControl< Item >( {
353
480
  onChange,
354
481
  hideLabelFromVision,
355
482
  }: DataFormControlProps< Item > ) {
356
- const { id, label, placeholder, description } = field;
357
- const value = field.getValue( { item: data } );
483
+ const { label, placeholder, description, getValue, setValue } = field;
484
+ const value = getValue( { item: data } );
358
485
 
359
486
  const onChangeControl = useCallback(
360
487
  ( newValue: string ) =>
361
- onChange( {
362
- [ id ]: newValue,
363
- } ),
364
- [ id, onChange ]
488
+ onChange( setValue( { item: data, value: newValue } ) ),
489
+ [ data, onChange, setValue ]
365
490
  );
366
491
 
367
492
  return (
@@ -390,18 +515,36 @@ const ValidationComponent = ( {
390
515
  } ) => {
391
516
  type ValidatedItem = {
392
517
  text: string;
518
+ select?: string;
519
+ textWithRadio?: string;
520
+ textarea: string;
393
521
  email: string;
522
+ telephone: string;
523
+ url: string;
524
+ color: string;
394
525
  integer: number;
395
526
  boolean: boolean;
396
527
  customEdit: string;
528
+ password: string;
529
+ toggle?: boolean;
530
+ toggleGroup?: string;
397
531
  };
398
532
 
399
533
  const [ post, setPost ] = useState< ValidatedItem >( {
400
534
  text: 'Can have letters and spaces',
535
+ select: undefined,
536
+ textWithRadio: undefined,
537
+ textarea: 'Can have letters and spaces',
401
538
  email: 'hi@example.com',
539
+ telephone: '+306978241796',
540
+ url: 'https://example.com',
541
+ color: '#ff6600',
402
542
  integer: 2,
403
543
  boolean: true,
404
544
  customEdit: 'custom control',
545
+ password: 'secretpassword123',
546
+ toggle: undefined,
547
+ toggleGroup: undefined,
405
548
  } );
406
549
 
407
550
  const customTextRule = ( value: ValidatedItem ) => {
@@ -411,6 +554,29 @@ const ValidationComponent = ( {
411
554
 
412
555
  return null;
413
556
  };
557
+
558
+ const customSelectRule = ( value: ValidatedItem ) => {
559
+ if ( value.select !== 'option1' ) {
560
+ return 'Value must be Option 1.';
561
+ }
562
+ return null;
563
+ };
564
+
565
+ const customTextRadioRule = ( value: ValidatedItem ) => {
566
+ if ( value.textWithRadio !== 'item1' ) {
567
+ return 'Value must be Item 1.';
568
+ }
569
+
570
+ return null;
571
+ };
572
+
573
+ const customTextareaRule = ( value: ValidatedItem ) => {
574
+ if ( ! /^[a-zA-Z ]+$/.test( value.textarea ) ) {
575
+ return 'Value must only contain letters and spaces.';
576
+ }
577
+
578
+ return null;
579
+ };
414
580
  const customEmailRule = ( value: ValidatedItem ) => {
415
581
  if ( ! /^[a-zA-Z0-9._%+-]+@example\.com$/.test( value.email ) ) {
416
582
  return 'Email address must be from @example.com domain.';
@@ -418,6 +584,27 @@ const ValidationComponent = ( {
418
584
 
419
585
  return null;
420
586
  };
587
+ const customTelephoneRule = ( value: ValidatedItem ) => {
588
+ if ( ! /^\+30\d{10}$/.test( value.telephone ) ) {
589
+ return 'Telephone number must start with +30 and have 10 digits after.';
590
+ }
591
+
592
+ return null;
593
+ };
594
+ const customUrlRule = ( value: ValidatedItem ) => {
595
+ if ( ! /^https:\/\/example\.com$/.test( value.url ) ) {
596
+ return 'URL must be from https://example.com domain.';
597
+ }
598
+
599
+ return null;
600
+ };
601
+ const customColorRule = ( value: ValidatedItem ) => {
602
+ if ( ! /^#[0-9A-Fa-f]{6}$/.test( value.color ) ) {
603
+ return 'Color must be a valid hex format (e.g., #ff6600).';
604
+ }
605
+
606
+ return null;
607
+ };
421
608
  const customIntegerRule = ( value: ValidatedItem ) => {
422
609
  if ( value.integer % 2 !== 0 ) {
423
610
  return 'Integer must be an even number.';
@@ -425,6 +612,41 @@ const ValidationComponent = ( {
425
612
 
426
613
  return null;
427
614
  };
615
+ const customBooleanRule = ( value: ValidatedItem ) => {
616
+ if ( value.boolean !== true ) {
617
+ return 'Boolean must be active.';
618
+ }
619
+
620
+ return null;
621
+ };
622
+ const customToggleRule = ( value: ValidatedItem ) => {
623
+ if ( value.toggle !== true ) {
624
+ return 'Toggle must be checked.';
625
+ }
626
+
627
+ return null;
628
+ };
629
+ const customToggleGroupRule = ( value: ValidatedItem ) => {
630
+ if ( value.toggleGroup !== 'option1' ) {
631
+ return 'Value must be Option 1.';
632
+ }
633
+
634
+ return null;
635
+ };
636
+
637
+ const customPasswordRule = ( value: ValidatedItem ) => {
638
+ if ( value.password.length < 8 ) {
639
+ return 'Password must be at least 8 characters long.';
640
+ }
641
+ if ( ! /[A-Z]/.test( value.password ) ) {
642
+ return 'Password must contain at least one uppercase letter.';
643
+ }
644
+ if ( ! /[0-9]/.test( value.password ) ) {
645
+ return 'Password must contain at least one number.';
646
+ }
647
+
648
+ return null;
649
+ };
428
650
 
429
651
  const maybeCustomRule = (
430
652
  rule: ( item: ValidatedItem ) => null | string
@@ -442,6 +664,43 @@ const ValidationComponent = ( {
442
664
  custom: maybeCustomRule( customTextRule ),
443
665
  },
444
666
  },
667
+ {
668
+ id: 'select',
669
+ type: 'text',
670
+ label: 'Select',
671
+ elements: [
672
+ { value: 'option1', label: 'Option 1' },
673
+ { value: 'option2', label: 'Option 2' },
674
+ ],
675
+ isValid: {
676
+ required,
677
+ custom: maybeCustomRule( customSelectRule ),
678
+ },
679
+ },
680
+ {
681
+ id: 'textWithRadio',
682
+ type: 'text',
683
+ Edit: 'radio',
684
+ label: 'Text with radio',
685
+ elements: [
686
+ { value: 'item1', label: 'Item 1' },
687
+ { value: 'item2', label: 'Item 2' },
688
+ ],
689
+ isValid: {
690
+ required,
691
+ custom: maybeCustomRule( customTextRadioRule ),
692
+ },
693
+ },
694
+ {
695
+ id: 'textarea',
696
+ type: 'text',
697
+ Edit: 'textarea',
698
+ label: 'Textarea',
699
+ isValid: {
700
+ required,
701
+ custom: maybeCustomRule( customTextareaRule ),
702
+ },
703
+ },
445
704
  {
446
705
  id: 'email',
447
706
  type: 'email',
@@ -451,6 +710,33 @@ const ValidationComponent = ( {
451
710
  custom: maybeCustomRule( customEmailRule ),
452
711
  },
453
712
  },
713
+ {
714
+ id: 'telephone',
715
+ type: 'telephone',
716
+ label: 'telephone',
717
+ isValid: {
718
+ required,
719
+ custom: maybeCustomRule( customTelephoneRule ),
720
+ },
721
+ },
722
+ {
723
+ id: 'url',
724
+ type: 'url',
725
+ label: 'URL',
726
+ isValid: {
727
+ required,
728
+ custom: maybeCustomRule( customUrlRule ),
729
+ },
730
+ },
731
+ {
732
+ id: 'color',
733
+ type: 'color',
734
+ label: 'Color',
735
+ isValid: {
736
+ required,
737
+ custom: maybeCustomRule( customColorRule ),
738
+ },
739
+ },
454
740
  {
455
741
  id: 'integer',
456
742
  type: 'integer',
@@ -466,6 +752,7 @@ const ValidationComponent = ( {
466
752
  label: 'Boolean',
467
753
  isValid: {
468
754
  required,
755
+ custom: maybeCustomRule( customBooleanRule ),
469
756
  },
470
757
  },
471
758
  {
@@ -476,11 +763,60 @@ const ValidationComponent = ( {
476
763
  required,
477
764
  },
478
765
  },
766
+ {
767
+ id: 'password',
768
+ type: 'password',
769
+ label: 'Password',
770
+ isValid: {
771
+ required,
772
+ custom: maybeCustomRule( customPasswordRule ),
773
+ },
774
+ },
775
+ {
776
+ id: 'toggle',
777
+ type: 'boolean',
778
+ label: 'Toggle',
779
+ Edit: 'toggle',
780
+ isValid: {
781
+ required,
782
+ custom: maybeCustomRule( customToggleRule ),
783
+ },
784
+ },
785
+ {
786
+ id: 'toggleGroup',
787
+ type: 'text',
788
+ label: 'Toggle Group',
789
+ Edit: 'toggleGroup',
790
+ elements: [
791
+ { value: 'option1', label: 'Option 1' },
792
+ { value: 'option2', label: 'Option 2' },
793
+ { value: 'option3', label: 'Option 3' },
794
+ ],
795
+ isValid: {
796
+ required,
797
+ custom: maybeCustomRule( customToggleGroupRule ),
798
+ },
799
+ },
479
800
  ];
480
801
 
481
802
  const form = {
482
803
  layout: { type },
483
- fields: [ 'text', 'email', 'integer', 'boolean', 'customEdit' ],
804
+ fields: [
805
+ 'text',
806
+ 'select',
807
+ 'textWithRadio',
808
+ 'textarea',
809
+ 'email',
810
+ 'telephone',
811
+ 'url',
812
+ 'color',
813
+ 'integer',
814
+ 'boolean',
815
+ 'toggle',
816
+ 'toggleGroup',
817
+ 'password',
818
+ 'customEdit',
819
+ ],
484
820
  };
485
821
 
486
822
  const canSave = isItemValid( post, _fields, form );
@@ -671,6 +1007,8 @@ const LayoutCardComponent = ( { withHeader }: { withHeader: boolean } ) => {
671
1007
  {
672
1008
  id: 'customerCard',
673
1009
  label: 'Customer',
1010
+ description:
1011
+ 'Enter your contact details, plan type, and addresses to complete your customer information.',
674
1012
  children: [
675
1013
  {
676
1014
  id: 'customerContact',
@@ -751,6 +1089,247 @@ const LayoutCardComponent = ( { withHeader }: { withHeader: boolean } ) => {
751
1089
  );
752
1090
  };
753
1091
 
1092
+ const LayoutRowComponent = ( {
1093
+ alignment,
1094
+ }: {
1095
+ alignment: 'start' | 'center' | 'end';
1096
+ } ) => {
1097
+ type Customer = {
1098
+ name: string;
1099
+ email: string;
1100
+ phone: string;
1101
+ plan: string;
1102
+ shippingAddress: string;
1103
+ shippingCity: string;
1104
+ shippingPostalCode: string;
1105
+ shippingCountry: string;
1106
+ billingAddress: string;
1107
+ billingCity: string;
1108
+ billingPostalCode: string;
1109
+ totalOrders: number;
1110
+ totalRevenue: number;
1111
+ averageOrderValue: number;
1112
+ hasVat: boolean;
1113
+ hasDiscount: boolean;
1114
+ vat: number;
1115
+ commission: number;
1116
+ };
1117
+
1118
+ const customerFields: Field< Customer >[] = [
1119
+ {
1120
+ id: 'name',
1121
+ label: 'Customer Name',
1122
+ type: 'text',
1123
+ },
1124
+ {
1125
+ id: 'phone',
1126
+ label: 'Phone',
1127
+ type: 'text',
1128
+ },
1129
+ {
1130
+ id: 'email',
1131
+ label: 'Email',
1132
+ type: 'email',
1133
+ },
1134
+ {
1135
+ id: 'shippingAddress',
1136
+ label: 'Shipping Address',
1137
+ type: 'text',
1138
+ },
1139
+ {
1140
+ id: 'shippingCity',
1141
+ label: 'Shipping City',
1142
+ type: 'text',
1143
+ },
1144
+ {
1145
+ id: 'shippingPostalCode',
1146
+ label: 'Shipping Postal Code',
1147
+ type: 'text',
1148
+ },
1149
+ {
1150
+ id: 'shippingCountry',
1151
+ label: 'Shipping Country',
1152
+ type: 'text',
1153
+ },
1154
+ {
1155
+ id: 'billingAddress',
1156
+ label: 'Billing Address',
1157
+ type: 'text',
1158
+ },
1159
+ {
1160
+ id: 'billingCity',
1161
+ label: 'Billing City',
1162
+ type: 'text',
1163
+ },
1164
+ {
1165
+ id: 'billingPostalCode',
1166
+ label: 'Billing Postal Code',
1167
+ type: 'text',
1168
+ },
1169
+ {
1170
+ id: 'vat',
1171
+ label: 'VAT',
1172
+ type: 'integer',
1173
+ },
1174
+ {
1175
+ id: 'commission',
1176
+ label: 'Commission',
1177
+ type: 'integer',
1178
+ },
1179
+ {
1180
+ id: 'hasDiscount',
1181
+ label: 'Has Discount?',
1182
+ type: 'boolean',
1183
+ },
1184
+ {
1185
+ id: 'plan',
1186
+ label: 'Plan',
1187
+ type: 'text',
1188
+ Edit: 'toggleGroup',
1189
+ elements: [
1190
+ { value: 'basic', label: 'Basic' },
1191
+ { value: 'business', label: 'Business' },
1192
+ { value: 'vip', label: 'VIP' },
1193
+ ],
1194
+ },
1195
+ {
1196
+ id: 'renewal',
1197
+ label: 'Renewal',
1198
+ type: 'text',
1199
+ Edit: 'radio',
1200
+ elements: [
1201
+ { value: 'weekly', label: 'Weekly' },
1202
+ { value: 'monthly', label: 'Monthly' },
1203
+ { value: 'yearly', label: 'Yearly' },
1204
+ ],
1205
+ },
1206
+ ];
1207
+
1208
+ const [ customer, setCustomer ] = useState< Customer >( {
1209
+ name: 'Danyka Romaguera',
1210
+ email: 'aromaguera@example.org',
1211
+ phone: '1-828-352-1250',
1212
+ plan: 'Business',
1213
+ shippingAddress: 'N/A',
1214
+ shippingCity: 'N/A',
1215
+ shippingPostalCode: 'N/A',
1216
+ shippingCountry: 'N/A',
1217
+ billingAddress: 'Danyka Romaguera, West Myrtiehaven, 80240-4282, BI',
1218
+ billingCity: 'City',
1219
+ billingPostalCode: 'PC',
1220
+ totalOrders: 2,
1221
+ totalRevenue: 1430,
1222
+ averageOrderValue: 715,
1223
+ hasVat: true,
1224
+ vat: 10,
1225
+ commission: 5,
1226
+ hasDiscount: true,
1227
+ } );
1228
+
1229
+ const form: Form = useMemo(
1230
+ () => ( {
1231
+ fields: [
1232
+ {
1233
+ id: 'customer',
1234
+ label: 'Customer',
1235
+ layout: {
1236
+ type: 'row',
1237
+ alignment,
1238
+ },
1239
+ children: [ 'name', 'phone', 'email' ],
1240
+ },
1241
+ {
1242
+ id: 'addressRow',
1243
+ label: 'Billing & Shipping Addresses',
1244
+ layout: {
1245
+ type: 'row',
1246
+ alignment,
1247
+ },
1248
+ children: [
1249
+ {
1250
+ id: 'billingAddress',
1251
+ children: [
1252
+ 'billingAddress',
1253
+ 'billingCity',
1254
+ 'billingPostalCode',
1255
+ ],
1256
+ },
1257
+ {
1258
+ id: 'shippingAddress',
1259
+ children: [
1260
+ 'shippingAddress',
1261
+ 'shippingCity',
1262
+ 'shippingPostalCode',
1263
+ 'shippingCountry',
1264
+ ],
1265
+ },
1266
+ ],
1267
+ },
1268
+ {
1269
+ id: 'payments-and-tax',
1270
+ label: 'Payments & Taxes',
1271
+ layout: {
1272
+ type: 'row',
1273
+ alignment,
1274
+ },
1275
+ children: [ 'vat', 'commission', 'hasDiscount' ],
1276
+ },
1277
+ {
1278
+ id: 'planRow',
1279
+ label: 'Subscription',
1280
+ layout: {
1281
+ type: 'row',
1282
+ alignment,
1283
+ },
1284
+ children: [ 'plan', 'renewal' ],
1285
+ },
1286
+ ],
1287
+ } ),
1288
+ [ alignment ]
1289
+ );
1290
+
1291
+ const topLevelLayout: Form = useMemo(
1292
+ () => ( {
1293
+ layout: {
1294
+ type: 'row',
1295
+ alignment,
1296
+ },
1297
+ fields: [ 'name', 'phone', 'email' ],
1298
+ } ),
1299
+ [ alignment ]
1300
+ );
1301
+
1302
+ return (
1303
+ <>
1304
+ <h1>Row Layout</h1>
1305
+ <h2>As top-level layout</h2>
1306
+ <DataForm
1307
+ data={ customer }
1308
+ fields={ customerFields }
1309
+ form={ topLevelLayout }
1310
+ onChange={ ( edits ) =>
1311
+ setCustomer( ( prev ) => ( {
1312
+ ...prev,
1313
+ ...edits,
1314
+ } ) )
1315
+ }
1316
+ />
1317
+ <h2>Per field layout</h2>
1318
+ <DataForm
1319
+ data={ customer }
1320
+ fields={ customerFields }
1321
+ form={ form }
1322
+ onChange={ ( edits ) =>
1323
+ setCustomer( ( prev ) => ( {
1324
+ ...prev,
1325
+ ...edits,
1326
+ } ) )
1327
+ }
1328
+ />
1329
+ </>
1330
+ );
1331
+ };
1332
+
754
1333
  const LayoutMixedComponent = () => {
755
1334
  const [ post, setPost ] = useState< SamplePost >( {
756
1335
  title: 'Hello, World!',
@@ -767,14 +1346,18 @@ const LayoutMixedComponent = () => {
767
1346
  const form: Form = {
768
1347
  fields: [
769
1348
  {
770
- id: 'title',
1349
+ id: 'title-and-status',
1350
+ children: [
1351
+ {
1352
+ id: 'title',
1353
+ layout: { type: 'panel' },
1354
+ },
1355
+ 'status',
1356
+ ],
771
1357
  layout: {
772
- type: 'panel',
773
- labelPosition: 'top',
774
- openAs: 'dropdown',
1358
+ type: 'row',
775
1359
  },
776
1360
  },
777
- 'status',
778
1361
  {
779
1362
  id: 'order',
780
1363
  layout: {
@@ -814,17 +1397,6 @@ const meta = {
814
1397
  };
815
1398
  export default meta;
816
1399
 
817
- export const Default = {
818
- render: LayoutRegularComponent,
819
- argTypes: {
820
- type: {
821
- control: { type: 'select' },
822
- description: 'Chooses the layout type.',
823
- options: [ 'default', 'card', 'panel', 'regular' ],
824
- },
825
- },
826
- };
827
-
828
1400
  export const LayoutCard = {
829
1401
  render: LayoutCardComponent,
830
1402
  argTypes: {
@@ -865,6 +1437,20 @@ export const LayoutRegular = {
865
1437
  },
866
1438
  };
867
1439
 
1440
+ export const LayoutRow = {
1441
+ render: LayoutRowComponent,
1442
+ argTypes: {
1443
+ alignment: {
1444
+ control: { type: 'select' },
1445
+ description: 'The alignment of the fields.',
1446
+ options: [ 'start', 'center', 'end' ],
1447
+ },
1448
+ },
1449
+ args: {
1450
+ alignment: 'center',
1451
+ },
1452
+ };
1453
+
868
1454
  export const LayoutMixed = {
869
1455
  render: LayoutMixedComponent,
870
1456
  };
@@ -896,3 +1482,211 @@ export const Validation = {
896
1482
  export const Visibility = {
897
1483
  render: VisibilityComponent,
898
1484
  };
1485
+
1486
+ const DataAdapterComponent = () => {
1487
+ type DataAdapterItem = {
1488
+ user: {
1489
+ profile: {
1490
+ name: string;
1491
+ email: string;
1492
+ };
1493
+ preferences: {
1494
+ notifications: boolean;
1495
+ };
1496
+ };
1497
+ revenue: {
1498
+ total: number;
1499
+ units: number;
1500
+ pricePerUnit: number;
1501
+ };
1502
+ };
1503
+
1504
+ const [ data, setData ] = useState< DataAdapterItem >( {
1505
+ user: {
1506
+ profile: {
1507
+ name: 'John Doe',
1508
+ email: 'john@example.com',
1509
+ },
1510
+ preferences: {
1511
+ notifications: true,
1512
+ },
1513
+ },
1514
+ revenue: {
1515
+ total: 30,
1516
+ units: 10,
1517
+ pricePerUnit: 3,
1518
+ },
1519
+ } );
1520
+
1521
+ const nestedFields: Field< DataAdapterItem >[] = [
1522
+ // Examples of autogenerated getValue/setValue methods
1523
+ // for nested data based on the field id.
1524
+ {
1525
+ id: 'user.profile.name',
1526
+ label: 'User Name',
1527
+ type: 'text',
1528
+ },
1529
+ {
1530
+ id: 'user.profile.email',
1531
+ label: 'User Email',
1532
+ type: 'email',
1533
+ },
1534
+ // Example of adapting a data value to a control value
1535
+ // by providing getValue/setValue methods.
1536
+ {
1537
+ id: 'user.preferences.notifications',
1538
+ label: 'Notifications',
1539
+ type: 'boolean',
1540
+ Edit: 'radio',
1541
+ elements: [
1542
+ { label: 'Enabled', value: 'enabled' },
1543
+ { label: 'Disabled', value: 'disabled' },
1544
+ ],
1545
+ getValue: ( { item } ) =>
1546
+ item.user.preferences.notifications === true
1547
+ ? 'enabled'
1548
+ : 'disabled',
1549
+ setValue: ( { value } ) => ( {
1550
+ user: {
1551
+ preferences: { notifications: value === 'enabled' },
1552
+ },
1553
+ } ),
1554
+ },
1555
+ // Example of deriving data by leveraging setValue method.
1556
+ {
1557
+ id: 'revenue.total',
1558
+ label: 'Total Revenue',
1559
+ type: 'integer',
1560
+ readOnly: true,
1561
+ },
1562
+ {
1563
+ id: 'revenue.pricePerUnit',
1564
+ label: 'Price Per Unit',
1565
+ type: 'integer',
1566
+ setValue: ( { item, value } ) => ( {
1567
+ revenue: {
1568
+ total: value * item.revenue.units,
1569
+ pricePerUnit: value,
1570
+ },
1571
+ } ),
1572
+ },
1573
+ {
1574
+ id: 'revenue.units',
1575
+ label: 'Units',
1576
+ type: 'integer',
1577
+ setValue: ( { item, value } ) => ( {
1578
+ revenue: {
1579
+ total: item.revenue.pricePerUnit * value,
1580
+ units: value,
1581
+ },
1582
+ } ),
1583
+ },
1584
+ ];
1585
+
1586
+ const handleChange = useCallback( ( edits: any ) => {
1587
+ // Edits will respect the shape of the data
1588
+ // because fields provide the proper information
1589
+ // (via field.id or via field.setValue).
1590
+ setData( ( prev ) => deepMerge( prev, edits ) );
1591
+ }, [] );
1592
+
1593
+ return (
1594
+ <>
1595
+ <h1>Data adapter</h1>
1596
+ <p>
1597
+ This story is best looked at with the code on the side. It aims
1598
+ to highlight how DataForm can wrangle data in scenarios such as
1599
+ nested data, bridge data to/from UI controls, and derived data.
1600
+ </p>
1601
+ <p>
1602
+ <b>Current data snapshot:</b>
1603
+ </p>
1604
+ <pre>{ JSON.stringify( data, null, 2 ) }</pre>
1605
+ <h2>Nested data</h2>
1606
+ <p>
1607
+ The first example demonstrates how to signal nested data via{ ' ' }
1608
+ <code>field.id</code>.
1609
+ </p>
1610
+ <p>
1611
+ By using <code>{ `{ id: 'user.profile.name' }` }</code> as field
1612
+ id, when users edit the name, the edits will come in this shape:
1613
+ <code>{ `{ user: { profile: { name: 'John Doe' } } }` }</code>
1614
+ </p>
1615
+ <DataForm< DataAdapterItem >
1616
+ data={ data }
1617
+ fields={ nestedFields }
1618
+ form={ {
1619
+ layout: {
1620
+ type: 'panel',
1621
+ labelPosition: 'top',
1622
+ openAs: 'modal',
1623
+ },
1624
+ fields: [
1625
+ {
1626
+ id: 'userProfile',
1627
+ label: 'User Profile',
1628
+ children: [
1629
+ 'user.profile.name',
1630
+ 'user.profile.email',
1631
+ ],
1632
+ },
1633
+ ],
1634
+ } }
1635
+ onChange={ handleChange }
1636
+ />
1637
+ <h2>Adapt data and UI control</h2>
1638
+ <p>
1639
+ Sometimes, we need to adapt the data type to and from the UI
1640
+ control response. This example demonstrates how to adapt a
1641
+ boolean to a text string (Enabled/Disabled).
1642
+ </p>
1643
+ <DataForm< DataAdapterItem >
1644
+ data={ data }
1645
+ fields={ nestedFields }
1646
+ form={ {
1647
+ layout: {
1648
+ type: 'panel',
1649
+ labelPosition: 'top',
1650
+ openAs: 'modal',
1651
+ },
1652
+ fields: [ 'user.preferences.notifications' ],
1653
+ } }
1654
+ onChange={ handleChange }
1655
+ />
1656
+ <h2>Derived data</h2>
1657
+ <p>
1658
+ Last, but not least, this example showcases how to work with
1659
+ derived data by providing a custom setValue function. Note how,
1660
+ changing UNITS or PRICE PER UNIT, updates the TOTAL value as
1661
+ well.
1662
+ </p>
1663
+ <DataForm< DataAdapterItem >
1664
+ data={ data }
1665
+ fields={ nestedFields }
1666
+ form={ {
1667
+ layout: {
1668
+ type: 'panel',
1669
+ labelPosition: 'top',
1670
+ openAs: 'modal',
1671
+ },
1672
+ fields: [
1673
+ {
1674
+ id: 'revenue',
1675
+ label: 'Revenue',
1676
+ children: [
1677
+ 'revenue.pricePerUnit',
1678
+ 'revenue.units',
1679
+ 'revenue.total',
1680
+ ],
1681
+ },
1682
+ ],
1683
+ } }
1684
+ onChange={ handleChange }
1685
+ />
1686
+ </>
1687
+ );
1688
+ };
1689
+
1690
+ export const DataAdapter = {
1691
+ render: DataAdapterComponent,
1692
+ };