@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
@@ -0,0 +1,82 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { createInterpolateElement } from '@wordpress/element';
5
+ import { __ } from '@wordpress/i18n';
6
+ import { info } from '@wordpress/icons';
7
+ // eslint-disable-next-line @wordpress/use-recommended-components
8
+ import { Icon, Link, Popover, Stack, VisuallyHidden } from '@wordpress/ui';
9
+
10
+ /**
11
+ * Internal dependencies
12
+ */
13
+ import styles from './widget-header.module.css';
14
+
15
+ export interface WidgetInfotipProps {
16
+ /**
17
+ * Help content to display; may carry `<em>`/`<strong>`.
18
+ */
19
+ content: string;
20
+
21
+ /**
22
+ * Links rendered after the content.
23
+ */
24
+ links?: {
25
+ label: string;
26
+ href: string;
27
+ }[];
28
+ }
29
+
30
+ /**
31
+ * Header infotip: a click-open popover holding the widget type's help note.
32
+ *
33
+ * @param {WidgetInfotipProps} props Component props.
34
+ */
35
+ export function WidgetInfotip( {
36
+ content,
37
+ links,
38
+ }: WidgetInfotipProps ): React.ReactNode {
39
+ return (
40
+ <Popover.Root modal="trap-focus">
41
+ <Popover.Trigger
42
+ aria-label={ __( 'More information' ) }
43
+ className={ styles.help }
44
+ >
45
+ <Icon icon={ info } size={ 20 } />
46
+ </Popover.Trigger>
47
+
48
+ <Popover.Popup
49
+ className={ styles.popoverPopup }
50
+ positioner={ <Popover.Positioner side="top" align="start" /> }
51
+ >
52
+ <Popover.Arrow />
53
+ <VisuallyHidden render={ <Popover.Title /> }>
54
+ { __( 'More information' ) }
55
+ </VisuallyHidden>
56
+
57
+ <Stack direction="column" align="start" gap="sm">
58
+ <Popover.Description>
59
+ { createInterpolateElement( content, {
60
+ em: <em />,
61
+ strong: <strong />,
62
+ } ) }
63
+ </Popover.Description>
64
+
65
+ { links && links.length > 0 && (
66
+ <Stack direction="row" align="start" gap="sm">
67
+ { links.map( ( link ) => (
68
+ <Link
69
+ key={ link.href }
70
+ href={ link.href }
71
+ className={ styles.link }
72
+ >
73
+ { link.label }
74
+ </Link>
75
+ ) ) }
76
+ </Stack>
77
+ ) }
78
+ </Stack>
79
+ </Popover.Popup>
80
+ </Popover.Root>
81
+ );
82
+ }
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Tile header row: identity leads, toolbar trails, on one line.
3
+ */
4
+ .widgetHeader {
5
+ display: flex;
6
+ align-items: center;
7
+ gap: var(--wpds-dimension-gap-sm);
8
+ }
9
+
10
+ /**
11
+ * Identity and toolbar share one box so they stay aligned.
12
+ */
13
+ .identity,
14
+ .toolbar {
15
+ display: flex;
16
+ align-items: center;
17
+ height: var(--wpds-dimension-size-lg);
18
+ }
19
+
20
+ /**
21
+ * Shrink a long title instead of pushing the toolbar out.
22
+ */
23
+ .identity {
24
+ min-width: 0;
25
+ }
26
+
27
+ .icon {
28
+ display: inline-flex;
29
+ color: var(--wpds-color-foreground-content-neutral);
30
+ }
31
+
32
+ .popoverPopup {
33
+ max-width: 300px;
34
+ }
35
+
36
+ /**
37
+ * Infotip trigger: a bare icon button beside the title.
38
+ */
39
+ .help {
40
+ display: inline-flex;
41
+ align-items: center;
42
+ padding: 0;
43
+ border: 0;
44
+ background: none;
45
+ color: var(--wpds-color-foreground-content-neutral-weak);
46
+ cursor: var(--wpds-cursor-control);
47
+ }
48
+
49
+ /**
50
+ * Divide adjacent links in the infotip.
51
+ */
52
+ .link + .link {
53
+ border-inline-start: var(--wpds-border-width-xs) solid var(--wpds-color-stroke-surface-neutral);
54
+ padding-inline-start: var(--wpds-dimension-gap-sm);
55
+ }
56
+
57
+ .toolbar {
58
+ margin-inline-start: auto;
59
+ }
60
+
61
+ /**
62
+ * Floats over the tile, click-through except the toolbar; re-declares the card
63
+ * padding var (outside Card.Root).
64
+ */
65
+ .overlay {
66
+ position: absolute;
67
+ inset-block-start: 0;
68
+ inset-inline: 0;
69
+ z-index: 1;
70
+ pointer-events: none;
71
+ --wp-ui-card-padding: var(--wpds-dimension-padding-2xl);
72
+ }
73
+
74
+ .overlay .toolbar {
75
+ pointer-events: auto;
76
+ }
@@ -0,0 +1,101 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import clsx from 'clsx';
5
+ import type { ReactNode } from 'react';
6
+
7
+ /**
8
+ * WordPress dependencies
9
+ */
10
+ import { Card, Icon, Stack } from '@wordpress/ui';
11
+ import type { WidgetType } from '@wordpress/widget-primitives';
12
+
13
+ /**
14
+ * Internal dependencies
15
+ */
16
+ import { WidgetInfotip } from './widget-header-infotip';
17
+ import styles from './widget-header.module.css';
18
+
19
+ export interface WidgetHeaderProps {
20
+ /**
21
+ * Widget type, source of the icon, title, and help note shown as
22
+ * identity.
23
+ */
24
+ widgetType?: WidgetType;
25
+
26
+ /**
27
+ * Id linking the title to the tile's labelled region.
28
+ */
29
+ titleId?: string;
30
+
31
+ /**
32
+ * Render the icon + title cluster on the leading edge.
33
+ */
34
+ showIdentity?: boolean;
35
+
36
+ /**
37
+ * Float over the tile instead of sitting in the card flow.
38
+ */
39
+ overlay?: boolean;
40
+
41
+ /**
42
+ * Inert the identity while customizing, so it does not capture interaction.
43
+ */
44
+ editMode?: boolean;
45
+
46
+ /**
47
+ * Toolbar placed on the trailing edge.
48
+ */
49
+ children?: ReactNode;
50
+ }
51
+
52
+ /**
53
+ * Tile header row: identity (icon + title) and a toolbar on one line. Rendered
54
+ * in the card flow, or as an `overlay` in the grid slot for full-bleed widgets
55
+ * that have no in-card header.
56
+ *
57
+ * @param {WidgetHeaderProps} props Component props.
58
+ */
59
+ export function WidgetHeader( {
60
+ widgetType,
61
+ titleId,
62
+ showIdentity = false,
63
+ overlay = false,
64
+ editMode = false,
65
+ children,
66
+ }: WidgetHeaderProps ): React.ReactNode {
67
+ return (
68
+ <Card.Header
69
+ className={ clsx( styles.widgetHeader, overlay && styles.overlay ) }
70
+ >
71
+ { showIdentity && widgetType?.title && (
72
+ <Stack
73
+ direction="row"
74
+ align="center"
75
+ gap="sm"
76
+ className={ styles.identity }
77
+ { ...( editMode ? { inert: 'true' } : {} ) }
78
+ >
79
+ { widgetType.icon && (
80
+ <span className={ styles.icon } aria-hidden="true">
81
+ <Icon icon={ widgetType.icon } />
82
+ </span>
83
+ ) }
84
+
85
+ <Card.Title id={ titleId } render={ <h2 /> }>
86
+ { widgetType.title }
87
+ </Card.Title>
88
+
89
+ { widgetType.help && (
90
+ <WidgetInfotip
91
+ content={ widgetType.help.content }
92
+ links={ widgetType.help.links }
93
+ />
94
+ ) }
95
+ </Stack>
96
+ ) }
97
+
98
+ { children && <div className={ styles.toolbar }>{ children }</div> }
99
+ </Card.Header>
100
+ );
101
+ }
@@ -0,0 +1,2 @@
1
+ export { WidgetLayoutControls } from './widget-layout-controls';
2
+ export type { WidgetLayoutControlsProps } from './widget-layout-controls';
@@ -4,7 +4,6 @@
4
4
  import { privateApis as componentsPrivateApis } from '@wordpress/components';
5
5
  import { __ } from '@wordpress/i18n';
6
6
  import { moreVertical, trash } from '@wordpress/icons';
7
- // Dashboard is still experimental.
8
7
  // eslint-disable-next-line @wordpress/use-recommended-components
9
8
  import { IconButton } from '@wordpress/ui';
10
9
 
@@ -13,8 +12,6 @@ import { IconButton } from '@wordpress/ui';
13
12
  */
14
13
  import { unlock } from '../../lock-unlock';
15
14
  import { useDashboardInternalContext } from '../../context/dashboard-context';
16
- import { WidgetToolbar } from '../widget-toolbar';
17
- import styles from './widget-layout-toolbar.module.css';
18
15
  import type { DashboardWidget, GridTilePlacement } from '../../types';
19
16
 
20
17
  const { Menu } = unlock( componentsPrivateApis );
@@ -24,21 +21,21 @@ type NamedGridWidth = Exclude<
24
21
  number
25
22
  >;
26
23
 
27
- export interface WidgetLayoutToolbarProps {
28
- /** The instance this toolbar manages within the layout. */
24
+ export interface WidgetLayoutControlsProps {
25
+ /**
26
+ * The instance these controls manage within the layout.
27
+ */
29
28
  widget: DashboardWidget< unknown >;
30
29
  }
31
30
 
32
31
  /**
33
- * Customize-mode per-tile toolbar: a width menu and removal, editing the
34
- * widget's place in the layout. Lives in the grid's `actionableArea` slot, so
35
- * it stays interactive while the card is `inert`.
32
+ * Customize-mode controls: width menu and removal.
36
33
  *
37
- * @param {WidgetLayoutToolbarProps} props Component props.
34
+ * @param {WidgetLayoutControlsProps} props Component props.
38
35
  */
39
- export function WidgetLayoutToolbar( {
36
+ export function WidgetLayoutControls( {
40
37
  widget,
41
- }: WidgetLayoutToolbarProps ): React.ReactNode {
38
+ }: WidgetLayoutControlsProps ): React.ReactNode {
42
39
  const { layout, onLayoutChange } = useDashboardInternalContext();
43
40
  const width = widget.placement?.width;
44
41
 
@@ -70,7 +67,7 @@ export function WidgetLayoutToolbar( {
70
67
  };
71
68
 
72
69
  return (
73
- <WidgetToolbar className={ styles.widgetLayoutToolbar }>
70
+ <>
74
71
  <Menu>
75
72
  <Menu.TriggerButton
76
73
  render={
@@ -83,6 +80,7 @@ export function WidgetLayoutToolbar( {
83
80
  />
84
81
  }
85
82
  />
83
+
86
84
  <Menu.Popover>
87
85
  <Menu.Group>
88
86
  <Menu.GroupLabel>{ __( 'Width' ) }</Menu.GroupLabel>
@@ -105,6 +103,7 @@ export function WidgetLayoutToolbar( {
105
103
  </Menu.Group>
106
104
  </Menu.Popover>
107
105
  </Menu>
106
+
108
107
  <IconButton
109
108
  icon={ trash }
110
109
  label={ __( 'Remove' ) }
@@ -113,6 +112,6 @@ export function WidgetLayoutToolbar( {
113
112
  tone="neutral"
114
113
  onClick={ onRemove }
115
114
  />
116
- </WidgetToolbar>
115
+ </>
117
116
  );
118
117
  }
@@ -3,7 +3,7 @@
3
3
  */
4
4
  import { DataViewsPicker, filterSortAndPaginate } from '@wordpress/dataviews';
5
5
  import type { Field, View } from '@wordpress/dataviews';
6
- import { Suspense, useMemo, useState } from '@wordpress/element';
6
+ import { useMemo, useState } from '@wordpress/element';
7
7
  import { __ } from '@wordpress/i18n';
8
8
  import type { WidgetType } from '@wordpress/widget-primitives';
9
9
 
@@ -12,8 +12,7 @@ import type { WidgetType } from '@wordpress/widget-primitives';
12
12
  */
13
13
  import { useDashboardInternalContext } from '../../context/dashboard-context';
14
14
  import { createDashboardWidget } from '../../utils/create-dashboard-widget';
15
- import { WidgetRender } from '../widget-render';
16
- import styles from './widget-picker.module.css';
15
+ import { WidgetPreviewChrome } from '../widget-preview-chrome';
17
16
 
18
17
  const DEFAULT_VIEW: View = {
19
18
  type: 'pickerGrid',
@@ -21,6 +20,8 @@ const DEFAULT_VIEW: View = {
21
20
  search: '',
22
21
  mediaField: 'preview',
23
22
  titleField: 'title',
23
+ // Larger default tile than the built-in 230.
24
+ layout: { previewSize: 290 },
24
25
  };
25
26
 
26
27
  const getItemId = ( item: WidgetType ) => item.name;
@@ -31,13 +32,7 @@ function WidgetPreview( { item }: { item: WidgetType } ) {
31
32
  [ item ]
32
33
  );
33
34
 
34
- return (
35
- <div className={ styles.preview } { ...{ inert: '' } }>
36
- <Suspense fallback={ null }>
37
- <WidgetRender widget={ exampleWidget } widgetType={ item } />
38
- </Suspense>
39
- </div>
40
- );
35
+ return <WidgetPreviewChrome widget={ exampleWidget } widgetType={ item } />;
41
36
  }
42
37
 
43
38
  const fields: Field< WidgetType >[] = [
@@ -0,0 +1,2 @@
1
+ export { WidgetPreviewChrome } from './widget-preview-chrome';
2
+ export type { WidgetPreviewChromeProps } from './widget-preview-chrome';
@@ -0,0 +1,22 @@
1
+ /* Fills the tile and clips the render; inert + click-transparent so the tile owns interaction. */
2
+ .viewport {
3
+ position: absolute;
4
+ inset: 0;
5
+ overflow: hidden;
6
+ border-radius: var(--wpds-border-radius-md);
7
+ background: var(--wpds-color-background-surface-neutral-weak);
8
+ pointer-events: none;
9
+ user-select: none;
10
+ }
11
+
12
+ /* Grid stretches the card to fill the tile regardless of the card's own height. */
13
+ .canvas {
14
+ display: grid;
15
+ width: 100%;
16
+ height: 100%;
17
+ }
18
+
19
+ .card {
20
+ height: 100%;
21
+ min-height: 0;
22
+ }
@@ -0,0 +1,65 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { useId, useMemo } from '@wordpress/element';
5
+ import { Card } from '@wordpress/ui';
6
+ import type { WidgetType } from '@wordpress/widget-primitives';
7
+
8
+ /**
9
+ * Internal dependencies
10
+ */
11
+ import { WidgetContextProvider } from '../../context/widget-context';
12
+ import { WidgetFrame } from '../widget-frame';
13
+ import styles from './widget-preview-chrome.module.css';
14
+ import type { DashboardWidget } from '../../types';
15
+
16
+ export interface WidgetPreviewChromeProps {
17
+ widget: DashboardWidget< unknown >;
18
+ widgetType: WidgetType;
19
+ index?: number;
20
+ }
21
+
22
+ /**
23
+ * Catalog host-chrome: the faithful `WidgetFrame` in a viewport that scales the
24
+ * card to fill the tile at any zoom; inert so the picker owns selection.
25
+ *
26
+ * @param {WidgetPreviewChromeProps} props Component props.
27
+ */
28
+ export function WidgetPreviewChrome( {
29
+ widget,
30
+ widgetType,
31
+ index = 0,
32
+ }: WidgetPreviewChromeProps ) {
33
+ const titleId = useId();
34
+
35
+ const contextValue = useMemo(
36
+ () => ( {
37
+ uuid: widget.uuid,
38
+ name: widget.type,
39
+ index,
40
+ } ),
41
+ [ widget.uuid, widget.type, index ]
42
+ );
43
+
44
+ return (
45
+ <WidgetContextProvider value={ contextValue }>
46
+ <div className={ styles.viewport } { ...{ inert: '' } }>
47
+ <div className={ styles.canvas }>
48
+ <Card.Root
49
+ render={ <section /> }
50
+ className={ styles.card }
51
+ aria-labelledby={
52
+ widgetType.title ? titleId : undefined
53
+ }
54
+ >
55
+ <WidgetFrame
56
+ widget={ widget }
57
+ widgetType={ widgetType }
58
+ titleId={ titleId }
59
+ />
60
+ </Card.Root>
61
+ </div>
62
+ </div>
63
+ </WidgetContextProvider>
64
+ );
65
+ }
@@ -1,4 +1,4 @@
1
1
  export { WidgetSettings } from './widget-settings';
2
2
  export { getWidgetSettingsTitle } from './utils';
3
- export { WidgetSettingsToolbar } from './widget-settings-toolbar';
4
- export type { WidgetSettingsToolbarProps } from './widget-settings-toolbar';
3
+ export { WidgetSettingsTrigger } from './widget-settings-trigger';
4
+ export type { WidgetSettingsTriggerProps } from './widget-settings-trigger';
@@ -1,2 +1 @@
1
- export { getAdminMenuInset } from './get-admin-menu-inset';
2
1
  export { getWidgetSettingsTitle } from './get-widget-settings';
@@ -3,7 +3,7 @@
3
3
  */
4
4
  import { useCallback } from '@wordpress/element';
5
5
  import { __ } from '@wordpress/i18n';
6
- import { cog } from '@wordpress/icons';
6
+ import { moreVertical } from '@wordpress/icons';
7
7
  // Dashboard is still experimental.
8
8
  // eslint-disable-next-line @wordpress/use-recommended-components
9
9
  import { IconButton } from '@wordpress/ui';
@@ -12,8 +12,8 @@ import type { WidgetType } from '@wordpress/widget-primitives';
12
12
  /**
13
13
  * Internal dependencies
14
14
  */
15
+ import { useDashboardInternalContext } from '../../context/dashboard-context';
15
16
  import { useDashboardUIContext } from '../../context/ui-context';
16
- import { getAdminMenuInset } from './utils';
17
17
  import type { DashboardWidget } from '../../types';
18
18
 
19
19
  export interface WidgetSettingsTriggerProps {
@@ -30,10 +30,11 @@ export interface WidgetSettingsTriggerProps {
30
30
  }
31
31
 
32
32
  /**
33
- * Per-instance gear that opens the shared settings drawer by writing the
33
+ * Per-instance gear that toggles the shared settings drawer by writing the
34
34
  * instance `uuid` to the UI context; the single `WidgetSettings` at the root
35
- * reacts to it. Returns `null` when the type declares no attributes, so chrome
36
- * can mount it unconditionally.
35
+ * reacts to it. Clicking the gear of the instance whose drawer is already
36
+ * open closes it. Returns `null` when no attribute needs the drawer (none, or
37
+ * all already promoted inline), so chrome can mount it unconditionally.
37
38
  *
38
39
  * @param {WidgetSettingsTriggerProps} props Component props.
39
40
  */
@@ -41,56 +42,48 @@ export function WidgetSettingsTrigger( {
41
42
  widget,
42
43
  widgetType,
43
44
  }: WidgetSettingsTriggerProps ): React.ReactNode {
44
- const {
45
- setSettingsWidgetUuid,
46
- setSettingsDrawerSide,
47
- setSettingsDrawerInset,
48
- } = useDashboardUIContext();
45
+ const { settingsWidgetUuid, setSettingsWidgetUuid } =
46
+ useDashboardUIContext();
47
+ const { cancel, flushAutoSave } = useDashboardInternalContext();
49
48
 
50
- const open = useCallback(
51
- ( event: React.MouseEvent< HTMLElement > ) => {
52
- // Open the drawer on the side away from the widget: compare the
53
- // tile's center against the midpoint of the usable content area
54
- // (which starts after the admin menu). Past it opens left.
55
- const adminMenuInset = getAdminMenuInset();
56
- // The gear sits in the grid slot, outside the card, so reach the
57
- // tile via the grid item's data hook.
58
- const tile = event.currentTarget.closest(
59
- '[data-wp-grid-item-key]'
60
- );
61
- const rect = (
62
- tile ?? event.currentTarget
63
- ).getBoundingClientRect();
64
- const widgetCenter = rect.left + rect.width / 2;
65
- const contentCenter = ( adminMenuInset + window.innerWidth ) / 2;
66
- const side = widgetCenter > contentCenter ? 'left' : 'right';
49
+ const toggle = useCallback( () => {
50
+ // Re-clicking the open instance's gear closes the drawer, discarding
51
+ // staged edits like any other non-Save exit.
52
+ if ( settingsWidgetUuid === widget.uuid ) {
53
+ cancel();
54
+ setSettingsWidgetUuid( null );
55
+ return;
56
+ }
57
+ // Persist any pending inline edit before opening, so the drawer's edits
58
+ // stay isolated and its Cancel discards only the drawer's own changes.
59
+ flushAutoSave();
60
+ setSettingsWidgetUuid( widget.uuid );
61
+ }, [
62
+ cancel,
63
+ flushAutoSave,
64
+ settingsWidgetUuid,
65
+ setSettingsWidgetUuid,
66
+ widget.uuid,
67
+ ] );
67
68
 
68
- setSettingsDrawerSide( side );
69
- // A left drawer would otherwise slide over the fixed admin menu;
70
- // offset it by the menu width so it lands clear of it.
71
- setSettingsDrawerInset( side === 'left' ? adminMenuInset : 0 );
72
- setSettingsWidgetUuid( widget.uuid );
73
- },
74
- [
75
- setSettingsDrawerSide,
76
- setSettingsDrawerInset,
77
- setSettingsWidgetUuid,
78
- widget.uuid,
79
- ]
69
+ // Surface the drawer only when there are attributes not already promoted
70
+ // inline; if every attribute is high-relevance, the drawer would just
71
+ // repeat the toolbar.
72
+ const hasNonPromotedAttributes = widgetType.attributes?.some(
73
+ ( attribute ) => attribute.relevance !== 'high'
80
74
  );
81
-
82
- if ( ! widgetType.attributes?.length ) {
75
+ if ( ! hasNonPromotedAttributes ) {
83
76
  return null;
84
77
  }
85
78
 
86
79
  return (
87
80
  <IconButton
88
- icon={ cog }
81
+ icon={ moreVertical }
89
82
  label={ __( 'Widget settings' ) }
90
83
  variant="minimal"
91
84
  tone="neutral"
92
85
  size="compact"
93
- onClick={ open }
86
+ onClick={ toggle }
94
87
  />
95
88
  );
96
89
  }
@@ -23,8 +23,8 @@ type WidgetAttributes = Record< string, unknown >;
23
23
  * Side drawer that edits one instance's attributes, mounted once at the
24
24
  * dashboard root. It resolves the active instance from `settingsWidgetUuid`
25
25
  * in the UI context (set by the per-instance gear), renders the type's
26
- * declarative `attributes` through `DataForm`, and enters from the edge away
27
- * from the widget.
26
+ * declarative `attributes` through `DataForm`, and enters from the
27
+ * inline-end edge.
28
28
  *
29
29
  * Edits write to the staging layer, so they preview live behind the drawer
30
30
  * and are published on Save or reverted on any other exit. Available in
@@ -39,12 +39,8 @@ export function WidgetSettings(): React.ReactNode {
39
39
  cancel: cancelStaging,
40
40
  hasUncommittedChanges,
41
41
  } = useDashboardInternalContext();
42
- const {
43
- settingsWidgetUuid,
44
- setSettingsWidgetUuid,
45
- settingsDrawerSide,
46
- settingsDrawerInset,
47
- } = useDashboardUIContext();
42
+ const { settingsWidgetUuid, setSettingsWidgetUuid } =
43
+ useDashboardUIContext();
48
44
 
49
45
  const open = settingsWidgetUuid !== null;
50
46
 
@@ -117,7 +113,7 @@ export function WidgetSettings(): React.ReactNode {
117
113
  const handleOpenChange = useCallback(
118
114
  ( nextOpen: boolean ) => {
119
115
  // Any path out of the drawer other than Save discards the
120
- // staged edits, matching the layout-settings drawer.
116
+ // staged edits.
121
117
  if ( ! nextOpen ) {
122
118
  cancelStaging();
123
119
  close();
@@ -126,17 +122,6 @@ export function WidgetSettings(): React.ReactNode {
126
122
  [ cancelStaging, close ]
127
123
  );
128
124
 
129
- // For a left drawer, clear the fixed admin menu on the inline-start
130
- // edge so the drawer lands beside it. The admin bar at the top is
131
- // cleared in the CSS module.
132
- const popupStyle = useMemo< React.CSSProperties >(
133
- () =>
134
- settingsDrawerSide === 'left' && settingsDrawerInset > 0
135
- ? { marginLeft: settingsDrawerInset }
136
- : {},
137
- [ settingsDrawerSide, settingsDrawerInset ]
138
- );
139
-
140
125
  const hasForm = !! widget && !! widgetType && fields.length > 0;
141
126
 
142
127
  if ( ! hasForm ) {
@@ -152,15 +137,11 @@ export function WidgetSettings(): React.ReactNode {
152
137
  <Drawer.Root
153
138
  open={ open }
154
139
  onOpenChange={ handleOpenChange }
155
- swipeDirection={ settingsDrawerSide }
140
+ swipeDirection="right"
156
141
  modal={ false }
157
142
  disablePointerDismissal
158
143
  >
159
- <Drawer.Popup
160
- size="medium"
161
- className={ styles.popup }
162
- style={ popupStyle }
163
- >
144
+ <Drawer.Popup size="medium" className={ styles.popup }>
164
145
  <Drawer.Header>
165
146
  <Drawer.Title>{ title }</Drawer.Title>
166
147
  <Drawer.CloseIcon />