@wix/patterns-fields 1.123.0 → 1.125.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 (251) hide show
  1. package/dist/cjs/components/address/input/address-input.st.css.js +3 -3
  2. package/dist/cjs/components/address/input/address-input.st.css.js.map +1 -1
  3. package/dist/cjs/components/audio/actions/actions-menu/actions-menu.st.css.js +3 -3
  4. package/dist/cjs/components/audio/actions/actions-menu/actions-menu.st.css.js.map +1 -1
  5. package/dist/cjs/components/audio/audio-field/form-audio-field.st.css.js +4 -4
  6. package/dist/cjs/components/audio/audio-field/form-audio-field.st.css.js.map +1 -1
  7. package/dist/cjs/components/audio/audio-player/audio-player.st.css.js +2 -2
  8. package/dist/cjs/components/audio/audio-player/audio-player.st.css.js.map +1 -1
  9. package/dist/cjs/components/color-view/cell-color-view.st.css.js +3 -3
  10. package/dist/cjs/components/color-view/cell-color-view.st.css.js.map +1 -1
  11. package/dist/cjs/components/color-view/color-view.st.css.js +4 -4
  12. package/dist/cjs/components/color-view/color-view.st.css.js.map +1 -1
  13. package/dist/cjs/components/delete-dialog/delete-dialog.st.css.js +3 -3
  14. package/dist/cjs/components/delete-dialog/delete-dialog.st.css.js.map +1 -1
  15. package/dist/cjs/components/document/form-document-field.st.css.js +7 -7
  16. package/dist/cjs/components/document/form-document-field.st.css.js.map +1 -1
  17. package/dist/cjs/components/exclamation/exclamation.st.css.js +5 -5
  18. package/dist/cjs/components/exclamation/exclamation.st.css.js.map +1 -1
  19. package/dist/cjs/components/field-validation-settings/field-validation-settings-input.st.css.js +3 -3
  20. package/dist/cjs/components/field-validation-settings/field-validation-settings-input.st.css.js.map +1 -1
  21. package/dist/cjs/components/highlighted-text/highlighted-text.st.css.js +5 -5
  22. package/dist/cjs/components/highlighted-text/highlighted-text.st.css.js.map +1 -1
  23. package/dist/cjs/components/image/thumbnail-replace-overlay.st.css.js +3 -3
  24. package/dist/cjs/components/image/thumbnail-replace-overlay.st.css.js.map +1 -1
  25. package/dist/cjs/components/media-control/cell-media-edit-shell.st.css.js +2 -2
  26. package/dist/cjs/components/media-control/cell-media-edit-shell.st.css.js.map +1 -1
  27. package/dist/cjs/components/media-control/paste-url-button.st.css.js +4 -4
  28. package/dist/cjs/components/media-control/paste-url-button.st.css.js.map +1 -1
  29. package/dist/cjs/components/media-gallery/form-media-gallery-field.st.css.js +10 -10
  30. package/dist/cjs/components/media-gallery/form-media-gallery-field.st.css.js.map +1 -1
  31. package/dist/cjs/components/media-gallery/media-preview-modal.js +12 -10
  32. package/dist/cjs/components/media-gallery/media-preview-modal.js.map +1 -1
  33. package/dist/cjs/components/media-image/media-image.st.css.js +4 -4
  34. package/dist/cjs/components/media-image/media-image.st.css.js.map +1 -1
  35. package/dist/cjs/components/media-image/overlays/overlay.st.css.js +3 -3
  36. package/dist/cjs/components/media-image/overlays/overlay.st.css.js.map +1 -1
  37. package/dist/cjs/components/media-image-field/cell-media-image-edit.js +46 -213
  38. package/dist/cjs/components/media-image-field/cell-media-image-edit.js.map +1 -1
  39. package/dist/cjs/components/media-image-field/cell-media-image-edit.st.css.js +8 -8
  40. package/dist/cjs/components/media-image-field/cell-media-image-edit.st.css.js.map +1 -1
  41. package/dist/cjs/components/media-image-field/form-media-image-field.js +116 -24
  42. package/dist/cjs/components/media-image-field/form-media-image-field.js.map +1 -1
  43. package/dist/cjs/components/media-image-field/form-media-image-field.uni.driver.js +24 -8
  44. package/dist/cjs/components/media-image-field/form-media-image-field.uni.driver.js.map +1 -1
  45. package/dist/cjs/components/media-image-field/media-image-actions.js +256 -0
  46. package/dist/cjs/components/media-image-field/media-image-actions.js.map +1 -0
  47. package/dist/cjs/components/media-image-field/media-image-view.st.css.js +3 -3
  48. package/dist/cjs/components/media-image-field/media-image-view.st.css.js.map +1 -1
  49. package/dist/cjs/components/media-tag/web-media-tag/media-tag.st.css.js +2 -2
  50. package/dist/cjs/components/media-tag/web-media-tag/media-tag.st.css.js.map +1 -1
  51. package/dist/cjs/components/multi-document/cell-multi-document-edit.js +31 -38
  52. package/dist/cjs/components/multi-document/cell-multi-document-edit.js.map +1 -1
  53. package/dist/cjs/components/multi-document/cell-multi-document-edit.st.css.js +3 -3
  54. package/dist/cjs/components/multi-document/cell-multi-document-edit.st.css.js.map +1 -1
  55. package/dist/cjs/components/multi-document/multi-document-input/form-multi-document.st.css.js +5 -5
  56. package/dist/cjs/components/multi-document/multi-document-input/form-multi-document.st.css.js.map +1 -1
  57. package/dist/cjs/components/reference/cell-multi-reference-input.st.css.js +2 -2
  58. package/dist/cjs/components/reference/cell-multi-reference-input.st.css.js.map +1 -1
  59. package/dist/cjs/components/reference/cell-multi-reference-view.js +12 -8
  60. package/dist/cjs/components/reference/cell-multi-reference-view.js.map +1 -1
  61. package/dist/cjs/components/reference/cell-multi-reference-view.st.css +6 -0
  62. package/dist/cjs/components/reference/cell-multi-reference-view.st.css.js +23 -0
  63. package/dist/cjs/components/reference/cell-multi-reference-view.st.css.js.map +1 -0
  64. package/dist/cjs/components/reference/cell-reference-input.st.css.js +3 -3
  65. package/dist/cjs/components/reference/cell-reference-input.st.css.js.map +1 -1
  66. package/dist/cjs/components/rich-content/rich-content-input/default-value-input/rich-content-default-value-input.st.css.js +4 -4
  67. package/dist/cjs/components/rich-content/rich-content-input/default-value-input/rich-content-default-value-input.st.css.js.map +1 -1
  68. package/dist/cjs/components/rich-content/rich-content-input/form-input/rich-content-form-input.st.css.js +3 -3
  69. package/dist/cjs/components/rich-content/rich-content-input/form-input/rich-content-form-input.st.css.js.map +1 -1
  70. package/dist/cjs/components/rich-content/rich-content-input/form-read-only-input/rich-content-form-read-only-input.st.css.js +2 -2
  71. package/dist/cjs/components/rich-content/rich-content-input/form-read-only-input/rich-content-form-read-only-input.st.css.js.map +1 -1
  72. package/dist/cjs/components/rich-content/rich-content-input/rich-content-common/fullscreen-modal/fullscreen-modal.st.css.js +3 -3
  73. package/dist/cjs/components/rich-content/rich-content-input/rich-content-common/fullscreen-modal/fullscreen-modal.st.css.js.map +1 -1
  74. package/dist/cjs/components/rich-content/rich-content-input/rich-content-common/publish-loader/publish-loader.st.css.js +3 -3
  75. package/dist/cjs/components/rich-content/rich-content-input/rich-content-common/publish-loader/publish-loader.st.css.js.map +1 -1
  76. package/dist/cjs/components/rich-content/rich-content-input/rich-content-common/toggle-fullscreen-button/toggle-fullscreen-button.st.css.js +2 -2
  77. package/dist/cjs/components/rich-content/rich-content-input/rich-content-common/toggle-fullscreen-button/toggle-fullscreen-button.st.css.js.map +1 -1
  78. package/dist/cjs/components/rich-content/rich-content-input/rich-content-editor/rich-content-editor.st.css.js +7 -7
  79. package/dist/cjs/components/rich-content/rich-content-input/rich-content-editor/rich-content-editor.st.css.js.map +1 -1
  80. package/dist/cjs/components/rich-content/rich-content-input/rich-content-editor/rich-content-toolbar.st.css.js +5 -5
  81. package/dist/cjs/components/rich-content/rich-content-input/rich-content-editor/rich-content-toolbar.st.css.js.map +1 -1
  82. package/dist/cjs/components/rich-content/rich-content-input/rich-content-viewer/rich-content-viewer.st.css.js +4 -4
  83. package/dist/cjs/components/rich-content/rich-content-input/rich-content-viewer/rich-content-viewer.st.css.js.map +1 -1
  84. package/dist/cjs/components/rich-text/rich-text-input/rich-text-editor/rich-editor.st.css.js +18 -18
  85. package/dist/cjs/components/rich-text/rich-text-input/rich-text-editor/rich-editor.st.css.js.map +1 -1
  86. package/dist/cjs/components/rich-text/rich-text-input/rich-text-editor/rich-text-editor.st.css.js +4 -4
  87. package/dist/cjs/components/rich-text/rich-text-input/rich-text-editor/rich-text-editor.st.css.js.map +1 -1
  88. package/dist/cjs/components/rich-text/rich-text-input/rich-text-editor/toolbar/toolbar.st.css.js +18 -18
  89. package/dist/cjs/components/rich-text/rich-text-input/rich-text-editor/toolbar/toolbar.st.css.js.map +1 -1
  90. package/dist/cjs/components/text/text-view.st.css.js +3 -3
  91. package/dist/cjs/components/text/text-view.st.css.js.map +1 -1
  92. package/dist/cjs/styles.global.css +1 -1
  93. package/dist/cjs/utils/detect-field-type.js +9 -17
  94. package/dist/cjs/utils/detect-field-type.js.map +1 -1
  95. package/dist/esm/components/address/input/address-input.st.css.js +2 -2
  96. package/dist/esm/components/audio/actions/actions-menu/actions-menu.st.css.js +2 -2
  97. package/dist/esm/components/audio/actions/actions-menu/actions-menu.st.css.js.map +1 -1
  98. package/dist/esm/components/audio/audio-field/form-audio-field.st.css.js +2 -2
  99. package/dist/esm/components/audio/audio-field/form-audio-field.st.css.js.map +1 -1
  100. package/dist/esm/components/audio/audio-player/audio-player.st.css.js +2 -2
  101. package/dist/esm/components/color-view/cell-color-view.st.css.js +2 -2
  102. package/dist/esm/components/color-view/cell-color-view.st.css.js.map +1 -1
  103. package/dist/esm/components/color-view/color-view.st.css.js +2 -2
  104. package/dist/esm/components/color-view/color-view.st.css.js.map +1 -1
  105. package/dist/esm/components/delete-dialog/delete-dialog.st.css.js +2 -2
  106. package/dist/esm/components/document/form-document-field.st.css.js +2 -2
  107. package/dist/esm/components/exclamation/exclamation.st.css.js +2 -2
  108. package/dist/esm/components/exclamation/exclamation.st.css.js.map +1 -1
  109. package/dist/esm/components/field-validation-settings/field-validation-settings-input.st.css.js +2 -2
  110. package/dist/esm/components/field-validation-settings/field-validation-settings-input.st.css.js.map +1 -1
  111. package/dist/esm/components/highlighted-text/highlighted-text.st.css.js +3 -3
  112. package/dist/esm/components/image/thumbnail-replace-overlay.st.css.js +2 -2
  113. package/dist/esm/components/media-control/cell-media-edit-shell.st.css.js +2 -2
  114. package/dist/esm/components/media-control/paste-url-button.st.css.js +2 -2
  115. package/dist/esm/components/media-control/paste-url-button.st.css.js.map +1 -1
  116. package/dist/esm/components/media-gallery/form-media-gallery-field.st.css.js +2 -2
  117. package/dist/esm/components/media-gallery/media-preview-modal.js +2 -2
  118. package/dist/esm/components/media-gallery/media-preview-modal.js.map +1 -1
  119. package/dist/esm/components/media-image/media-image.st.css.js +3 -3
  120. package/dist/esm/components/media-image/media-image.st.css.js.map +1 -1
  121. package/dist/esm/components/media-image/overlays/overlay.st.css.js +2 -2
  122. package/dist/esm/components/media-image/overlays/overlay.st.css.js.map +1 -1
  123. package/dist/esm/components/media-image-field/cell-media-image-edit.js +11 -37
  124. package/dist/esm/components/media-image-field/cell-media-image-edit.js.map +1 -1
  125. package/dist/esm/components/media-image-field/cell-media-image-edit.st.css.js +2 -2
  126. package/dist/esm/components/media-image-field/form-media-image-field.js +37 -9
  127. package/dist/esm/components/media-image-field/form-media-image-field.js.map +1 -1
  128. package/dist/esm/components/media-image-field/form-media-image-field.uni.driver.js +24 -8
  129. package/dist/esm/components/media-image-field/form-media-image-field.uni.driver.js.map +1 -1
  130. package/dist/esm/components/media-image-field/media-image-actions.js +52 -0
  131. package/dist/esm/components/media-image-field/media-image-actions.js.map +1 -0
  132. package/dist/esm/components/media-image-field/media-image-view.st.css.js +2 -2
  133. package/dist/esm/components/media-tag/web-media-tag/media-tag.st.css.js +2 -2
  134. package/dist/esm/components/multi-document/cell-multi-document-edit.js +2 -8
  135. package/dist/esm/components/multi-document/cell-multi-document-edit.js.map +1 -1
  136. package/dist/esm/components/multi-document/cell-multi-document-edit.st.css.js +2 -2
  137. package/dist/esm/components/multi-document/cell-multi-document-edit.st.css.js.map +1 -1
  138. package/dist/esm/components/multi-document/multi-document-input/form-multi-document.st.css.js +2 -2
  139. package/dist/esm/components/reference/cell-multi-reference-input.st.css.js +2 -2
  140. package/dist/esm/components/reference/cell-multi-reference-view.js +12 -9
  141. package/dist/esm/components/reference/cell-multi-reference-view.js.map +1 -1
  142. package/dist/esm/components/reference/cell-multi-reference-view.st.css +6 -0
  143. package/dist/esm/components/reference/cell-multi-reference-view.st.css.js +15 -0
  144. package/dist/esm/components/reference/cell-multi-reference-view.st.css.js.map +1 -0
  145. package/dist/esm/components/reference/cell-reference-input.st.css.js +2 -2
  146. package/dist/esm/components/rich-content/rich-content-input/default-value-input/rich-content-default-value-input.st.css.js +2 -2
  147. package/dist/esm/components/rich-content/rich-content-input/form-input/rich-content-form-input.st.css.js +2 -2
  148. package/dist/esm/components/rich-content/rich-content-input/form-input/rich-content-form-input.st.css.js.map +1 -1
  149. package/dist/esm/components/rich-content/rich-content-input/form-read-only-input/rich-content-form-read-only-input.st.css.js +2 -2
  150. package/dist/esm/components/rich-content/rich-content-input/form-read-only-input/rich-content-form-read-only-input.st.css.js.map +1 -1
  151. package/dist/esm/components/rich-content/rich-content-input/rich-content-common/fullscreen-modal/fullscreen-modal.st.css.js +2 -2
  152. package/dist/esm/components/rich-content/rich-content-input/rich-content-common/fullscreen-modal/fullscreen-modal.st.css.js.map +1 -1
  153. package/dist/esm/components/rich-content/rich-content-input/rich-content-common/publish-loader/publish-loader.st.css.js +2 -2
  154. package/dist/esm/components/rich-content/rich-content-input/rich-content-common/publish-loader/publish-loader.st.css.js.map +1 -1
  155. package/dist/esm/components/rich-content/rich-content-input/rich-content-common/toggle-fullscreen-button/toggle-fullscreen-button.st.css.js +2 -2
  156. package/dist/esm/components/rich-content/rich-content-input/rich-content-editor/rich-content-editor.st.css.js +2 -2
  157. package/dist/esm/components/rich-content/rich-content-input/rich-content-editor/rich-content-editor.st.css.js.map +1 -1
  158. package/dist/esm/components/rich-content/rich-content-input/rich-content-editor/rich-content-toolbar.st.css.js +2 -2
  159. package/dist/esm/components/rich-content/rich-content-input/rich-content-editor/rich-content-toolbar.st.css.js.map +1 -1
  160. package/dist/esm/components/rich-content/rich-content-input/rich-content-viewer/rich-content-viewer.st.css.js +2 -2
  161. package/dist/esm/components/rich-text/rich-text-input/rich-text-editor/rich-editor.st.css.js +2 -2
  162. package/dist/esm/components/rich-text/rich-text-input/rich-text-editor/rich-editor.st.css.js.map +1 -1
  163. package/dist/esm/components/rich-text/rich-text-input/rich-text-editor/rich-text-editor.st.css.js +2 -2
  164. package/dist/esm/components/rich-text/rich-text-input/rich-text-editor/toolbar/toolbar.st.css.js +2 -2
  165. package/dist/esm/components/rich-text/rich-text-input/rich-text-editor/toolbar/toolbar.st.css.js.map +1 -1
  166. package/dist/esm/components/text/text-view.st.css.js +2 -2
  167. package/dist/esm/styles.global.css +1 -1
  168. package/dist/esm/utils/detect-field-type.js +12 -16
  169. package/dist/esm/utils/detect-field-type.js.map +1 -1
  170. package/dist/types/components/audio/actions/actions-menu/actions-menu.st.css.d.ts.map +1 -1
  171. package/dist/types/components/audio/audio-field/form-audio-field.st.css.d.ts.map +1 -1
  172. package/dist/types/components/color-view/cell-color-view.st.css.d.ts.map +1 -1
  173. package/dist/types/components/color-view/color-view.st.css.d.ts.map +1 -1
  174. package/dist/types/components/exclamation/exclamation.st.css.d.ts.map +1 -1
  175. package/dist/types/components/field-validation-settings/field-validation-settings-input.st.css.d.ts.map +1 -1
  176. package/dist/types/components/media-control/paste-url-button.st.css.d.ts.map +1 -1
  177. package/dist/types/components/media-image/media-image.st.css.d.ts.map +1 -1
  178. package/dist/types/components/media-image/overlays/overlay.st.css.d.ts.map +1 -1
  179. package/dist/types/components/media-image-field/cell-media-image-edit.d.ts.map +1 -1
  180. package/dist/types/components/media-image-field/form-media-image-field.d.ts.map +1 -1
  181. package/dist/types/components/media-image-field/form-media-image-field.uni.driver.d.ts +8 -4
  182. package/dist/types/components/media-image-field/form-media-image-field.uni.driver.d.ts.map +1 -1
  183. package/dist/types/components/media-image-field/media-image-actions.d.ts +33 -0
  184. package/dist/types/components/media-image-field/media-image-actions.d.ts.map +1 -0
  185. package/dist/types/components/multi-document/cell-multi-document-edit.d.ts.map +1 -1
  186. package/dist/types/components/multi-document/cell-multi-document-edit.st.css.d.ts.map +1 -1
  187. package/dist/types/components/reference/cell-multi-reference-view.d.ts +2 -0
  188. package/dist/types/components/reference/cell-multi-reference-view.d.ts.map +1 -1
  189. package/dist/types/components/reference/cell-multi-reference-view.st.css.d.ts +14 -0
  190. package/dist/types/components/reference/cell-multi-reference-view.st.css.d.ts.map +1 -0
  191. package/dist/types/components/rich-content/rich-content-input/form-input/rich-content-form-input.st.css.d.ts.map +1 -1
  192. package/dist/types/components/rich-content/rich-content-input/form-read-only-input/rich-content-form-read-only-input.st.css.d.ts.map +1 -1
  193. package/dist/types/components/rich-content/rich-content-input/rich-content-common/fullscreen-modal/fullscreen-modal.st.css.d.ts.map +1 -1
  194. package/dist/types/components/rich-content/rich-content-input/rich-content-common/publish-loader/publish-loader.st.css.d.ts.map +1 -1
  195. package/dist/types/components/rich-content/rich-content-input/rich-content-editor/rich-content-editor.st.css.d.ts.map +1 -1
  196. package/dist/types/components/rich-content/rich-content-input/rich-content-editor/rich-content-toolbar.st.css.d.ts.map +1 -1
  197. package/dist/types/components/rich-text/rich-text-input/rich-text-editor/rich-editor.st.css.d.ts.map +1 -1
  198. package/dist/types/components/rich-text/rich-text-input/rich-text-editor/toolbar/toolbar.st.css.d.ts.map +1 -1
  199. package/dist/types/utils/detect-field-type.d.ts +1 -1
  200. package/dist/types/utils/detect-field-type.d.ts.map +1 -1
  201. package/package.json +4 -4
  202. package/src/__tests__/components/media-image-field/form-media-image-input.spec.tsx +69 -2
  203. package/src/__tests__/utils/detect-field-type.spec.ts +5 -5
  204. package/src/components/address/input/address-input.st.css.ts +2 -2
  205. package/src/components/audio/actions/actions-menu/actions-menu.st.css.ts +2 -2
  206. package/src/components/audio/audio-field/form-audio-field.st.css.ts +2 -2
  207. package/src/components/audio/audio-player/audio-player.st.css.ts +2 -2
  208. package/src/components/color-view/cell-color-view.st.css.ts +2 -2
  209. package/src/components/color-view/color-view.st.css.ts +2 -2
  210. package/src/components/delete-dialog/delete-dialog.st.css.ts +2 -2
  211. package/src/components/document/form-document-field.st.css.ts +2 -2
  212. package/src/components/exclamation/exclamation.st.css.ts +2 -2
  213. package/src/components/field-validation-settings/field-validation-settings-input.st.css.ts +2 -2
  214. package/src/components/highlighted-text/highlighted-text.st.css.ts +3 -3
  215. package/src/components/image/thumbnail-replace-overlay.st.css.ts +2 -2
  216. package/src/components/media-control/cell-media-edit-shell.st.css.ts +2 -2
  217. package/src/components/media-control/paste-url-button.st.css.ts +2 -2
  218. package/src/components/media-gallery/form-media-gallery-field.st.css.ts +2 -2
  219. package/src/components/media-gallery/media-preview-modal.tsx +2 -1
  220. package/src/components/media-image/media-image.st.css.ts +3 -3
  221. package/src/components/media-image/overlays/overlay.st.css.ts +2 -2
  222. package/src/components/media-image-field/cell-media-image-edit.st.css.ts +2 -2
  223. package/src/components/media-image-field/cell-media-image-edit.tsx +26 -129
  224. package/src/components/media-image-field/form-media-image-field.tsx +105 -23
  225. package/src/components/media-image-field/form-media-image-field.uni.driver.ts +45 -10
  226. package/src/components/media-image-field/media-image-actions.tsx +205 -0
  227. package/src/components/media-image-field/media-image-view.st.css.ts +2 -2
  228. package/src/components/media-tag/web-media-tag/media-tag.st.css.ts +2 -2
  229. package/src/components/multi-document/cell-multi-document-edit.st.css.ts +2 -2
  230. package/src/components/multi-document/cell-multi-document-edit.tsx +3 -6
  231. package/src/components/multi-document/multi-document-input/form-multi-document.st.css.ts +2 -2
  232. package/src/components/reference/cell-multi-reference-input.st.css.ts +2 -2
  233. package/src/components/reference/cell-multi-reference-view.st.css +6 -0
  234. package/src/components/reference/cell-multi-reference-view.st.css.ts +25 -0
  235. package/src/components/reference/cell-multi-reference-view.tsx +23 -14
  236. package/src/components/reference/cell-reference-input.st.css.ts +2 -2
  237. package/src/components/rich-content/rich-content-input/default-value-input/rich-content-default-value-input.st.css.ts +2 -2
  238. package/src/components/rich-content/rich-content-input/form-input/rich-content-form-input.st.css.ts +2 -2
  239. package/src/components/rich-content/rich-content-input/form-read-only-input/rich-content-form-read-only-input.st.css.ts +2 -2
  240. package/src/components/rich-content/rich-content-input/rich-content-common/fullscreen-modal/fullscreen-modal.st.css.ts +2 -2
  241. package/src/components/rich-content/rich-content-input/rich-content-common/publish-loader/publish-loader.st.css.ts +2 -2
  242. package/src/components/rich-content/rich-content-input/rich-content-common/toggle-fullscreen-button/toggle-fullscreen-button.st.css.ts +2 -2
  243. package/src/components/rich-content/rich-content-input/rich-content-editor/rich-content-editor.st.css.ts +2 -2
  244. package/src/components/rich-content/rich-content-input/rich-content-editor/rich-content-toolbar.st.css.ts +2 -2
  245. package/src/components/rich-content/rich-content-input/rich-content-viewer/rich-content-viewer.st.css.ts +2 -2
  246. package/src/components/rich-text/rich-text-input/rich-text-editor/rich-editor.st.css.ts +2 -2
  247. package/src/components/rich-text/rich-text-input/rich-text-editor/rich-text-editor.st.css.ts +2 -2
  248. package/src/components/rich-text/rich-text-input/rich-text-editor/toolbar/toolbar.st.css.ts +2 -2
  249. package/src/components/text/text-view.st.css.ts +2 -2
  250. package/src/styles.global.css +1 -1
  251. package/src/utils/detect-field-type.ts +14 -16
@@ -5,19 +5,9 @@ import {
5
5
  IconButton,
6
6
  Input,
7
7
  Popover,
8
- PopoverMenu,
9
8
  Tooltip,
10
9
  } from '@wix/design-system';
11
- import {
12
- Add,
13
- Delete,
14
- Download,
15
- Link,
16
- LinkSmall,
17
- Maximize,
18
- MoreSmall,
19
- Replace,
20
- } from '@wix/wix-ui-icons-common/lazy';
10
+ import { Add, LinkSmall } from '@wix/wix-ui-icons-common/lazy';
21
11
  import { ThumbnailSize } from '../../auto-field-types';
22
12
  import { useTranslations } from '../../hooks';
23
13
  import type { MediaImageValue } from '../../types/media-image';
@@ -30,14 +20,18 @@ import {
30
20
  toMediaImageValue,
31
21
  withAltText,
32
22
  } from '../../utils/media-image-value';
33
- import { executeDownloading, MEDIA_TYPES } from '../../utils/media-utils';
23
+ import { MEDIA_TYPES } from '../../utils/media-utils';
34
24
  import {
35
25
  CellMediaEditShell,
36
26
  MediaFieldType,
37
27
  useCellMediaEdit,
38
28
  } from '../media-control';
39
- import { MediaPreviewModal } from '../media-gallery/media-preview-modal';
40
29
  import { MediaImage } from '../media-image';
30
+ import {
31
+ MediaImageActions,
32
+ MediaImagePreviewModal,
33
+ useMediaImageDownload,
34
+ } from './media-image-actions';
41
35
  import { MediaImageView } from './media-image-view';
42
36
  import { st, classes } from './cell-media-image-edit.st.css.js';
43
37
 
@@ -64,45 +58,6 @@ type Layer = PopoverLayer | 'pasteUrl' | 'loading';
64
58
  const imageFromUrl = (url: string, current: MediaImageValue | null) =>
65
59
  replaceImage(current, fromImageUrl(url));
66
60
 
67
- interface MenuTriggerProps {
68
- isOpen: boolean;
69
- toggle: () => void;
70
- /** Lets WDS put focus back here when the menu closes. */
71
- buttonRef?: React.RefObject<HTMLElement>;
72
- onOpenChange: (isOpen: boolean) => void;
73
- ariaLabel: string;
74
- }
75
-
76
- /** WDS shows the menu's open state only to its trigger, so the trigger
77
- * reports it. */
78
- const MenuTrigger: React.FC<MenuTriggerProps> = ({
79
- isOpen,
80
- toggle,
81
- buttonRef,
82
- onOpenChange,
83
- ariaLabel,
84
- }) => {
85
- useEffect(() => {
86
- onOpenChange(isOpen);
87
- }, [isOpen, onOpenChange]);
88
-
89
- return (
90
- <IconButton
91
- ref={buttonRef}
92
- size="small"
93
- skin="light"
94
- priority="secondary"
95
- dataHook="media-image-edit-more-button"
96
- ariaLabel={ariaLabel}
97
- aria-haspopup="menu"
98
- aria-expanded={isOpen}
99
- onClick={toggle}
100
- >
101
- <MoreSmall />
102
- </IconButton>
103
- );
104
- };
105
-
106
61
  /**
107
62
  * Edits a `MEDIA_IMAGE` cell. An empty cell shows the add and paste-URL
108
63
  * buttons. A cell with an image opens a popover with the image and its alt
@@ -158,14 +113,7 @@ export const CellMediaImageEdit: React.FC<CellMediaImageEditProps> = ({
158
113
  value: isExternalMediaImage(image) ? image.url : undefined,
159
114
  });
160
115
 
161
- const handleDownload = useCallback(() => {
162
- // The Media Manager can't make a download link for an external URL.
163
- if (isExternalMediaImage(image)) {
164
- executeDownloading(image.url);
165
- } else if (src) {
166
- downloadMedia(src);
167
- }
168
- }, [src, image, downloadMedia]);
116
+ const handleDownload = useMediaImageDownload(image, downloadMedia);
169
117
 
170
118
  const commit = useCallback(() => {
171
119
  setPopoverLayer('none');
@@ -265,7 +213,9 @@ export const CellMediaImageEdit: React.FC<CellMediaImageEditProps> = ({
265
213
  shown={openLayer === 'popover' || openLayer === 'menu'}
266
214
  appendTo="window"
267
215
  placement="bottom-start"
268
- moveBy={{ x: 0, y: 4 }}
216
+ // The anchor sits inside the cell's 1px border. Figma puts the
217
+ // popover 4px under the border, aligned with its left edge.
218
+ moveBy={{ x: -1, y: 5 }}
269
219
  zIndex={5001}
270
220
  animate
271
221
  flip
@@ -301,64 +251,16 @@ export const CellMediaImageEdit: React.FC<CellMediaImageEditProps> = ({
301
251
  menuOpen: popoverLayer === 'menu',
302
252
  })}
303
253
  >
304
- <Tooltip
305
- content={t('CMS.image.replace')}
306
- appendTo="window"
307
- >
308
- <IconButton
309
- size="small"
310
- skin="light"
311
- priority="secondary"
312
- dataHook="media-image-edit-replace-button"
313
- ariaLabel={t('CMS.image.replace')}
314
- onClick={handleCallMedia}
315
- >
316
- <Replace />
317
- </IconButton>
318
- </Tooltip>
319
- <PopoverMenu
320
- textSize="small"
321
- appendTo="window"
322
- zIndex={5002}
323
- triggerElement={({ isOpen, toggle, ref }) => (
324
- <MenuTrigger
325
- isOpen={isOpen}
326
- toggle={toggle}
327
- buttonRef={ref}
328
- onOpenChange={handleMenuOpenChange}
329
- ariaLabel={t(
330
- 'auto-patterns.fields.more_actions_tooltip',
331
- )}
332
- />
333
- )}
334
- >
335
- <PopoverMenu.MenuItem
336
- dataHook="media-image-edit-action-replace-url"
337
- text={t('CMS.image.replaceWithUrl.button')}
338
- prefixIcon={<Link />}
339
- onClick={openPasteUrl}
340
- />
341
- <PopoverMenu.MenuItem
342
- dataHook="media-image-edit-action-preview"
343
- text={t('CMS.mediaGallery.preview')}
344
- prefixIcon={<Maximize />}
345
- onClick={() => setPopoverLayer('preview')}
346
- />
347
- <PopoverMenu.MenuItem
348
- dataHook="media-image-edit-action-download"
349
- text={t('CMS.image.download')}
350
- prefixIcon={<Download />}
351
- onClick={handleDownload}
352
- />
353
- <PopoverMenu.Divider />
354
- <PopoverMenu.MenuItem
355
- dataHook="media-image-edit-action-delete"
356
- text={t('CMS.image.clear')}
357
- skin="destructive"
358
- prefixIcon={<Delete />}
359
- onClick={handleDelete}
360
- />
361
- </PopoverMenu>
254
+ <MediaImageActions
255
+ dataHook="media-image-edit"
256
+ onReplace={handleCallMedia}
257
+ onReplaceWithUrl={openPasteUrl}
258
+ onPreview={() => setPopoverLayer('preview')}
259
+ onDownload={handleDownload}
260
+ onDelete={handleDelete}
261
+ onMenuOpenChange={handleMenuOpenChange}
262
+ menuZIndex={5002}
263
+ />
362
264
  </div>
363
265
  </div>
364
266
  </FormField>
@@ -382,18 +284,13 @@ export const CellMediaImageEdit: React.FC<CellMediaImageEditProps> = ({
382
284
  )}
383
285
  </CellMediaEditShell>
384
286
  {image && (
385
- <MediaPreviewModal
287
+ <MediaImagePreviewModal
386
288
  isOpen={popoverLayer === 'preview'}
387
- value={src}
289
+ image={image}
388
290
  onClose={() => setPopoverLayer('popover')}
389
- onRequestMedia={handleCallMedia}
390
- onClearMedia={handleDelete}
391
- onDownloadMedia={handleDownload}
392
- textKeys={{
393
- replace: 'CMS.image.replace',
394
- download: 'CMS.image.download',
395
- delete: 'CMS.image.clear',
396
- }}
291
+ onReplace={handleCallMedia}
292
+ onDelete={handleDelete}
293
+ onDownload={handleDownload}
397
294
  />
398
295
  )}
399
296
  </>
@@ -1,9 +1,17 @@
1
1
  import type { FC } from 'react';
2
- import React, { useCallback, useRef } from 'react';
2
+ import React, { useCallback, useRef, useState } from 'react';
3
3
  import type { FormFieldProps } from '@wix/design-system';
4
- import { Box, FormField, ImageViewer, Input } from '@wix/design-system';
4
+ import {
5
+ Box,
6
+ FormField,
7
+ Image,
8
+ ImageViewer,
9
+ Input,
10
+ MediaOverlay,
11
+ } from '@wix/design-system';
5
12
  import { useIsMobile, useWixPatternsContainer } from '@wix/bex-core/react';
6
13
 
14
+ import { Z_INDEX_MODAL_POPOVER } from '../common';
7
15
  import type { ControlledInputProps } from '../../types/controlled-input';
8
16
  import type { MediaImageValue } from '../../types/media-image';
9
17
  import { useMergedRef, useTranslations } from '../../hooks';
@@ -11,12 +19,25 @@ import { getImageSource } from '../../utils/get-image-source';
11
19
  import { getImageUrl } from '../../utils/get-image-url';
12
20
  import { MEDIA_HEIGHT, MEDIA_MAX_WIDTH } from '../../utils/media-constants';
13
21
  import {
22
+ fromImageUrl,
14
23
  fromMediaManagerPick,
24
+ isExternalMediaImage,
25
+ replaceImage,
15
26
  toMediaImageValue,
16
27
  withAltText,
17
28
  } from '../../utils/media-image-value';
18
29
  import { MEDIA_TYPES } from '../../utils/media-utils';
19
- import { useMediaControl } from '../media-control';
30
+ import {
31
+ MediaFieldType,
32
+ PasteURLForm,
33
+ useMediaControl,
34
+ usePasteURLForm,
35
+ } from '../media-control';
36
+ import {
37
+ MediaImageActions,
38
+ MediaImagePreviewModal,
39
+ useMediaImageDownload,
40
+ } from './media-image-actions';
20
41
 
21
42
  interface ImageViewerActions {
22
43
  focus: () => void;
@@ -77,7 +98,7 @@ export const FormMediaImageField: FC<FormMediaImageFieldProps> = ({
77
98
  [onChange],
78
99
  );
79
100
 
80
- const { callMedia, onMediaLoad } = useMediaControl({
101
+ const { callMedia, downloadMedia } = useMediaControl({
81
102
  mediaType: MEDIA_TYPES.IMAGE,
82
103
  value: getImageSource(image),
83
104
  onChange: handlePick,
@@ -85,9 +106,28 @@ export const FormMediaImageField: FC<FormMediaImageFieldProps> = ({
85
106
  readOnly,
86
107
  onBlur,
87
108
  inputRef,
88
- initialLoading: true,
89
109
  });
90
110
 
111
+ const pasteUrlForm = usePasteURLForm({
112
+ onChange: (url) =>
113
+ onChange(replaceImage(imageRef.current, fromImageUrl(url))),
114
+ });
115
+ const openPasteUrl = pasteUrlForm.onOpen({
116
+ title: t('CMS.image.replaceWithUrl.title'),
117
+ value: isExternalMediaImage(image) ? image.url : undefined,
118
+ });
119
+
120
+ const [isPreviewOpen, setIsPreviewOpen] = useState(false);
121
+ const handleDownload = useMediaImageDownload(image, downloadMedia);
122
+ const handleDelete = useCallback(() => {
123
+ setIsPreviewOpen(false);
124
+ onChange(null);
125
+ }, [onChange]);
126
+ const handlePreviewReplace = useCallback(() => {
127
+ setIsPreviewOpen(false);
128
+ callMedia();
129
+ }, [callMedia]);
130
+
91
131
  const canEdit = !isMobile && !readOnly;
92
132
 
93
133
  const handleAltTextChange = (e: React.ChangeEvent<HTMLInputElement>) => {
@@ -100,24 +140,47 @@ export const FormMediaImageField: FC<FormMediaImageFieldProps> = ({
100
140
  <Box dataHook={dataHook} gap="SP4" width="100%">
101
141
  <Box width="100%" maxWidth={MEDIA_MAX_WIDTH} flexShrink={0}>
102
142
  <FormField {...imageFormFieldProps} dataHook="media-image-field-image">
103
- <ImageViewer
104
- ref={setInputRef}
105
- dataHook="media-image-field-viewer"
106
- imageUrl={image ? getImageUrl(image) : undefined}
107
- onImageLoad={onMediaLoad}
108
- onAddImage={canEdit ? callMedia : undefined}
109
- onUpdateImage={canEdit ? callMedia : undefined}
110
- disabled={image ? Boolean(readOnly) : !canEdit}
111
- showUpdateButton={canEdit}
112
- showRemoveButton={!readOnly}
113
- updateImageInfo={translate('cairo.replace-image.tooltip')}
114
- removeImageInfo={translate('cairo.remove-image.tooltip')}
115
- addImageInfo={translate('cairo.add-image.tooltip')}
116
- height={MEDIA_HEIGHT}
117
- width="100%"
118
- fit="cover"
119
- onRemoveImage={() => onChange(null)}
120
- />
143
+ {image ? (
144
+ <MediaOverlay
145
+ dataHook="media-image-field-overlay"
146
+ hoverSkin="dark"
147
+ media={
148
+ <Image
149
+ dataHook="media-image-field-current-image"
150
+ src={getImageUrl(image)}
151
+ width="100%"
152
+ height={MEDIA_HEIGHT}
153
+ fit="cover"
154
+ />
155
+ }
156
+ >
157
+ <MediaOverlay.Content placement="middle" visible="hover">
158
+ <Box gap="SP2">
159
+ <MediaImageActions
160
+ dataHook="media-image-field"
161
+ onReplace={canEdit ? callMedia : undefined}
162
+ onReplaceWithUrl={readOnly ? undefined : openPasteUrl}
163
+ onPreview={() => setIsPreviewOpen(true)}
164
+ onDownload={handleDownload}
165
+ onDelete={readOnly ? undefined : handleDelete}
166
+ menuZIndex={Z_INDEX_MODAL_POPOVER}
167
+ />
168
+ </Box>
169
+ </MediaOverlay.Content>
170
+ </MediaOverlay>
171
+ ) : (
172
+ <ImageViewer
173
+ // Only the empty state has a focusable control, so this is the
174
+ // only place inputRef can land.
175
+ ref={setInputRef}
176
+ dataHook="media-image-field-viewer"
177
+ onAddImage={canEdit ? callMedia : undefined}
178
+ disabled={!canEdit}
179
+ addImageInfo={translate('cairo.add-image.tooltip')}
180
+ height={MEDIA_HEIGHT}
181
+ width="100%"
182
+ />
183
+ )}
121
184
  </FormField>
122
185
  </Box>
123
186
  {image && (
@@ -133,6 +196,25 @@ export const FormMediaImageField: FC<FormMediaImageFieldProps> = ({
133
196
  </FormField>
134
197
  </Box>
135
198
  )}
199
+ <PasteURLForm
200
+ title={pasteUrlForm.title}
201
+ value={pasteUrlForm.value}
202
+ show={pasteUrlForm.isOpen}
203
+ closeModal={pasteUrlForm.onClose}
204
+ onSave={pasteUrlForm.onSave}
205
+ fieldType={MediaFieldType.image}
206
+ />
207
+ {image && (
208
+ <MediaImagePreviewModal
209
+ isOpen={isPreviewOpen}
210
+ image={image}
211
+ onClose={() => setIsPreviewOpen(false)}
212
+ onReplace={handlePreviewReplace}
213
+ onDelete={handleDelete}
214
+ onDownload={handleDownload}
215
+ readOnly={!canEdit}
216
+ />
217
+ )}
136
218
  </Box>
137
219
  );
138
220
  };
@@ -1,11 +1,16 @@
1
1
  import type { UniDriver } from '@wix/wix-ui-test-utils/unidriver';
2
2
  import {
3
+ ButtonUniDriver,
4
+ CustomModalLayoutUniDriver,
3
5
  FormFieldUniDriver,
6
+ IconButtonUniDriver,
4
7
  ImageViewerUniDriver,
8
+ InputUniDriver,
5
9
  } from '@wix/design-system/dist/testkit/unidriver';
6
10
 
7
11
  import { baseUniDriverFactory } from '../../testkit/base-driver';
8
12
 
13
+ /** The more actions menu, the URL form and the preview render in the body. */
9
14
  export function FormMediaImageFieldUniDriver(base: UniDriver, body: UniDriver) {
10
15
  const formField = FormFieldUniDriver(
11
16
  base.$('[data-hook="media-image-field-image"]'),
@@ -15,7 +20,15 @@ export function FormMediaImageFieldUniDriver(base: UniDriver, body: UniDriver) {
15
20
  base.$('[data-hook="media-image-field-viewer"]'),
16
21
  body,
17
22
  );
23
+ const replaceButton = IconButtonUniDriver(
24
+ base.$('[data-hook="media-image-field-replace-button"]'),
25
+ body,
26
+ );
18
27
  const altInput = base.$('[data-hook="media-image-field-alt-input"] input');
28
+ const menuItem = (action: string) =>
29
+ body.$(`[data-hook="media-image-field-action-${action}"]`);
30
+ const openMenu = () =>
31
+ base.$('[data-hook="media-image-field-more-button"]').click();
19
32
 
20
33
  return {
21
34
  ...baseUniDriverFactory(base),
@@ -23,20 +36,42 @@ export function FormMediaImageFieldUniDriver(base: UniDriver, body: UniDriver) {
23
36
  isRequired: () => formField.isRequired(),
24
37
  hasError: () => formField.hasStatus('error'),
25
38
  getErrorMessage: () => formField.getStatusMessage(),
26
- getImageUrl: () => imageViewer.getImageUrl(),
27
- isAddItemVisible: () => imageViewer.isAddItemVisible(),
28
39
  clickAdd: () => imageViewer.clickAdd(),
29
- clickReplace: () => imageViewer.clickUpdate(),
30
- clickRemove: () => imageViewer.clickRemove(),
40
+ clickReplace: () => replaceButton.click(),
41
+ isReplaceDisabled: () => replaceButton.isButtonDisabled(),
42
+ replaceWithUrl: async (url: string) => {
43
+ await openMenu();
44
+ await menuItem('replace-url').click();
45
+ await InputUniDriver(
46
+ body.$('[data-hook="paste-url-form.urlInput"]'),
47
+ body,
48
+ ).enterText(url);
49
+ await (
50
+ await CustomModalLayoutUniDriver(
51
+ body.$('[data-hook="paste-url-form.layout"]'),
52
+ body,
53
+ ).getPrimaryButtonDriver()
54
+ ).click();
55
+ },
56
+ openPreview: async () => {
57
+ await openMenu();
58
+ await menuItem('preview').click();
59
+ },
60
+ isPreviewOpen: () => body.$('[data-hook="preview-modal-content"]').exists(),
61
+ pressEscapeInPreview: () =>
62
+ body.$('[data-hook="preview-modal-content"]').pressKey('Escape'),
63
+ clickPreviewReplace: () =>
64
+ ButtonUniDriver(
65
+ body.$('[data-hook="preview-modal-replace-button"]'),
66
+ body,
67
+ ).click(),
68
+ clickDelete: async () => {
69
+ await openMenu();
70
+ await menuItem('delete').click();
71
+ },
31
72
  hasAltTextInput: () => altInput.exists(),
32
73
  getAltText: () => altInput.value(),
33
74
  getAltTextPlaceholder: () => altInput.attr('placeholder'),
34
75
  enterAltText: (text: string) => altInput.enterValue(text),
35
- // ImageViewer hides its edit buttons behind a loader until the image
36
- // loads, and jsdom never fires that event on its own.
37
- simulateImageLoad: async () =>
38
- (
39
- await base.$('[data-hook="image-viewer-current-image"]').getNative()
40
- ).dispatchEvent(new Event('load')),
41
76
  };
42
77
  }
@@ -0,0 +1,205 @@
1
+ import React, { useCallback, useEffect } from 'react';
2
+ import { IconButton, PopoverMenu, Tooltip } from '@wix/design-system';
3
+ import {
4
+ Delete,
5
+ Download,
6
+ Link,
7
+ Maximize,
8
+ MoreSmall,
9
+ Replace,
10
+ } from '@wix/wix-ui-icons-common/lazy';
11
+ import { useTranslations } from '../../hooks';
12
+ import type { MediaImageValue } from '../../types/media-image';
13
+ import { getImageSource } from '../../utils/get-image-source';
14
+ import { isExternalMediaImage } from '../../utils/media-image-value';
15
+ import { executeDownloading } from '../../utils/media-utils';
16
+ import { MediaPreviewModal } from '../media-gallery/media-preview-modal';
17
+
18
+ interface MenuTriggerProps {
19
+ isOpen: boolean;
20
+ toggle: () => void;
21
+ /** Lets WDS put focus back here when the menu closes. */
22
+ buttonRef?: React.RefObject<HTMLElement>;
23
+ onOpenChange?: (isOpen: boolean) => void;
24
+ ariaLabel: string;
25
+ dataHook: string;
26
+ }
27
+
28
+ /** WDS shows the menu's open state only to its trigger, so the trigger
29
+ * reports it. */
30
+ const MenuTrigger: React.FC<MenuTriggerProps> = ({
31
+ isOpen,
32
+ toggle,
33
+ buttonRef,
34
+ onOpenChange,
35
+ ariaLabel,
36
+ dataHook,
37
+ }) => {
38
+ useEffect(() => {
39
+ onOpenChange?.(isOpen);
40
+ }, [isOpen, onOpenChange]);
41
+
42
+ return (
43
+ <IconButton
44
+ ref={buttonRef}
45
+ size="small"
46
+ skin="light"
47
+ priority="secondary"
48
+ dataHook={dataHook}
49
+ ariaLabel={ariaLabel}
50
+ aria-haspopup="menu"
51
+ aria-expanded={isOpen}
52
+ onClick={toggle}
53
+ >
54
+ <MoreSmall />
55
+ </IconButton>
56
+ );
57
+ };
58
+
59
+ export interface MediaImageActionsProps {
60
+ /** Every action's data-hook starts with it. */
61
+ dataHook: string;
62
+ /** Opens the media manager. The button is disabled without it. */
63
+ onReplace?: () => void;
64
+ /** The menu item is disabled without it. */
65
+ onReplaceWithUrl?: () => void;
66
+ onPreview: () => void;
67
+ onDownload: () => void;
68
+ /** The menu item is disabled without it. */
69
+ onDelete?: () => void;
70
+ onMenuOpenChange?: (isOpen: boolean) => void;
71
+ menuZIndex: number;
72
+ }
73
+
74
+ /** The actions over a `MEDIA_IMAGE` image: Replace, and a menu with Replace
75
+ * with URL, Preview, Download and Delete. */
76
+ export const MediaImageActions: React.FC<MediaImageActionsProps> = ({
77
+ dataHook,
78
+ onReplace,
79
+ onReplaceWithUrl,
80
+ onPreview,
81
+ onDownload,
82
+ onDelete,
83
+ onMenuOpenChange,
84
+ menuZIndex,
85
+ }) => {
86
+ const { t } = useTranslations();
87
+
88
+ return (
89
+ <>
90
+ <Tooltip content={t('CMS.image.replace')} appendTo="window">
91
+ <IconButton
92
+ size="small"
93
+ skin="light"
94
+ priority="secondary"
95
+ dataHook={`${dataHook}-replace-button`}
96
+ ariaLabel={t('CMS.image.replace')}
97
+ disabled={!onReplace}
98
+ onClick={onReplace}
99
+ >
100
+ <Replace />
101
+ </IconButton>
102
+ </Tooltip>
103
+ <PopoverMenu
104
+ textSize="small"
105
+ appendTo="window"
106
+ zIndex={menuZIndex}
107
+ triggerElement={({ isOpen, toggle, ref }) => (
108
+ <MenuTrigger
109
+ isOpen={isOpen}
110
+ toggle={toggle}
111
+ buttonRef={ref}
112
+ onOpenChange={onMenuOpenChange}
113
+ ariaLabel={t('auto-patterns.fields.more_actions_tooltip')}
114
+ dataHook={`${dataHook}-more-button`}
115
+ />
116
+ )}
117
+ >
118
+ <PopoverMenu.MenuItem
119
+ dataHook={`${dataHook}-action-replace-url`}
120
+ text={t('CMS.image.replaceWithUrl.button')}
121
+ prefixIcon={<Link />}
122
+ disabled={!onReplaceWithUrl}
123
+ onClick={() => onReplaceWithUrl?.()}
124
+ />
125
+ <PopoverMenu.MenuItem
126
+ dataHook={`${dataHook}-action-preview`}
127
+ text={t('CMS.mediaGallery.preview')}
128
+ prefixIcon={<Maximize />}
129
+ onClick={onPreview}
130
+ />
131
+ <PopoverMenu.MenuItem
132
+ dataHook={`${dataHook}-action-download`}
133
+ text={t('CMS.image.download')}
134
+ prefixIcon={<Download />}
135
+ onClick={onDownload}
136
+ />
137
+ <PopoverMenu.Divider />
138
+ <PopoverMenu.MenuItem
139
+ dataHook={`${dataHook}-action-delete`}
140
+ text={t('CMS.image.clear')}
141
+ skin="destructive"
142
+ prefixIcon={<Delete />}
143
+ disabled={!onDelete}
144
+ onClick={() => onDelete?.()}
145
+ />
146
+ </PopoverMenu>
147
+ </>
148
+ );
149
+ };
150
+
151
+ MediaImageActions.displayName = 'MediaImageActions';
152
+
153
+ /** Downloads the image: through the Media Manager, or straight from an
154
+ * external URL, which the Media Manager can't make a download link for. */
155
+ export const useMediaImageDownload = (
156
+ image: MediaImageValue | null,
157
+ downloadMedia: (src: string) => void,
158
+ ) =>
159
+ useCallback(() => {
160
+ if (isExternalMediaImage(image)) {
161
+ executeDownloading(image.url);
162
+ return;
163
+ }
164
+ const src = getImageSource(image);
165
+ if (src) {
166
+ downloadMedia(src);
167
+ }
168
+ }, [image, downloadMedia]);
169
+
170
+ export interface MediaImagePreviewModalProps {
171
+ isOpen: boolean;
172
+ image: MediaImageValue;
173
+ onClose: () => void;
174
+ onReplace: () => void;
175
+ onDelete?: () => void;
176
+ onDownload: () => void;
177
+ readOnly?: boolean;
178
+ }
179
+
180
+ export const MediaImagePreviewModal: React.FC<MediaImagePreviewModalProps> = ({
181
+ isOpen,
182
+ image,
183
+ onClose,
184
+ onReplace,
185
+ onDelete,
186
+ onDownload,
187
+ readOnly,
188
+ }) => (
189
+ <MediaPreviewModal
190
+ isOpen={isOpen}
191
+ value={getImageSource(image)}
192
+ onClose={onClose}
193
+ onRequestMedia={onReplace}
194
+ onClearMedia={onDelete}
195
+ onDownloadMedia={onDownload}
196
+ readOnly={readOnly}
197
+ textKeys={{
198
+ replace: 'CMS.image.replace',
199
+ download: 'CMS.image.download',
200
+ delete: 'CMS.image.clear',
201
+ }}
202
+ />
203
+ );
204
+
205
+ MediaImagePreviewModal.displayName = 'MediaImagePreviewModal';