@wordpress/widget-dashboard 0.2.0 → 0.3.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 (283) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +29 -16
  3. package/build/components/actions/actions.cjs +6 -23
  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 +28 -69
  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 +176 -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/widget-resize-handle.cjs +4 -4
  44. package/build/components/widgets/widget-resize-handle.cjs.map +2 -2
  45. package/build/components/widgets/widgets.cjs +18 -11
  46. package/build/components/widgets/widgets.cjs.map +2 -2
  47. package/build/context/dashboard-context.cjs +31 -80
  48. package/build/context/dashboard-context.cjs.map +2 -2
  49. package/build/context/ui-context.cjs +2 -18
  50. package/build/context/ui-context.cjs.map +2 -2
  51. package/build/types.cjs.map +1 -1
  52. package/build/utils/index.cjs +2 -5
  53. package/build/utils/index.cjs.map +2 -2
  54. package/build/widget-dashboard.cjs +0 -4
  55. package/build/widget-dashboard.cjs.map +2 -2
  56. package/build-module/components/actions/actions.mjs +7 -24
  57. package/build-module/components/actions/actions.mjs.map +2 -2
  58. package/build-module/components/commands/commands.mjs +2 -67
  59. package/build-module/components/commands/commands.mjs.map +2 -2
  60. package/build-module/components/widget-attribute-controls/index.mjs +6 -0
  61. package/build-module/components/widget-attribute-controls/index.mjs.map +7 -0
  62. package/build-module/components/widget-attribute-controls/widget-attribute-controls.mjs +68 -0
  63. package/build-module/components/widget-attribute-controls/widget-attribute-controls.mjs.map +7 -0
  64. package/build-module/components/widget-chrome/widget-chrome.mjs +29 -76
  65. package/build-module/components/widget-chrome/widget-chrome.mjs.map +2 -2
  66. package/build-module/components/widget-frame/index.mjs +7 -0
  67. package/build-module/components/widget-frame/index.mjs.map +7 -0
  68. package/build-module/components/widget-frame/widget-frame.mjs +157 -0
  69. package/build-module/components/widget-frame/widget-frame.mjs.map +7 -0
  70. package/build-module/components/widget-header/index.mjs +6 -0
  71. package/build-module/components/widget-header/index.mjs.map +7 -0
  72. package/build-module/components/widget-header/widget-header-infotip.mjs +141 -0
  73. package/build-module/components/widget-header/widget-header-infotip.mjs.map +7 -0
  74. package/build-module/components/widget-header/widget-header.mjs +141 -0
  75. package/build-module/components/widget-header/widget-header.mjs.map +7 -0
  76. package/build-module/components/widget-layout-controls/index.mjs +6 -0
  77. package/build-module/components/widget-layout-controls/index.mjs.map +7 -0
  78. package/build-module/components/widget-layout-controls/widget-layout-controls.mjs +90 -0
  79. package/build-module/components/widget-layout-controls/widget-layout-controls.mjs.map +7 -0
  80. package/build-module/components/widget-picker/widget-picker.mjs +6 -94
  81. package/build-module/components/widget-picker/widget-picker.mjs.map +3 -3
  82. package/build-module/components/widget-preview-chrome/index.mjs +6 -0
  83. package/build-module/components/widget-preview-chrome/index.mjs.map +7 -0
  84. package/build-module/components/{widget-settings/widget-settings-toolbar.mjs → widget-preview-chrome/widget-preview-chrome.mjs} +37 -19
  85. package/build-module/components/widget-preview-chrome/widget-preview-chrome.mjs.map +7 -0
  86. package/build-module/components/widget-settings/index.mjs +2 -2
  87. package/build-module/components/widget-settings/index.mjs.map +1 -1
  88. package/build-module/components/widget-settings/utils/index.mjs +0 -2
  89. package/build-module/components/widget-settings/utils/index.mjs.map +2 -2
  90. package/build-module/components/widget-settings/widget-settings-trigger.mjs +23 -29
  91. package/build-module/components/widget-settings/widget-settings-trigger.mjs.map +2 -2
  92. package/build-module/components/widget-settings/widget-settings.mjs +40 -57
  93. package/build-module/components/widget-settings/widget-settings.mjs.map +2 -2
  94. package/build-module/components/widget-toolbar/widget-toolbar.mjs +7 -4
  95. package/build-module/components/widget-toolbar/widget-toolbar.mjs.map +2 -2
  96. package/build-module/components/widgets/widget-resize-handle.mjs +4 -4
  97. package/build-module/components/widgets/widget-resize-handle.mjs.map +2 -2
  98. package/build-module/components/widgets/widgets.mjs +18 -11
  99. package/build-module/components/widgets/widgets.mjs.map +2 -2
  100. package/build-module/context/dashboard-context.mjs +31 -80
  101. package/build-module/context/dashboard-context.mjs.map +2 -2
  102. package/build-module/context/ui-context.mjs +2 -18
  103. package/build-module/context/ui-context.mjs.map +2 -2
  104. package/build-module/types.mjs.map +1 -1
  105. package/build-module/utils/index.mjs +1 -3
  106. package/build-module/utils/index.mjs.map +2 -2
  107. package/build-module/widget-dashboard.mjs +0 -4
  108. package/build-module/widget-dashboard.mjs.map +2 -2
  109. package/build-types/components/actions/actions.d.ts.map +1 -1
  110. package/build-types/components/commands/commands.d.ts.map +1 -1
  111. package/build-types/components/commands/use-pending-when-edit-mode.d.ts +1 -1
  112. package/build-types/components/commands/use-pending-when-edit-mode.d.ts.map +1 -1
  113. package/build-types/components/no-widgets-state/no-widgets-state.d.ts +1 -1
  114. package/build-types/components/no-widgets-state/no-widgets-state.d.ts.map +1 -1
  115. package/build-types/components/widget-attribute-controls/index.d.ts +2 -0
  116. package/build-types/components/widget-attribute-controls/index.d.ts.map +1 -0
  117. package/build-types/components/widget-attribute-controls/widget-attribute-controls.d.ts +23 -0
  118. package/build-types/components/widget-attribute-controls/widget-attribute-controls.d.ts.map +1 -0
  119. package/build-types/components/widget-chrome/widget-chrome.d.ts +8 -8
  120. package/build-types/components/widget-chrome/widget-chrome.d.ts.map +1 -1
  121. package/build-types/components/widget-frame/index.d.ts +3 -0
  122. package/build-types/components/widget-frame/index.d.ts.map +1 -0
  123. package/build-types/components/widget-frame/widget-frame.d.ts +25 -0
  124. package/build-types/components/widget-frame/widget-frame.d.ts.map +1 -0
  125. package/build-types/components/widget-header/index.d.ts +3 -0
  126. package/build-types/components/widget-header/index.d.ts.map +1 -0
  127. package/build-types/components/widget-header/widget-header-infotip.d.ts +20 -0
  128. package/build-types/components/widget-header/widget-header-infotip.d.ts.map +1 -0
  129. package/build-types/components/widget-header/widget-header.d.ts +38 -0
  130. package/build-types/components/widget-header/widget-header.d.ts.map +1 -0
  131. package/build-types/components/widget-layout-controls/index.d.ts +3 -0
  132. package/build-types/components/widget-layout-controls/index.d.ts.map +1 -0
  133. package/build-types/components/widget-layout-controls/widget-layout-controls.d.ts +14 -0
  134. package/build-types/components/widget-layout-controls/widget-layout-controls.d.ts.map +1 -0
  135. package/build-types/components/widget-picker/widget-picker.d.ts +1 -1
  136. package/build-types/components/widget-picker/widget-picker.d.ts.map +1 -1
  137. package/build-types/components/widget-preview-chrome/index.d.ts +3 -0
  138. package/build-types/components/widget-preview-chrome/index.d.ts.map +1 -0
  139. package/build-types/components/widget-preview-chrome/widget-preview-chrome.d.ts +15 -0
  140. package/build-types/components/widget-preview-chrome/widget-preview-chrome.d.ts.map +1 -0
  141. package/build-types/components/widget-settings/index.d.ts +2 -2
  142. package/build-types/components/widget-settings/utils/index.d.ts +0 -1
  143. package/build-types/components/widget-settings/utils/index.d.ts.map +1 -1
  144. package/build-types/components/widget-settings/widget-settings-trigger.d.ts +7 -5
  145. package/build-types/components/widget-settings/widget-settings-trigger.d.ts.map +1 -1
  146. package/build-types/components/widget-settings/widget-settings.d.ts +5 -4
  147. package/build-types/components/widget-settings/widget-settings.d.ts.map +1 -1
  148. package/build-types/components/widget-toolbar/widget-toolbar.d.ts +10 -7
  149. package/build-types/components/widget-toolbar/widget-toolbar.d.ts.map +1 -1
  150. package/build-types/components/widgets/widgets.d.ts.map +1 -1
  151. package/build-types/context/dashboard-context.d.ts +23 -40
  152. package/build-types/context/dashboard-context.d.ts.map +1 -1
  153. package/build-types/context/ui-context.d.ts +0 -18
  154. package/build-types/context/ui-context.d.ts.map +1 -1
  155. package/build-types/context/widget-context.d.ts +1 -1
  156. package/build-types/context/widget-context.d.ts.map +1 -1
  157. package/build-types/types.d.ts +9 -15
  158. package/build-types/types.d.ts.map +1 -1
  159. package/build-types/utils/index.d.ts +0 -1
  160. package/build-types/utils/index.d.ts.map +1 -1
  161. package/build-types/widget-dashboard.d.ts +5 -5
  162. package/build-types/widget-dashboard.d.ts.map +1 -1
  163. package/package.json +20 -20
  164. package/src/components/actions/actions.module.css +7 -7
  165. package/src/components/actions/actions.tsx +5 -25
  166. package/src/components/commands/commands.tsx +3 -70
  167. package/src/components/widget-attribute-controls/index.ts +1 -0
  168. package/src/components/widget-attribute-controls/widget-attribute-controls.tsx +108 -0
  169. package/src/components/widget-chrome/widget-chrome.module.css +6 -71
  170. package/src/components/widget-chrome/widget-chrome.tsx +31 -136
  171. package/src/components/widget-frame/index.ts +2 -0
  172. package/src/components/widget-frame/widget-frame.module.css +17 -0
  173. package/src/components/widget-frame/widget-frame.tsx +138 -0
  174. package/src/components/widget-header/index.ts +2 -0
  175. package/src/components/widget-header/widget-header-infotip.tsx +82 -0
  176. package/src/components/widget-header/widget-header.module.css +59 -0
  177. package/src/components/widget-header/widget-header.tsx +104 -0
  178. package/src/components/widget-layout-controls/index.ts +2 -0
  179. package/src/components/{widgets/widget-layout-toolbar.tsx → widget-layout-controls/widget-layout-controls.tsx} +12 -13
  180. package/src/components/widget-picker/widget-picker.tsx +5 -10
  181. package/src/components/widget-preview-chrome/index.ts +2 -0
  182. package/src/components/widget-preview-chrome/widget-preview-chrome.module.css +22 -0
  183. package/src/components/widget-preview-chrome/widget-preview-chrome.tsx +65 -0
  184. package/src/components/widget-settings/index.ts +2 -2
  185. package/src/components/widget-settings/utils/index.ts +0 -1
  186. package/src/components/widget-settings/widget-settings-trigger.tsx +39 -44
  187. package/src/components/widget-settings/widget-settings.tsx +10 -28
  188. package/src/components/widget-toolbar/widget-toolbar.module.css +13 -10
  189. package/src/components/widget-toolbar/widget-toolbar.tsx +14 -8
  190. package/src/components/widgets/widget-resize-handle.module.css +21 -21
  191. package/src/components/widgets/widget-resize-handle.tsx +2 -2
  192. package/src/components/widgets/widgets.module.css +20 -11
  193. package/src/components/widgets/widgets.tsx +33 -10
  194. package/src/context/dashboard-context.tsx +70 -133
  195. package/src/context/ui-context.tsx +1 -39
  196. package/src/test/actions.test.tsx +7 -77
  197. package/src/test/commands.test.tsx +6 -45
  198. package/src/test/staging.test.tsx +82 -144
  199. package/src/test/widget-dashboard.test.tsx +24 -0
  200. package/src/types.ts +9 -16
  201. package/src/utils/index.ts +0 -1
  202. package/src/widget-dashboard.tsx +4 -8
  203. package/build/components/layout-settings/index.cjs.map +0 -7
  204. package/build/components/layout-settings/layout-model-edit-field/index.cjs +0 -186
  205. package/build/components/layout-settings/layout-model-edit-field/index.cjs.map +0 -7
  206. package/build/components/layout-settings/layout-model-edit-field/thumbnail-grid.cjs +0 -53
  207. package/build/components/layout-settings/layout-model-edit-field/thumbnail-grid.cjs.map +0 -7
  208. package/build/components/layout-settings/layout-model-edit-field/thumbnail-masonry.cjs +0 -53
  209. package/build/components/layout-settings/layout-model-edit-field/thumbnail-masonry.cjs.map +0 -7
  210. package/build/components/layout-settings/layout-settings.cjs +0 -207
  211. package/build/components/layout-settings/layout-settings.cjs.map +0 -7
  212. package/build/components/widget-settings/utils/get-admin-menu-inset.cjs.map +0 -7
  213. package/build/components/widget-settings/widget-settings-toolbar.cjs.map +0 -7
  214. package/build/components/widgets/widget-layout-toolbar.cjs.map +0 -7
  215. package/build/utils/grid-model-change/grid-model-change.cjs +0 -56
  216. package/build/utils/grid-model-change/grid-model-change.cjs.map +0 -7
  217. package/build/utils/grid-model-change/index.cjs.map +0 -7
  218. package/build/utils/migrate-layout/index.cjs.map +0 -7
  219. package/build/utils/migrate-layout/migrate-layout.cjs +0 -94
  220. package/build/utils/migrate-layout/migrate-layout.cjs.map +0 -7
  221. package/build-module/components/layout-settings/index.mjs +0 -6
  222. package/build-module/components/layout-settings/index.mjs.map +0 -7
  223. package/build-module/components/layout-settings/layout-model-edit-field/index.mjs +0 -151
  224. package/build-module/components/layout-settings/layout-model-edit-field/index.mjs.map +0 -7
  225. package/build-module/components/layout-settings/layout-model-edit-field/thumbnail-grid.mjs +0 -28
  226. package/build-module/components/layout-settings/layout-model-edit-field/thumbnail-grid.mjs.map +0 -7
  227. package/build-module/components/layout-settings/layout-model-edit-field/thumbnail-masonry.mjs +0 -28
  228. package/build-module/components/layout-settings/layout-model-edit-field/thumbnail-masonry.mjs.map +0 -7
  229. package/build-module/components/layout-settings/layout-settings.mjs +0 -187
  230. package/build-module/components/layout-settings/layout-settings.mjs.map +0 -7
  231. package/build-module/components/widget-settings/utils/get-admin-menu-inset.mjs +0 -16
  232. package/build-module/components/widget-settings/utils/get-admin-menu-inset.mjs.map +0 -7
  233. package/build-module/components/widget-settings/widget-settings-toolbar.mjs.map +0 -7
  234. package/build-module/components/widgets/widget-layout-toolbar.mjs +0 -181
  235. package/build-module/components/widgets/widget-layout-toolbar.mjs.map +0 -7
  236. package/build-module/utils/grid-model-change/grid-model-change.mjs +0 -30
  237. package/build-module/utils/grid-model-change/grid-model-change.mjs.map +0 -7
  238. package/build-module/utils/grid-model-change/index.mjs +0 -7
  239. package/build-module/utils/grid-model-change/index.mjs.map +0 -7
  240. package/build-module/utils/migrate-layout/index.mjs +0 -6
  241. package/build-module/utils/migrate-layout/index.mjs.map +0 -7
  242. package/build-module/utils/migrate-layout/migrate-layout.mjs +0 -69
  243. package/build-module/utils/migrate-layout/migrate-layout.mjs.map +0 -7
  244. package/build-types/components/layout-settings/index.d.ts +0 -2
  245. package/build-types/components/layout-settings/index.d.ts.map +0 -1
  246. package/build-types/components/layout-settings/layout-model-edit-field/index.d.ts +0 -17
  247. package/build-types/components/layout-settings/layout-model-edit-field/index.d.ts.map +0 -1
  248. package/build-types/components/layout-settings/layout-model-edit-field/thumbnail-grid.d.ts +0 -6
  249. package/build-types/components/layout-settings/layout-model-edit-field/thumbnail-grid.d.ts.map +0 -1
  250. package/build-types/components/layout-settings/layout-model-edit-field/thumbnail-masonry.d.ts +0 -6
  251. package/build-types/components/layout-settings/layout-model-edit-field/thumbnail-masonry.d.ts.map +0 -1
  252. package/build-types/components/layout-settings/layout-settings.d.ts +0 -14
  253. package/build-types/components/layout-settings/layout-settings.d.ts.map +0 -1
  254. package/build-types/components/widget-settings/utils/get-admin-menu-inset.d.ts +0 -17
  255. package/build-types/components/widget-settings/utils/get-admin-menu-inset.d.ts.map +0 -1
  256. package/build-types/components/widget-settings/widget-settings-toolbar.d.ts +0 -20
  257. package/build-types/components/widget-settings/widget-settings-toolbar.d.ts.map +0 -1
  258. package/build-types/components/widgets/widget-layout-toolbar.d.ts +0 -14
  259. package/build-types/components/widgets/widget-layout-toolbar.d.ts.map +0 -1
  260. package/build-types/utils/grid-model-change/grid-model-change.d.ts +0 -20
  261. package/build-types/utils/grid-model-change/grid-model-change.d.ts.map +0 -1
  262. package/build-types/utils/grid-model-change/index.d.ts +0 -2
  263. package/build-types/utils/grid-model-change/index.d.ts.map +0 -1
  264. package/build-types/utils/migrate-layout/index.d.ts +0 -2
  265. package/build-types/utils/migrate-layout/index.d.ts.map +0 -1
  266. package/build-types/utils/migrate-layout/migrate-layout.d.ts +0 -36
  267. package/build-types/utils/migrate-layout/migrate-layout.d.ts.map +0 -1
  268. package/src/components/layout-settings/index.ts +0 -1
  269. package/src/components/layout-settings/layout-model-edit-field/index.tsx +0 -98
  270. package/src/components/layout-settings/layout-model-edit-field/style.module.css +0 -34
  271. package/src/components/layout-settings/layout-model-edit-field/thumbnail-grid.tsx +0 -28
  272. package/src/components/layout-settings/layout-model-edit-field/thumbnail-masonry.tsx +0 -28
  273. package/src/components/layout-settings/layout-settings.tsx +0 -217
  274. package/src/components/widget-picker/widget-picker.module.css +0 -11
  275. package/src/components/widget-settings/utils/get-admin-menu-inset.ts +0 -30
  276. package/src/components/widget-settings/widget-settings-toolbar.module.css +0 -25
  277. package/src/components/widget-settings/widget-settings-toolbar.tsx +0 -45
  278. package/src/components/widgets/widget-layout-toolbar.module.css +0 -6
  279. package/src/utils/grid-model-change/grid-model-change.ts +0 -53
  280. package/src/utils/grid-model-change/index.ts +0 -1
  281. package/src/utils/migrate-layout/index.ts +0 -1
  282. package/src/utils/migrate-layout/migrate-layout.ts +0 -156
  283. package/src/utils/migrate-layout/test/migrate-layout.test.ts +0 -114
@@ -7,6 +7,7 @@ import type { ReactNode } from 'react';
7
7
  /**
8
8
  * WordPress dependencies
9
9
  */
10
+ import { debounce, useEvent } from '@wordpress/compose';
10
11
  import {
11
12
  createContext,
12
13
  useCallback,
@@ -24,14 +25,9 @@ import type {
24
25
  * Internal dependencies
25
26
  */
26
27
  import { DEFAULT_GRID } from '../utils/default-grid';
27
- import { computeGridModelChange } from '../utils/grid-model-change';
28
28
  import { normalizeGridSettings } from '../utils/normalize-grid-settings';
29
29
  import { DEFAULT_ROW_HEIGHT } from '../utils/row-height-presets';
30
- import type {
31
- WidgetGridModel,
32
- WidgetGridSettings,
33
- DashboardWidget,
34
- } from '../types';
30
+ import type { WidgetGridSettings, DashboardWidget } from '../types';
35
31
  import { WIDGET_DASHBOARD_COLUMN_COUNT } from '../types';
36
32
 
37
33
  type GridSettingsWithColumns = WidgetGridSettings & { columns: number };
@@ -49,6 +45,12 @@ function resolveGridSettings(
49
45
  const DEFAULT_RESOLVE_WIDGET_MODULE: ResolveWidgetModule = ( moduleId ) =>
50
46
  import( /* webpackIgnore: true */ moduleId );
51
47
 
48
+ /**
49
+ * Inline widget-instance edits stage live, then publish once the user pauses.
50
+ * A single global timer, so editing several widgets settles into one save.
51
+ */
52
+ const AUTO_SAVE_DELAY_MS = 5000;
53
+
52
54
  /**
53
55
  * Canonical form of `layout`: widgets sorted by `placement.order` (falling
54
56
  * back to array index), then `order` stripped since position now implies it.
@@ -80,10 +82,9 @@ function canonicalize( layout: DashboardWidget[] ): DashboardWidget[] {
80
82
  * Rich state distributed to every compound component inside `WidgetDashboard`.
81
83
  * Internal — compounds reach the full state via `useDashboardInternalContext()`.
82
84
  *
83
- * `layout`/`onLayoutChange` and `gridSettings`/`onGridSettingsChange` here
84
- * operate on the staging layer, not the committed props. Mutations from
85
- * compound children stay in staging until `commit` publishes them on the
86
- * consumer.
85
+ * `layout`/`onLayoutChange` here operate on the staging layer, not the
86
+ * committed props. Mutations from compound children stay in staging until
87
+ * `commit` publishes them on the consumer.
87
88
  */
88
89
  interface InternalDashboardContextValue {
89
90
  widgetTypes: WidgetType[];
@@ -92,39 +93,32 @@ interface InternalDashboardContextValue {
92
93
  onLayoutChange: ( layout: DashboardWidget[] ) => void;
93
94
  onLayoutReset?: () => void;
94
95
  gridSettings: GridSettingsWithColumns;
95
- onGridSettingsChange: ( gridSettings: WidgetGridSettings ) => void;
96
- canEditGridSettings: boolean;
97
96
 
98
97
  /**
99
- * Restores the staging copy of `gridSettings` to the package's
100
- * built-in defaults. Does not touch the committed slice; the user
101
- * must `commit` to publish the reset, or `cancel` to discard it.
98
+ * Publishes the staged layout when it differs from the committed
99
+ * prop. By default also exits edit mode; pass `{ exitEditMode: false }`
100
+ * for inline auto-saves that keep the current mode.
102
101
  */
103
- resetGridSettings: () => void;
102
+ commit: ( options?: CommitOptions ) => void;
104
103
 
105
104
  /**
106
- * Publishes staged slices that differ from their committed
107
- * counterparts. By default also exits edit mode; pass
108
- * `{ exitEditMode: false }` when committing from the layout
109
- * settings drawer so customize mode stays active.
105
+ * Reverts the staged layout and exits edit mode.
110
106
  */
111
- commit: ( options?: CommitOptions ) => void;
107
+ cancel: () => void;
112
108
 
113
109
  /**
114
- * Switches the layout model, updates staging, and publishes
115
- * immediately equivalent to changing the model in layout
116
- * settings and clicking Save.
110
+ * Debounced auto-save for inline widget-instance edits. Controls call it
111
+ * after staging a change; a single global timer publishes once the edits
112
+ * settle. The settings drawer does not use it (it commits on Save).
117
113
  */
118
- commitGridModelChange: ( targetModel: WidgetGridModel ) => void;
114
+ scheduleAutoSave: () => void;
119
115
 
120
116
  /**
121
- * Reverts staging slices. By default reverts both layout and grid
122
- * settings and exits edit mode. Pass `{ exitEditMode: false }` when
123
- * dismissing the layout settings drawer. Pass `{ revertLayout: false }`
124
- * to revert only grid settings (preserves in-progress widget layout
125
- * edits while customize mode is active).
117
+ * Publishes any pending auto-save immediately. Called when leaving the
118
+ * inline surface (opening the drawer, entering customize) so staged inline
119
+ * edits do not commingle with the drawer's explicit-save flow.
126
120
  */
127
- cancel: ( options?: CancelOptions ) => void;
121
+ flushAutoSave: () => void;
128
122
 
129
123
  hasUncommittedChanges: boolean;
130
124
  editMode: boolean;
@@ -136,11 +130,6 @@ interface CommitOptions {
136
130
  exitEditMode?: boolean;
137
131
  }
138
132
 
139
- interface CancelOptions {
140
- exitEditMode?: boolean;
141
- revertLayout?: boolean;
142
- }
143
-
144
133
  const Context = createContext< InternalDashboardContextValue | null >( null );
145
134
 
146
135
  /**
@@ -184,21 +173,15 @@ interface ProviderProps {
184
173
 
185
174
  gridSettings?: WidgetGridSettings;
186
175
 
187
- /**
188
- * Fired on commit when the staged settings differ from
189
- * `gridSettings`.
190
- */
191
- onGridSettingsChange?: ( gridSettings: WidgetGridSettings ) => void;
192
-
193
176
  children: ReactNode;
194
177
  }
195
178
 
196
179
  /**
197
- * Provider for the dashboard's staging layer. Owns staging copies of
198
- * `layout` and `gridSettings`; `commit` publishes whichever slice
199
- * differs from its committed prop, `cancel` reverts both.
180
+ * Provider for the dashboard's staging layer. Owns the staging copy of
181
+ * `layout`; `commit` publishes it when it differs from the committed
182
+ * prop, `cancel` reverts it.
200
183
  *
201
- * Staging re-syncs from the committed props on prop change. In-flight
184
+ * Staging re-syncs from the committed prop on prop change. In-flight
202
185
  * edits are dropped silently when an external update (cross-tab commit,
203
186
  * reset, websocket push) lands. Consumers that cannot tolerate this
204
187
  * loss should mediate the prop updates before forwarding them here.
@@ -215,7 +198,6 @@ export function WidgetDashboardProvider( {
215
198
  onEditChange,
216
199
  resolveWidgetModule = DEFAULT_RESOLVE_WIDGET_MODULE,
217
200
  gridSettings: committedGridSettings = DEFAULT_GRID,
218
- onGridSettingsChange,
219
201
  children,
220
202
  }: ProviderProps ): React.ReactNode {
221
203
  const [ stagingLayout, setStagingLayout ] =
@@ -228,17 +210,10 @@ export function WidgetDashboardProvider( {
228
210
  setStagingLayout( committedLayout );
229
211
  }, [ committedLayout ] );
230
212
 
231
- const [ stagingGridSettings, setStagingGridSettings ] =
232
- useState< WidgetGridSettings >( () =>
233
- normalizeGridSettings( committedGridSettings, DEFAULT_ROW_HEIGHT )
234
- );
235
-
236
- // Same external-resync semantics as `stagingLayout`.
237
- useEffect( () => {
238
- setStagingGridSettings(
239
- normalizeGridSettings( committedGridSettings, DEFAULT_ROW_HEIGHT )
240
- );
241
- }, [ committedGridSettings ] );
213
+ const gridSettings = useMemo(
214
+ () => resolveGridSettings( committedGridSettings ),
215
+ [ committedGridSettings ]
216
+ );
242
217
 
243
218
  const hasLayoutChanges = useMemo(
244
219
  () =>
@@ -249,12 +224,7 @@ export function WidgetDashboardProvider( {
249
224
  [ committedLayout, stagingLayout ]
250
225
  );
251
226
 
252
- const hasGridSettingsChanges = useMemo(
253
- () => ! fastDeepEqual( committedGridSettings, stagingGridSettings ),
254
- [ committedGridSettings, stagingGridSettings ]
255
- );
256
-
257
- const hasUncommittedChanges = hasLayoutChanges || hasGridSettingsChanges;
227
+ const hasUncommittedChanges = hasLayoutChanges;
258
228
 
259
229
  const commit = useCallback(
260
230
  ( options?: CommitOptions ) => {
@@ -262,75 +232,47 @@ export function WidgetDashboardProvider( {
262
232
  onLayoutChange( canonicalize( stagingLayout ) );
263
233
  }
264
234
 
265
- if ( hasGridSettingsChanges ) {
266
- onGridSettingsChange?.(
267
- normalizeGridSettings(
268
- stagingGridSettings,
269
- DEFAULT_ROW_HEIGHT
270
- )
271
- );
272
- }
273
-
274
235
  if ( options?.exitEditMode !== false ) {
275
236
  onEditChange?.( false );
276
237
  }
277
238
  },
278
- [
279
- hasLayoutChanges,
280
- hasGridSettingsChanges,
281
- onLayoutChange,
282
- onGridSettingsChange,
283
- stagingLayout,
284
- stagingGridSettings,
285
- onEditChange,
286
- ]
239
+ [ hasLayoutChanges, onLayoutChange, stagingLayout, onEditChange ]
287
240
  );
288
241
 
289
- const cancel = useCallback(
290
- ( options?: CancelOptions ) => {
291
- if ( options?.revertLayout !== false ) {
292
- setStagingLayout( committedLayout );
293
- }
294
- setStagingGridSettings( committedGridSettings );
295
- if ( options?.exitEditMode !== false ) {
296
- onEditChange?.( false );
297
- }
298
- },
299
- [ committedLayout, committedGridSettings, onEditChange ]
242
+ // Auto-save for inline edits.
243
+ // A single debounced timer publishes through `useEvent`, so it always
244
+ // reads the latest `commit` (and so the current staging) without
245
+ // resetting on staging re-renders.
246
+ const publishAutoSave = useEvent( () => commit( { exitEditMode: false } ) );
247
+
248
+ const scheduleAutoSave = useMemo(
249
+ () => debounce( publishAutoSave, AUTO_SAVE_DELAY_MS ),
250
+ [ publishAutoSave ]
300
251
  );
301
252
 
302
- const commitGridModelChange = useCallback(
303
- ( targetModel: WidgetGridModel ) => {
304
- const next = computeGridModelChange( {
305
- layout: stagingLayout,
306
- gridSettings: stagingGridSettings,
307
- targetModel,
308
- } );
253
+ const flushAutoSave = useCallback(
254
+ () => scheduleAutoSave.flush(),
255
+ [ scheduleAutoSave ]
256
+ );
309
257
 
310
- if ( ! next ) {
311
- return;
312
- }
258
+ // Entering customize flushes any pending inline save first, so it does not
259
+ // commingle with the layout edit flow.
260
+ useEffect( () => {
261
+ if ( ! editMode ) {
262
+ return;
263
+ }
313
264
 
314
- setStagingLayout( next.layout );
315
- setStagingGridSettings( next.gridSettings );
316
- onLayoutChange( canonicalize( next.layout ) );
317
- onGridSettingsChange?.(
318
- normalizeGridSettings( next.gridSettings, DEFAULT_ROW_HEIGHT )
319
- );
320
- onEditChange?.( false );
321
- },
322
- [
323
- stagingLayout,
324
- stagingGridSettings,
325
- onLayoutChange,
326
- onGridSettingsChange,
327
- onEditChange,
328
- ]
329
- );
265
+ scheduleAutoSave.flush();
266
+ }, [ editMode, scheduleAutoSave ] );
330
267
 
331
- const resetGridSettings = useCallback( () => {
332
- setStagingGridSettings( DEFAULT_GRID );
333
- }, [] );
268
+ // Flush, not cancel, on unmount: an edit still inside the debounce window
269
+ // must persist when the user navigates away from the dashboard.
270
+ useEffect( () => () => scheduleAutoSave.flush(), [ scheduleAutoSave ] );
271
+
272
+ const cancel = useCallback( () => {
273
+ setStagingLayout( committedLayout );
274
+ onEditChange?.( false );
275
+ }, [ committedLayout, onEditChange ] );
334
276
 
335
277
  useEffect( () => {
336
278
  if ( stagingLayout.length === 0 ) {
@@ -343,8 +285,6 @@ export function WidgetDashboardProvider( {
343
285
  // eslint-disable-next-line react-hooks/exhaustive-deps
344
286
  }, [ stagingLayout.length === 0 ] );
345
287
 
346
- const canEditGridSettings = onGridSettingsChange !== undefined;
347
-
348
288
  const value = useMemo< InternalDashboardContextValue >(
349
289
  () => ( {
350
290
  widgetTypes,
@@ -352,13 +292,11 @@ export function WidgetDashboardProvider( {
352
292
  layout: stagingLayout,
353
293
  onLayoutChange: setStagingLayout,
354
294
  onLayoutReset,
355
- gridSettings: resolveGridSettings( stagingGridSettings ),
356
- onGridSettingsChange: setStagingGridSettings,
357
- canEditGridSettings,
358
- resetGridSettings,
295
+ gridSettings,
359
296
  commit,
360
- commitGridModelChange,
361
297
  cancel,
298
+ scheduleAutoSave,
299
+ flushAutoSave,
362
300
  hasUncommittedChanges,
363
301
  editMode,
364
302
  onEditChange,
@@ -369,12 +307,11 @@ export function WidgetDashboardProvider( {
369
307
  isResolvingWidgetTypes,
370
308
  stagingLayout,
371
309
  onLayoutReset,
372
- stagingGridSettings,
373
- canEditGridSettings,
374
- resetGridSettings,
310
+ gridSettings,
375
311
  commit,
376
- commitGridModelChange,
377
312
  cancel,
313
+ scheduleAutoSave,
314
+ flushAutoSave,
378
315
  hasUncommittedChanges,
379
316
  editMode,
380
317
  onEditChange,
@@ -13,14 +13,10 @@ import {
13
13
  useState,
14
14
  } from '@wordpress/element';
15
15
 
16
- type DrawerSide = 'left' | 'right';
17
-
18
16
  interface DashboardUIContextValue {
19
17
  inserterOpen: boolean;
20
18
  setInserterOpen: ( next: boolean ) => void;
21
19
 
22
- layoutSettingsOpen: boolean;
23
- setLayoutSettingsOpen: ( next: boolean ) => void;
24
20
  resetDialogOpen: boolean;
25
21
  setResetDialogOpen: ( next: boolean ) => void;
26
22
 
@@ -32,23 +28,6 @@ interface DashboardUIContextValue {
32
28
  */
33
29
  settingsWidgetUuid: string | null;
34
30
  setSettingsWidgetUuid: ( next: string | null ) => void;
35
-
36
- /**
37
- * Edge the settings drawer slides in from. The gear sets it from the
38
- * widget's on-screen position so the drawer opens on the side away
39
- * from the widget, trying not to cover it.
40
- */
41
- settingsDrawerSide: DrawerSide;
42
- setSettingsDrawerSide: ( next: DrawerSide ) => void;
43
-
44
- /**
45
- * Inline-start inset (px) the settings drawer is offset by when it
46
- * opens from the left, so it clears fixed page chrome (the WordPress
47
- * admin menu) instead of sliding over it. `0` when there's nothing to
48
- * clear.
49
- */
50
- settingsDrawerInset: number;
51
- setSettingsDrawerInset: ( next: number ) => void;
52
31
  }
53
32
 
54
33
  const Context = createContext< DashboardUIContextValue | null >( null );
@@ -80,38 +59,21 @@ interface ProviderProps {
80
59
  */
81
60
  export function WidgetDashboardUIProvider( { children }: ProviderProps ) {
82
61
  const [ inserterOpen, setInserterOpen ] = useState( false );
83
- const [ layoutSettingsOpen, setLayoutSettingsOpen ] = useState( false );
84
62
  const [ resetDialogOpen, setResetDialogOpen ] = useState( false );
85
63
  const [ settingsWidgetUuid, setSettingsWidgetUuid ] = useState<
86
64
  string | null
87
65
  >( null );
88
- const [ settingsDrawerSide, setSettingsDrawerSide ] =
89
- useState< DrawerSide >( 'right' );
90
- const [ settingsDrawerInset, setSettingsDrawerInset ] = useState( 0 );
91
66
 
92
67
  const value = useMemo< DashboardUIContextValue >(
93
68
  () => ( {
94
69
  inserterOpen,
95
70
  setInserterOpen,
96
- layoutSettingsOpen,
97
- setLayoutSettingsOpen,
98
71
  resetDialogOpen,
99
72
  setResetDialogOpen,
100
73
  settingsWidgetUuid,
101
74
  setSettingsWidgetUuid,
102
- settingsDrawerSide,
103
- setSettingsDrawerSide,
104
- settingsDrawerInset,
105
- setSettingsDrawerInset,
106
75
  } ),
107
- [
108
- inserterOpen,
109
- layoutSettingsOpen,
110
- resetDialogOpen,
111
- settingsWidgetUuid,
112
- settingsDrawerSide,
113
- settingsDrawerInset,
114
- ]
76
+ [ inserterOpen, resetDialogOpen, settingsWidgetUuid ]
115
77
  );
116
78
 
117
79
  return <Context.Provider value={ value }>{ children }</Context.Provider>;
@@ -15,7 +15,7 @@ import type { WidgetType } from '@wordpress/widget-primitives';
15
15
  * Internal dependencies
16
16
  */
17
17
  import { WidgetDashboard } from '../widget-dashboard';
18
- import type { DashboardWidget, WidgetGridSettings } from '../types';
18
+ import type { DashboardWidget } from '../types';
19
19
 
20
20
  const widgetTypes: WidgetType[] = [];
21
21
 
@@ -25,24 +25,16 @@ const layout: DashboardWidget[] = [
25
25
  { uuid: 'a', type: 'core/test', placement: { width: 1, height: 1 } },
26
26
  ];
27
27
 
28
- const gridSettings: WidgetGridSettings = {
29
- model: 'grid',
30
- minColumnWidth: 350,
31
- rowHeight: 200,
32
- };
33
-
34
28
  interface HarnessProps {
35
29
  initialEditMode?: boolean;
36
30
  onEditChange?: ( next: boolean ) => void;
37
31
  onLayoutChange?: ( next: DashboardWidget[] ) => void;
38
- onGridSettingsChange?: ( next: WidgetGridSettings ) => void;
39
32
  }
40
33
 
41
34
  function Harness( {
42
35
  initialEditMode = false,
43
36
  onEditChange,
44
37
  onLayoutChange = () => {},
45
- onGridSettingsChange,
46
38
  }: HarnessProps ) {
47
39
  const [ editMode, setEditMode ] = useState( initialEditMode );
48
40
 
@@ -50,8 +42,6 @@ function Harness( {
50
42
  <WidgetDashboard
51
43
  layout={ layout }
52
44
  onLayoutChange={ onLayoutChange }
53
- gridSettings={ gridSettings }
54
- onGridSettingsChange={ onGridSettingsChange }
55
45
  widgetTypes={ widgetTypes }
56
46
  editMode={ editMode }
57
47
  onEditChange={ ( next ) => {
@@ -146,72 +136,12 @@ describe( 'WidgetDashboard.Actions', () => {
146
136
  ).not.toBeInTheDocument();
147
137
  } );
148
138
 
149
- describe( 'Layout settings', () => {
150
- it( 'is hidden when editMode is false', () => {
151
- render( <Harness onGridSettingsChange={ () => {} } /> );
152
-
153
- expect(
154
- screen.queryByRole( 'button', { name: 'Layout settings' } )
155
- ).not.toBeInTheDocument();
156
- } );
157
-
158
- it( 'is visible in the edit toolbar when grid settings are editable', () => {
159
- render(
160
- <Harness initialEditMode onGridSettingsChange={ () => {} } />
161
- );
162
-
163
- expect(
164
- screen.getByRole( 'button', { name: 'Layout settings' } )
165
- ).toBeInTheDocument();
166
- } );
167
-
168
- it( 'is hidden when onGridSettingsChange is not provided', () => {
169
- render( <Harness initialEditMode /> );
170
-
171
- expect(
172
- screen.queryByRole( 'button', { name: 'Layout settings' } )
173
- ).not.toBeInTheDocument();
174
- } );
175
-
176
- it( 'opens the layout settings drawer when clicked', async () => {
177
- render(
178
- <Harness initialEditMode onGridSettingsChange={ () => {} } />
179
- );
180
-
181
- await user.click(
182
- screen.getByRole( 'button', { name: 'Layout settings' } )
183
- );
184
-
185
- expect(
186
- await screen.findByRole( 'dialog', { name: 'Layout settings' } )
187
- ).toBeInTheDocument();
188
- } );
189
-
190
- it( 'is not in the more-actions menu', async () => {
191
- const onLayoutReset = jest.fn();
192
- render(
193
- <WidgetDashboard
194
- layout={ layout }
195
- onLayoutChange={ () => {} }
196
- onLayoutReset={ onLayoutReset }
197
- gridSettings={ gridSettings }
198
- onGridSettingsChange={ () => {} }
199
- widgetTypes={ widgetTypes }
200
- editMode
201
- onEditChange={ () => {} }
202
- >
203
- <WidgetDashboard.Actions />
204
- </WidgetDashboard>
205
- );
206
-
207
- await user.click(
208
- screen.getByRole( 'button', { name: 'More options' } )
209
- );
210
-
211
- expect(
212
- screen.queryByRole( 'menuitem', { name: 'Layout settings' } )
213
- ).not.toBeInTheDocument();
214
- } );
139
+ it( 'does not render a Layout settings button', () => {
140
+ render( <Harness initialEditMode /> );
141
+
142
+ expect(
143
+ screen.queryByRole( 'button', { name: 'Layout settings' } )
144
+ ).not.toBeInTheDocument();
215
145
  } );
216
146
 
217
147
  it( 'throws when used outside a WidgetDashboard subtree', () => {
@@ -60,23 +60,20 @@ function CommandsProbe( { names }: { names: string[] } ) {
60
60
  const COMMAND_NAMES = [
61
61
  'core/dashboard/customize',
62
62
  'core/dashboard/add-widgets',
63
+ 'core/dashboard/reset-to-default',
64
+ // Removed commands, probed to assert they stay unregistered.
63
65
  'core/dashboard/switch-to-masonry-layout',
64
66
  'core/dashboard/switch-to-grid-layout',
65
- 'core/dashboard/reset-to-default',
66
67
  ];
67
68
 
68
69
  interface HarnessProps {
69
70
  initialEditMode?: boolean;
70
- withGridSettings?: boolean;
71
71
  withLayoutReset?: boolean;
72
- gridModel?: 'grid' | 'masonry';
73
72
  }
74
73
 
75
74
  function Harness( {
76
75
  initialEditMode = false,
77
- withGridSettings = false,
78
76
  withLayoutReset = false,
79
- gridModel = 'grid',
80
77
  }: HarnessProps ) {
81
78
  const [ editMode, setEditMode ] = useState( initialEditMode );
82
79
 
@@ -88,10 +85,6 @@ function Harness( {
88
85
  editMode={ editMode }
89
86
  onEditChange={ setEditMode }
90
87
  onLayoutReset={ withLayoutReset ? async () => {} : undefined }
91
- gridSettings={
92
- withGridSettings ? { model: gridModel, columns: 6 } : undefined
93
- }
94
- onGridSettingsChange={ withGridSettings ? () => {} : undefined }
95
88
  >
96
89
  <WidgetDashboard.Commands />
97
90
  <CommandsProbe names={ COMMAND_NAMES } />
@@ -105,7 +98,7 @@ function getRegistered( probe: HTMLElement ): Record< string, boolean > {
105
98
 
106
99
  describe( 'WidgetDashboard.Commands', () => {
107
100
  it( 'sets the dashboard command context and registers core commands', () => {
108
- render( <Harness withGridSettings withLayoutReset /> );
101
+ render( <Harness withLayoutReset /> );
109
102
  const probe = screen.getByTestId( 'commands-probe' );
110
103
  const registered = getRegistered( probe );
111
104
 
@@ -119,7 +112,7 @@ describe( 'WidgetDashboard.Commands', () => {
119
112
  } );
120
113
 
121
114
  it( 'unregisters Customize while edit mode is active', () => {
122
- render( <Harness initialEditMode withGridSettings withLayoutReset /> );
115
+ render( <Harness initialEditMode withLayoutReset /> );
123
116
  const registered = getRegistered(
124
117
  screen.getByTestId( 'commands-probe' )
125
118
  );
@@ -128,15 +121,8 @@ describe( 'WidgetDashboard.Commands', () => {
128
121
  expect( registered[ 'core/dashboard/add-widgets' ] ).toBe( true );
129
122
  } );
130
123
 
131
- it( 'disables layout commands while edit mode is active', () => {
132
- render(
133
- <Harness
134
- initialEditMode
135
- withGridSettings
136
- withLayoutReset
137
- gridModel="grid"
138
- />
139
- );
124
+ it( 'does not register layout-model switch commands', () => {
125
+ render( <Harness withLayoutReset /> );
140
126
  const registered = getRegistered(
141
127
  screen.getByTestId( 'commands-probe' )
142
128
  );
@@ -148,29 +134,4 @@ describe( 'WidgetDashboard.Commands', () => {
148
134
  false
149
135
  );
150
136
  } );
151
-
152
- it( 'only registers the active layout-model switch command', () => {
153
- render( <Harness withGridSettings withLayoutReset gridModel="grid" /> );
154
- const registered = getRegistered(
155
- screen.getByTestId( 'commands-probe' )
156
- );
157
-
158
- expect( registered[ 'core/dashboard/switch-to-masonry-layout' ] ).toBe(
159
- true
160
- );
161
- expect( registered[ 'core/dashboard/switch-to-grid-layout' ] ).toBe(
162
- false
163
- );
164
- } );
165
-
166
- it( 'omits grid-settings commands when grid settings are not editable', () => {
167
- render( <Harness withLayoutReset /> );
168
- const registered = getRegistered(
169
- screen.getByTestId( 'commands-probe' )
170
- );
171
-
172
- expect( registered[ 'core/dashboard/switch-to-masonry-layout' ] ).toBe(
173
- false
174
- );
175
- } );
176
137
  } );