@allxsmith/bestax-bulma 5.64.0 → 5.65.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 (41) hide show
  1. package/dist/bestax.css +1 -1
  2. package/dist/bestax.css.map +1 -1
  3. package/dist/esm/components/Carousel.js +12 -66
  4. package/dist/esm/components/Carousel.js.map +1 -1
  5. package/dist/esm/components/Lightbox.js +756 -0
  6. package/dist/esm/components/Lightbox.js.map +1 -0
  7. package/dist/esm/components/Reveal.js +1 -24
  8. package/dist/esm/components/Reveal.js.map +1 -1
  9. package/dist/esm/helpers/chevronIcons.js +24 -0
  10. package/dist/esm/helpers/chevronIcons.js.map +1 -0
  11. package/dist/esm/helpers/usePrefersReducedMotion.js +34 -0
  12. package/dist/esm/helpers/usePrefersReducedMotion.js.map +1 -0
  13. package/dist/esm/helpers/useSwipe.js +82 -0
  14. package/dist/esm/helpers/useSwipe.js.map +1 -0
  15. package/dist/extras.css +1 -1
  16. package/dist/extras.css.map +1 -1
  17. package/dist/index.cjs +924 -149
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.esm.js +1 -0
  20. package/dist/index.esm.js.map +1 -1
  21. package/dist/types/components/Lightbox.d.ts +244 -0
  22. package/dist/types/helpers/chevronIcons.d.ts +14 -0
  23. package/dist/types/helpers/usePrefersReducedMotion.d.ts +10 -0
  24. package/dist/types/helpers/useSwipe.d.ts +66 -0
  25. package/dist/types/index.d.ts +1 -0
  26. package/dist/types-cjs/components/Lightbox.d.ts +244 -0
  27. package/dist/types-cjs/helpers/chevronIcons.d.ts +14 -0
  28. package/dist/types-cjs/helpers/usePrefersReducedMotion.d.ts +10 -0
  29. package/dist/types-cjs/helpers/useSwipe.d.ts +66 -0
  30. package/dist/types-cjs/index.d.ts +1 -0
  31. package/dist/versions/bestax-no-dark-mode.css +1 -1
  32. package/dist/versions/bestax-no-dark-mode.css.map +1 -1
  33. package/dist/versions/bestax-no-helpers-prefixed.css +1 -1
  34. package/dist/versions/bestax-no-helpers-prefixed.css.map +1 -1
  35. package/dist/versions/bestax-no-helpers.css +1 -1
  36. package/dist/versions/bestax-no-helpers.css.map +1 -1
  37. package/dist/versions/bestax-prefixed.css +1 -1
  38. package/dist/versions/bestax-prefixed.css.map +1 -1
  39. package/package.json +1 -1
  40. package/src/scss/components/_index.scss +1 -0
  41. package/src/scss/components/_lightbox.scss +392 -0
@@ -13,6 +13,7 @@
13
13
  @use 'toast';
14
14
  @use 'dialog';
15
15
  @use 'carousel';
16
+ @use 'lightbox';
16
17
  @use 'tabs';
17
18
  @use 'menu';
18
19
  @use 'tableofcontents';
@@ -0,0 +1,392 @@
1
+ // Bestax Extras - Lightbox Styles
2
+ // Bulma's image modal, finished: `.modal` with its near-black background and
3
+ // `.modal-close.is-large`, the image centred as large as the viewer allows,
4
+ // a bar along the top with the counter and the zoom buttons, round previous
5
+ // and next buttons at the inline edges, and the caption under the image.
6
+ //
7
+ // The root carries both `modal` and `lightbox`, so these rules outrank
8
+ // Bulma's `.modal` ones in either stylesheet order. The space around the
9
+ // image takes no pointer events, so a click there lands on
10
+ // `.modal-background`, which closes the viewer.
11
+
12
+ @use 'bulma/sass/utilities/initial-variables' as iv;
13
+ @use 'bulma/sass/utilities/css-variables' as cv;
14
+ @use '../variables' as *;
15
+ @use '../mixins' as *;
16
+
17
+ // Carousel's overlay arrows, light controls on a dark tint in either scheme.
18
+ // The same values rather than an `@use` of `_carousel.scss`, which would put
19
+ // the carousel's whole stylesheet into a modular build that asks only for
20
+ // this one.
21
+ $lightbox-arrow-background: hsla(
22
+ #{cv.getVar('scheme-h')},
23
+ #{cv.getVar('scheme-s')},
24
+ #{cv.getVar('scheme-invert-l')},
25
+ 0.3
26
+ ) !default;
27
+ $lightbox-arrow-background-hover: hsla(
28
+ #{cv.getVar('scheme-h')},
29
+ #{cv.getVar('scheme-s')},
30
+ #{cv.getVar('scheme-invert-l')},
31
+ 0.5
32
+ ) !default;
33
+ $lightbox-arrow-color: cv.getVar('white') !default;
34
+ $lightbox-arrow-size: 3rem !default;
35
+ $lightbox-arrow-offset: 1rem !default;
36
+ $lightbox-arrow-icon-size: 1.5rem !default;
37
+ // The zoom buttons in the toolbar start from the arrows' look.
38
+ $lightbox-toolbar-button-background: cv.getVar(
39
+ 'lightbox-arrow-background'
40
+ ) !default;
41
+ $lightbox-toolbar-button-background-hover: cv.getVar(
42
+ 'lightbox-arrow-background-hover'
43
+ ) !default;
44
+ $lightbox-toolbar-icon-size: 1.25rem !default;
45
+ // The round buttons' border, transparent until forced colors draws it.
46
+ $lightbox-button-border-width: 1px !default;
47
+ // A button that does nothing at an end, or at a zoom limit.
48
+ $lightbox-disabled-opacity: 0.4 !default;
49
+ // The close button, the toolbar and the arrows sit over the image.
50
+ $lightbox-controls-z-index: $extras-z-index-base !default;
51
+ // The modal's background stays near-black in Bulma's dark theme too, so the
52
+ // text on it is white in both.
53
+ $lightbox-toolbar-color: cv.getVar('white') !default;
54
+ $lightbox-toolbar-gap: 0.75rem !default;
55
+ $lightbox-caption-color: cv.getVar('white') !default;
56
+ $lightbox-caption-max-width: 40em !default;
57
+ $lightbox-caption-padding: 0.75rem 1rem 0 !default;
58
+ // A failed image's message and Retry, where the image would be.
59
+ $lightbox-error-color: cv.getVar('lightbox-caption-color') !default;
60
+ $lightbox-error-gap: 0.75rem !default;
61
+ $lightbox-error-padding: 1rem !default;
62
+ $lightbox-loader-size: 2.5rem !default;
63
+ // The band kept free above the image for the toolbar and the close button,
64
+ // and below it, so the image stays centred.
65
+ $lightbox-spacing: 4.5rem !default;
66
+ // The image and its caption share the viewer's height less the two bands.
67
+ $lightbox-image-max-height: calc(
68
+ 100% - 2 * #{cv.getVar('lightbox-spacing')}
69
+ ) !default;
70
+ // The fades and the zoom, timed and eased as Bulma's own transitions are.
71
+ $lightbox-animation-duration: cv.getVar('duration') !default;
72
+
73
+ .#{iv.$class-prefix}modal.#{iv.$class-prefix}lightbox {
74
+ @include cv.register-vars(
75
+ (
76
+ 'lightbox-arrow-background': #{$lightbox-arrow-background},
77
+ 'lightbox-arrow-background-hover': #{$lightbox-arrow-background-hover},
78
+ 'lightbox-arrow-color': #{$lightbox-arrow-color},
79
+ 'lightbox-arrow-size': #{$lightbox-arrow-size},
80
+ 'lightbox-arrow-offset': #{$lightbox-arrow-offset},
81
+ 'lightbox-arrow-icon-size': #{$lightbox-arrow-icon-size},
82
+ 'lightbox-toolbar-button-background':
83
+ #{$lightbox-toolbar-button-background},
84
+ 'lightbox-toolbar-button-background-hover':
85
+ #{$lightbox-toolbar-button-background-hover},
86
+ 'lightbox-toolbar-icon-size': #{$lightbox-toolbar-icon-size},
87
+ 'lightbox-button-border-width': #{$lightbox-button-border-width},
88
+ 'lightbox-disabled-opacity': #{$lightbox-disabled-opacity},
89
+ 'lightbox-controls-z-index': #{$lightbox-controls-z-index},
90
+ 'lightbox-toolbar-color': #{$lightbox-toolbar-color},
91
+ 'lightbox-toolbar-gap': #{$lightbox-toolbar-gap},
92
+ 'lightbox-caption-color': #{$lightbox-caption-color},
93
+ 'lightbox-caption-max-width': #{$lightbox-caption-max-width},
94
+ 'lightbox-caption-padding': #{$lightbox-caption-padding},
95
+ 'lightbox-error-color': #{$lightbox-error-color},
96
+ 'lightbox-error-gap': #{$lightbox-error-gap},
97
+ 'lightbox-error-padding': #{$lightbox-error-padding},
98
+ 'lightbox-loader-size': #{$lightbox-loader-size},
99
+ 'lightbox-spacing': #{$lightbox-spacing},
100
+ 'lightbox-image-max-height': #{$lightbox-image-max-height},
101
+ 'lightbox-animation-duration': #{$lightbox-animation-duration},
102
+ // Bulma's own, wide enough for the image with room for the arrows at
103
+ // either side, in place of its 40rem.
104
+ 'modal-content-width': calc(
105
+ 100% - 2 *
106
+ (
107
+ #{cv.getVar('lightbox-arrow-size')} + 2 *
108
+ #{cv.getVar('lightbox-arrow-offset')}
109
+ )
110
+ ),
111
+ )
112
+ );
113
+ }
114
+
115
+ // ---- The viewer ---------------------------------------------------------------
116
+
117
+ .#{iv.$class-prefix}modal.#{iv.$class-prefix}lightbox.#{iv.$class-prefix}is-active {
118
+ animation: extras-fade-in cv.getVar('lightbox-animation-duration')
119
+ $extras-easing;
120
+ }
121
+
122
+ .#{iv.$class-prefix}modal.#{iv.$class-prefix}lightbox:focus {
123
+ outline: none;
124
+ }
125
+
126
+ .#{iv.$class-prefix}modal.#{iv.$class-prefix}lightbox
127
+ > .#{iv.$class-prefix}modal-close {
128
+ z-index: cv.getVar('lightbox-controls-z-index');
129
+ }
130
+
131
+ // The image's area: the viewer's width less the arrows' room from a tablet
132
+ // up, and its whole width below, where the arrows sit over the image.
133
+ .#{iv.$class-prefix}modal.#{iv.$class-prefix}lightbox
134
+ > .#{iv.$class-prefix}modal-content {
135
+ height: cv.getVar('lightbox-image-max-height');
136
+ max-height: none;
137
+ margin: 0;
138
+ overflow: visible;
139
+ pointer-events: none;
140
+ }
141
+
142
+ // ---- The toolbar ----------------------------------------------------------------
143
+
144
+ .#{iv.$class-prefix}lightbox-toolbar {
145
+ position: absolute;
146
+ inset-block-start: 0;
147
+ inset-inline: 0;
148
+ z-index: cv.getVar('lightbox-controls-z-index');
149
+ display: flex;
150
+ align-items: center;
151
+ gap: cv.getVar('lightbox-toolbar-gap');
152
+ min-height: cv.getVar('lightbox-spacing');
153
+ // Level with the close button, and clear of it.
154
+ padding-block: cv.getVar('modal-close-top');
155
+ padding-inline: cv.getVar('modal-close-right')
156
+ calc(
157
+ #{cv.getVar('modal-close-right')} * 2 +
158
+ #{cv.getVar('modal-close-dimensions')}
159
+ );
160
+ color: cv.getVar('lightbox-toolbar-color');
161
+ pointer-events: none;
162
+
163
+ > .#{iv.$class-prefix}buttons {
164
+ flex-wrap: nowrap;
165
+ margin-block-end: 0;
166
+ margin-inline-start: auto;
167
+ }
168
+ }
169
+
170
+ .#{iv.$class-prefix}lightbox-progress {
171
+ font-variant-numeric: tabular-nums;
172
+ white-space: nowrap;
173
+ }
174
+
175
+ // ---- The buttons over the dark background ------------------------------------------
176
+
177
+ .#{iv.$class-prefix}modal.#{iv.$class-prefix}lightbox
178
+ .#{iv.$class-prefix}lightbox-toolbar
179
+ .#{iv.$class-prefix}button,
180
+ .#{iv.$class-prefix}modal.#{iv.$class-prefix}lightbox
181
+ .#{iv.$class-prefix}lightbox-arrow {
182
+ align-items: center;
183
+ justify-content: center;
184
+ width: cv.getVar('modal-close-dimensions');
185
+ height: cv.getVar('modal-close-dimensions');
186
+ padding: 0;
187
+ // Transparent until forced colors draws it.
188
+ border: cv.getVar('lightbox-button-border-width') solid transparent;
189
+ border-radius: cv.getVar('radius-rounded');
190
+ pointer-events: auto;
191
+
192
+ // Bulma's ring is a link-colored shadow, under 3:1 on the near-black
193
+ // background and gone in forced colors, so an outline in the buttons' own
194
+ // color takes its place.
195
+ &:focus-visible {
196
+ @include extras-focus-outline;
197
+ outline-color: currentColor;
198
+ box-shadow: none;
199
+ }
200
+
201
+ &[aria-disabled='true'] {
202
+ opacity: cv.getVar('lightbox-disabled-opacity');
203
+ cursor: not-allowed;
204
+ }
205
+ }
206
+
207
+ .#{iv.$class-prefix}modal.#{iv.$class-prefix}lightbox
208
+ .#{iv.$class-prefix}lightbox-toolbar
209
+ .#{iv.$class-prefix}button {
210
+ background-color: cv.getVar('lightbox-toolbar-button-background');
211
+ color: cv.getVar('lightbox-toolbar-color');
212
+
213
+ &:hover:not([aria-disabled='true']) {
214
+ background-color: cv.getVar('lightbox-toolbar-button-background-hover');
215
+ }
216
+
217
+ svg {
218
+ width: cv.getVar('lightbox-toolbar-icon-size');
219
+ height: cv.getVar('lightbox-toolbar-icon-size');
220
+ }
221
+ }
222
+
223
+ .#{iv.$class-prefix}modal.#{iv.$class-prefix}lightbox
224
+ .#{iv.$class-prefix}lightbox-arrow {
225
+ position: absolute;
226
+ inset-block-start: 50%;
227
+ z-index: cv.getVar('lightbox-controls-z-index');
228
+ width: cv.getVar('lightbox-arrow-size');
229
+ height: cv.getVar('lightbox-arrow-size');
230
+ transform: translateY(-50%);
231
+ background-color: cv.getVar('lightbox-arrow-background');
232
+ color: cv.getVar('lightbox-arrow-color');
233
+
234
+ &:hover:not([aria-disabled='true']) {
235
+ background-color: cv.getVar('lightbox-arrow-background-hover');
236
+ }
237
+
238
+ &.#{iv.$class-prefix}is-prev {
239
+ inset-inline-start: cv.getVar('lightbox-arrow-offset');
240
+ }
241
+
242
+ &.#{iv.$class-prefix}is-next {
243
+ inset-inline-end: cv.getVar('lightbox-arrow-offset');
244
+ }
245
+
246
+ svg {
247
+ width: cv.getVar('lightbox-arrow-icon-size');
248
+ height: cv.getVar('lightbox-arrow-icon-size');
249
+ }
250
+
251
+ // Right to left, the previous button is on the right, so its chevron
252
+ // points that way.
253
+ svg:dir(rtl) {
254
+ transform: scaleX(-1);
255
+ }
256
+ }
257
+
258
+ // ---- The image and its caption -----------------------------------------------------
259
+
260
+ // One cell the image fills, with the caption under it. The image, the one
261
+ // fading out over it, the Loader and the error share the cell.
262
+ .#{iv.$class-prefix}lightbox-figure {
263
+ display: grid;
264
+ grid-template-columns: minmax(0, 1fr);
265
+ grid-template-rows: minmax(0, 1fr) auto;
266
+ height: 100%;
267
+ margin: 0;
268
+ position: relative;
269
+ transition: transform cv.getVar('lightbox-animation-duration') $extras-easing;
270
+
271
+ > :not(.#{iv.$class-prefix}lightbox-caption) {
272
+ grid-area: 1 / 1;
273
+ place-self: center;
274
+ }
275
+ }
276
+
277
+ .#{iv.$class-prefix}lightbox-image {
278
+ display: block;
279
+ max-width: 100%;
280
+ max-height: 100%;
281
+ object-fit: contain;
282
+ pointer-events: auto;
283
+ // Pinch zooms the image rather than the page, and a drag pans it.
284
+ touch-action: none;
285
+ user-select: none;
286
+ -webkit-user-drag: none;
287
+ transition: transform cv.getVar('lightbox-animation-duration') $extras-easing;
288
+
289
+ // Hidden until it loads, then faded in.
290
+ &.#{iv.$class-prefix}is-loading {
291
+ opacity: 0;
292
+ }
293
+
294
+ &:not(.#{iv.$class-prefix}is-loading):not(.#{iv.$class-prefix}is-leaving) {
295
+ animation: extras-fade-in cv.getVar('lightbox-animation-duration')
296
+ $extras-easing;
297
+ }
298
+
299
+ // The image before it, on top, shown until the new one has loaded and then
300
+ // faded out as that one fades in. Animations rather than transitions, so
301
+ // the fades run for an image that was already loaded too.
302
+ &.#{iv.$class-prefix}is-leaving {
303
+ pointer-events: none;
304
+ }
305
+
306
+ &:not(.#{iv.$class-prefix}is-loading)
307
+ + .#{iv.$class-prefix}lightbox-image.#{iv.$class-prefix}is-leaving {
308
+ animation: extras-fade-out cv.getVar('lightbox-animation-duration')
309
+ $extras-easing forwards;
310
+ }
311
+ }
312
+
313
+ .#{iv.$class-prefix}modal.#{iv.$class-prefix}lightbox.#{iv.$class-prefix}is-zoomed
314
+ .#{iv.$class-prefix}lightbox-image {
315
+ cursor: grab;
316
+ }
317
+
318
+ .#{iv.$class-prefix}lightbox-caption {
319
+ justify-self: center;
320
+ max-width: cv.getVar('lightbox-caption-max-width');
321
+ padding: cv.getVar('lightbox-caption-padding');
322
+ color: cv.getVar('lightbox-caption-color');
323
+ text-align: center;
324
+ pointer-events: auto;
325
+ }
326
+
327
+ .#{iv.$class-prefix}lightbox-error {
328
+ display: flex;
329
+ flex-direction: column;
330
+ align-items: center;
331
+ gap: cv.getVar('lightbox-error-gap');
332
+ padding: cv.getVar('lightbox-error-padding');
333
+ color: cv.getVar('lightbox-error-color');
334
+ text-align: center;
335
+ pointer-events: auto;
336
+ }
337
+
338
+ .#{iv.$class-prefix}lightbox-figure > .#{iv.$class-prefix}loader {
339
+ font-size: cv.getVar('lightbox-loader-size');
340
+ }
341
+
342
+ // ---- The trigger ----------------------------------------------------------------------
343
+
344
+ // A button around a thumbnail, drawn as the thumbnail: no button chrome, as
345
+ // wide as the column or cell it's in, since a ratio `Image` has no width of
346
+ // its own, and an outline around what it holds. `:where()` keeps all of it
347
+ // at no specificity, so a trigger given Bulma's `button` class looks and
348
+ // sizes like a Bulma button instead.
349
+ :where(.#{iv.$class-prefix}lightbox-trigger) {
350
+ @include extras-button-reset;
351
+ text-align: inherit;
352
+ }
353
+
354
+ :where(.#{iv.$class-prefix}lightbox-trigger:not(.#{iv.$class-prefix}button)) {
355
+ display: block;
356
+ width: 100%;
357
+
358
+ &:focus-visible {
359
+ @include extras-focus-outline;
360
+ }
361
+ }
362
+
363
+ // ---- Motion and forced colors ------------------------------------------------------------
364
+
365
+ // The fades are on selectors more specific than these, hence `!important`.
366
+ // Script keeps no outgoing image under reduced motion either.
367
+ @media (prefers-reduced-motion: reduce) {
368
+ .#{iv.$class-prefix}modal.#{iv.$class-prefix}lightbox.#{iv.$class-prefix}is-active,
369
+ .#{iv.$class-prefix}lightbox-image {
370
+ animation: none !important;
371
+ }
372
+
373
+ .#{iv.$class-prefix}lightbox-figure,
374
+ .#{iv.$class-prefix}lightbox-image {
375
+ transition: none;
376
+ }
377
+ }
378
+
379
+ @media (forced-colors: active) {
380
+ .#{iv.$class-prefix}modal.#{iv.$class-prefix}lightbox
381
+ .#{iv.$class-prefix}lightbox-toolbar
382
+ .#{iv.$class-prefix}button,
383
+ .#{iv.$class-prefix}modal.#{iv.$class-prefix}lightbox
384
+ .#{iv.$class-prefix}lightbox-arrow {
385
+ border-color: ButtonText;
386
+
387
+ &[aria-disabled='true'] {
388
+ border-color: GrayText;
389
+ color: GrayText;
390
+ }
391
+ }
392
+ }