@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
@@ -1,12 +1,9 @@
1
- /*
2
- * Per-tile toolbar shell: anchored top-right (the grid item is the positioned
3
- * ancestor) with the shared padding and radius. Variants add the background.
4
- */
5
1
  .widgetToolbar {
6
- position: absolute;
7
- inset-block-start: var(--wpds-dimension-padding-sm);
8
- inset-inline-end: var(--wpds-dimension-padding-sm);
9
- z-index: 1;
10
2
  padding: var(--wpds-dimension-padding-xs);
11
- border-radius: var(--wpds-border-radius-md);
3
+ background: var(--wpds-color-background-surface-neutral-strong);
4
+ }
5
+
6
+ .elevated {
7
+ border: 1px solid var(--wpds-color-stroke-surface-neutral-weak);
8
+ box-shadow: var(--wpds-elevation-xs);
12
9
  }
@@ -15,30 +15,36 @@ import { Stack } from '@wordpress/ui';
15
15
  import styles from './widget-toolbar.module.css';
16
16
 
17
17
  export interface WidgetToolbarProps {
18
- /** Toolbar controls, laid out in one row. */
18
+ /**
19
+ * The active mode's controls.
20
+ */
19
21
  children: ReactNode;
20
22
 
21
- /** Variant surface class (background, reveal). */
22
- className?: string;
23
+ /**
24
+ * Lift the toolbar with a shadow while customizing.
25
+ */
26
+ editMode?: boolean;
23
27
  }
24
28
 
25
29
  /**
26
- * Shared shell for the per-tile action toolbars. Anchors to the tile's
27
- * top-right corner and lays controls out in the row the header also uses, so
28
- * a toolbar lines up with the title when they overlap.
30
+ * The per-tile toolbar chip holding the active mode's controls.
31
+ * Always visible; lifted with a shadow only while customizing.
29
32
  *
30
33
  * @param {WidgetToolbarProps} props Component props.
31
34
  */
32
35
  export function WidgetToolbar( {
33
36
  children,
34
- className,
37
+ editMode = false,
35
38
  }: WidgetToolbarProps ): React.ReactNode {
36
39
  return (
37
40
  <Stack
38
41
  direction="row"
39
42
  align="center"
40
43
  gap="xs"
41
- className={ clsx( styles.widgetToolbar, className ) }
44
+ className={ clsx(
45
+ styles.widgetToolbar,
46
+ editMode && styles.elevated
47
+ ) }
42
48
  >
43
49
  { children }
44
50
  </Stack>
@@ -1,5 +1,4 @@
1
1
  .grid {
2
- /* stylelint-disable-next-line property-no-unknown -- container queries for the dashboard grid surface */
3
2
  container-type: inline-size;
4
3
  container-name: widget-dashboard;
5
4
  width: 100%;
@@ -21,9 +21,11 @@ import type { WidgetName } from '@wordpress/widget-primitives';
21
21
  */
22
22
  import { useDashboardInternalContext } from '../../context/dashboard-context';
23
23
  import { useDashboardContainerColumnCount } from '../../hooks/use-dashboard-container-column-count';
24
+ import { WidgetAttributeControls } from '../widget-attribute-controls';
24
25
  import { WidgetChrome } from '../widget-chrome';
25
- import { WidgetSettingsToolbar } from '../widget-settings';
26
- import { WidgetLayoutToolbar } from './widget-layout-toolbar';
26
+ import { WidgetHeader } from '../widget-header';
27
+ import { WidgetLayoutControls } from '../widget-layout-controls';
28
+ import { WidgetToolbar } from '../widget-toolbar';
27
29
  import { WidgetResizeHandle } from './widget-resize-handle';
28
30
  import styles from './widgets.module.css';
29
31
  import type {
@@ -132,21 +134,40 @@ export const Widgets = forwardRef< HTMLDivElement, WidgetsProps >(
132
134
  ( type ) => type.name === widget.type
133
135
  );
134
136
  const hasSettings = !! widgetType?.attributes?.length;
137
+ const isFullBleed = widgetType?.presentation === 'full-bleed';
135
138
 
136
- // One slot, chosen by mode: layout toolbar while customizing,
137
- // settings toolbar otherwise (undefined when nothing to configure).
138
- let actionableArea: React.ReactNode;
139
+ // The active mode's controls: layout while customizing, the
140
+ // attribute controls (high-relevance fields plus the gear)
141
+ // otherwise.
142
+ let controls: React.ReactNode;
139
143
  if ( editMode ) {
140
- actionableArea = <WidgetLayoutToolbar widget={ widget } />;
144
+ controls = <WidgetLayoutControls widget={ widget } />;
141
145
  } else if ( hasSettings && widgetType ) {
142
- actionableArea = (
143
- <WidgetSettingsToolbar
146
+ controls = (
147
+ <WidgetAttributeControls
144
148
  widget={ widget }
145
149
  widgetType={ widgetType }
146
150
  />
147
151
  );
148
152
  }
149
153
 
154
+ const toolbar = controls ? (
155
+ <WidgetToolbar editMode={ editMode }>
156
+ { controls }
157
+ </WidgetToolbar>
158
+ ) : undefined;
159
+
160
+ // Normal mode hosts the toolbar in the in-card header, beside the
161
+ // identity. Customize controls and full-bleed widgets need it in
162
+ // the grid's actionable-area slot instead: the slot sits outside
163
+ // the draggable card, so the controls stay clickable (in-card they
164
+ // would be captured by the drag listeners).
165
+ const inSlot = editMode || isFullBleed;
166
+ const actionableArea =
167
+ inSlot && toolbar ? (
168
+ <WidgetHeader overlay>{ toolbar }</WidgetHeader>
169
+ ) : undefined;
170
+
150
171
  return (
151
172
  <WidgetChrome
152
173
  key={ widget.uuid }
@@ -156,6 +177,7 @@ export const Widgets = forwardRef< HTMLDivElement, WidgetsProps >(
156
177
  [ styles.tileEditMode ]: editMode,
157
178
  } ) }
158
179
  actionableArea={ actionableArea }
180
+ headerToolbar={ ! inSlot ? toolbar : undefined }
159
181
  />
160
182
  );
161
183
  } );
@@ -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', () => {