yet-another-react-lightbox-lite 1.1.0 → 1.2.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.
- package/README.md +36 -27
- package/dist/index.d.ts +15 -4
- package/dist/index.js +13 -7
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -110,7 +110,6 @@ with `next/image` with the following `render.slide` render function.
|
|
|
110
110
|
|
|
111
111
|
```tsx
|
|
112
112
|
<Lightbox
|
|
113
|
-
// ...
|
|
114
113
|
render={{
|
|
115
114
|
slide: ({ slide, rect }) => {
|
|
116
115
|
const width =
|
|
@@ -147,6 +146,7 @@ with `next/image` with the following `render.slide` render function.
|
|
|
147
146
|
);
|
|
148
147
|
},
|
|
149
148
|
}}
|
|
149
|
+
// ...
|
|
150
150
|
/>
|
|
151
151
|
```
|
|
152
152
|
|
|
@@ -203,6 +203,37 @@ Custom UI labels / translations.
|
|
|
203
203
|
/>
|
|
204
204
|
```
|
|
205
205
|
|
|
206
|
+
### toolbar
|
|
207
|
+
|
|
208
|
+
Type: `object`
|
|
209
|
+
|
|
210
|
+
Toolbar settings.
|
|
211
|
+
|
|
212
|
+
- `buttons` - custom toolbar buttons (type: `ReactNode[]`)
|
|
213
|
+
- `fixed` - if `true`, the toolbar is positioned statically above the carousel
|
|
214
|
+
|
|
215
|
+
Usage example:
|
|
216
|
+
|
|
217
|
+
```tsx
|
|
218
|
+
<Lightbox
|
|
219
|
+
toolbar={{
|
|
220
|
+
fixed: true,
|
|
221
|
+
buttons: [
|
|
222
|
+
<button
|
|
223
|
+
type="button"
|
|
224
|
+
className="yarll__button"
|
|
225
|
+
onClick={() => {
|
|
226
|
+
// ...
|
|
227
|
+
}}
|
|
228
|
+
>
|
|
229
|
+
<ButtonIcon />
|
|
230
|
+
</button>,
|
|
231
|
+
],
|
|
232
|
+
}}
|
|
233
|
+
// ...
|
|
234
|
+
/>
|
|
235
|
+
```
|
|
236
|
+
|
|
206
237
|
### controller
|
|
207
238
|
|
|
208
239
|
Type: `object`
|
|
@@ -220,12 +251,12 @@ Usage example:
|
|
|
220
251
|
|
|
221
252
|
```tsx
|
|
222
253
|
<Lightbox
|
|
223
|
-
// ...
|
|
224
254
|
controller={{
|
|
225
255
|
closeOnPullUp: false,
|
|
226
256
|
closeOnPullDown: false,
|
|
227
257
|
closeOnBackdropClick: false,
|
|
228
258
|
}}
|
|
259
|
+
// ...
|
|
229
260
|
/>
|
|
230
261
|
```
|
|
231
262
|
|
|
@@ -294,7 +325,6 @@ slides counter.
|
|
|
294
325
|
|
|
295
326
|
```tsx
|
|
296
327
|
<Lightbox
|
|
297
|
-
// ...
|
|
298
328
|
render={{
|
|
299
329
|
controls: () =>
|
|
300
330
|
index !== undefined && (
|
|
@@ -303,29 +333,7 @@ slides counter.
|
|
|
303
333
|
</div>
|
|
304
334
|
),
|
|
305
335
|
}}
|
|
306
|
-
/>
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
You can also use the `render.controls` render function to add custom buttons to
|
|
310
|
-
the toolbar.
|
|
311
|
-
|
|
312
|
-
```tsx
|
|
313
|
-
<Lightbox
|
|
314
336
|
// ...
|
|
315
|
-
render={{
|
|
316
|
-
controls: () => (
|
|
317
|
-
<button
|
|
318
|
-
type="button"
|
|
319
|
-
className="yarll__button"
|
|
320
|
-
style={{ position: "absolute", top: 8, right: 64 }}
|
|
321
|
-
onClick={() => {
|
|
322
|
-
// ...
|
|
323
|
-
}}
|
|
324
|
-
>
|
|
325
|
-
<ButtonIcon />
|
|
326
|
-
</button>
|
|
327
|
-
),
|
|
328
|
-
}}
|
|
329
337
|
/>
|
|
330
338
|
```
|
|
331
339
|
|
|
@@ -355,6 +363,7 @@ Supported customization slots:
|
|
|
355
363
|
- `carousel` - lightbox carousel
|
|
356
364
|
- `slide` - lightbox slide
|
|
357
365
|
- `image` - lightbox slide image
|
|
366
|
+
- `toolbar` - lightbox toolbar
|
|
358
367
|
- `button` - lightbox button
|
|
359
368
|
- `icon` - lightbox icon
|
|
360
369
|
|
|
@@ -362,10 +371,10 @@ Usage example:
|
|
|
362
371
|
|
|
363
372
|
```tsx
|
|
364
373
|
<Lightbox
|
|
365
|
-
// ...
|
|
366
374
|
styles={{
|
|
367
375
|
portal: { "--yarll__backdrop_color": "rgba(0, 0, 0, 0.6)" },
|
|
368
376
|
}}
|
|
377
|
+
// ...
|
|
369
378
|
/>
|
|
370
379
|
```
|
|
371
380
|
|
|
@@ -493,8 +502,8 @@ to use this feature, you can turn it off by assigning the
|
|
|
493
502
|
|
|
494
503
|
```tsx
|
|
495
504
|
<Lightbox
|
|
496
|
-
// ..
|
|
497
505
|
className="yarll__no_scroll_lock"
|
|
506
|
+
// ...
|
|
498
507
|
/>
|
|
499
508
|
```
|
|
500
509
|
|
package/dist/index.d.ts
CHANGED
|
@@ -13,8 +13,10 @@ interface LightboxProps {
|
|
|
13
13
|
labels?: Labels;
|
|
14
14
|
/** custom render functions */
|
|
15
15
|
render?: Render;
|
|
16
|
+
/** toolbar settings */
|
|
17
|
+
toolbar?: ToolbarSettings;
|
|
16
18
|
/** controller settings */
|
|
17
|
-
controller?:
|
|
19
|
+
controller?: ControllerSettings;
|
|
18
20
|
/** customization slots styles */
|
|
19
21
|
styles?: SlotStyles;
|
|
20
22
|
/** CSS class of the lightbox root element */
|
|
@@ -94,15 +96,22 @@ interface RenderSlideProps {
|
|
|
94
96
|
/** if `true`, the slide is the current slide in the viewport */
|
|
95
97
|
current: boolean;
|
|
96
98
|
}
|
|
99
|
+
/** Toolbar settings */
|
|
100
|
+
interface ToolbarSettings {
|
|
101
|
+
/** custom toolbar buttons */
|
|
102
|
+
buttons?: React.ReactNode[];
|
|
103
|
+
/** if `true`, the toolbar is positioned statically above the carousel */
|
|
104
|
+
fixed?: boolean;
|
|
105
|
+
}
|
|
97
106
|
/** Controller settings */
|
|
98
|
-
|
|
107
|
+
interface ControllerSettings {
|
|
99
108
|
/** if `true`, close the lightbox on pull-up gesture (default: `true`) */
|
|
100
109
|
closeOnPullUp?: boolean;
|
|
101
110
|
/** if `true`, close the lightbox on pull-down gesture (default: `true`) */
|
|
102
111
|
closeOnPullDown?: boolean;
|
|
103
112
|
/** if `true`, close the lightbox when the backdrop is clicked (default: `true`) */
|
|
104
113
|
closeOnBackdropClick?: boolean;
|
|
105
|
-
}
|
|
114
|
+
}
|
|
106
115
|
/** Customization slots */
|
|
107
116
|
interface SlotType {
|
|
108
117
|
/** lightbox portal (root) customization slot */
|
|
@@ -113,6 +122,8 @@ interface SlotType {
|
|
|
113
122
|
slide: "slide";
|
|
114
123
|
/** lightbox slide image customization slot */
|
|
115
124
|
image: "image";
|
|
125
|
+
/** lightbox toolbar customization slot */
|
|
126
|
+
toolbar: "toolbar";
|
|
116
127
|
/** lightbox button customization slot */
|
|
117
128
|
button: "button";
|
|
118
129
|
/** lightbox icon customization slot */
|
|
@@ -140,4 +151,4 @@ type RenderFunction<T = void> = [T] extends [void] ? () => React.ReactNode : (pr
|
|
|
140
151
|
|
|
141
152
|
declare function Lightbox({ slides, index, setIndex, ...rest }: LightboxProps): react_jsx_runtime.JSX.Element | null;
|
|
142
153
|
|
|
143
|
-
export { type Callback, type
|
|
154
|
+
export { type Callback, type ControllerSettings, type GenericSlide, type ImageSource, type Label, type Labels, type LightboxProps, type Rect, type Render, type RenderFunction, type RenderSlideProps, type Slide, type SlideImage, type SlideTypeKey, type SlideTypes, type Slot, type SlotStyles, type SlotType, type ToolbarSettings, Lightbox as default };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
-
import { useContext, createContext, useState, useRef, useCallback, useMemo, useEffect } from 'react';
|
|
2
|
+
import { useContext, createContext, useState, useRef, useCallback, useMemo, useEffect, isValidElement, cloneElement } from 'react';
|
|
3
3
|
import { flushSync, createPortal } from 'react-dom';
|
|
4
4
|
|
|
5
5
|
const cssPrefix = "yarll__";
|
|
@@ -137,9 +137,9 @@ const Next = createIcon("Next", jsx("path", { d: "M10 6L8.59 7.41 13.17 12l-4.58
|
|
|
137
137
|
const Previous = createIcon("Previous", jsx("path", { d: "M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z" }));
|
|
138
138
|
|
|
139
139
|
function Navigation() {
|
|
140
|
-
const { slides, index, render: { iconPrev, iconNext,
|
|
141
|
-
const { prev, next
|
|
142
|
-
return (jsxs(Fragment, { children: [slides.length > 1 && (jsxs(Fragment, { children: [jsx(Button, { label: "Previous", icon: Previous, renderIcon: iconPrev, onClick: prev, className: cssClass("button_prev"), disabled: index <= 0 }), jsx(Button, { label: "Next", icon: Next, renderIcon: iconNext, onClick: next, className: cssClass("button_next"), disabled: index >= slides.length - 1 })] })),
|
|
140
|
+
const { slides, index, render: { iconPrev, iconNext, controls } = {} } = useLightboxContext();
|
|
141
|
+
const { prev, next } = useController();
|
|
142
|
+
return (jsxs(Fragment, { children: [slides.length > 1 && (jsxs(Fragment, { children: [jsx(Button, { label: "Previous", icon: Previous, renderIcon: iconPrev, onClick: prev, className: cssClass("button_prev"), disabled: index <= 0 }), jsx(Button, { label: "Next", icon: Next, renderIcon: iconNext, onClick: next, className: cssClass("button_next"), disabled: index >= slides.length - 1 })] })), controls?.()] }));
|
|
143
143
|
}
|
|
144
144
|
|
|
145
145
|
function useSensors() {
|
|
@@ -193,8 +193,8 @@ function useSensors() {
|
|
|
193
193
|
}
|
|
194
194
|
else if ((deltaY > 50 && deltaY > 1.2 * deltaX && ((closeOnPullUp && dy < 0) || (closeOnPullDown && dy > 0))) ||
|
|
195
195
|
(closeOnBackdropClick &&
|
|
196
|
-
activePointer.current.target instanceof
|
|
197
|
-
activePointer.current.target.
|
|
196
|
+
activePointer.current.target instanceof Element &&
|
|
197
|
+
Array.from(activePointer.current.target.classList).some((className) => [cssClass("slide"), cssClass("portal")].includes(className)))) {
|
|
198
198
|
close();
|
|
199
199
|
}
|
|
200
200
|
activePointer.current = null;
|
|
@@ -325,10 +325,16 @@ function Portal({ children }) {
|
|
|
325
325
|
: null;
|
|
326
326
|
}
|
|
327
327
|
|
|
328
|
+
function Toolbar() {
|
|
329
|
+
const { render: { iconClose } = {}, toolbar: { buttons, fixed } = {}, styles } = useLightboxContext();
|
|
330
|
+
const { close } = useController();
|
|
331
|
+
return (jsxs("div", { style: styles?.toolbar, className: clsx(cssClass("toolbar"), fixed && cssClass("toolbar_fixed")), children: [buttons?.map((button, key) => (isValidElement(button) && !button.key ? cloneElement(button, { key }) : button)), jsx(Button, { label: "Close", icon: Close, renderIcon: iconClose, onClick: close })] }));
|
|
332
|
+
}
|
|
333
|
+
|
|
328
334
|
function Lightbox({ slides, index, setIndex, ...rest }) {
|
|
329
335
|
if (!Array.isArray(slides) || index === undefined || index < 0 || index >= slides.length)
|
|
330
336
|
return null;
|
|
331
|
-
return (jsx(LightboxContextProvider, { slides, index, ...rest, children: jsx(Controller, { setIndex, children: jsxs(Portal, { children: [jsx(Carousel, {}), jsx(Navigation, {})] }) }) }));
|
|
337
|
+
return (jsx(LightboxContextProvider, { slides, index, ...rest, children: jsx(Controller, { setIndex, children: jsxs(Portal, { children: [jsx(Toolbar, {}), jsx(Carousel, {}), jsx(Navigation, {})] }) }) }));
|
|
332
338
|
}
|
|
333
339
|
|
|
334
340
|
export { Lightbox as default };
|
package/dist/styles.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
body:has(>.yarll__portal){overscroll-behavior:none}body:has(>.yarll__portal:not(.yarll__no_scroll_lock)){height:100%;overflow:hidden;padding-right:var(--yarll__scrollbar-width,0)}body:has(>.yarll__portal:not(.yarll__no_scroll_lock)) .yarll_fixed{padding-right:var(--yarll__scrollbar-width,0)}.yarll__portal{align-items:center;display:flex;flex-direction:column;inset:0;justify-content:center;outline:none;overflow:hidden;overscroll-behavior:none;position:fixed;touch-action:none;-moz-user-select:none;user-select:none;-webkit-user-select:none;z-index:var(--yarll__portal_zindex,9999);-webkit-touch-callout:none;background-color:var(--yarll__backdrop_color,#000);color:var(--yarll__color,#fff);opacity:1;transition:var(--yarll__fade_transition,opacity .3s ease)}.yarll__portal_closed{opacity:0}.yarll__portal *{box-sizing:border-box}.yarll__carousel{align-self:stretch;flex:1;margin:var(--yarll__carousel_margin,16px);position:relative}.yarll__slide{align-items:center;display:flex;flex-direction:column;inset:0;justify-content:center;position:absolute}.yarll__slide[hidden]{display:none}.yarll__slide_image{display:block;flex:1;max-height:100%;max-width:100%;min-height:0;min-width:0;-o-object-fit:contain;object-fit:contain}.yarll__button{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--yarll__button_background_color,transparent);border:0;color:var(--yarll__button_color,var(--yarll__button_color,hsla(0,0%,100%,.8)));cursor:pointer;filter:var(--yarll__button_filter,drop-shadow(2px 2px 2px rgba(0,0,0,.8)));margin:0;padding:var(--yarll__button_padding,8px)}.yarll__button:focus-visible{box-shadow:var(--yarll__button_focus_box_shadow,0 0 0 4px #fff);color:var(--yarll__button_color_active,#fff);outline:var(--yarll__button_focus_outline,6px double #000)}@supports not selector(:focus-visible){.yarll__button:focus{box-shadow:var(--yarll__button_focus_box_shadow,0 0 0 4px #fff);color:var(--yarll__button_color_active,#fff);outline:var(--yarll__button_focus_outline,6px double #000)}}@media (hover:hover){.yarll__button:focus-visible:hover,.yarll__button:focus:hover,.yarll__button:hover{color:var(--yarll__button_color_active,#fff)}}.
|
|
1
|
+
body:has(>.yarll__portal){overscroll-behavior:none}body:has(>.yarll__portal:not(.yarll__no_scroll_lock)){height:100%;overflow:hidden;padding-right:var(--yarll__scrollbar-width,0)}body:has(>.yarll__portal:not(.yarll__no_scroll_lock)) .yarll_fixed{padding-right:var(--yarll__scrollbar-width,0)}.yarll__portal{align-items:center;display:flex;flex-direction:column;inset:0;justify-content:center;outline:none;overflow:hidden;overscroll-behavior:none;position:fixed;touch-action:none;-moz-user-select:none;user-select:none;-webkit-user-select:none;z-index:var(--yarll__portal_zindex,9999);-webkit-touch-callout:none;background-color:var(--yarll__backdrop_color,#000);color:var(--yarll__color,#fff);opacity:1;transition:var(--yarll__fade_transition,opacity .3s ease)}.yarll__portal_closed{opacity:0}.yarll__portal *{box-sizing:border-box}.yarll__carousel{align-self:stretch;flex:1;margin:var(--yarll__carousel_margin,16px);position:relative}.yarll__slide{align-items:center;display:flex;flex-direction:column;inset:0;justify-content:center;position:absolute}.yarll__slide[hidden]{display:none}.yarll__slide_image{display:block;flex:1;max-height:100%;max-width:100%;min-height:0;min-width:0;-o-object-fit:contain;object-fit:contain}.yarll__toolbar{align-items:center;display:flex;position:absolute;right:var(--yarll__toolbar_margin,8px);top:var(--yarll__toolbar_margin,8px);z-index:1}.yarll__toolbar_fixed{align-self:flex-end;margin-inline-end:var(--yarll__toolbar_margin,8px);position:static;z-index:unset}.yarll__toolbar_fixed,.yarll__toolbar_fixed+.yarll__carousel{margin-block-start:var(--yarll__toolbar_margin,8px)}.yarll__button{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--yarll__button_background_color,transparent);border:0;color:var(--yarll__button_color,var(--yarll__button_color,hsla(0,0%,100%,.8)));cursor:pointer;filter:var(--yarll__button_filter,drop-shadow(2px 2px 2px rgba(0,0,0,.8)));margin:0;padding:var(--yarll__button_padding,8px)}.yarll__button:focus-visible{box-shadow:var(--yarll__button_focus_box_shadow,0 0 0 4px #fff);color:var(--yarll__button_color_active,#fff);outline:var(--yarll__button_focus_outline,6px double #000)}@supports not selector(:focus-visible){.yarll__button:focus{box-shadow:var(--yarll__button_focus_box_shadow,0 0 0 4px #fff);color:var(--yarll__button_color_active,#fff);outline:var(--yarll__button_focus_outline,6px double #000)}}@media (hover:hover){.yarll__button:focus-visible:hover,.yarll__button:focus:hover,.yarll__button:hover{color:var(--yarll__button_color_active,#fff)}}.yarll__button_next,.yarll__button_prev{padding:var(--yarll__navigation_button_padding,24px 8px);position:absolute}.yarll__button_prev{left:8px}.yarll__button_next{right:8px}.yarll__button:disabled{color:var(--yarll__button_color_disabled,var(--yarll__button_color_disabled,hsla(0,0%,100%,.4)));cursor:default}.yarll__icon{display:block;height:var(--yarll__icon_size,32px);width:var(--yarll__icon_size,32px)}
|