@wordpress/block-library 8.22.0 → 8.24.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 (266) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/build/block/edit.js +11 -13
  3. package/build/block/edit.js.map +1 -1
  4. package/build/block/edit.native.js +3 -4
  5. package/build/block/edit.native.js.map +1 -1
  6. package/build/button/edit.js +61 -9
  7. package/build/button/edit.js.map +1 -1
  8. package/build/code/transforms.js +20 -7
  9. package/build/code/transforms.js.map +1 -1
  10. package/build/column/edit.js +1 -1
  11. package/build/column/edit.js.map +1 -1
  12. package/build/column/edit.native.js +1 -1
  13. package/build/column/edit.native.js.map +1 -1
  14. package/build/comments/edit/comments-inspector-controls.js +1 -0
  15. package/build/comments/edit/comments-inspector-controls.js.map +1 -1
  16. package/build/cover/edit/index.js +2 -1
  17. package/build/cover/edit/index.js.map +1 -1
  18. package/build/cover/edit/inspector-controls.js +1 -0
  19. package/build/cover/edit/inspector-controls.js.map +1 -1
  20. package/build/details/edit.js +1 -2
  21. package/build/details/edit.js.map +1 -1
  22. package/build/file/edit.js +8 -9
  23. package/build/file/edit.js.map +1 -1
  24. package/build/file/view.js +4 -6
  25. package/build/file/view.js.map +1 -1
  26. package/build/form/index.js +1 -1
  27. package/build/form/index.js.map +1 -1
  28. package/build/form-submit-button/edit.js +2 -1
  29. package/build/form-submit-button/edit.js.map +1 -1
  30. package/build/gallery/gap-styles.js +12 -7
  31. package/build/gallery/gap-styles.js.map +1 -1
  32. package/build/group/edit.js +4 -7
  33. package/build/group/edit.js.map +1 -1
  34. package/build/html/transforms.js +7 -2
  35. package/build/html/transforms.js.map +1 -1
  36. package/build/image/deprecated.js +8 -0
  37. package/build/image/deprecated.js.map +1 -1
  38. package/build/image/edit.js +17 -18
  39. package/build/image/edit.js.map +1 -1
  40. package/build/image/edit.native.js +22 -15
  41. package/build/image/edit.native.js.map +1 -1
  42. package/build/image/image.js +35 -27
  43. package/build/image/image.js.map +1 -1
  44. package/build/image/index.js +2 -3
  45. package/build/image/index.js.map +1 -1
  46. package/build/image/view.js +234 -266
  47. package/build/image/view.js.map +1 -1
  48. package/build/missing/index.js +1 -1
  49. package/build/navigation/edit/overlay-menu-preview.js +1 -1
  50. package/build/navigation/edit/overlay-menu-preview.js.map +1 -1
  51. package/build/navigation/use-template-part-area-label.js +2 -1
  52. package/build/navigation/use-template-part-area-label.js.map +1 -1
  53. package/build/navigation/view.js +153 -176
  54. package/build/navigation/view.js.map +1 -1
  55. package/build/navigation-link/edit.js +1 -1
  56. package/build/navigation-link/edit.js.map +1 -1
  57. package/build/navigation-link/index.js +2 -1
  58. package/build/navigation-link/index.js.map +1 -1
  59. package/build/pattern/edit.js +2 -4
  60. package/build/pattern/edit.js.map +1 -1
  61. package/build/post-author/edit.js +0 -1
  62. package/build/post-author/edit.js.map +1 -1
  63. package/build/post-featured-image/edit.js +21 -6
  64. package/build/post-featured-image/edit.js.map +1 -1
  65. package/build/post-template/edit.js +2 -8
  66. package/build/post-template/edit.js.map +1 -1
  67. package/build/post-template/index.js +1 -1
  68. package/build/post-terms/edit.js +0 -2
  69. package/build/post-terms/edit.js.map +1 -1
  70. package/build/preformatted/transforms.js +1 -4
  71. package/build/preformatted/transforms.js.map +1 -1
  72. package/build/query/edit/query-content.js +1 -0
  73. package/build/query/edit/query-content.js.map +1 -1
  74. package/build/query/view.js +52 -60
  75. package/build/query/view.js.map +1 -1
  76. package/build/quote/index.js +6 -0
  77. package/build/quote/index.js.map +1 -1
  78. package/build/search/view.js +66 -74
  79. package/build/search/view.js.map +1 -1
  80. package/build/template-part/edit/advanced-controls.js +1 -0
  81. package/build/template-part/edit/advanced-controls.js.map +1 -1
  82. package/build/template-part/edit/index.js +3 -7
  83. package/build/template-part/edit/index.js.map +1 -1
  84. package/build/template-part/index.js +6 -2
  85. package/build/template-part/index.js.map +1 -1
  86. package/build/template-part/variations.js +5 -1
  87. package/build/template-part/variations.js.map +1 -1
  88. package/build/utils/remove-anchor-tag.js +17 -0
  89. package/build/utils/remove-anchor-tag.js.map +1 -0
  90. package/build-module/block/edit.js +11 -13
  91. package/build-module/block/edit.js.map +1 -1
  92. package/build-module/block/edit.native.js +3 -4
  93. package/build-module/block/edit.native.js.map +1 -1
  94. package/build-module/button/edit.js +65 -13
  95. package/build-module/button/edit.js.map +1 -1
  96. package/build-module/code/transforms.js +20 -7
  97. package/build-module/code/transforms.js.map +1 -1
  98. package/build-module/column/edit.js +1 -1
  99. package/build-module/column/edit.js.map +1 -1
  100. package/build-module/column/edit.native.js +1 -1
  101. package/build-module/column/edit.native.js.map +1 -1
  102. package/build-module/comments/edit/comments-inspector-controls.js +1 -0
  103. package/build-module/comments/edit/comments-inspector-controls.js.map +1 -1
  104. package/build-module/cover/edit/index.js +2 -1
  105. package/build-module/cover/edit/index.js.map +1 -1
  106. package/build-module/cover/edit/inspector-controls.js +1 -0
  107. package/build-module/cover/edit/inspector-controls.js.map +1 -1
  108. package/build-module/details/edit.js +1 -2
  109. package/build-module/details/edit.js.map +1 -1
  110. package/build-module/file/edit.js +8 -9
  111. package/build-module/file/edit.js.map +1 -1
  112. package/build-module/file/view.js +5 -7
  113. package/build-module/file/view.js.map +1 -1
  114. package/build-module/form/index.js +1 -1
  115. package/build-module/form/index.js.map +1 -1
  116. package/build-module/form-submit-button/edit.js +2 -1
  117. package/build-module/form-submit-button/edit.js.map +1 -1
  118. package/build-module/gallery/gap-styles.js +13 -8
  119. package/build-module/gallery/gap-styles.js.map +1 -1
  120. package/build-module/group/edit.js +4 -7
  121. package/build-module/group/edit.js.map +1 -1
  122. package/build-module/html/transforms.js +7 -2
  123. package/build-module/html/transforms.js.map +1 -1
  124. package/build-module/image/deprecated.js +8 -0
  125. package/build-module/image/deprecated.js.map +1 -1
  126. package/build-module/image/edit.js +18 -19
  127. package/build-module/image/edit.js.map +1 -1
  128. package/build-module/image/edit.native.js +23 -16
  129. package/build-module/image/edit.native.js.map +1 -1
  130. package/build-module/image/image.js +36 -28
  131. package/build-module/image/image.js.map +1 -1
  132. package/build-module/image/index.js +2 -3
  133. package/build-module/image/index.js.map +1 -1
  134. package/build-module/image/view.js +235 -267
  135. package/build-module/image/view.js.map +1 -1
  136. package/build-module/missing/index.js +1 -1
  137. package/build-module/navigation/edit/overlay-menu-preview.js +1 -1
  138. package/build-module/navigation/edit/overlay-menu-preview.js.map +1 -1
  139. package/build-module/navigation/use-template-part-area-label.js +2 -1
  140. package/build-module/navigation/use-template-part-area-label.js.map +1 -1
  141. package/build-module/navigation/view.js +154 -177
  142. package/build-module/navigation/view.js.map +1 -1
  143. package/build-module/navigation-link/edit.js +2 -2
  144. package/build-module/navigation-link/edit.js.map +1 -1
  145. package/build-module/navigation-link/index.js +2 -1
  146. package/build-module/navigation-link/index.js.map +1 -1
  147. package/build-module/pattern/edit.js +2 -4
  148. package/build-module/pattern/edit.js.map +1 -1
  149. package/build-module/post-author/edit.js +0 -1
  150. package/build-module/post-author/edit.js.map +1 -1
  151. package/build-module/post-featured-image/edit.js +21 -6
  152. package/build-module/post-featured-image/edit.js.map +1 -1
  153. package/build-module/post-template/edit.js +2 -8
  154. package/build-module/post-template/edit.js.map +1 -1
  155. package/build-module/post-template/index.js +1 -1
  156. package/build-module/post-terms/edit.js +0 -2
  157. package/build-module/post-terms/edit.js.map +1 -1
  158. package/build-module/preformatted/transforms.js +1 -4
  159. package/build-module/preformatted/transforms.js.map +1 -1
  160. package/build-module/query/edit/query-content.js +1 -0
  161. package/build-module/query/edit/query-content.js.map +1 -1
  162. package/build-module/query/view.js +53 -61
  163. package/build-module/query/view.js.map +1 -1
  164. package/build-module/quote/index.js +6 -0
  165. package/build-module/quote/index.js.map +1 -1
  166. package/build-module/search/view.js +67 -75
  167. package/build-module/search/view.js.map +1 -1
  168. package/build-module/template-part/edit/advanced-controls.js +1 -0
  169. package/build-module/template-part/edit/advanced-controls.js.map +1 -1
  170. package/build-module/template-part/edit/index.js +5 -9
  171. package/build-module/template-part/edit/index.js.map +1 -1
  172. package/build-module/template-part/index.js +6 -2
  173. package/build-module/template-part/index.js.map +1 -1
  174. package/build-module/template-part/variations.js +5 -1
  175. package/build-module/template-part/variations.js.map +1 -1
  176. package/build-module/utils/remove-anchor-tag.js +11 -0
  177. package/build-module/utils/remove-anchor-tag.js.map +1 -0
  178. package/build-style/cover/style-rtl.css +14 -14
  179. package/build-style/cover/style.css +14 -14
  180. package/build-style/editor-rtl.css +15 -6
  181. package/build-style/editor.css +15 -6
  182. package/build-style/gallery/style-rtl.css +28 -0
  183. package/build-style/gallery/style.css +28 -0
  184. package/build-style/image/style-rtl.css +19 -13
  185. package/build-style/image/style.css +19 -13
  186. package/build-style/post-featured-image/editor-rtl.css +9 -0
  187. package/build-style/post-featured-image/editor.css +9 -0
  188. package/build-style/quote/style-rtl.css +3 -0
  189. package/build-style/quote/style.css +3 -0
  190. package/build-style/read-more/style-rtl.css +2 -2
  191. package/build-style/read-more/style.css +2 -2
  192. package/build-style/style-rtl.css +66 -29
  193. package/build-style/style.css +66 -29
  194. package/package.json +32 -32
  195. package/src/block/edit.js +20 -20
  196. package/src/block/edit.native.js +5 -13
  197. package/src/button/edit.js +76 -10
  198. package/src/buttons/test/__snapshots__/edit.native.js.snap +0 -6
  199. package/src/buttons/test/edit.native.js +0 -27
  200. package/src/code/transforms.js +14 -8
  201. package/src/column/edit.js +1 -1
  202. package/src/column/edit.native.js +1 -1
  203. package/src/comments/edit/comments-inspector-controls.js +1 -0
  204. package/src/cover/edit/index.js +1 -0
  205. package/src/cover/edit/inspector-controls.js +1 -0
  206. package/src/cover/style.scss +1 -1
  207. package/src/cover/test/edit.js +1 -1
  208. package/src/details/edit.js +0 -1
  209. package/src/editor.scss +6 -6
  210. package/src/file/edit.js +11 -10
  211. package/src/file/index.php +30 -11
  212. package/src/file/view.js +5 -7
  213. package/src/form/index.js +1 -1
  214. package/src/form-submit-button/edit.js +1 -0
  215. package/src/gallery/gap-styles.js +10 -9
  216. package/src/gallery/style.scss +1 -0
  217. package/src/group/edit.js +4 -11
  218. package/src/heading/test/__snapshots__/index.native.js.snap +6 -0
  219. package/src/heading/test/index.native.js +40 -0
  220. package/src/html/transforms.js +5 -2
  221. package/src/image/block.json +2 -3
  222. package/src/image/deprecated.js +8 -0
  223. package/src/image/edit.js +16 -21
  224. package/src/image/edit.native.js +17 -18
  225. package/src/image/image.js +48 -51
  226. package/src/image/index.php +57 -49
  227. package/src/image/style.scss +18 -13
  228. package/src/image/view.js +281 -324
  229. package/src/missing/block.json +1 -1
  230. package/src/navigation/edit/overlay-menu-preview.js +1 -1
  231. package/src/navigation/index.php +46 -402
  232. package/src/navigation/use-template-part-area-label.js +4 -2
  233. package/src/navigation/view.js +159 -192
  234. package/src/navigation-link/block.json +2 -1
  235. package/src/navigation-link/edit.js +2 -2
  236. package/src/navigation-link/index.php +57 -0
  237. package/src/paragraph/test/__snapshots__/transforms.native.js.snap +6 -0
  238. package/src/paragraph/test/edit.native.js +37 -1
  239. package/src/paragraph/test/transforms.native.js +1 -0
  240. package/src/pattern/edit.js +7 -4
  241. package/src/pattern/index.php +6 -1
  242. package/src/post-author/edit.js +0 -1
  243. package/src/post-featured-image/edit.js +38 -5
  244. package/src/post-featured-image/editor.scss +19 -0
  245. package/src/post-template/block.json +0 -1
  246. package/src/post-template/edit.js +1 -5
  247. package/src/post-terms/edit.js +0 -2
  248. package/src/preformatted/transforms.js +1 -4
  249. package/src/query/edit/query-content.js +1 -0
  250. package/src/query/index.php +42 -24
  251. package/src/query/view.js +58 -65
  252. package/src/query-pagination-next/index.php +3 -3
  253. package/src/query-pagination-numbers/index.php +1 -1
  254. package/src/query-pagination-previous/index.php +3 -3
  255. package/src/quote/block.json +6 -0
  256. package/src/quote/style.scss +4 -0
  257. package/src/read-more/style.scss +1 -1
  258. package/src/search/index.php +40 -40
  259. package/src/search/view.js +58 -63
  260. package/src/template-part/edit/advanced-controls.js +1 -0
  261. package/src/template-part/edit/index.js +7 -14
  262. package/src/template-part/index.js +4 -3
  263. package/src/template-part/index.php +4 -4
  264. package/src/template-part/variations.js +4 -2
  265. package/src/utils/remove-anchor-tag.js +10 -0
  266. package/tsconfig.json +1 -0
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { store } from '@wordpress/interactivity';
4
+ import { store, getContext, getElement } from '@wordpress/interactivity';
5
5
  const focusableSelectors = ['a[href]', 'area[href]', 'input:not([disabled]):not([type="hidden"]):not([aria-hidden])', 'select:not([disabled]):not([aria-hidden])', 'textarea:not([disabled]):not([aria-hidden])', 'button:not([disabled]):not([aria-hidden])', 'iframe', 'object', 'embed', '[contenteditable]', '[tabindex]:not([tabindex^="-"])'];
6
6
 
7
- /*
7
+ /**
8
8
  * Stores a context-bound scroll handler.
9
9
  *
10
10
  * This callback could be defined inline inside of the store
@@ -19,7 +19,7 @@ const focusableSelectors = ['a[href]', 'area[href]', 'input:not([disabled]):not(
19
19
  */
20
20
  let scrollCallback;
21
21
 
22
- /*
22
+ /**
23
23
  * Tracks whether user is touching screen; used to
24
24
  * differentiate behavior for touch and mouse input.
25
25
  *
@@ -27,7 +27,7 @@ let scrollCallback;
27
27
  */
28
28
  let isTouching = false;
29
29
 
30
- /*
30
+ /**
31
31
  * Tracks the last time the screen was touched; used to
32
32
  * differentiate behavior for touch and mouse input.
33
33
  *
@@ -35,7 +35,7 @@ let isTouching = false;
35
35
  */
36
36
  let lastTouchTime = 0;
37
37
 
38
- /*
38
+ /**
39
39
  * Lightbox page-scroll handler: prevents scrolling.
40
40
  *
41
41
  * This handler is added to prevent scrolling behaviors that
@@ -51,302 +51,269 @@ let lastTouchTime = 0;
51
51
  * instead to not rely on JavaScript, but this seems to be the best approach
52
52
  * for now that provides the best visual experience.
53
53
  *
54
- * @param {Object} context Interactivity page context?
54
+ * @param {Object} ctx Context object with the `core/image` namespace.
55
55
  */
56
- function handleScroll(context) {
56
+ function handleScroll(ctx) {
57
57
  // We can't override the scroll behavior on mobile devices
58
58
  // because doing so breaks the pinch to zoom functionality, and we
59
59
  // want to allow users to zoom in further on the high-res image.
60
60
  if (!isTouching && Date.now() - lastTouchTime > 450) {
61
61
  // We are unable to use event.preventDefault() to prevent scrolling
62
62
  // because the scroll event can't be canceled, so we reset the position instead.
63
- window.scrollTo(context.core.image.scrollLeftReset, context.core.image.scrollTopReset);
63
+ window.scrollTo(ctx.scrollLeftReset, ctx.scrollTopReset);
64
64
  }
65
65
  }
66
- store({
66
+ const {
67
+ state,
68
+ actions,
69
+ callbacks
70
+ } = store('core/image', {
67
71
  state: {
68
- core: {
69
- image: {
70
- windowWidth: window.innerWidth,
71
- windowHeight: window.innerHeight
72
+ windowWidth: window.innerWidth,
73
+ windowHeight: window.innerHeight,
74
+ get roleAttribute() {
75
+ const ctx = getContext();
76
+ return ctx.lightboxEnabled ? 'dialog' : null;
77
+ },
78
+ get ariaModal() {
79
+ const ctx = getContext();
80
+ return ctx.lightboxEnabled ? 'true' : null;
81
+ },
82
+ get dialogLabel() {
83
+ const ctx = getContext();
84
+ return ctx.lightboxEnabled ? ctx.dialogLabel : null;
85
+ },
86
+ get lightboxObjectFit() {
87
+ const ctx = getContext();
88
+ if (ctx.initialized) {
89
+ return 'cover';
72
90
  }
91
+ },
92
+ get enlargedImgSrc() {
93
+ const ctx = getContext();
94
+ return ctx.initialized ? ctx.imageUploadedSrc : 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=';
73
95
  }
74
96
  },
75
97
  actions: {
76
- core: {
77
- image: {
78
- showLightbox: ({
79
- context,
80
- event
81
- }) => {
82
- // We can't initialize the lightbox until the reference
83
- // image is loaded, otherwise the UX is broken.
84
- if (!context.core.image.imageLoaded) {
85
- return;
86
- }
87
- context.core.image.initialized = true;
88
- context.core.image.lastFocusedElement = window.document.activeElement;
89
- context.core.image.scrollDelta = 0;
90
- context.core.image.pointerType = event.pointerType;
91
- context.core.image.lightboxEnabled = true;
92
- setStyles(context, context.core.image.imageRef);
93
- context.core.image.scrollTopReset = window.pageYOffset || document.documentElement.scrollTop;
98
+ showLightbox(event) {
99
+ const ctx = getContext();
100
+ // We can't initialize the lightbox until the reference
101
+ // image is loaded, otherwise the UX is broken.
102
+ if (!ctx.imageLoaded) {
103
+ return;
104
+ }
105
+ ctx.initialized = true;
106
+ ctx.lastFocusedElement = window.document.activeElement;
107
+ ctx.scrollDelta = 0;
108
+ ctx.pointerType = event.pointerType;
109
+ ctx.lightboxEnabled = true;
110
+ setStyles(ctx, ctx.imageRef);
111
+ ctx.scrollTopReset = window.pageYOffset || document.documentElement.scrollTop;
94
112
 
95
- // In most cases, this value will be 0, but this is included
96
- // in case a user has created a page with horizontal scrolling.
97
- context.core.image.scrollLeftReset = window.pageXOffset || document.documentElement.scrollLeft;
113
+ // In most cases, this value will be 0, but this is included
114
+ // in case a user has created a page with horizontal scrolling.
115
+ ctx.scrollLeftReset = window.pageXOffset || document.documentElement.scrollLeft;
98
116
 
99
- // We define and bind the scroll callback here so
100
- // that we can pass the context and as an argument.
101
- // We may be able to change this in the future if we
102
- // define the scroll callback in the store instead, but
103
- // this approach seems to tbe clearest for now.
104
- scrollCallback = handleScroll.bind(null, context);
117
+ // We define and bind the scroll callback here so
118
+ // that we can pass the context and as an argument.
119
+ // We may be able to change this in the future if we
120
+ // define the scroll callback in the store instead, but
121
+ // this approach seems to tbe clearest for now.
122
+ scrollCallback = handleScroll.bind(null, ctx);
105
123
 
106
- // We need to add a scroll event listener to the window
107
- // here because we are unable to otherwise access it via
108
- // the Interactivity API directives. If we add a native way
109
- // to access the window, we can remove this.
110
- window.addEventListener('scroll', scrollCallback, false);
111
- },
112
- hideLightbox: async ({
113
- context
114
- }) => {
115
- context.core.image.hideAnimationEnabled = true;
116
- if (context.core.image.lightboxEnabled) {
117
- // We want to wait until the close animation is completed
118
- // before allowing a user to scroll again. The duration of this
119
- // animation is defined in the styles.scss and depends on if the
120
- // animation is 'zoom' or 'fade', but in any case we should wait
121
- // a few milliseconds longer than the duration, otherwise a user
122
- // may scroll too soon and cause the animation to look sloppy.
123
- setTimeout(function () {
124
- window.removeEventListener('scroll', scrollCallback);
125
- // If we don't delay before changing the focus,
126
- // the focus ring will appear on Firefox before
127
- // the image has finished animating, which looks broken.
128
- context.core.image.lightboxTriggerRef.focus({
129
- preventScroll: true
130
- });
131
- }, 450);
132
- context.core.image.lightboxEnabled = false;
133
- }
134
- },
135
- handleKeydown: ({
136
- context,
137
- actions,
138
- event
139
- }) => {
140
- if (context.core.image.lightboxEnabled) {
141
- if (event.key === 'Tab' || event.keyCode === 9) {
142
- // If shift + tab it change the direction
143
- if (event.shiftKey && window.document.activeElement === context.core.image.firstFocusableElement) {
144
- event.preventDefault();
145
- context.core.image.lastFocusableElement.focus();
146
- } else if (!event.shiftKey && window.document.activeElement === context.core.image.lastFocusableElement) {
147
- event.preventDefault();
148
- context.core.image.firstFocusableElement.focus();
149
- }
150
- }
151
- if (event.key === 'Escape' || event.keyCode === 27) {
152
- actions.core.image.hideLightbox({
153
- context,
154
- event
155
- });
156
- }
157
- }
158
- },
159
- // This is fired just by lazily loaded
160
- // images on the page, not all images.
161
- handleLoad: ({
162
- context,
163
- effects,
164
- ref
165
- }) => {
166
- context.core.image.imageLoaded = true;
167
- context.core.image.imageCurrentSrc = ref.currentSrc;
168
- effects.core.image.setButtonStyles({
169
- context,
170
- ref
124
+ // We need to add a scroll event listener to the window
125
+ // here because we are unable to otherwise access it via
126
+ // the Interactivity API directives. If we add a native way
127
+ // to access the window, we can remove this.
128
+ window.addEventListener('scroll', scrollCallback, false);
129
+ },
130
+ hideLightbox() {
131
+ const ctx = getContext();
132
+ ctx.hideAnimationEnabled = true;
133
+ if (ctx.lightboxEnabled) {
134
+ // We want to wait until the close animation is completed
135
+ // before allowing a user to scroll again. The duration of this
136
+ // animation is defined in the styles.scss and depends on if the
137
+ // animation is 'zoom' or 'fade', but in any case we should wait
138
+ // a few milliseconds longer than the duration, otherwise a user
139
+ // may scroll too soon and cause the animation to look sloppy.
140
+ setTimeout(function () {
141
+ window.removeEventListener('scroll', scrollCallback);
142
+ // If we don't delay before changing the focus,
143
+ // the focus ring will appear on Firefox before
144
+ // the image has finished animating, which looks broken.
145
+ ctx.lightboxTriggerRef.focus({
146
+ preventScroll: true
171
147
  });
172
- },
173
- handleTouchStart: () => {
174
- isTouching = true;
175
- },
176
- handleTouchMove: ({
177
- context,
178
- event
179
- }) => {
180
- // On mobile devices, we want to prevent triggering the
181
- // scroll event because otherwise the page jumps around as
182
- // we reset the scroll position. This also means that closing
183
- // the lightbox requires that a user perform a simple tap. This
184
- // may be changed in the future if we find a better alternative
185
- // to override or reset the scroll position during swipe actions.
186
- if (context.core.image.lightboxEnabled) {
148
+ }, 450);
149
+ ctx.lightboxEnabled = false;
150
+ }
151
+ },
152
+ handleKeydown(event) {
153
+ const ctx = getContext();
154
+ if (ctx.lightboxEnabled) {
155
+ if (event.key === 'Tab' || event.keyCode === 9) {
156
+ // If shift + tab it change the direction
157
+ if (event.shiftKey && window.document.activeElement === ctx.firstFocusableElement) {
158
+ event.preventDefault();
159
+ ctx.lastFocusableElement.focus();
160
+ } else if (!event.shiftKey && window.document.activeElement === ctx.lastFocusableElement) {
187
161
  event.preventDefault();
162
+ ctx.firstFocusableElement.focus();
188
163
  }
189
- },
190
- handleTouchEnd: () => {
191
- // We need to wait a few milliseconds before resetting
192
- // to ensure that pinch to zoom works consistently
193
- // on mobile devices when the lightbox is open.
194
- lastTouchTime = Date.now();
195
- isTouching = false;
196
164
  }
197
- }
198
- }
199
- },
200
- selectors: {
201
- core: {
202
- image: {
203
- roleAttribute: ({
204
- context
205
- }) => {
206
- return context.core.image.lightboxEnabled ? 'dialog' : null;
207
- },
208
- ariaModal: ({
209
- context
210
- }) => {
211
- return context.core.image.lightboxEnabled ? 'true' : null;
212
- },
213
- dialogLabel: ({
214
- context
215
- }) => {
216
- return context.core.image.lightboxEnabled ? context.core.image.dialogLabel : null;
217
- },
218
- lightboxObjectFit: ({
219
- context
220
- }) => {
221
- if (context.core.image.initialized) {
222
- return 'cover';
223
- }
224
- },
225
- enlargedImgSrc: ({
226
- context
227
- }) => {
228
- return context.core.image.initialized ? context.core.image.imageUploadedSrc : 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=';
165
+ if (event.key === 'Escape' || event.keyCode === 27) {
166
+ actions.hideLightbox(event);
229
167
  }
230
168
  }
169
+ },
170
+ // This is fired just by lazily loaded
171
+ // images on the page, not all images.
172
+ handleLoad() {
173
+ const ctx = getContext();
174
+ const {
175
+ ref
176
+ } = getElement();
177
+ ctx.imageLoaded = true;
178
+ ctx.imageCurrentSrc = ref.currentSrc;
179
+ callbacks.setButtonStyles();
180
+ },
181
+ handleTouchStart() {
182
+ isTouching = true;
183
+ },
184
+ handleTouchMove(event) {
185
+ const ctx = getContext();
186
+ // On mobile devices, we want to prevent triggering the
187
+ // scroll event because otherwise the page jumps around as
188
+ // we reset the scroll position. This also means that closing
189
+ // the lightbox requires that a user perform a simple tap. This
190
+ // may be changed in the future if we find a better alternative
191
+ // to override or reset the scroll position during swipe actions.
192
+ if (ctx.lightboxEnabled) {
193
+ event.preventDefault();
194
+ }
195
+ },
196
+ handleTouchEnd() {
197
+ // We need to wait a few milliseconds before resetting
198
+ // to ensure that pinch to zoom works consistently
199
+ // on mobile devices when the lightbox is open.
200
+ lastTouchTime = Date.now();
201
+ isTouching = false;
231
202
  }
232
203
  },
233
- effects: {
234
- core: {
235
- image: {
236
- initOriginImage: ({
237
- context,
238
- ref
239
- }) => {
240
- context.core.image.imageRef = ref;
241
- context.core.image.lightboxTriggerRef = ref.parentElement.querySelector('.lightbox-trigger');
242
- if (ref.complete) {
243
- context.core.image.imageLoaded = true;
244
- context.core.image.imageCurrentSrc = ref.currentSrc;
245
- }
246
- },
247
- initLightbox: async ({
248
- context,
249
- ref
250
- }) => {
251
- if (context.core.image.lightboxEnabled) {
252
- const focusableElements = ref.querySelectorAll(focusableSelectors);
253
- context.core.image.firstFocusableElement = focusableElements[0];
254
- context.core.image.lastFocusableElement = focusableElements[focusableElements.length - 1];
204
+ callbacks: {
205
+ initOriginImage() {
206
+ const ctx = getContext();
207
+ const {
208
+ ref
209
+ } = getElement();
210
+ ctx.imageRef = ref;
211
+ ctx.lightboxTriggerRef = ref.parentElement.querySelector('.lightbox-trigger');
212
+ if (ref.complete) {
213
+ ctx.imageLoaded = true;
214
+ ctx.imageCurrentSrc = ref.currentSrc;
215
+ }
216
+ },
217
+ initLightbox() {
218
+ const ctx = getContext();
219
+ const {
220
+ ref
221
+ } = getElement();
222
+ if (ctx.lightboxEnabled) {
223
+ const focusableElements = ref.querySelectorAll(focusableSelectors);
224
+ ctx.firstFocusableElement = focusableElements[0];
225
+ ctx.lastFocusableElement = focusableElements[focusableElements.length - 1];
255
226
 
256
- // Move focus to the dialog when opening it.
257
- ref.focus();
258
- }
259
- },
260
- setButtonStyles: ({
261
- context,
262
- ref
263
- }) => {
264
- const {
265
- naturalWidth,
266
- naturalHeight,
267
- offsetWidth,
268
- offsetHeight
269
- } = ref;
227
+ // Move focus to the dialog when opening it.
228
+ ref.focus();
229
+ }
230
+ },
231
+ setButtonStyles() {
232
+ const {
233
+ ref
234
+ } = getElement();
235
+ const {
236
+ naturalWidth,
237
+ naturalHeight,
238
+ offsetWidth,
239
+ offsetHeight
240
+ } = ref;
270
241
 
271
- // If the image isn't loaded yet, we can't
272
- // calculate where the button should be.
273
- if (naturalWidth === 0 || naturalHeight === 0) {
274
- return;
275
- }
276
- const figure = ref.parentElement;
277
- const figureWidth = ref.parentElement.clientWidth;
242
+ // If the image isn't loaded yet, we can't
243
+ // calculate where the button should be.
244
+ if (naturalWidth === 0 || naturalHeight === 0) {
245
+ return;
246
+ }
247
+ const figure = ref.parentElement;
248
+ const figureWidth = ref.parentElement.clientWidth;
278
249
 
279
- // We need special handling for the height because
280
- // a caption will cause the figure to be taller than
281
- // the image, which means we need to account for that
282
- // when calculating the placement of the button in the
283
- // top right corner of the image.
284
- let figureHeight = ref.parentElement.clientHeight;
285
- const caption = figure.querySelector('figcaption');
286
- if (caption) {
287
- const captionComputedStyle = window.getComputedStyle(caption);
288
- figureHeight = figureHeight - caption.offsetHeight - parseFloat(captionComputedStyle.marginTop) - parseFloat(captionComputedStyle.marginBottom);
289
- }
290
- const buttonOffsetTop = figureHeight - offsetHeight;
291
- const buttonOffsetRight = figureWidth - offsetWidth;
250
+ // We need special handling for the height because
251
+ // a caption will cause the figure to be taller than
252
+ // the image, which means we need to account for that
253
+ // when calculating the placement of the button in the
254
+ // top right corner of the image.
255
+ let figureHeight = ref.parentElement.clientHeight;
256
+ const caption = figure.querySelector('figcaption');
257
+ if (caption) {
258
+ const captionComputedStyle = window.getComputedStyle(caption);
259
+ if (!['absolute', 'fixed'].includes(captionComputedStyle.position)) {
260
+ figureHeight = figureHeight - caption.offsetHeight - parseFloat(captionComputedStyle.marginTop) - parseFloat(captionComputedStyle.marginBottom);
261
+ }
262
+ }
263
+ const buttonOffsetTop = figureHeight - offsetHeight;
264
+ const buttonOffsetRight = figureWidth - offsetWidth;
265
+ const ctx = getContext();
292
266
 
293
- // In the case of an image with object-fit: contain, the
294
- // size of the <img> element can be larger than the image itself,
295
- // so we need to calculate where to place the button.
296
- if (context.core.image.scaleAttr === 'contain') {
297
- // Natural ratio of the image.
298
- const naturalRatio = naturalWidth / naturalHeight;
299
- // Offset ratio of the image.
300
- const offsetRatio = offsetWidth / offsetHeight;
301
- if (naturalRatio >= offsetRatio) {
302
- // If it reaches the width first, keep
303
- // the width and compute the height.
304
- const referenceHeight = offsetWidth / naturalRatio;
305
- context.core.image.imageButtonTop = (offsetHeight - referenceHeight) / 2 + buttonOffsetTop + 10;
306
- context.core.image.imageButtonRight = buttonOffsetRight + 10;
307
- } else {
308
- // If it reaches the height first, keep
309
- // the height and compute the width.
310
- const referenceWidth = offsetHeight * naturalRatio;
311
- context.core.image.imageButtonTop = buttonOffsetTop + 10;
312
- context.core.image.imageButtonRight = (offsetWidth - referenceWidth) / 2 + buttonOffsetRight + 10;
313
- }
314
- } else {
315
- context.core.image.imageButtonTop = buttonOffsetTop + 10;
316
- context.core.image.imageButtonRight = buttonOffsetRight + 10;
317
- }
318
- },
319
- setStylesOnResize: ({
320
- state,
321
- context,
322
- ref
323
- }) => {
324
- if (context.core.image.lightboxEnabled && (state.core.image.windowWidth || state.core.image.windowHeight)) {
325
- setStyles(context, ref);
326
- }
267
+ // In the case of an image with object-fit: contain, the
268
+ // size of the <img> element can be larger than the image itself,
269
+ // so we need to calculate where to place the button.
270
+ if (ctx.scaleAttr === 'contain') {
271
+ // Natural ratio of the image.
272
+ const naturalRatio = naturalWidth / naturalHeight;
273
+ // Offset ratio of the image.
274
+ const offsetRatio = offsetWidth / offsetHeight;
275
+ if (naturalRatio >= offsetRatio) {
276
+ // If it reaches the width first, keep
277
+ // the width and compute the height.
278
+ const referenceHeight = offsetWidth / naturalRatio;
279
+ ctx.imageButtonTop = (offsetHeight - referenceHeight) / 2 + buttonOffsetTop + 16;
280
+ ctx.imageButtonRight = buttonOffsetRight + 16;
281
+ } else {
282
+ // If it reaches the height first, keep
283
+ // the height and compute the width.
284
+ const referenceWidth = offsetHeight * naturalRatio;
285
+ ctx.imageButtonTop = buttonOffsetTop + 16;
286
+ ctx.imageButtonRight = (offsetWidth - referenceWidth) / 2 + buttonOffsetRight + 16;
327
287
  }
288
+ } else {
289
+ ctx.imageButtonTop = buttonOffsetTop + 16;
290
+ ctx.imageButtonRight = buttonOffsetRight + 16;
291
+ }
292
+ },
293
+ setStylesOnResize() {
294
+ const ctx = getContext();
295
+ const {
296
+ ref
297
+ } = getElement();
298
+ if (ctx.lightboxEnabled && (state.windowWidth || state.windowHeight)) {
299
+ setStyles(ctx, ref);
328
300
  }
329
301
  }
330
302
  }
331
- }, {
332
- afterLoad: ({
333
- state
334
- }) => {
335
- window.addEventListener('resize', debounce(() => {
336
- state.core.image.windowWidth = window.innerWidth;
337
- state.core.image.windowHeight = window.innerHeight;
338
- }));
339
- }
340
303
  });
304
+ window.addEventListener('resize', debounce(() => {
305
+ state.windowWidth = window.innerWidth;
306
+ state.windowHeight = window.innerHeight;
307
+ }));
341
308
 
342
- /*
309
+ /**
343
310
  * Computes styles for the lightbox and adds them to the document.
344
311
  *
345
312
  * @function
346
- * @param {Object} context - An Interactivity API context
347
- * @param {Object} event - A triggering event
313
+ * @param {Object} ctx - Context for the `core/image` namespace.
314
+ * @param {Object} ref - The element reference.
348
315
  */
349
- function setStyles(context, ref) {
316
+ function setStyles(ctx, ref) {
350
317
  // The reference img element lies adjacent
351
318
  // to the event target button in the DOM.
352
319
  let {
@@ -367,7 +334,7 @@ function setStyles(context, ref) {
367
334
 
368
335
  // If it has object-fit: contain, recalculate the original sizes
369
336
  // and the screen position without the blank spaces.
370
- if (context.core.image.scaleAttr === 'contain') {
337
+ if (ctx.scaleAttr === 'contain') {
371
338
  if (naturalRatio > originalRatio) {
372
339
  const heightWithoutSpace = originalWidth / naturalRatio;
373
340
  // Recalculate screen position without the top space.
@@ -386,8 +353,8 @@ function setStyles(context, ref) {
386
353
  // dimensions have not been set (i.e. an external image with only one size),
387
354
  // the image's dimensions in the lightbox are the same
388
355
  // as those of the image in the content.
389
- let imgMaxWidth = parseFloat(context.core.image.targetWidth !== 'none' ? context.core.image.targetWidth : naturalWidth);
390
- let imgMaxHeight = parseFloat(context.core.image.targetHeight !== 'none' ? context.core.image.targetHeight : naturalHeight);
356
+ let imgMaxWidth = parseFloat(ctx.targetWidth !== 'none' ? ctx.targetWidth : naturalWidth);
357
+ let imgMaxHeight = parseFloat(ctx.targetHeight !== 'none' ? ctx.targetHeight : naturalHeight);
391
358
 
392
359
  // Ratio of the biggest image stored in the database.
393
360
  let imgRatio = imgMaxWidth / imgMaxHeight;
@@ -493,16 +460,17 @@ function setStyles(context, ref) {
493
460
  --wp--lightbox-image-width: ${lightboxImgWidth}px;
494
461
  --wp--lightbox-image-height: ${lightboxImgHeight}px;
495
462
  --wp--lightbox-scale: ${containerScale};
463
+ --wp--lightbox-scrollbar-width: ${window.innerWidth - document.documentElement.clientWidth}px;
496
464
  }
497
465
  `;
498
466
  }
499
467
 
500
- /*
468
+ /**
501
469
  * Debounces a function call.
502
470
  *
503
471
  * @function
504
472
  * @param {Function} func - A function to be called
505
- * @param {number} wait - The time to wait before calling the function
473
+ * @param {number} wait - The time to wait before calling the function
506
474
  */
507
475
  function debounce(func, wait = 50) {
508
476
  let timeout;