@wordpress/widget-dashboard 0.2.0 → 0.3.1-next.v.202607070741.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 (269) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +10 -16
  3. package/build/components/actions/actions.cjs +2 -19
  4. package/build/components/actions/actions.cjs.map +3 -3
  5. package/build/components/commands/commands.cjs +1 -60
  6. package/build/components/commands/commands.cjs.map +2 -2
  7. package/build/{utils/grid-model-change → components/widget-attribute-controls}/index.cjs +7 -9
  8. package/build/components/widget-attribute-controls/index.cjs.map +7 -0
  9. package/build/components/widget-attribute-controls/widget-attribute-controls.cjs +93 -0
  10. package/build/components/widget-attribute-controls/widget-attribute-controls.cjs.map +7 -0
  11. package/build/components/widget-chrome/widget-chrome.cjs +16 -63
  12. package/build/components/widget-chrome/widget-chrome.cjs.map +2 -2
  13. package/build/components/{layout-settings → widget-frame}/index.cjs +9 -7
  14. package/build/components/widget-frame/index.cjs.map +7 -0
  15. package/build/components/widget-frame/widget-frame.cjs +193 -0
  16. package/build/components/widget-frame/widget-frame.cjs.map +7 -0
  17. package/build/{utils/migrate-layout → components/widget-header}/index.cjs +7 -7
  18. package/build/components/widget-header/index.cjs.map +7 -0
  19. package/build/components/widget-header/widget-header-infotip.cjs +166 -0
  20. package/build/components/widget-header/widget-header-infotip.cjs.map +7 -0
  21. package/build/components/widget-header/widget-header.cjs +173 -0
  22. package/build/components/widget-header/widget-header.cjs.map +7 -0
  23. package/build/components/{widget-settings/utils/get-admin-menu-inset.cjs → widget-layout-controls/index.cjs} +8 -18
  24. package/build/components/widget-layout-controls/index.cjs.map +7 -0
  25. package/build/components/{widgets/widget-layout-toolbar.cjs → widget-layout-controls/widget-layout-controls.cjs} +9 -100
  26. package/build/components/widget-layout-controls/widget-layout-controls.cjs.map +7 -0
  27. package/build/components/widget-picker/widget-picker.cjs +5 -93
  28. package/build/components/widget-picker/widget-picker.cjs.map +3 -3
  29. package/build/components/widget-preview-chrome/index.cjs +31 -0
  30. package/build/components/widget-preview-chrome/index.cjs.map +7 -0
  31. package/build/components/{widget-settings/widget-settings-toolbar.cjs → widget-preview-chrome/widget-preview-chrome.cjs} +41 -23
  32. package/build/components/widget-preview-chrome/widget-preview-chrome.cjs.map +7 -0
  33. package/build/components/widget-settings/index.cjs +3 -3
  34. package/build/components/widget-settings/index.cjs.map +1 -1
  35. package/build/components/widget-settings/utils/index.cjs +0 -3
  36. package/build/components/widget-settings/utils/index.cjs.map +2 -2
  37. package/build/components/widget-settings/widget-settings-trigger.cjs +22 -28
  38. package/build/components/widget-settings/widget-settings-trigger.cjs.map +2 -2
  39. package/build/components/widget-settings/widget-settings.cjs +40 -57
  40. package/build/components/widget-settings/widget-settings.cjs.map +2 -2
  41. package/build/components/widget-toolbar/widget-toolbar.cjs +7 -4
  42. package/build/components/widget-toolbar/widget-toolbar.cjs.map +2 -2
  43. package/build/components/widgets/widgets.cjs +14 -7
  44. package/build/components/widgets/widgets.cjs.map +2 -2
  45. package/build/context/dashboard-context.cjs +31 -80
  46. package/build/context/dashboard-context.cjs.map +2 -2
  47. package/build/context/ui-context.cjs +2 -18
  48. package/build/context/ui-context.cjs.map +2 -2
  49. package/build/types.cjs.map +1 -1
  50. package/build/utils/index.cjs +2 -5
  51. package/build/utils/index.cjs.map +2 -2
  52. package/build/widget-dashboard.cjs +0 -4
  53. package/build/widget-dashboard.cjs.map +2 -2
  54. package/build-module/components/actions/actions.mjs +3 -20
  55. package/build-module/components/actions/actions.mjs.map +2 -2
  56. package/build-module/components/commands/commands.mjs +2 -67
  57. package/build-module/components/commands/commands.mjs.map +2 -2
  58. package/build-module/components/widget-attribute-controls/index.mjs +6 -0
  59. package/build-module/components/widget-attribute-controls/index.mjs.map +7 -0
  60. package/build-module/components/widget-attribute-controls/widget-attribute-controls.mjs +68 -0
  61. package/build-module/components/widget-attribute-controls/widget-attribute-controls.mjs.map +7 -0
  62. package/build-module/components/widget-chrome/widget-chrome.mjs +17 -70
  63. package/build-module/components/widget-chrome/widget-chrome.mjs.map +2 -2
  64. package/build-module/components/widget-frame/index.mjs +7 -0
  65. package/build-module/components/widget-frame/index.mjs.map +7 -0
  66. package/build-module/components/widget-frame/widget-frame.mjs +157 -0
  67. package/build-module/components/widget-frame/widget-frame.mjs.map +7 -0
  68. package/build-module/components/widget-header/index.mjs +6 -0
  69. package/build-module/components/widget-header/index.mjs.map +7 -0
  70. package/build-module/components/widget-header/widget-header-infotip.mjs +141 -0
  71. package/build-module/components/widget-header/widget-header-infotip.mjs.map +7 -0
  72. package/build-module/components/widget-header/widget-header.mjs +138 -0
  73. package/build-module/components/widget-header/widget-header.mjs.map +7 -0
  74. package/build-module/components/widget-layout-controls/index.mjs +6 -0
  75. package/build-module/components/widget-layout-controls/index.mjs.map +7 -0
  76. package/build-module/components/widget-layout-controls/widget-layout-controls.mjs +90 -0
  77. package/build-module/components/widget-layout-controls/widget-layout-controls.mjs.map +7 -0
  78. package/build-module/components/widget-picker/widget-picker.mjs +6 -94
  79. package/build-module/components/widget-picker/widget-picker.mjs.map +3 -3
  80. package/build-module/components/widget-preview-chrome/index.mjs +6 -0
  81. package/build-module/components/widget-preview-chrome/index.mjs.map +7 -0
  82. package/build-module/components/{widget-settings/widget-settings-toolbar.mjs → widget-preview-chrome/widget-preview-chrome.mjs} +37 -19
  83. package/build-module/components/widget-preview-chrome/widget-preview-chrome.mjs.map +7 -0
  84. package/build-module/components/widget-settings/index.mjs +2 -2
  85. package/build-module/components/widget-settings/index.mjs.map +1 -1
  86. package/build-module/components/widget-settings/utils/index.mjs +0 -2
  87. package/build-module/components/widget-settings/utils/index.mjs.map +2 -2
  88. package/build-module/components/widget-settings/widget-settings-trigger.mjs +23 -29
  89. package/build-module/components/widget-settings/widget-settings-trigger.mjs.map +2 -2
  90. package/build-module/components/widget-settings/widget-settings.mjs +40 -57
  91. package/build-module/components/widget-settings/widget-settings.mjs.map +2 -2
  92. package/build-module/components/widget-toolbar/widget-toolbar.mjs +7 -4
  93. package/build-module/components/widget-toolbar/widget-toolbar.mjs.map +2 -2
  94. package/build-module/components/widgets/widgets.mjs +14 -7
  95. package/build-module/components/widgets/widgets.mjs.map +2 -2
  96. package/build-module/context/dashboard-context.mjs +31 -80
  97. package/build-module/context/dashboard-context.mjs.map +2 -2
  98. package/build-module/context/ui-context.mjs +2 -18
  99. package/build-module/context/ui-context.mjs.map +2 -2
  100. package/build-module/types.mjs.map +1 -1
  101. package/build-module/utils/index.mjs +1 -3
  102. package/build-module/utils/index.mjs.map +2 -2
  103. package/build-module/widget-dashboard.mjs +0 -4
  104. package/build-module/widget-dashboard.mjs.map +2 -2
  105. package/build-types/components/actions/actions.d.ts.map +1 -1
  106. package/build-types/components/commands/commands.d.ts.map +1 -1
  107. package/build-types/components/widget-attribute-controls/index.d.ts +2 -0
  108. package/build-types/components/widget-attribute-controls/index.d.ts.map +1 -0
  109. package/build-types/components/widget-attribute-controls/widget-attribute-controls.d.ts +23 -0
  110. package/build-types/components/widget-attribute-controls/widget-attribute-controls.d.ts.map +1 -0
  111. package/build-types/components/widget-chrome/widget-chrome.d.ts +8 -8
  112. package/build-types/components/widget-chrome/widget-chrome.d.ts.map +1 -1
  113. package/build-types/components/widget-frame/index.d.ts +3 -0
  114. package/build-types/components/widget-frame/index.d.ts.map +1 -0
  115. package/build-types/components/widget-frame/widget-frame.d.ts +25 -0
  116. package/build-types/components/widget-frame/widget-frame.d.ts.map +1 -0
  117. package/build-types/components/widget-header/index.d.ts +3 -0
  118. package/build-types/components/widget-header/index.d.ts.map +1 -0
  119. package/build-types/components/widget-header/widget-header-infotip.d.ts +20 -0
  120. package/build-types/components/widget-header/widget-header-infotip.d.ts.map +1 -0
  121. package/build-types/components/widget-header/widget-header.d.ts +38 -0
  122. package/build-types/components/widget-header/widget-header.d.ts.map +1 -0
  123. package/build-types/components/widget-layout-controls/index.d.ts +3 -0
  124. package/build-types/components/widget-layout-controls/index.d.ts.map +1 -0
  125. package/build-types/components/widget-layout-controls/widget-layout-controls.d.ts +14 -0
  126. package/build-types/components/widget-layout-controls/widget-layout-controls.d.ts.map +1 -0
  127. package/build-types/components/widget-picker/widget-picker.d.ts.map +1 -1
  128. package/build-types/components/widget-preview-chrome/index.d.ts +3 -0
  129. package/build-types/components/widget-preview-chrome/index.d.ts.map +1 -0
  130. package/build-types/components/widget-preview-chrome/widget-preview-chrome.d.ts +15 -0
  131. package/build-types/components/widget-preview-chrome/widget-preview-chrome.d.ts.map +1 -0
  132. package/build-types/components/widget-settings/index.d.ts +2 -2
  133. package/build-types/components/widget-settings/utils/index.d.ts +0 -1
  134. package/build-types/components/widget-settings/utils/index.d.ts.map +1 -1
  135. package/build-types/components/widget-settings/widget-settings-trigger.d.ts +4 -3
  136. package/build-types/components/widget-settings/widget-settings-trigger.d.ts.map +1 -1
  137. package/build-types/components/widget-settings/widget-settings.d.ts +2 -2
  138. package/build-types/components/widget-settings/widget-settings.d.ts.map +1 -1
  139. package/build-types/components/widget-toolbar/widget-toolbar.d.ts +10 -7
  140. package/build-types/components/widget-toolbar/widget-toolbar.d.ts.map +1 -1
  141. package/build-types/components/widgets/widgets.d.ts.map +1 -1
  142. package/build-types/context/dashboard-context.d.ts +23 -40
  143. package/build-types/context/dashboard-context.d.ts.map +1 -1
  144. package/build-types/context/ui-context.d.ts +0 -18
  145. package/build-types/context/ui-context.d.ts.map +1 -1
  146. package/build-types/types.d.ts +9 -15
  147. package/build-types/types.d.ts.map +1 -1
  148. package/build-types/utils/index.d.ts +0 -1
  149. package/build-types/utils/index.d.ts.map +1 -1
  150. package/build-types/widget-dashboard.d.ts +5 -5
  151. package/build-types/widget-dashboard.d.ts.map +1 -1
  152. package/package.json +17 -17
  153. package/src/components/actions/actions.tsx +2 -22
  154. package/src/components/commands/commands.tsx +3 -70
  155. package/src/components/widget-attribute-controls/index.ts +1 -0
  156. package/src/components/widget-attribute-controls/widget-attribute-controls.tsx +108 -0
  157. package/src/components/widget-chrome/widget-chrome.module.css +3 -68
  158. package/src/components/widget-chrome/widget-chrome.tsx +19 -130
  159. package/src/components/widget-frame/index.ts +2 -0
  160. package/src/components/widget-frame/widget-frame.module.css +17 -0
  161. package/src/components/widget-frame/widget-frame.tsx +138 -0
  162. package/src/components/widget-header/index.ts +2 -0
  163. package/src/components/widget-header/widget-header-infotip.tsx +82 -0
  164. package/src/components/widget-header/widget-header.module.css +76 -0
  165. package/src/components/widget-header/widget-header.tsx +101 -0
  166. package/src/components/widget-layout-controls/index.ts +2 -0
  167. package/src/components/{widgets/widget-layout-toolbar.tsx → widget-layout-controls/widget-layout-controls.tsx} +12 -13
  168. package/src/components/widget-picker/widget-picker.tsx +5 -10
  169. package/src/components/widget-preview-chrome/index.ts +2 -0
  170. package/src/components/widget-preview-chrome/widget-preview-chrome.module.css +22 -0
  171. package/src/components/widget-preview-chrome/widget-preview-chrome.tsx +65 -0
  172. package/src/components/widget-settings/index.ts +2 -2
  173. package/src/components/widget-settings/utils/index.ts +0 -1
  174. package/src/components/widget-settings/widget-settings-trigger.tsx +36 -43
  175. package/src/components/widget-settings/widget-settings.tsx +7 -26
  176. package/src/components/widget-toolbar/widget-toolbar.module.css +6 -9
  177. package/src/components/widget-toolbar/widget-toolbar.tsx +14 -8
  178. package/src/components/widgets/widgets.module.css +0 -1
  179. package/src/components/widgets/widgets.tsx +30 -8
  180. package/src/context/dashboard-context.tsx +70 -133
  181. package/src/context/ui-context.tsx +1 -39
  182. package/src/test/actions.test.tsx +7 -77
  183. package/src/test/commands.test.tsx +6 -45
  184. package/src/test/staging.test.tsx +82 -144
  185. package/src/test/widget-dashboard.test.tsx +24 -0
  186. package/src/types.ts +9 -16
  187. package/src/utils/index.ts +0 -1
  188. package/src/widget-dashboard.tsx +4 -8
  189. package/build/components/layout-settings/index.cjs.map +0 -7
  190. package/build/components/layout-settings/layout-model-edit-field/index.cjs +0 -186
  191. package/build/components/layout-settings/layout-model-edit-field/index.cjs.map +0 -7
  192. package/build/components/layout-settings/layout-model-edit-field/thumbnail-grid.cjs +0 -53
  193. package/build/components/layout-settings/layout-model-edit-field/thumbnail-grid.cjs.map +0 -7
  194. package/build/components/layout-settings/layout-model-edit-field/thumbnail-masonry.cjs +0 -53
  195. package/build/components/layout-settings/layout-model-edit-field/thumbnail-masonry.cjs.map +0 -7
  196. package/build/components/layout-settings/layout-settings.cjs +0 -207
  197. package/build/components/layout-settings/layout-settings.cjs.map +0 -7
  198. package/build/components/widget-settings/utils/get-admin-menu-inset.cjs.map +0 -7
  199. package/build/components/widget-settings/widget-settings-toolbar.cjs.map +0 -7
  200. package/build/components/widgets/widget-layout-toolbar.cjs.map +0 -7
  201. package/build/utils/grid-model-change/grid-model-change.cjs +0 -56
  202. package/build/utils/grid-model-change/grid-model-change.cjs.map +0 -7
  203. package/build/utils/grid-model-change/index.cjs.map +0 -7
  204. package/build/utils/migrate-layout/index.cjs.map +0 -7
  205. package/build/utils/migrate-layout/migrate-layout.cjs +0 -94
  206. package/build/utils/migrate-layout/migrate-layout.cjs.map +0 -7
  207. package/build-module/components/layout-settings/index.mjs +0 -6
  208. package/build-module/components/layout-settings/index.mjs.map +0 -7
  209. package/build-module/components/layout-settings/layout-model-edit-field/index.mjs +0 -151
  210. package/build-module/components/layout-settings/layout-model-edit-field/index.mjs.map +0 -7
  211. package/build-module/components/layout-settings/layout-model-edit-field/thumbnail-grid.mjs +0 -28
  212. package/build-module/components/layout-settings/layout-model-edit-field/thumbnail-grid.mjs.map +0 -7
  213. package/build-module/components/layout-settings/layout-model-edit-field/thumbnail-masonry.mjs +0 -28
  214. package/build-module/components/layout-settings/layout-model-edit-field/thumbnail-masonry.mjs.map +0 -7
  215. package/build-module/components/layout-settings/layout-settings.mjs +0 -187
  216. package/build-module/components/layout-settings/layout-settings.mjs.map +0 -7
  217. package/build-module/components/widget-settings/utils/get-admin-menu-inset.mjs +0 -16
  218. package/build-module/components/widget-settings/utils/get-admin-menu-inset.mjs.map +0 -7
  219. package/build-module/components/widget-settings/widget-settings-toolbar.mjs.map +0 -7
  220. package/build-module/components/widgets/widget-layout-toolbar.mjs +0 -181
  221. package/build-module/components/widgets/widget-layout-toolbar.mjs.map +0 -7
  222. package/build-module/utils/grid-model-change/grid-model-change.mjs +0 -30
  223. package/build-module/utils/grid-model-change/grid-model-change.mjs.map +0 -7
  224. package/build-module/utils/grid-model-change/index.mjs +0 -7
  225. package/build-module/utils/grid-model-change/index.mjs.map +0 -7
  226. package/build-module/utils/migrate-layout/index.mjs +0 -6
  227. package/build-module/utils/migrate-layout/index.mjs.map +0 -7
  228. package/build-module/utils/migrate-layout/migrate-layout.mjs +0 -69
  229. package/build-module/utils/migrate-layout/migrate-layout.mjs.map +0 -7
  230. package/build-types/components/layout-settings/index.d.ts +0 -2
  231. package/build-types/components/layout-settings/index.d.ts.map +0 -1
  232. package/build-types/components/layout-settings/layout-model-edit-field/index.d.ts +0 -17
  233. package/build-types/components/layout-settings/layout-model-edit-field/index.d.ts.map +0 -1
  234. package/build-types/components/layout-settings/layout-model-edit-field/thumbnail-grid.d.ts +0 -6
  235. package/build-types/components/layout-settings/layout-model-edit-field/thumbnail-grid.d.ts.map +0 -1
  236. package/build-types/components/layout-settings/layout-model-edit-field/thumbnail-masonry.d.ts +0 -6
  237. package/build-types/components/layout-settings/layout-model-edit-field/thumbnail-masonry.d.ts.map +0 -1
  238. package/build-types/components/layout-settings/layout-settings.d.ts +0 -14
  239. package/build-types/components/layout-settings/layout-settings.d.ts.map +0 -1
  240. package/build-types/components/widget-settings/utils/get-admin-menu-inset.d.ts +0 -17
  241. package/build-types/components/widget-settings/utils/get-admin-menu-inset.d.ts.map +0 -1
  242. package/build-types/components/widget-settings/widget-settings-toolbar.d.ts +0 -20
  243. package/build-types/components/widget-settings/widget-settings-toolbar.d.ts.map +0 -1
  244. package/build-types/components/widgets/widget-layout-toolbar.d.ts +0 -14
  245. package/build-types/components/widgets/widget-layout-toolbar.d.ts.map +0 -1
  246. package/build-types/utils/grid-model-change/grid-model-change.d.ts +0 -20
  247. package/build-types/utils/grid-model-change/grid-model-change.d.ts.map +0 -1
  248. package/build-types/utils/grid-model-change/index.d.ts +0 -2
  249. package/build-types/utils/grid-model-change/index.d.ts.map +0 -1
  250. package/build-types/utils/migrate-layout/index.d.ts +0 -2
  251. package/build-types/utils/migrate-layout/index.d.ts.map +0 -1
  252. package/build-types/utils/migrate-layout/migrate-layout.d.ts +0 -36
  253. package/build-types/utils/migrate-layout/migrate-layout.d.ts.map +0 -1
  254. package/src/components/layout-settings/index.ts +0 -1
  255. package/src/components/layout-settings/layout-model-edit-field/index.tsx +0 -98
  256. package/src/components/layout-settings/layout-model-edit-field/style.module.css +0 -34
  257. package/src/components/layout-settings/layout-model-edit-field/thumbnail-grid.tsx +0 -28
  258. package/src/components/layout-settings/layout-model-edit-field/thumbnail-masonry.tsx +0 -28
  259. package/src/components/layout-settings/layout-settings.tsx +0 -217
  260. package/src/components/widget-picker/widget-picker.module.css +0 -11
  261. package/src/components/widget-settings/utils/get-admin-menu-inset.ts +0 -30
  262. package/src/components/widget-settings/widget-settings-toolbar.module.css +0 -25
  263. package/src/components/widget-settings/widget-settings-toolbar.tsx +0 -45
  264. package/src/components/widgets/widget-layout-toolbar.module.css +0 -6
  265. package/src/utils/grid-model-change/grid-model-change.ts +0 -53
  266. package/src/utils/grid-model-change/index.ts +0 -1
  267. package/src/utils/migrate-layout/index.ts +0 -1
  268. package/src/utils/migrate-layout/migrate-layout.ts +0 -156
  269. package/src/utils/migrate-layout/test/migrate-layout.test.ts +0 -114
@@ -7,13 +7,7 @@ import {
7
7
  useCommands,
8
8
  privateApis as commandsPrivateApis,
9
9
  } from '@wordpress/commands';
10
- import {
11
- columns,
12
- grid,
13
- layout as layoutIcon,
14
- plus,
15
- trash,
16
- } from '@wordpress/icons';
10
+ import { layout as layoutIcon, plus, trash } from '@wordpress/icons';
17
11
 
18
12
  /**
19
13
  * Internal dependencies
@@ -21,7 +15,6 @@ import {
21
15
  import { unlock } from '../../lock-unlock';
22
16
  import { useDashboardInternalContext } from '../../context/dashboard-context';
23
17
  import { useDashboardUIContext } from '../../context/ui-context';
24
- import { getGridModel } from '../../utils/grid-model-change';
25
18
  import { usePendingWhenEditMode } from './use-pending-when-edit-mode';
26
19
 
27
20
  const { useCommandContext } = unlock( commandsPrivateApis );
@@ -35,14 +28,8 @@ type CommandCallback = ( options: { close: () => void } ) => void;
35
28
  * active command context so they surface under Suggestions by default.
36
29
  */
37
30
  export function Commands() {
38
- const {
39
- editMode,
40
- onEditChange,
41
- onLayoutReset,
42
- gridSettings,
43
- canEditGridSettings,
44
- commitGridModelChange,
45
- } = useDashboardInternalContext();
31
+ const { editMode, onEditChange, onLayoutReset } =
32
+ useDashboardInternalContext();
46
33
 
47
34
  const { setInserterOpen, setResetDialogOpen } = useDashboardUIContext();
48
35
 
@@ -53,26 +40,6 @@ export function Commands() {
53
40
  onEditChange,
54
41
  } );
55
42
 
56
- const gridModel = getGridModel( gridSettings );
57
- const isGridLayout = gridModel === 'grid';
58
- const isMasonryLayout = gridModel === 'masonry';
59
-
60
- const switchToMasonry = useCallback< CommandCallback >(
61
- ( { close } ) => {
62
- close();
63
- commitGridModelChange( 'masonry' );
64
- },
65
- [ commitGridModelChange ]
66
- );
67
-
68
- const switchToGrid = useCallback< CommandCallback >(
69
- ( { close } ) => {
70
- close();
71
- commitGridModelChange( 'grid' );
72
- },
73
- [ commitGridModelChange ]
74
- );
75
-
76
43
  const resetToDefault = useCallback< CommandCallback >(
77
44
  ( { close } ) => {
78
45
  close();
@@ -121,35 +88,6 @@ export function Commands() {
121
88
  disabled: ! onEditChange,
122
89
  callback: addWidgets,
123
90
  },
124
- {
125
- name: 'core/dashboard/switch-to-masonry-layout',
126
- label: __( 'Switch dashboard to masonry layout' ),
127
- icon: columns,
128
- category: 'command',
129
- context: DASHBOARD_COMMAND_CONTEXT,
130
- keywords: [
131
- __( 'layout' ),
132
- __( 'layout model' ),
133
- __( 'masonry' ),
134
- ],
135
- disabled: ! canEditGridSettings || isMasonryLayout || editMode,
136
- callback: switchToMasonry,
137
- },
138
- {
139
- name: 'core/dashboard/switch-to-grid-layout',
140
- label: __( 'Switch dashboard to grid layout' ),
141
- icon: grid,
142
- category: 'command',
143
- context: DASHBOARD_COMMAND_CONTEXT,
144
- keywords: [
145
- __( 'layout' ),
146
- __( 'layout model' ),
147
- __( 'grid' ),
148
- __( 'standard grid' ),
149
- ],
150
- disabled: ! canEditGridSettings || isGridLayout || editMode,
151
- callback: switchToGrid,
152
- },
153
91
  {
154
92
  name: 'core/dashboard/reset-to-default',
155
93
  label: __( 'Reset dashboard widgets to default' ),
@@ -166,11 +104,6 @@ export function Commands() {
166
104
  editMode,
167
105
  customize,
168
106
  addWidgets,
169
- canEditGridSettings,
170
- isMasonryLayout,
171
- isGridLayout,
172
- switchToMasonry,
173
- switchToGrid,
174
107
  onLayoutReset,
175
108
  resetToDefault,
176
109
  ]
@@ -0,0 +1 @@
1
+ export { WidgetAttributeControls } from './widget-attribute-controls';
@@ -0,0 +1,108 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { DataForm } from '@wordpress/dataviews';
5
+ import type { Field, Form } from '@wordpress/dataviews';
6
+ import { useCallback, useMemo } from '@wordpress/element';
7
+ import type { WidgetType } from '@wordpress/widget-primitives';
8
+
9
+ /**
10
+ * Internal dependencies
11
+ */
12
+ import { useDashboardInternalContext } from '../../context/dashboard-context';
13
+ import { WidgetSettingsTrigger } from '../widget-settings';
14
+ import type { DashboardWidget } from '../../types';
15
+
16
+ type WidgetAttributes = Record< string, unknown >;
17
+
18
+ type WidgetAttributeControlsProps = {
19
+ /**
20
+ * The instance whose attributes these controls edit.
21
+ */
22
+ widget: DashboardWidget< unknown >;
23
+
24
+ /**
25
+ * The instance's widget type, source of the attribute schema.
26
+ */
27
+ widgetType: WidgetType;
28
+ };
29
+
30
+ /**
31
+ * Normal-mode controls: the `relevance: 'high'` attributes inline, plus the
32
+ * settings trigger that opens the full settings drawer when needed. Inline
33
+ * controls appear only for the high-relevance fields; edits stage live and
34
+ * auto-save on the dashboard's shared debounce.
35
+ *
36
+ * @param {WidgetAttributeControlsProps} props Component props.
37
+ */
38
+ export function WidgetAttributeControls( {
39
+ widget,
40
+ widgetType,
41
+ }: WidgetAttributeControlsProps ): React.ReactNode {
42
+ const { layout, onLayoutChange, scheduleAutoSave } =
43
+ useDashboardInternalContext();
44
+
45
+ const fields = useMemo< Field< WidgetAttributes >[] >(
46
+ () =>
47
+ ( widgetType.attributes ?? [] ).filter(
48
+ ( attribute ) => attribute.relevance === 'high'
49
+ ) as Field< WidgetAttributes >[],
50
+ [ widgetType.attributes ]
51
+ );
52
+
53
+ // A `row` top-level layout lays the controls out horizontally; each field
54
+ // carries `labelPosition: 'none'` so the control renders bare.
55
+ const form = useMemo< Form >(
56
+ () => ( {
57
+ layout: { type: 'row', alignment: 'center' },
58
+ fields: fields.map( ( field ) => ( {
59
+ id: field.id,
60
+ layout: { type: 'regular', labelPosition: 'none' },
61
+ } ) ),
62
+ } ),
63
+ [ fields ]
64
+ );
65
+
66
+ const handleChange = useCallback(
67
+ ( edits: Record< string, unknown > ) => {
68
+ onLayoutChange(
69
+ layout.map( ( instance ) =>
70
+ instance.uuid === widget.uuid
71
+ ? {
72
+ ...instance,
73
+ attributes: {
74
+ ...( instance.attributes as object ),
75
+ ...edits,
76
+ },
77
+ }
78
+ : instance
79
+ )
80
+ );
81
+
82
+ scheduleAutoSave();
83
+ },
84
+ [ layout, onLayoutChange, widget.uuid, scheduleAutoSave ]
85
+ );
86
+
87
+ const data = ( widget.attributes ??
88
+ widgetType.example?.attributes ??
89
+ {} ) as WidgetAttributes;
90
+
91
+ return (
92
+ <>
93
+ { fields.length > 0 && (
94
+ <DataForm< WidgetAttributes >
95
+ data={ data }
96
+ fields={ fields }
97
+ form={ form }
98
+ onChange={ handleChange }
99
+ />
100
+ ) }
101
+
102
+ <WidgetSettingsTrigger
103
+ widget={ widget }
104
+ widgetType={ widgetType }
105
+ />
106
+ </>
107
+ );
108
+ }
@@ -1,26 +1,5 @@
1
- .widgetChrome {
2
- height: 100%;
3
-
4
- /*
5
- * Isolate the widget body from the surrounding layout. In a fixed-row
6
- * grid the tile height comes from its row span, but a body taller than
7
- * the tile lets its intrinsic size feed the grid item's `min-height: auto`
8
- * and overflow the cell, adding scroll space below the grid. Layout
9
- * containment severs that propagation so the body stays within the tile
10
- * and scrolls internally. It contains layout only, not size or paint, so
11
- * the masonry surface still measures the tile from its content and the
12
- * tile elevation is not clipped.
13
- */
14
- contain: layout;
15
- }
16
-
17
- /*
18
- * When keyboard focus lands on the widget's own content (a link or control
19
- * the render module draws), outline the whole tile so Tab users can tell
20
- * which widget holds focus, since an inner ring alone is easy to miss. Scoped
21
- * to content focus, and to `:focus-visible` so a mouse click doesn't draw it.
22
- */
23
- .widgetChrome:has(.widgetChromeContent :focus-visible) {
1
+ /* Outline the whole tile when the body holds keyboard focus; an inner ring is easy to miss. */
2
+ .widgetChrome:has(:focus-visible) {
24
3
  outline: var(--wpds-border-width-focus) solid var(--wpds-color-stroke-focus);
25
4
  outline-offset: 2px;
26
5
  }
@@ -30,58 +9,14 @@
30
9
  color: var(--wpds-color-foreground-content-neutral);
31
10
  }
32
11
 
33
- /*
34
- * Scroll container for the widget body. The card root clips its own overflow
35
- * and the header is a fixed-size flex sibling, so confining the scroll to this
36
- * element is what keeps the header pinned while the body scrolls.
37
- */
12
+ /* Fill the tile so placeholder states center in the full height. */
38
13
  .widgetChromeContent {
39
14
  flex: 1;
40
15
  height: 100%;
41
- overflow-y: auto;
42
-
43
- /*
44
- * As a flex item, the content area defaults to `min-height: auto`, which
45
- * lets tall widget content expand it past the height the card allots
46
- * instead of staying bounded. Pinning the min sizes to 0 keeps the area
47
- * within its slot so a widget's own `overflow` scrolls internally rather
48
- * than pushing past the card.
49
- */
50
16
  min-width: 0;
51
17
  min-height: 0;
52
18
  }
53
19
 
54
- /*
55
- * Bleed block edges: zero the content's block padding so the body fills the
56
- * card top to bottom. The top is ours to flush (a full-bleed widget hides its
57
- * header in a position:absolute VisuallyHidden node that stays the card's
58
- * :first-child and blocks Card.FullBleed's top-flush rule). The bottom pairs
59
- * with the `margin-block-end: 0` on the bleed scroll wrapper below.
60
- */
61
- .widgetChromeContentBleed {
62
- padding-block: 0;
63
- }
64
-
65
- /*
66
- * Scroll container for a bleeding body. Card.FullBleed only does the edge
67
- * breakout (negative margins) and declares no height or overflow, so the scroll
68
- * container must be re-established here, on the wrapper that spans the card
69
- * edges, so the scrollbar tracks the edge and the header stays pinned.
70
- *
71
- * Card.FullBleed also adds `margin-block-end: calc(var(--wp-ui-card-padding) *
72
- * -1)` to cancel the content's bottom padding; that padding is zeroed above, so
73
- * neutralize the margin. Left in, it pulls the wrapper's box short of the body,
74
- * surfacing as a phantom scrollbar on a content-driven tile or a bottom inset
75
- * on a fixed-height one.
76
- */
77
- .widgetChromeBleedScroll {
78
- height: 100%;
79
- overflow-y: auto;
80
- margin-block-end: 0;
81
- }
82
-
83
- .loading,
84
20
  .unavailable {
85
21
  height: 100%;
86
22
  }
87
-
@@ -7,69 +7,20 @@ import type { ReactNode } from 'react';
7
7
  /**
8
8
  * WordPress dependencies
9
9
  */
10
- import { Spinner } from '@wordpress/components';
11
- import {
12
- Component,
13
- Suspense,
14
- forwardRef,
15
- useId,
16
- useMemo,
17
- } from '@wordpress/element';
10
+ import { forwardRef, useId, useMemo } from '@wordpress/element';
18
11
  import { __ } from '@wordpress/i18n';
19
12
  import { plugins } from '@wordpress/icons';
20
- // eslint-disable-next-line @wordpress/use-recommended-components
21
- import { Card, Icon, Stack, Notice, Text, VisuallyHidden } from '@wordpress/ui';
22
- import type { WidgetType } from '@wordpress/widget-primitives';
13
+ import { Card, Icon, Stack, Text } from '@wordpress/ui';
23
14
 
24
15
  /**
25
16
  * Internal dependencies
26
17
  */
27
18
  import { useDashboardInternalContext } from '../../context/dashboard-context';
28
19
  import { WidgetContextProvider } from '../../context/widget-context';
29
- import { WidgetRender } from '../widget-render';
20
+ import { LoadingOverlay, WidgetFrame } from '../widget-frame';
30
21
  import styles from './widget-chrome.module.css';
31
22
  import type { DashboardWidget } from '../../types';
32
23
 
33
- interface ErrorBoundaryProps {
34
- children: ReactNode;
35
- }
36
-
37
- interface ErrorBoundaryState {
38
- hasError: boolean;
39
- }
40
-
41
- class WidgetErrorBoundary extends Component<
42
- ErrorBoundaryProps,
43
- ErrorBoundaryState
44
- > {
45
- state: ErrorBoundaryState = { hasError: false };
46
-
47
- static getDerivedStateFromError(): ErrorBoundaryState {
48
- return { hasError: true };
49
- }
50
-
51
- render() {
52
- if ( this.state.hasError ) {
53
- return (
54
- <Notice.Root intent="error">
55
- <Notice.Description>
56
- { __( 'This widget encountered an error.' ) }
57
- </Notice.Description>
58
- </Notice.Root>
59
- );
60
- }
61
- return this.props.children;
62
- }
63
- }
64
-
65
- function LoadingOverlay() {
66
- return (
67
- <Stack justify="center" align="center" className={ styles.loading }>
68
- <Spinner />
69
- </Stack>
70
- );
71
- }
72
-
73
24
  interface UnavailableWidgetProps {
74
25
  widgetTypeName: string;
75
26
  }
@@ -101,56 +52,27 @@ function UnavailableWidget( { widgetTypeName }: UnavailableWidgetProps ) {
101
52
  );
102
53
  }
103
54
 
104
- interface HeaderProps {
105
- titleId: string;
106
- widgetType: WidgetType;
107
- }
108
-
109
- function Header( { titleId, widgetType }: HeaderProps ) {
110
- if ( ! widgetType.title ) {
111
- return null;
112
- }
113
-
114
- return (
115
- <Card.Header>
116
- <Stack direction="row" align="center" gap="sm">
117
- { widgetType.icon && (
118
- <span
119
- className={ styles.widgetChromeHeaderIcon }
120
- aria-hidden="true"
121
- >
122
- <Icon icon={ widgetType.icon } />
123
- </span>
124
- ) }
125
- <Card.Title id={ titleId } render={ <h2 /> }>
126
- { widgetType.title }
127
- </Card.Title>
128
- </Stack>
129
- </Card.Header>
130
- );
131
- }
132
-
133
55
  export interface WidgetChromeProps {
134
56
  widget: DashboardWidget< unknown >;
135
57
  index: number;
136
58
  /**
137
- * Lifted by the surrounding `@wordpress/grid` surface into a sibling
138
- * slot of the grid item; not rendered by `WidgetChrome` itself.
139
- * Living outside `Card.Root` is what keeps these controls interactive
140
- * while edit mode applies `inert` to the chrome.
59
+ * Lifted by `@wordpress/grid` into a sibling slot outside `Card.Root`,
60
+ * for full-bleed widgets with no in-card header to host the toolbar.
141
61
  */
142
62
  actionableArea?: ReactNode;
63
+ /**
64
+ * Toolbar rendered in the in-card header (framed and content-bleed).
65
+ */
66
+ headerToolbar?: ReactNode;
143
67
  className?: string;
144
68
  }
145
69
 
146
70
  /**
147
- * Per-instance wrapper. Owns the chrome around a widget instance: identity
148
- * context, header (title + icon), edit-mode `inert` attribute, and the
149
- * error/loading boundaries that keep neighbours mounted when one widget fails
150
- * or is still resolving.
71
+ * Dashboard chrome: wraps `WidgetFrame` in the grid tile's `Card.Root`, owning
72
+ * the missing and resolving states.
151
73
  */
152
74
  export const WidgetChrome = forwardRef< HTMLDivElement, WidgetChromeProps >(
153
- function WidgetChrome( { widget, index, className }, ref ) {
75
+ function WidgetChrome( { widget, index, className, headerToolbar }, ref ) {
154
76
  const { widgetTypes, isResolvingWidgetTypes, editMode } =
155
77
  useDashboardInternalContext();
156
78
  const widgetType = widgetTypes.find( ( t ) => t.name === widget.type );
@@ -200,23 +122,6 @@ export const WidgetChrome = forwardRef< HTMLDivElement, WidgetChromeProps >(
200
122
  );
201
123
  }
202
124
 
203
- // `presentation` encodes two independent axes. `full-bleed` hides
204
- // the header; both `full-bleed` and `content-bleed` let the body
205
- // break out of the content padding.
206
- const { presentation } = widgetType;
207
- const isHeaderHidden = presentation === 'full-bleed';
208
- const isBodyBleeding =
209
- presentation === 'full-bleed' || presentation === 'content-bleed';
210
- const header = <Header titleId={ titleId } widgetType={ widgetType } />;
211
-
212
- const body = (
213
- <WidgetErrorBoundary>
214
- <Suspense fallback={ <LoadingOverlay /> }>
215
- <WidgetRender widget={ widget } widgetType={ widgetType } />
216
- </Suspense>
217
- </WidgetErrorBoundary>
218
- );
219
-
220
125
  return (
221
126
  <WidgetContextProvider value={ contextValue }>
222
127
  <Card.Root
@@ -224,30 +129,14 @@ export const WidgetChrome = forwardRef< HTMLDivElement, WidgetChromeProps >(
224
129
  ref={ ref }
225
130
  className={ clsx( styles.widgetChrome, className ) }
226
131
  aria-labelledby={ widgetType.title ? titleId : undefined }
227
- { ...( editMode ? { inert: 'true' } : {} ) }
228
132
  >
229
- { isHeaderHidden ? (
230
- <VisuallyHidden>{ header }</VisuallyHidden>
231
- ) : (
232
- header
233
- ) }
234
-
235
- <Card.Content
236
- className={ clsx(
237
- styles.widgetChromeContent,
238
- isBodyBleeding && styles.widgetChromeContentBleed
239
- ) }
240
- >
241
- { isBodyBleeding ? (
242
- <Card.FullBleed
243
- className={ styles.widgetChromeBleedScroll }
244
- >
245
- { body }
246
- </Card.FullBleed>
247
- ) : (
248
- body
249
- ) }
250
- </Card.Content>
133
+ <WidgetFrame
134
+ widget={ widget }
135
+ widgetType={ widgetType }
136
+ titleId={ titleId }
137
+ editMode={ editMode }
138
+ headerToolbar={ headerToolbar }
139
+ />
251
140
  </Card.Root>
252
141
  </WidgetContextProvider>
253
142
  );
@@ -0,0 +1,2 @@
1
+ export { WidgetFrame, LoadingOverlay } from './widget-frame';
2
+ export type { WidgetFrameProps } from './widget-frame';
@@ -0,0 +1,17 @@
1
+ /* Scroll viewport that fills the tile height; min:0 bounds tall content. */
2
+ .content {
3
+ flex: 1;
4
+ height: 100%;
5
+ overflow-y: auto;
6
+ min-width: 0;
7
+ min-height: 0;
8
+ }
9
+
10
+ /* Bleeding body reaches the card borders. Card exposes no padding-less section. */
11
+ .bleedContent {
12
+ padding: 0;
13
+ }
14
+
15
+ .loading {
16
+ height: 100%;
17
+ }
@@ -0,0 +1,138 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import clsx from 'clsx';
5
+ import type { ReactNode } from 'react';
6
+
7
+ /**
8
+ * WordPress dependencies
9
+ */
10
+ import { Spinner } from '@wordpress/components';
11
+ import { Component, Suspense } from '@wordpress/element';
12
+ import { __ } from '@wordpress/i18n';
13
+ // eslint-disable-next-line @wordpress/use-recommended-components
14
+ import { Card, Notice, Stack, VisuallyHidden } from '@wordpress/ui';
15
+ import type { WidgetType } from '@wordpress/widget-primitives';
16
+
17
+ /**
18
+ * Internal dependencies
19
+ */
20
+ import { WidgetHeader } from '../widget-header';
21
+ import { WidgetRender } from '../widget-render';
22
+ import styles from './widget-frame.module.css';
23
+ import type { DashboardWidget } from '../../types';
24
+
25
+ interface ErrorBoundaryProps {
26
+ children: ReactNode;
27
+ }
28
+
29
+ interface ErrorBoundaryState {
30
+ hasError: boolean;
31
+ }
32
+
33
+ class WidgetErrorBoundary extends Component<
34
+ ErrorBoundaryProps,
35
+ ErrorBoundaryState
36
+ > {
37
+ state: ErrorBoundaryState = { hasError: false };
38
+
39
+ static getDerivedStateFromError(): ErrorBoundaryState {
40
+ return { hasError: true };
41
+ }
42
+
43
+ render() {
44
+ if ( this.state.hasError ) {
45
+ return (
46
+ <Notice.Root intent="error">
47
+ <Notice.Description>
48
+ { __( 'This widget encountered an error.' ) }
49
+ </Notice.Description>
50
+ </Notice.Root>
51
+ );
52
+ }
53
+ return this.props.children;
54
+ }
55
+ }
56
+
57
+ /* Centered spinner for resolving and Suspense waits. */
58
+ export function LoadingOverlay() {
59
+ return (
60
+ <Stack justify="center" align="center" className={ styles.loading }>
61
+ <Spinner />
62
+ </Stack>
63
+ );
64
+ }
65
+
66
+ export interface WidgetFrameProps {
67
+ widget: DashboardWidget< unknown >;
68
+ widgetType: WidgetType;
69
+ titleId: string;
70
+
71
+ /**
72
+ * Inert the body and identity while customizing.
73
+ */
74
+ editMode?: boolean;
75
+
76
+ /**
77
+ * Toolbar shown beside the identity in the in-card header.
78
+ */
79
+ headerToolbar?: ReactNode;
80
+ }
81
+
82
+ /**
83
+ * Shared framing: `presentation` into header + content, with the error/loading
84
+ * boundaries. Hosts supply the `Card.Root` and their own concerns.
85
+ *
86
+ * @param {WidgetFrameProps} props Component props.
87
+ */
88
+ export function WidgetFrame( {
89
+ widget,
90
+ widgetType,
91
+ titleId,
92
+ editMode = false,
93
+ headerToolbar,
94
+ }: WidgetFrameProps ) {
95
+ // full-bleed hides the header; full-bleed and content-bleed bleed the body.
96
+ const { presentation } = widgetType;
97
+ const isHeaderHidden = presentation === 'full-bleed';
98
+ const isBodyBleeding =
99
+ presentation === 'full-bleed' || presentation === 'content-bleed';
100
+
101
+ const body = (
102
+ <WidgetErrorBoundary>
103
+ <Suspense fallback={ <LoadingOverlay /> }>
104
+ <WidgetRender widget={ widget } widgetType={ widgetType } />
105
+ </Suspense>
106
+ </WidgetErrorBoundary>
107
+ );
108
+
109
+ return (
110
+ <>
111
+ { ! isHeaderHidden && (
112
+ <WidgetHeader
113
+ showIdentity
114
+ widgetType={ widgetType }
115
+ titleId={ titleId }
116
+ editMode={ editMode }
117
+ >
118
+ { headerToolbar }
119
+ </WidgetHeader>
120
+ ) }
121
+
122
+ <Card.Content
123
+ className={ clsx(
124
+ styles.content,
125
+ isBodyBleeding && styles.bleedContent
126
+ ) }
127
+ { ...( editMode ? { inert: 'true' } : {} ) }
128
+ >
129
+ { isHeaderHidden && widgetType.title && (
130
+ <VisuallyHidden render={ <h2 id={ titleId } /> }>
131
+ { widgetType.title }
132
+ </VisuallyHidden>
133
+ ) }
134
+ { body }
135
+ </Card.Content>
136
+ </>
137
+ );
138
+ }
@@ -0,0 +1,2 @@
1
+ export { WidgetHeader } from './widget-header';
2
+ export type { WidgetHeaderProps } from './widget-header';