@wix/patterns-fields 1.116.0 → 1.117.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 (443) hide show
  1. package/dist/cjs/assets/locale/messages_ar.json +2 -0
  2. package/dist/cjs/assets/locale/messages_bg.json +2 -0
  3. package/dist/cjs/assets/locale/messages_ca.json +2 -0
  4. package/dist/cjs/assets/locale/messages_cs.json +2 -0
  5. package/dist/cjs/assets/locale/messages_da.json +2 -0
  6. package/dist/cjs/assets/locale/messages_de.json +2 -0
  7. package/dist/cjs/assets/locale/messages_el.json +2 -0
  8. package/dist/cjs/assets/locale/messages_en.json +2 -0
  9. package/dist/cjs/assets/locale/messages_es.json +2 -0
  10. package/dist/cjs/assets/locale/messages_fi.json +2 -0
  11. package/dist/cjs/assets/locale/messages_fr.json +2 -0
  12. package/dist/cjs/assets/locale/messages_he.json +2 -0
  13. package/dist/cjs/assets/locale/messages_hi.json +2 -0
  14. package/dist/cjs/assets/locale/messages_hu.json +2 -0
  15. package/dist/cjs/assets/locale/messages_id.json +2 -0
  16. package/dist/cjs/assets/locale/messages_it.json +2 -0
  17. package/dist/cjs/assets/locale/messages_ja.json +2 -0
  18. package/dist/cjs/assets/locale/messages_ko.json +2 -0
  19. package/dist/cjs/assets/locale/messages_lt.json +2 -0
  20. package/dist/cjs/assets/locale/messages_ms.json +2 -0
  21. package/dist/cjs/assets/locale/messages_nl.json +2 -0
  22. package/dist/cjs/assets/locale/messages_no.json +2 -0
  23. package/dist/cjs/assets/locale/messages_pl.json +2 -0
  24. package/dist/cjs/assets/locale/messages_pt.json +2 -0
  25. package/dist/cjs/assets/locale/messages_ro.json +2 -0
  26. package/dist/cjs/assets/locale/messages_ru.json +2 -0
  27. package/dist/cjs/assets/locale/messages_sk.json +2 -0
  28. package/dist/cjs/assets/locale/messages_sl.json +2 -0
  29. package/dist/cjs/assets/locale/messages_sv.json +2 -0
  30. package/dist/cjs/assets/locale/messages_th.json +2 -0
  31. package/dist/cjs/assets/locale/messages_tl.json +2 -0
  32. package/dist/cjs/assets/locale/messages_tr.json +2 -0
  33. package/dist/cjs/assets/locale/messages_uk.json +2 -0
  34. package/dist/cjs/assets/locale/messages_vi.json +2 -0
  35. package/dist/cjs/assets/locale/messages_zh.json +2 -0
  36. package/dist/cjs/assets/locale/version_file +1 -1
  37. package/dist/cjs/components/address/input/address-input.st.css.js +3 -3
  38. package/dist/cjs/components/address/input/address-input.st.css.js.map +1 -1
  39. package/dist/cjs/components/audio/actions/actions-menu/actions-menu.st.css.js +3 -3
  40. package/dist/cjs/components/audio/actions/actions-menu/actions-menu.st.css.js.map +1 -1
  41. package/dist/cjs/components/audio/audio-field/form-audio-field.st.css.js +4 -4
  42. package/dist/cjs/components/audio/audio-field/form-audio-field.st.css.js.map +1 -1
  43. package/dist/cjs/components/audio/audio-player/audio-player.st.css.js +2 -2
  44. package/dist/cjs/components/audio/audio-player/audio-player.st.css.js.map +1 -1
  45. package/dist/cjs/components/audio/cell-audio-edit.js +10 -11
  46. package/dist/cjs/components/audio/cell-audio-edit.js.map +1 -1
  47. package/dist/cjs/components/color-view/cell-color-view.st.css.js +3 -3
  48. package/dist/cjs/components/color-view/cell-color-view.st.css.js.map +1 -1
  49. package/dist/cjs/components/color-view/color-view.st.css.js +4 -4
  50. package/dist/cjs/components/color-view/color-view.st.css.js.map +1 -1
  51. package/dist/cjs/components/delete-dialog/delete-dialog.st.css.js +3 -3
  52. package/dist/cjs/components/delete-dialog/delete-dialog.st.css.js.map +1 -1
  53. package/dist/cjs/components/document/cell-document-edit.js +25 -26
  54. package/dist/cjs/components/document/cell-document-edit.js.map +1 -1
  55. package/dist/cjs/components/document/form-document-field.st.css.js +7 -7
  56. package/dist/cjs/components/document/form-document-field.st.css.js.map +1 -1
  57. package/dist/cjs/components/exclamation/exclamation.st.css.js +5 -5
  58. package/dist/cjs/components/exclamation/exclamation.st.css.js.map +1 -1
  59. package/dist/cjs/components/field-validation-settings/field-validation-settings-input.st.css.js +3 -3
  60. package/dist/cjs/components/field-validation-settings/field-validation-settings-input.st.css.js.map +1 -1
  61. package/dist/cjs/components/highlighted-text/highlighted-text.st.css.js +5 -5
  62. package/dist/cjs/components/highlighted-text/highlighted-text.st.css.js.map +1 -1
  63. package/dist/cjs/components/image/cell-image-edit.js +22 -23
  64. package/dist/cjs/components/image/cell-image-edit.js.map +1 -1
  65. package/dist/cjs/components/image/image-preview-popover.js +77 -0
  66. package/dist/cjs/components/image/image-preview-popover.js.map +1 -0
  67. package/dist/cjs/components/image/image-thumbnail.js +14 -12
  68. package/dist/cjs/components/image/image-thumbnail.js.map +1 -1
  69. package/dist/cjs/components/image/image-view.js +9 -57
  70. package/dist/cjs/components/image/image-view.js.map +1 -1
  71. package/dist/cjs/components/image/thumbnail-replace-overlay.st.css.js +3 -3
  72. package/dist/cjs/components/image/thumbnail-replace-overlay.st.css.js.map +1 -1
  73. package/dist/cjs/components/index.js +6 -0
  74. package/dist/cjs/components/index.js.map +1 -1
  75. package/dist/cjs/components/media-control/cell-media-edit-shell.js +19 -31
  76. package/dist/cjs/components/media-control/cell-media-edit-shell.js.map +1 -1
  77. package/dist/cjs/components/media-control/cell-media-edit-shell.st.css.js +2 -2
  78. package/dist/cjs/components/media-control/cell-media-edit-shell.st.css.js.map +1 -1
  79. package/dist/cjs/components/media-control/paste-url-button.st.css.js +4 -4
  80. package/dist/cjs/components/media-control/paste-url-button.st.css.js.map +1 -1
  81. package/dist/cjs/components/media-control/use-cell-media-edit.js +51 -23
  82. package/dist/cjs/components/media-control/use-cell-media-edit.js.map +1 -1
  83. package/dist/cjs/components/media-gallery/form-media-gallery-field.st.css.js +10 -10
  84. package/dist/cjs/components/media-gallery/form-media-gallery-field.st.css.js.map +1 -1
  85. package/dist/cjs/components/media-image/media-image.st.css.js +4 -4
  86. package/dist/cjs/components/media-image/media-image.st.css.js.map +1 -1
  87. package/dist/cjs/components/media-image/overlays/overlay.st.css.js +3 -3
  88. package/dist/cjs/components/media-image/overlays/overlay.st.css.js.map +1 -1
  89. package/dist/cjs/components/media-image-field/cell-media-image-edit.js +530 -0
  90. package/dist/cjs/components/media-image-field/cell-media-image-edit.js.map +1 -0
  91. package/dist/cjs/components/media-image-field/cell-media-image-edit.st.css +63 -0
  92. package/dist/cjs/components/media-image-field/cell-media-image-edit.st.css.js +33 -0
  93. package/dist/cjs/components/media-image-field/cell-media-image-edit.st.css.js.map +1 -0
  94. package/dist/cjs/components/media-image-field/form-media-image-field.js +180 -0
  95. package/dist/cjs/components/media-image-field/form-media-image-field.js.map +1 -0
  96. package/dist/cjs/components/media-image-field/form-media-image-field.uni.driver.js +34 -0
  97. package/dist/cjs/components/media-image-field/form-media-image-field.uni.driver.js.map +1 -0
  98. package/dist/cjs/components/media-image-field/form-media-image-input.js +64 -0
  99. package/dist/cjs/components/media-image-field/form-media-image-input.js.map +1 -0
  100. package/dist/cjs/components/media-image-field/index.js +28 -0
  101. package/dist/cjs/components/media-image-field/index.js.map +1 -0
  102. package/dist/cjs/components/media-image-field/media-image-view.js +114 -0
  103. package/dist/cjs/components/media-image-field/media-image-view.js.map +1 -0
  104. package/dist/cjs/components/media-image-field/media-image-view.st.css +16 -0
  105. package/dist/cjs/components/media-image-field/media-image-view.st.css.js +27 -0
  106. package/dist/cjs/components/media-image-field/media-image-view.st.css.js.map +1 -0
  107. package/dist/cjs/components/media-image-field/media-image-view.uni.driver.js +18 -0
  108. package/dist/cjs/components/media-image-field/media-image-view.uni.driver.js.map +1 -0
  109. package/dist/cjs/components/media-tag/web-media-tag/media-tag.st.css.js +2 -2
  110. package/dist/cjs/components/media-tag/web-media-tag/media-tag.st.css.js.map +1 -1
  111. package/dist/cjs/components/multi-document/cell-multi-document-edit.st.css.js +3 -3
  112. package/dist/cjs/components/multi-document/cell-multi-document-edit.st.css.js.map +1 -1
  113. package/dist/cjs/components/multi-document/multi-document-input/form-multi-document.st.css.js +5 -5
  114. package/dist/cjs/components/multi-document/multi-document-input/form-multi-document.st.css.js.map +1 -1
  115. package/dist/cjs/components/reference/cell-multi-reference-input.st.css.js +2 -2
  116. package/dist/cjs/components/reference/cell-multi-reference-input.st.css.js.map +1 -1
  117. package/dist/cjs/components/reference/cell-reference-input.st.css.js +3 -3
  118. package/dist/cjs/components/reference/cell-reference-input.st.css.js.map +1 -1
  119. package/dist/cjs/components/rich-content/rich-content-input/default-value-input/rich-content-default-value-input.st.css.js +4 -4
  120. package/dist/cjs/components/rich-content/rich-content-input/default-value-input/rich-content-default-value-input.st.css.js.map +1 -1
  121. package/dist/cjs/components/rich-content/rich-content-input/form-input/rich-content-form-input.st.css.js +3 -3
  122. package/dist/cjs/components/rich-content/rich-content-input/form-input/rich-content-form-input.st.css.js.map +1 -1
  123. package/dist/cjs/components/rich-content/rich-content-input/form-read-only-input/rich-content-form-read-only-input.st.css.js +2 -2
  124. 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
  125. package/dist/cjs/components/rich-content/rich-content-input/rich-content-common/fullscreen-modal/fullscreen-modal.st.css.js +3 -3
  126. package/dist/cjs/components/rich-content/rich-content-input/rich-content-common/fullscreen-modal/fullscreen-modal.st.css.js.map +1 -1
  127. package/dist/cjs/components/rich-content/rich-content-input/rich-content-common/publish-loader/publish-loader.st.css.js +3 -3
  128. package/dist/cjs/components/rich-content/rich-content-input/rich-content-common/publish-loader/publish-loader.st.css.js.map +1 -1
  129. package/dist/cjs/components/rich-content/rich-content-input/rich-content-common/toggle-fullscreen-button/toggle-fullscreen-button.st.css.js +2 -2
  130. package/dist/cjs/components/rich-content/rich-content-input/rich-content-common/toggle-fullscreen-button/toggle-fullscreen-button.st.css.js.map +1 -1
  131. package/dist/cjs/components/rich-content/rich-content-input/rich-content-editor/rich-content-editor.st.css.js +7 -7
  132. package/dist/cjs/components/rich-content/rich-content-input/rich-content-editor/rich-content-editor.st.css.js.map +1 -1
  133. package/dist/cjs/components/rich-content/rich-content-input/rich-content-editor/rich-content-toolbar.st.css.js +5 -5
  134. package/dist/cjs/components/rich-content/rich-content-input/rich-content-editor/rich-content-toolbar.st.css.js.map +1 -1
  135. package/dist/cjs/components/rich-content/rich-content-input/rich-content-viewer/rich-content-viewer.st.css.js +4 -4
  136. package/dist/cjs/components/rich-content/rich-content-input/rich-content-viewer/rich-content-viewer.st.css.js.map +1 -1
  137. package/dist/cjs/components/rich-text/rich-text-input/rich-text-editor/rich-editor.st.css.js +18 -18
  138. package/dist/cjs/components/rich-text/rich-text-input/rich-text-editor/rich-editor.st.css.js.map +1 -1
  139. package/dist/cjs/components/rich-text/rich-text-input/rich-text-editor/rich-text-editor.st.css.js +4 -4
  140. package/dist/cjs/components/rich-text/rich-text-input/rich-text-editor/rich-text-editor.st.css.js.map +1 -1
  141. package/dist/cjs/components/rich-text/rich-text-input/rich-text-editor/toolbar/toolbar.st.css.js +18 -18
  142. package/dist/cjs/components/rich-text/rich-text-input/rich-text-editor/toolbar/toolbar.st.css.js.map +1 -1
  143. package/dist/cjs/components/text/text-view.st.css.js +3 -3
  144. package/dist/cjs/components/text/text-view.st.css.js.map +1 -1
  145. package/dist/cjs/services/translations.js.map +1 -1
  146. package/dist/cjs/styles.global.css +1 -1
  147. package/dist/cjs/types/index.js +6 -0
  148. package/dist/cjs/types/index.js.map +1 -1
  149. package/dist/cjs/types/media-image.js +4 -0
  150. package/dist/cjs/types/media-image.js.map +1 -0
  151. package/dist/cjs/utils/index.js +6 -0
  152. package/dist/cjs/utils/index.js.map +1 -1
  153. package/dist/cjs/utils/media-image-value.js +95 -0
  154. package/dist/cjs/utils/media-image-value.js.map +1 -0
  155. package/dist/esm/assets/locale/messages_ar.json +2 -0
  156. package/dist/esm/assets/locale/messages_bg.json +2 -0
  157. package/dist/esm/assets/locale/messages_ca.json +2 -0
  158. package/dist/esm/assets/locale/messages_cs.json +2 -0
  159. package/dist/esm/assets/locale/messages_da.json +2 -0
  160. package/dist/esm/assets/locale/messages_de.json +2 -0
  161. package/dist/esm/assets/locale/messages_el.json +2 -0
  162. package/dist/esm/assets/locale/messages_en.json +2 -0
  163. package/dist/esm/assets/locale/messages_es.json +2 -0
  164. package/dist/esm/assets/locale/messages_fi.json +2 -0
  165. package/dist/esm/assets/locale/messages_fr.json +2 -0
  166. package/dist/esm/assets/locale/messages_he.json +2 -0
  167. package/dist/esm/assets/locale/messages_hi.json +2 -0
  168. package/dist/esm/assets/locale/messages_hu.json +2 -0
  169. package/dist/esm/assets/locale/messages_id.json +2 -0
  170. package/dist/esm/assets/locale/messages_it.json +2 -0
  171. package/dist/esm/assets/locale/messages_ja.json +2 -0
  172. package/dist/esm/assets/locale/messages_ko.json +2 -0
  173. package/dist/esm/assets/locale/messages_lt.json +2 -0
  174. package/dist/esm/assets/locale/messages_ms.json +2 -0
  175. package/dist/esm/assets/locale/messages_nl.json +2 -0
  176. package/dist/esm/assets/locale/messages_no.json +2 -0
  177. package/dist/esm/assets/locale/messages_pl.json +2 -0
  178. package/dist/esm/assets/locale/messages_pt.json +2 -0
  179. package/dist/esm/assets/locale/messages_ro.json +2 -0
  180. package/dist/esm/assets/locale/messages_ru.json +2 -0
  181. package/dist/esm/assets/locale/messages_sk.json +2 -0
  182. package/dist/esm/assets/locale/messages_sl.json +2 -0
  183. package/dist/esm/assets/locale/messages_sv.json +2 -0
  184. package/dist/esm/assets/locale/messages_th.json +2 -0
  185. package/dist/esm/assets/locale/messages_tl.json +2 -0
  186. package/dist/esm/assets/locale/messages_tr.json +2 -0
  187. package/dist/esm/assets/locale/messages_uk.json +2 -0
  188. package/dist/esm/assets/locale/messages_vi.json +2 -0
  189. package/dist/esm/assets/locale/messages_zh.json +2 -0
  190. package/dist/esm/assets/locale/version_file +1 -1
  191. package/dist/esm/components/address/input/address-input.st.css.js +2 -2
  192. package/dist/esm/components/address/input/address-input.st.css.js.map +1 -1
  193. package/dist/esm/components/audio/actions/actions-menu/actions-menu.st.css.js +2 -2
  194. package/dist/esm/components/audio/audio-field/form-audio-field.st.css.js +2 -2
  195. package/dist/esm/components/audio/audio-field/form-audio-field.st.css.js.map +1 -1
  196. package/dist/esm/components/audio/audio-player/audio-player.st.css.js +2 -2
  197. package/dist/esm/components/audio/audio-player/audio-player.st.css.js.map +1 -1
  198. package/dist/esm/components/audio/cell-audio-edit.js +1 -1
  199. package/dist/esm/components/audio/cell-audio-edit.js.map +1 -1
  200. package/dist/esm/components/color-view/cell-color-view.st.css.js +2 -2
  201. package/dist/esm/components/color-view/cell-color-view.st.css.js.map +1 -1
  202. package/dist/esm/components/color-view/color-view.st.css.js +2 -2
  203. package/dist/esm/components/delete-dialog/delete-dialog.st.css.js +2 -2
  204. package/dist/esm/components/document/cell-document-edit.js +1 -1
  205. package/dist/esm/components/document/cell-document-edit.js.map +1 -1
  206. package/dist/esm/components/document/form-document-field.st.css.js +2 -2
  207. package/dist/esm/components/document/form-document-field.st.css.js.map +1 -1
  208. package/dist/esm/components/exclamation/exclamation.st.css.js +2 -2
  209. package/dist/esm/components/field-validation-settings/field-validation-settings-input.st.css.js +2 -2
  210. package/dist/esm/components/highlighted-text/highlighted-text.st.css.js +3 -3
  211. package/dist/esm/components/image/cell-image-edit.js +1 -1
  212. package/dist/esm/components/image/cell-image-edit.js.map +1 -1
  213. package/dist/esm/components/image/image-preview-popover.js +16 -0
  214. package/dist/esm/components/image/image-preview-popover.js.map +1 -0
  215. package/dist/esm/components/image/image-thumbnail.js +5 -6
  216. package/dist/esm/components/image/image-thumbnail.js.map +1 -1
  217. package/dist/esm/components/image/image-view.js +4 -13
  218. package/dist/esm/components/image/image-view.js.map +1 -1
  219. package/dist/esm/components/image/thumbnail-replace-overlay.st.css.js +2 -2
  220. package/dist/esm/components/index.js +1 -0
  221. package/dist/esm/components/index.js.map +1 -1
  222. package/dist/esm/components/media-control/cell-media-edit-shell.js +5 -7
  223. package/dist/esm/components/media-control/cell-media-edit-shell.js.map +1 -1
  224. package/dist/esm/components/media-control/cell-media-edit-shell.st.css.js +2 -2
  225. package/dist/esm/components/media-control/paste-url-button.st.css.js +2 -2
  226. package/dist/esm/components/media-control/paste-url-button.st.css.js.map +1 -1
  227. package/dist/esm/components/media-control/use-cell-media-edit.js +48 -30
  228. package/dist/esm/components/media-control/use-cell-media-edit.js.map +1 -1
  229. package/dist/esm/components/media-gallery/form-media-gallery-field.st.css.js +2 -2
  230. package/dist/esm/components/media-image/media-image.st.css.js +3 -3
  231. package/dist/esm/components/media-image/media-image.st.css.js.map +1 -1
  232. package/dist/esm/components/media-image/overlays/overlay.st.css.js +2 -2
  233. package/dist/esm/components/media-image/overlays/overlay.st.css.js.map +1 -1
  234. package/dist/esm/components/media-image-field/cell-media-image-edit.js +159 -0
  235. package/dist/esm/components/media-image-field/cell-media-image-edit.js.map +1 -0
  236. package/dist/esm/components/media-image-field/cell-media-image-edit.st.css +63 -0
  237. package/dist/esm/components/media-image-field/cell-media-image-edit.st.css.js +15 -0
  238. package/dist/esm/components/media-image-field/cell-media-image-edit.st.css.js.map +1 -0
  239. package/dist/esm/components/media-image-field/form-media-image-field.js +59 -0
  240. package/dist/esm/components/media-image-field/form-media-image-field.js.map +1 -0
  241. package/dist/esm/components/media-image-field/form-media-image-field.uni.driver.js +27 -0
  242. package/dist/esm/components/media-image-field/form-media-image-field.uni.driver.js.map +1 -0
  243. package/dist/esm/components/media-image-field/form-media-image-input.js +40 -0
  244. package/dist/esm/components/media-image-field/form-media-image-input.js.map +1 -0
  245. package/dist/esm/components/media-image-field/index.js +5 -0
  246. package/dist/esm/components/media-image-field/index.js.map +1 -0
  247. package/dist/esm/components/media-image-field/media-image-view.js +34 -0
  248. package/dist/esm/components/media-image-field/media-image-view.js.map +1 -0
  249. package/dist/esm/components/media-image-field/media-image-view.st.css +16 -0
  250. package/dist/esm/components/media-image-field/media-image-view.st.css.js +15 -0
  251. package/dist/esm/components/media-image-field/media-image-view.st.css.js.map +1 -0
  252. package/dist/esm/components/media-image-field/media-image-view.uni.driver.js +14 -0
  253. package/dist/esm/components/media-image-field/media-image-view.uni.driver.js.map +1 -0
  254. package/dist/esm/components/media-tag/web-media-tag/media-tag.st.css.js +2 -2
  255. package/dist/esm/components/media-tag/web-media-tag/media-tag.st.css.js.map +1 -1
  256. package/dist/esm/components/multi-document/cell-multi-document-edit.st.css.js +2 -2
  257. package/dist/esm/components/multi-document/cell-multi-document-edit.st.css.js.map +1 -1
  258. package/dist/esm/components/multi-document/multi-document-input/form-multi-document.st.css.js +2 -2
  259. package/dist/esm/components/multi-document/multi-document-input/form-multi-document.st.css.js.map +1 -1
  260. package/dist/esm/components/reference/cell-multi-reference-input.st.css.js +2 -2
  261. package/dist/esm/components/reference/cell-reference-input.st.css.js +2 -2
  262. package/dist/esm/components/rich-content/rich-content-input/default-value-input/rich-content-default-value-input.st.css.js +2 -2
  263. package/dist/esm/components/rich-content/rich-content-input/form-input/rich-content-form-input.st.css.js +2 -2
  264. package/dist/esm/components/rich-content/rich-content-input/form-read-only-input/rich-content-form-read-only-input.st.css.js +2 -2
  265. package/dist/esm/components/rich-content/rich-content-input/rich-content-common/fullscreen-modal/fullscreen-modal.st.css.js +2 -2
  266. package/dist/esm/components/rich-content/rich-content-input/rich-content-common/publish-loader/publish-loader.st.css.js +2 -2
  267. package/dist/esm/components/rich-content/rich-content-input/rich-content-common/toggle-fullscreen-button/toggle-fullscreen-button.st.css.js +2 -2
  268. package/dist/esm/components/rich-content/rich-content-input/rich-content-editor/rich-content-editor.st.css.js +2 -2
  269. package/dist/esm/components/rich-content/rich-content-input/rich-content-editor/rich-content-toolbar.st.css.js +2 -2
  270. package/dist/esm/components/rich-content/rich-content-input/rich-content-viewer/rich-content-viewer.st.css.js +2 -2
  271. package/dist/esm/components/rich-content/rich-content-input/rich-content-viewer/rich-content-viewer.st.css.js.map +1 -1
  272. package/dist/esm/components/rich-text/rich-text-input/rich-text-editor/rich-editor.st.css.js +2 -2
  273. package/dist/esm/components/rich-text/rich-text-input/rich-text-editor/rich-text-editor.st.css.js +2 -2
  274. package/dist/esm/components/rich-text/rich-text-input/rich-text-editor/rich-text-editor.st.css.js.map +1 -1
  275. package/dist/esm/components/rich-text/rich-text-input/rich-text-editor/toolbar/toolbar.st.css.js +2 -2
  276. package/dist/esm/components/rich-text/rich-text-input/rich-text-editor/toolbar/toolbar.st.css.js.map +1 -1
  277. package/dist/esm/components/text/text-view.st.css.js +2 -2
  278. package/dist/esm/styles.global.css +1 -1
  279. package/dist/esm/types/index.js +1 -0
  280. package/dist/esm/types/index.js.map +1 -1
  281. package/dist/esm/types/media-image.js +2 -0
  282. package/dist/esm/types/media-image.js.map +1 -0
  283. package/dist/esm/utils/index.js +1 -0
  284. package/dist/esm/utils/index.js.map +1 -1
  285. package/dist/esm/utils/media-image-value.js +65 -0
  286. package/dist/esm/utils/media-image-value.js.map +1 -0
  287. package/dist/types/components/address/input/address-input.st.css.d.ts.map +1 -1
  288. package/dist/types/components/audio/audio-field/form-audio-field.st.css.d.ts.map +1 -1
  289. package/dist/types/components/audio/audio-player/audio-player.st.css.d.ts.map +1 -1
  290. package/dist/types/components/audio/cell-audio-edit.d.ts.map +1 -1
  291. package/dist/types/components/color-view/cell-color-view.st.css.d.ts.map +1 -1
  292. package/dist/types/components/document/cell-document-edit.d.ts.map +1 -1
  293. package/dist/types/components/document/form-document-field.st.css.d.ts.map +1 -1
  294. package/dist/types/components/image/cell-image-edit.d.ts.map +1 -1
  295. package/dist/types/components/image/image-preview-popover.d.ts +10 -0
  296. package/dist/types/components/image/image-preview-popover.d.ts.map +1 -0
  297. package/dist/types/components/image/image-thumbnail.d.ts +3 -0
  298. package/dist/types/components/image/image-thumbnail.d.ts.map +1 -1
  299. package/dist/types/components/image/image-view.d.ts.map +1 -1
  300. package/dist/types/components/index.d.ts +1 -0
  301. package/dist/types/components/index.d.ts.map +1 -1
  302. package/dist/types/components/media-control/cell-media-edit-shell.d.ts +1 -2
  303. package/dist/types/components/media-control/cell-media-edit-shell.d.ts.map +1 -1
  304. package/dist/types/components/media-control/paste-url-button.st.css.d.ts.map +1 -1
  305. package/dist/types/components/media-control/use-cell-media-edit.d.ts +20 -4
  306. package/dist/types/components/media-control/use-cell-media-edit.d.ts.map +1 -1
  307. package/dist/types/components/media-image/media-image.st.css.d.ts.map +1 -1
  308. package/dist/types/components/media-image/overlays/overlay.st.css.d.ts.map +1 -1
  309. package/dist/types/components/media-image-field/cell-media-image-edit.d.ts +26 -0
  310. package/dist/types/components/media-image-field/cell-media-image-edit.d.ts.map +1 -0
  311. package/dist/types/components/media-image-field/cell-media-image-edit.st.css.d.ts +24 -0
  312. package/dist/types/components/media-image-field/cell-media-image-edit.st.css.d.ts.map +1 -0
  313. package/dist/types/components/media-image-field/form-media-image-field.d.ts +32 -0
  314. package/dist/types/components/media-image-field/form-media-image-field.d.ts.map +1 -0
  315. package/dist/types/components/media-image-field/form-media-image-field.uni.driver.d.ts +22 -0
  316. package/dist/types/components/media-image-field/form-media-image-field.uni.driver.d.ts.map +1 -0
  317. package/dist/types/components/media-image-field/form-media-image-input.d.ts +9 -0
  318. package/dist/types/components/media-image-field/form-media-image-input.d.ts.map +1 -0
  319. package/dist/types/components/media-image-field/index.d.ts +5 -0
  320. package/dist/types/components/media-image-field/index.d.ts.map +1 -0
  321. package/dist/types/components/media-image-field/media-image-view.d.ts +13 -0
  322. package/dist/types/components/media-image-field/media-image-view.d.ts.map +1 -0
  323. package/dist/types/components/media-image-field/media-image-view.st.css.d.ts +18 -0
  324. package/dist/types/components/media-image-field/media-image-view.st.css.d.ts.map +1 -0
  325. package/dist/types/components/media-image-field/media-image-view.uni.driver.d.ts +12 -0
  326. package/dist/types/components/media-image-field/media-image-view.uni.driver.d.ts.map +1 -0
  327. package/dist/types/components/media-tag/web-media-tag/media-tag.st.css.d.ts.map +1 -1
  328. package/dist/types/components/multi-document/cell-multi-document-edit.st.css.d.ts.map +1 -1
  329. package/dist/types/components/multi-document/multi-document-input/form-multi-document.st.css.d.ts.map +1 -1
  330. package/dist/types/components/rich-content/rich-content-input/rich-content-viewer/rich-content-viewer.st.css.d.ts.map +1 -1
  331. package/dist/types/components/rich-text/rich-text-input/rich-text-editor/rich-text-editor.st.css.d.ts.map +1 -1
  332. package/dist/types/components/rich-text/rich-text-input/rich-text-editor/toolbar/toolbar.st.css.d.ts.map +1 -1
  333. package/dist/types/services/translations.d.ts +1 -1
  334. package/dist/types/services/translations.d.ts.map +1 -1
  335. package/dist/types/types/index.d.ts +1 -0
  336. package/dist/types/types/index.d.ts.map +1 -1
  337. package/dist/types/types/media-image.d.ts +23 -0
  338. package/dist/types/types/media-image.d.ts.map +1 -0
  339. package/dist/types/utils/index.d.ts +1 -0
  340. package/dist/types/utils/index.d.ts.map +1 -1
  341. package/dist/types/utils/media-image-value.d.ts +31 -0
  342. package/dist/types/utils/media-image-value.d.ts.map +1 -0
  343. package/package.json +4 -4
  344. package/src/__tests__/components/media-image-field/form-media-image-input.spec.tsx +130 -0
  345. package/src/__tests__/components/media-image-field/media-image-view.spec.tsx +51 -0
  346. package/src/__tests__/utils/media-image-value.spec.ts +153 -0
  347. package/src/assets/locale/messages_ar.json +2 -0
  348. package/src/assets/locale/messages_bg.json +2 -0
  349. package/src/assets/locale/messages_ca.json +2 -0
  350. package/src/assets/locale/messages_cs.json +2 -0
  351. package/src/assets/locale/messages_da.json +2 -0
  352. package/src/assets/locale/messages_de.json +2 -0
  353. package/src/assets/locale/messages_el.json +2 -0
  354. package/src/assets/locale/messages_en.json +2 -0
  355. package/src/assets/locale/messages_es.json +2 -0
  356. package/src/assets/locale/messages_fi.json +2 -0
  357. package/src/assets/locale/messages_fr.json +2 -0
  358. package/src/assets/locale/messages_he.json +2 -0
  359. package/src/assets/locale/messages_hi.json +2 -0
  360. package/src/assets/locale/messages_hu.json +2 -0
  361. package/src/assets/locale/messages_id.json +2 -0
  362. package/src/assets/locale/messages_it.json +2 -0
  363. package/src/assets/locale/messages_ja.json +2 -0
  364. package/src/assets/locale/messages_ko.json +2 -0
  365. package/src/assets/locale/messages_lt.json +2 -0
  366. package/src/assets/locale/messages_ms.json +2 -0
  367. package/src/assets/locale/messages_nl.json +2 -0
  368. package/src/assets/locale/messages_no.json +2 -0
  369. package/src/assets/locale/messages_pl.json +2 -0
  370. package/src/assets/locale/messages_pt.json +2 -0
  371. package/src/assets/locale/messages_ro.json +2 -0
  372. package/src/assets/locale/messages_ru.json +2 -0
  373. package/src/assets/locale/messages_sk.json +2 -0
  374. package/src/assets/locale/messages_sl.json +2 -0
  375. package/src/assets/locale/messages_sv.json +2 -0
  376. package/src/assets/locale/messages_th.json +2 -0
  377. package/src/assets/locale/messages_tl.json +2 -0
  378. package/src/assets/locale/messages_tr.json +2 -0
  379. package/src/assets/locale/messages_uk.json +2 -0
  380. package/src/assets/locale/messages_vi.json +2 -0
  381. package/src/assets/locale/messages_zh.json +2 -0
  382. package/src/assets/locale/version_file +1 -1
  383. package/src/components/address/input/address-input.st.css.ts +2 -2
  384. package/src/components/audio/actions/actions-menu/actions-menu.st.css.ts +2 -2
  385. package/src/components/audio/audio-field/form-audio-field.st.css.ts +2 -2
  386. package/src/components/audio/audio-player/audio-player.st.css.ts +2 -2
  387. package/src/components/audio/cell-audio-edit.tsx +0 -1
  388. package/src/components/color-view/cell-color-view.st.css.ts +2 -2
  389. package/src/components/color-view/color-view.st.css.ts +2 -2
  390. package/src/components/delete-dialog/delete-dialog.st.css.ts +2 -2
  391. package/src/components/document/cell-document-edit.tsx +0 -1
  392. package/src/components/document/form-document-field.st.css.ts +2 -2
  393. package/src/components/exclamation/exclamation.st.css.ts +2 -2
  394. package/src/components/field-validation-settings/field-validation-settings-input.st.css.ts +2 -2
  395. package/src/components/highlighted-text/highlighted-text.st.css.ts +3 -3
  396. package/src/components/image/cell-image-edit.tsx +0 -1
  397. package/src/components/image/image-preview-popover.tsx +52 -0
  398. package/src/components/image/image-thumbnail.tsx +12 -7
  399. package/src/components/image/image-view.tsx +16 -42
  400. package/src/components/image/thumbnail-replace-overlay.st.css.ts +2 -2
  401. package/src/components/index.ts +1 -0
  402. package/src/components/media-control/cell-media-edit-shell.st.css.ts +2 -2
  403. package/src/components/media-control/cell-media-edit-shell.tsx +7 -20
  404. package/src/components/media-control/paste-url-button.st.css.ts +2 -2
  405. package/src/components/media-control/use-cell-media-edit.ts +98 -28
  406. package/src/components/media-gallery/form-media-gallery-field.st.css.ts +2 -2
  407. package/src/components/media-image/media-image.st.css.ts +3 -3
  408. package/src/components/media-image/overlays/overlay.st.css.ts +2 -2
  409. package/src/components/media-image-field/cell-media-image-edit.st.css +63 -0
  410. package/src/components/media-image-field/cell-media-image-edit.st.css.ts +25 -0
  411. package/src/components/media-image-field/cell-media-image-edit.tsx +402 -0
  412. package/src/components/media-image-field/form-media-image-field.tsx +165 -0
  413. package/src/components/media-image-field/form-media-image-field.uni.driver.ts +42 -0
  414. package/src/components/media-image-field/form-media-image-input.tsx +56 -0
  415. package/src/components/media-image-field/index.ts +4 -0
  416. package/src/components/media-image-field/media-image-view.st.css +16 -0
  417. package/src/components/media-image-field/media-image-view.st.css.ts +25 -0
  418. package/src/components/media-image-field/media-image-view.tsx +95 -0
  419. package/src/components/media-image-field/media-image-view.uni.driver.ts +18 -0
  420. package/src/components/media-tag/web-media-tag/media-tag.st.css.ts +2 -2
  421. package/src/components/multi-document/cell-multi-document-edit.st.css.ts +2 -2
  422. package/src/components/multi-document/multi-document-input/form-multi-document.st.css.ts +2 -2
  423. package/src/components/reference/cell-multi-reference-input.st.css.ts +2 -2
  424. package/src/components/reference/cell-reference-input.st.css.ts +2 -2
  425. package/src/components/rich-content/rich-content-input/default-value-input/rich-content-default-value-input.st.css.ts +2 -2
  426. package/src/components/rich-content/rich-content-input/form-input/rich-content-form-input.st.css.ts +2 -2
  427. package/src/components/rich-content/rich-content-input/form-read-only-input/rich-content-form-read-only-input.st.css.ts +2 -2
  428. package/src/components/rich-content/rich-content-input/rich-content-common/fullscreen-modal/fullscreen-modal.st.css.ts +2 -2
  429. package/src/components/rich-content/rich-content-input/rich-content-common/publish-loader/publish-loader.st.css.ts +2 -2
  430. package/src/components/rich-content/rich-content-input/rich-content-common/toggle-fullscreen-button/toggle-fullscreen-button.st.css.ts +2 -2
  431. package/src/components/rich-content/rich-content-input/rich-content-editor/rich-content-editor.st.css.ts +2 -2
  432. package/src/components/rich-content/rich-content-input/rich-content-editor/rich-content-toolbar.st.css.ts +2 -2
  433. package/src/components/rich-content/rich-content-input/rich-content-viewer/rich-content-viewer.st.css.ts +2 -2
  434. package/src/components/rich-text/rich-text-input/rich-text-editor/rich-editor.st.css.ts +2 -2
  435. package/src/components/rich-text/rich-text-input/rich-text-editor/rich-text-editor.st.css.ts +2 -2
  436. package/src/components/rich-text/rich-text-input/rich-text-editor/toolbar/toolbar.st.css.ts +2 -2
  437. package/src/components/text/text-view.st.css.ts +2 -2
  438. package/src/services/translations.ts +2 -0
  439. package/src/styles.global.css +1 -1
  440. package/src/types/index.ts +1 -0
  441. package/src/types/media-image.ts +24 -0
  442. package/src/utils/index.ts +1 -0
  443. package/src/utils/media-image-value.ts +99 -0
@@ -0,0 +1,402 @@
1
+ import React, { useCallback, useEffect, useState } from 'react';
2
+ import {
3
+ Box,
4
+ FormField,
5
+ IconButton,
6
+ Input,
7
+ Popover,
8
+ PopoverMenu,
9
+ Tooltip,
10
+ } 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';
21
+ import { ThumbnailSize } from '../../auto-field-types';
22
+ import { useTranslations } from '../../hooks';
23
+ import type { MediaImageValue } from '../../types/media-image';
24
+ import { getImageSource } from '../../utils/get-image-source';
25
+ import {
26
+ fromImageUrl,
27
+ fromMediaManagerPick,
28
+ isExternalMediaImage,
29
+ replaceImage,
30
+ toMediaImageValue,
31
+ withAltText,
32
+ } from '../../utils/media-image-value';
33
+ import { executeDownloading, MEDIA_TYPES } from '../../utils/media-utils';
34
+ import {
35
+ CellMediaEditShell,
36
+ MediaFieldType,
37
+ useCellMediaEdit,
38
+ } from '../media-control';
39
+ import { MediaPreviewModal } from '../media-gallery/media-preview-modal';
40
+ import { MediaImage } from '../media-image';
41
+ import { MediaImageView } from './media-image-view';
42
+ import { st, classes } from './cell-media-image-edit.st.css.js';
43
+
44
+ export interface CellMediaImageEditProps {
45
+ /** A `MEDIA_IMAGE` value. */
46
+ value: unknown;
47
+ onChange: (value: MediaImageValue | null) => void;
48
+ onCommit: () => void;
49
+ onCancel?: () => void;
50
+ /**
51
+ * Called before opening external UI (media manager / paste-URL form) so the
52
+ * table can set isEditing=true and protect cell focus while the modal is open.
53
+ */
54
+ onStartEdit?: () => void;
55
+ inputRef?: React.MutableRefObject<{ focus: () => void } | null | undefined>;
56
+ dataHook?: string;
57
+ }
58
+
59
+ type PopoverLayer = 'none' | 'popover' | 'menu' | 'preview';
60
+
61
+ /** What is on top of the editor. Escape and click-outside act on it. */
62
+ type Layer = PopoverLayer | 'pasteUrl' | 'loading';
63
+
64
+ const imageFromUrl = (url: string, current: MediaImageValue | null) =>
65
+ replaceImage(current, fromImageUrl(url));
66
+
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
+ /**
107
+ * Edits a `MEDIA_IMAGE` cell. An empty cell shows the add and paste-URL
108
+ * buttons. A cell with an image opens a popover with the image and its alt
109
+ * text. Changes go to `onChange` as they happen and are committed once, when
110
+ * the popover closes.
111
+ */
112
+ export const CellMediaImageEdit: React.FC<CellMediaImageEditProps> = ({
113
+ value,
114
+ onChange,
115
+ onCommit,
116
+ onCancel,
117
+ onStartEdit,
118
+ inputRef,
119
+ dataHook,
120
+ }) => {
121
+ const { t } = useTranslations();
122
+ const image = toMediaImageValue(value);
123
+ const src = getImageSource(image);
124
+ // 'none' once committed.
125
+ const [popoverLayer, setPopoverLayer] = useState<PopoverLayer>('popover');
126
+
127
+ const mediaEdit = useCellMediaEdit({
128
+ mediaType: MEDIA_TYPES.IMAGE,
129
+ value: image,
130
+ onChange,
131
+ onCommit,
132
+ onCancel,
133
+ onStartEdit,
134
+ inputRef,
135
+ fromPick: fromMediaManagerPick,
136
+ fromUrl: imageFromUrl,
137
+ commitOnPick: false,
138
+ });
139
+ const {
140
+ loading,
141
+ pasteUrlForm,
142
+ handleCallMedia,
143
+ handleDelete,
144
+ downloadMedia,
145
+ } = mediaEdit;
146
+ const closePasteUrl = pasteUrlForm.handleClose;
147
+ // The media manager and the URL form sit above the popover layers.
148
+ const openLayer: Layer = loading
149
+ ? 'loading'
150
+ : pasteUrlForm.isOpen
151
+ ? 'pasteUrl'
152
+ : image
153
+ ? popoverLayer
154
+ : 'none';
155
+
156
+ const openPasteUrl = mediaEdit.startEditAndOpenPasteUrl({
157
+ title: t('CMS.image.replaceWithUrl.title'),
158
+ value: isExternalMediaImage(image) ? image.url : undefined,
159
+ });
160
+
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]);
169
+
170
+ const commit = useCallback(() => {
171
+ setPopoverLayer('none');
172
+ onCommit();
173
+ }, [onCommit]);
174
+
175
+ // Picking Preview sets its own layer, which closing the menu must not undo.
176
+ const handleMenuOpenChange = useCallback((isOpen: boolean) => {
177
+ setPopoverLayer((layer) => {
178
+ if (isOpen) {
179
+ return 'menu';
180
+ }
181
+ return layer === 'menu' ? 'popover' : layer;
182
+ });
183
+ }, []);
184
+
185
+ // Fires on mouseup, before the click that closes a menu or a modal, so
186
+ // `openLayer` still says what was open.
187
+ const handleClickOutside = useCallback(() => {
188
+ if (openLayer === 'popover') {
189
+ commit();
190
+ }
191
+ }, [openLayer, commit]);
192
+
193
+ useEffect(() => {
194
+ // WDS closes the menu on Escape and stops the event there.
195
+ if (
196
+ openLayer === 'none' ||
197
+ openLayer === 'loading' ||
198
+ openLayer === 'menu'
199
+ ) {
200
+ return;
201
+ }
202
+ // Capture phase, so the table doesn't cancel the edit first.
203
+ const handleKeyDown = (e: KeyboardEvent) => {
204
+ if (e.key !== 'Escape') {
205
+ return;
206
+ }
207
+ e.stopPropagation();
208
+ if (openLayer === 'pasteUrl') {
209
+ closePasteUrl();
210
+ } else if (openLayer === 'preview') {
211
+ setPopoverLayer('popover');
212
+ } else {
213
+ commit();
214
+ }
215
+ };
216
+ document.addEventListener('keydown', handleKeyDown, true);
217
+ return () => document.removeEventListener('keydown', handleKeyDown, true);
218
+ }, [openLayer, closePasteUrl, commit]);
219
+
220
+ const emptyActions = (
221
+ <>
222
+ <Tooltip content={t('CMS.image.add')} appendTo="window">
223
+ <IconButton
224
+ size="tiny"
225
+ priority="secondary"
226
+ dataHook="media-image-edit-add-button"
227
+ ariaLabel={t('CMS.image.add')}
228
+ onClick={handleCallMedia}
229
+ >
230
+ <Add />
231
+ </IconButton>
232
+ </Tooltip>
233
+ <Tooltip content={t('CMS.image.replaceWithUrl.button')} appendTo="window">
234
+ <IconButton
235
+ size="tiny"
236
+ priority="tertiary"
237
+ dataHook="media-image-edit-paste-url-button"
238
+ ariaLabel={t('CMS.image.replaceWithUrl.button')}
239
+ onClick={openPasteUrl}
240
+ >
241
+ <LinkSmall />
242
+ </IconButton>
243
+ </Tooltip>
244
+ </>
245
+ );
246
+
247
+ // One return for both states, so the shell and its container stay mounted
248
+ // when a pick fills an empty cell.
249
+ return (
250
+ <>
251
+ <CellMediaEditShell
252
+ dataHook={dataHook}
253
+ mediaEdit={mediaEdit}
254
+ fieldType={MediaFieldType.image}
255
+ padding={image ? '0' : undefined}
256
+ >
257
+ {!image ? (
258
+ emptyActions
259
+ ) : (
260
+ <div className={classes.view}>
261
+ <MediaImageView value={image} />
262
+ <div className={classes.anchor}>
263
+ <Popover
264
+ shown={popoverLayer !== 'none'}
265
+ appendTo="window"
266
+ placement="bottom-start"
267
+ moveBy={{ x: 0, y: 4 }}
268
+ zIndex={5001}
269
+ animate
270
+ flip
271
+ fixed={false}
272
+ onClickOutside={handleClickOutside}
273
+ >
274
+ <Popover.Element>
275
+ <div className={classes.anchorBox} />
276
+ </Popover.Element>
277
+ <Popover.Content>
278
+ <Box
279
+ dataHook="media-image-edit-popover"
280
+ className={classes.popoverContent}
281
+ direction="vertical"
282
+ gap="SP3"
283
+ padding="SP3"
284
+ >
285
+ <FormField label={t('CMS.image.thumbnail.label')}>
286
+ <div className={classes.image}>
287
+ <MediaImage
288
+ dataHook="media-image-edit-image"
289
+ src={src}
290
+ alt=""
291
+ fit="cover"
292
+ transparent
293
+ size={ThumbnailSize.L}
294
+ width="180px"
295
+ height="180px"
296
+ borderRadius="0"
297
+ />
298
+ <div
299
+ className={st(classes.imageActions, {
300
+ menuOpen: popoverLayer === 'menu',
301
+ })}
302
+ >
303
+ <Tooltip
304
+ content={t('CMS.image.replace')}
305
+ appendTo="window"
306
+ >
307
+ <IconButton
308
+ size="small"
309
+ skin="light"
310
+ priority="secondary"
311
+ dataHook="media-image-edit-replace-button"
312
+ ariaLabel={t('CMS.image.replace')}
313
+ onClick={handleCallMedia}
314
+ >
315
+ <Replace />
316
+ </IconButton>
317
+ </Tooltip>
318
+ <PopoverMenu
319
+ textSize="small"
320
+ appendTo="window"
321
+ zIndex={5002}
322
+ triggerElement={({ isOpen, toggle, ref }) => (
323
+ <MenuTrigger
324
+ isOpen={isOpen}
325
+ toggle={toggle}
326
+ buttonRef={ref}
327
+ onOpenChange={handleMenuOpenChange}
328
+ ariaLabel={t(
329
+ 'auto-patterns.fields.more_actions_tooltip',
330
+ )}
331
+ />
332
+ )}
333
+ >
334
+ <PopoverMenu.MenuItem
335
+ dataHook="media-image-edit-action-replace-url"
336
+ text={t('CMS.image.replaceWithUrl.button')}
337
+ prefixIcon={<Link />}
338
+ onClick={openPasteUrl}
339
+ />
340
+ <PopoverMenu.MenuItem
341
+ dataHook="media-image-edit-action-preview"
342
+ text={t('CMS.mediaGallery.preview')}
343
+ prefixIcon={<Maximize />}
344
+ onClick={() => setPopoverLayer('preview')}
345
+ />
346
+ <PopoverMenu.MenuItem
347
+ dataHook="media-image-edit-action-download"
348
+ text={t('CMS.image.download')}
349
+ prefixIcon={<Download />}
350
+ onClick={handleDownload}
351
+ />
352
+ <PopoverMenu.Divider />
353
+ <PopoverMenu.MenuItem
354
+ dataHook="media-image-edit-action-delete"
355
+ text={t('CMS.image.clear')}
356
+ skin="destructive"
357
+ prefixIcon={<Delete />}
358
+ onClick={handleDelete}
359
+ />
360
+ </PopoverMenu>
361
+ </div>
362
+ </div>
363
+ </FormField>
364
+ <FormField label={t('CMS.image.altText.label')}>
365
+ <Input
366
+ dataHook="media-image-edit-alt-input"
367
+ size="small"
368
+ value={image.altText ?? ''}
369
+ placeholder={t('CMS.image.altText.inputPlaceholder')}
370
+ onChange={(e) =>
371
+ onChange(withAltText(image, e.target.value))
372
+ }
373
+ onEnterPressed={commit}
374
+ />
375
+ </FormField>
376
+ </Box>
377
+ </Popover.Content>
378
+ </Popover>
379
+ </div>
380
+ </div>
381
+ )}
382
+ </CellMediaEditShell>
383
+ {image && (
384
+ <MediaPreviewModal
385
+ isOpen={popoverLayer === 'preview'}
386
+ value={src}
387
+ onClose={() => setPopoverLayer('popover')}
388
+ onRequestMedia={handleCallMedia}
389
+ onClearMedia={handleDelete}
390
+ onDownloadMedia={handleDownload}
391
+ textKeys={{
392
+ replace: 'CMS.image.replace',
393
+ download: 'CMS.image.download',
394
+ delete: 'CMS.image.clear',
395
+ }}
396
+ />
397
+ )}
398
+ </>
399
+ );
400
+ };
401
+
402
+ CellMediaImageEdit.displayName = 'CellMediaImageEdit';
@@ -0,0 +1,165 @@
1
+ import type { FC } from 'react';
2
+ import React, { useCallback, useRef } from 'react';
3
+ import type { FormFieldProps } from '@wix/design-system';
4
+ import { Box, FormField, ImageViewer, Input } from '@wix/design-system';
5
+ import { useIsMobile, useWixPatternsContainer } from '@wix/bex-core/react';
6
+
7
+ import type { ControlledInputProps } from '../../types/controlled-input';
8
+ import type { MediaImageValue } from '../../types/media-image';
9
+ import { useMergedRef, useTranslations } from '../../hooks';
10
+ import { getImageSource } from '../../utils/get-image-source';
11
+ import { getImageUrl } from '../../utils/get-image-url';
12
+ import { MEDIA_HEIGHT, MEDIA_MAX_WIDTH } from '../../utils/media-constants';
13
+ import {
14
+ fromMediaManagerPick,
15
+ toMediaImageValue,
16
+ withAltText,
17
+ } from '../../utils/media-image-value';
18
+ import { MEDIA_TYPES } from '../../utils/media-utils';
19
+ import { useMediaControl } from '../media-control';
20
+
21
+ interface ImageViewerActions {
22
+ focus: () => void;
23
+ }
24
+
25
+ export interface FormMediaImageFieldProps {
26
+ /** A `MEDIA_IMAGE` value. */
27
+ data?: unknown;
28
+ onChange: (value: MediaImageValue | null) => void;
29
+ /** Fires when the media manager closes, whether or not a file was picked. */
30
+ onBlur?: () => void;
31
+ readOnly?: boolean;
32
+ autoFocus?: boolean;
33
+ dataHook?: string;
34
+ inputRef?: React.Ref<ImageViewerActions>;
35
+ /** The FormField around the image, e.g. the field's label and its error.
36
+ * ImageViewer takes its error styling from it. */
37
+ imageFormFieldProps?: Pick<
38
+ FormFieldProps,
39
+ 'label' | 'required' | 'status' | 'statusMessage'
40
+ >;
41
+ }
42
+
43
+ /**
44
+ * The entity page input of a `MEDIA_IMAGE` field: the image, and an alt text
45
+ * input to its right once there is an image. A pick fills an empty alt text
46
+ * from the file name; a replace keeps the current one.
47
+ */
48
+ export const FormMediaImageField: FC<FormMediaImageFieldProps> = ({
49
+ data,
50
+ onChange,
51
+ onBlur,
52
+ readOnly,
53
+ autoFocus,
54
+ dataHook,
55
+ inputRef: forwardedRef,
56
+ imageFormFieldProps,
57
+ }) => {
58
+ const { translate } = useWixPatternsContainer();
59
+ const { t } = useTranslations();
60
+ const isMobile = useIsMobile();
61
+ const image = toMediaImageValue(data);
62
+ // The media manager calls back after it closes, so it reads the value from
63
+ // here rather than from the render that opened it.
64
+ const imageRef = useRef(image);
65
+ imageRef.current = image;
66
+
67
+ const [inputRef, setInputRef] =
68
+ useMergedRef<ImageViewerActions>(forwardedRef);
69
+
70
+ const handlePick = useCallback(
71
+ (uri: string) => {
72
+ const next = fromMediaManagerPick(uri, imageRef.current);
73
+ if (next) {
74
+ onChange(next);
75
+ }
76
+ },
77
+ [onChange],
78
+ );
79
+
80
+ const { callMedia, onMediaLoad } = useMediaControl({
81
+ mediaType: MEDIA_TYPES.IMAGE,
82
+ value: getImageSource(image),
83
+ onChange: handlePick,
84
+ autoFocus,
85
+ readOnly,
86
+ onBlur,
87
+ inputRef,
88
+ initialLoading: true,
89
+ });
90
+
91
+ const canEdit = !isMobile && !readOnly;
92
+
93
+ const handleAltTextChange = (e: React.ChangeEvent<HTMLInputElement>) => {
94
+ if (image) {
95
+ onChange(withAltText(image, e.target.value));
96
+ }
97
+ };
98
+
99
+ return (
100
+ <Box dataHook={dataHook} gap="SP4" width="100%">
101
+ <Box width="100%" maxWidth={MEDIA_MAX_WIDTH} flexShrink={0}>
102
+ <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
+ />
121
+ </FormField>
122
+ </Box>
123
+ {image && (
124
+ <Box direction="vertical" flexGrow={1} minWidth="0">
125
+ <FormField label={t('CMS.image.altText.label')}>
126
+ <Input
127
+ dataHook="media-image-field-alt-input"
128
+ value={image.altText ?? ''}
129
+ placeholder={t('CMS.image.altText.inputPlaceholder')}
130
+ onChange={handleAltTextChange}
131
+ readOnly={readOnly}
132
+ />
133
+ </FormField>
134
+ </Box>
135
+ )}
136
+ </Box>
137
+ );
138
+ };
139
+
140
+ FormMediaImageField.displayName = 'FormMediaImageField';
141
+
142
+ export type ControlledMediaImageInputProps = Omit<
143
+ ControlledInputProps<MediaImageValue | null>,
144
+ 'invalid'
145
+ >;
146
+
147
+ export const ControlledMediaImageInput: FC<ControlledMediaImageInputProps> = ({
148
+ data,
149
+ onChange,
150
+ onBlur,
151
+ readOnly,
152
+ autoFocus,
153
+ dataHook,
154
+ }) => (
155
+ <FormMediaImageField
156
+ data={data}
157
+ onChange={onChange}
158
+ onBlur={onBlur}
159
+ readOnly={readOnly}
160
+ autoFocus={autoFocus}
161
+ dataHook={dataHook}
162
+ />
163
+ );
164
+
165
+ ControlledMediaImageInput.displayName = 'ControlledMediaImageInput';
@@ -0,0 +1,42 @@
1
+ import type { UniDriver } from '@wix/wix-ui-test-utils/unidriver';
2
+ import {
3
+ FormFieldUniDriver,
4
+ ImageViewerUniDriver,
5
+ } from '@wix/design-system/dist/testkit/unidriver';
6
+
7
+ import { baseUniDriverFactory } from '../../testkit/base-driver';
8
+
9
+ export function FormMediaImageFieldUniDriver(base: UniDriver, body: UniDriver) {
10
+ const formField = FormFieldUniDriver(
11
+ base.$('[data-hook="media-image-field-image"]'),
12
+ body,
13
+ );
14
+ const imageViewer = ImageViewerUniDriver(
15
+ base.$('[data-hook="media-image-field-viewer"]'),
16
+ body,
17
+ );
18
+ const altInput = base.$('[data-hook="media-image-field-alt-input"] input');
19
+
20
+ return {
21
+ ...baseUniDriverFactory(base),
22
+ getLabel: async () => (await formField.getLabel())?.textContent ?? '',
23
+ isRequired: () => formField.isRequired(),
24
+ hasError: () => formField.hasStatus('error'),
25
+ getErrorMessage: () => formField.getStatusMessage(),
26
+ getImageUrl: () => imageViewer.getImageUrl(),
27
+ isAddItemVisible: () => imageViewer.isAddItemVisible(),
28
+ clickAdd: () => imageViewer.clickAdd(),
29
+ clickReplace: () => imageViewer.clickUpdate(),
30
+ clickRemove: () => imageViewer.clickRemove(),
31
+ hasAltTextInput: () => altInput.exists(),
32
+ getAltText: () => altInput.value(),
33
+ getAltTextPlaceholder: () => altInput.attr('placeholder'),
34
+ 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
+ };
42
+ }
@@ -0,0 +1,56 @@
1
+ import React from 'react';
2
+ import { observer } from 'mobx-react-lite';
3
+ import { useWixPatternsContainer } from '@wix/bex-core/react';
4
+ import { useController } from '@wix/bex-core/form';
5
+
6
+ import type { BaseInputProps } from '../../types/base-input';
7
+ import type { MediaImageValue } from '../../types/media-image';
8
+ import { useFieldRef } from '../../hooks';
9
+ import { isMediaImageEmpty } from '../../utils/media-image-value';
10
+ import { FormMediaImageField } from './form-media-image-field';
11
+
12
+ export interface FormMediaImageInputProps
13
+ extends BaseInputProps<MediaImageValue | null> {}
14
+
15
+ const _FormMediaImageInput = (props: FormMediaImageInputProps) => {
16
+ const { field, dataHook, formControl, data } = props;
17
+
18
+ const { translate: t } = useWixPatternsContainer();
19
+
20
+ const controller = useController({
21
+ name: field?.id ?? '',
22
+ control: formControl,
23
+ defaultValue: data?.[field?.id ?? ''],
24
+ rules: {
25
+ validate: (value) => {
26
+ // Alt text alone doesn't make the field filled.
27
+ if (field.validation?.required && isMediaImageEmpty(value)) {
28
+ return t('cairo.fieldValidation.requiredField');
29
+ }
30
+
31
+ return true;
32
+ },
33
+ },
34
+ });
35
+
36
+ const setFieldRef = useFieldRef(controller.field.ref);
37
+
38
+ return (
39
+ <FormMediaImageField
40
+ // Hands the live button to react-hook-form so shouldFocusError can
41
+ // reach this field when it blocks save.
42
+ inputRef={setFieldRef}
43
+ data={controller.field.value}
44
+ onChange={(value) => controller.field.onChange(value)}
45
+ dataHook={dataHook}
46
+ imageFormFieldProps={{
47
+ label: field.displayName,
48
+ required: field.validation?.required,
49
+ status: controller.fieldState.error ? 'error' : undefined,
50
+ statusMessage: controller.fieldState.error?.message,
51
+ }}
52
+ />
53
+ );
54
+ };
55
+
56
+ export const FormMediaImageInput = observer(_FormMediaImageInput);
@@ -0,0 +1,4 @@
1
+ export * from './media-image-view';
2
+ export * from './cell-media-image-edit';
3
+ export * from './form-media-image-field';
4
+ export * from './form-media-image-input';
@@ -0,0 +1,16 @@
1
+ @property st-global(--wds-color-text-standard-primary);
2
+ @property st-global(--wds-color-text-placeholder);
3
+ @property st-global(--wsr-color-D40);
4
+
5
+ .root {
6
+ box-sizing: border-box;
7
+ }
8
+
9
+ /* WDS <Text> reads its colour from the primary text token, so the placeholder
10
+ colour goes through it. */
11
+ .altTextPlaceholder {
12
+ --wds-color-text-standard-primary: var(
13
+ --wds-color-text-placeholder,
14
+ var(--wsr-color-D40, #868AA5)
15
+ );
16
+ }