lightgallery 3.0.0-beta.2 → 3.0.0-beta.3

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 (69) hide show
  1. package/dist/lightgallery.es5.js +5 -56
  2. package/dist/lightgallery.es5.js.map +1 -1
  3. package/dist/lightgallery.min.js +1 -1
  4. package/dist/lightgallery.umd.js +5 -56
  5. package/dist/lightgallery.umd.js.map +1 -1
  6. package/dist/package.json +1 -1
  7. package/dist/plugins/autoplay/lg-autoplay.es5.js +1 -1
  8. package/dist/plugins/autoplay/lg-autoplay.umd.js +1 -1
  9. package/dist/plugins/comment/lg-comment.es5.js +1 -1
  10. package/dist/plugins/comment/lg-comment.umd.js +1 -1
  11. package/dist/plugins/fullscreen/lg-fullscreen.es5.js +1 -1
  12. package/dist/plugins/fullscreen/lg-fullscreen.umd.js +1 -1
  13. package/dist/plugins/hash/lg-hash.es5.js +1 -1
  14. package/dist/plugins/hash/lg-hash.umd.js +1 -1
  15. package/dist/plugins/justified/lg-justified.es5.js +1 -1
  16. package/dist/plugins/justified/lg-justified.umd.js +1 -1
  17. package/dist/plugins/mediumZoom/lg-medium-zoom.es5.js +1 -1
  18. package/dist/plugins/mediumZoom/lg-medium-zoom.umd.js +1 -1
  19. package/dist/plugins/originCrop/lg-origin-crop.es5.js +1 -1
  20. package/dist/plugins/originCrop/lg-origin-crop.umd.js +1 -1
  21. package/dist/plugins/pager/lg-pager.es5.js +1 -1
  22. package/dist/plugins/pager/lg-pager.umd.js +1 -1
  23. package/dist/plugins/relativeCaption/lg-relative-caption.es5.js +1 -1
  24. package/dist/plugins/relativeCaption/lg-relative-caption.umd.js +1 -1
  25. package/dist/plugins/rotate/lg-rotate.es5.js +1 -1
  26. package/dist/plugins/rotate/lg-rotate.umd.js +1 -1
  27. package/dist/plugins/share/lg-share.es5.js +1 -1
  28. package/dist/plugins/share/lg-share.umd.js +1 -1
  29. package/dist/plugins/thumbnail/lg-thumbnail.es5.js +1 -1
  30. package/dist/plugins/thumbnail/lg-thumbnail.umd.js +1 -1
  31. package/dist/plugins/video/lg-video.es5.js +1 -1
  32. package/dist/plugins/video/lg-video.umd.js +1 -1
  33. package/dist/plugins/vimeoThumbnail/lg-vimeo-thumbnail.es5.js +1 -1
  34. package/dist/plugins/vimeoThumbnail/lg-vimeo-thumbnail.umd.js +1 -1
  35. package/dist/plugins/zoom/lg-zoom.es5.js +1 -1
  36. package/dist/plugins/zoom/lg-zoom.umd.js +1 -1
  37. package/dist/types/headless/announce.d.ts +22 -0
  38. package/dist/types/headless/emitter.d.ts +14 -0
  39. package/dist/types/headless/gestures.d.ts +128 -0
  40. package/dist/types/headless/hash-driver.d.ts +77 -0
  41. package/dist/types/headless/icons.d.ts +56 -0
  42. package/dist/types/headless/index.d.ts +34 -0
  43. package/dist/types/headless/items.d.ts +92 -0
  44. package/dist/types/headless/justified-layout.d.ts +71 -0
  45. package/dist/types/headless/license.d.ts +35 -0
  46. package/dist/types/headless/origin-crop.d.ts +135 -0
  47. package/dist/types/headless/origin.d.ts +65 -0
  48. package/dist/types/headless/plugin-slices.d.ts +64 -0
  49. package/dist/types/headless/preload.d.ts +36 -0
  50. package/dist/types/headless/responsive.d.ts +90 -0
  51. package/dist/types/headless/settings.d.ts +268 -0
  52. package/dist/types/headless/share-urls.d.ts +60 -0
  53. package/dist/types/headless/spring.d.ts +42 -0
  54. package/dist/types/headless/state.d.ts +63 -0
  55. package/dist/types/headless/thumb-math.d.ts +85 -0
  56. package/dist/types/headless/toolbar-overflow.d.ts +61 -0
  57. package/dist/types/headless/transition.d.ts +33 -0
  58. package/dist/types/headless/velocity.d.ts +31 -0
  59. package/dist/types/headless/video-urls.d.ts +64 -0
  60. package/dist/types/headless/zoom-math.d.ts +89 -0
  61. package/dist/types/index.d.ts +2 -1
  62. package/dist/types/lg-icons.d.ts +1 -1
  63. package/dist/types/lg-settings.d.ts +1 -7
  64. package/dist/types/lg-spring-runner.d.ts +1 -1
  65. package/dist/types/lightgallery.d.ts +0 -1
  66. package/dist/types/plugins/hash/lg-hash-settings.d.ts +1 -1
  67. package/dist/types/plugins/video/lg-video-settings.d.ts +1 -1
  68. package/dist/types/plugins/zoom/lg-zoom.d.ts +1 -1
  69. package/package.json +56 -71
@@ -0,0 +1,268 @@
1
+ /**
2
+ * Typed core settings and the non-mutating merge, ported from
3
+ * `src/lg-settings.ts` (2.x) with the ADR 0001 §7 renames applied:
4
+ * `appendSubHtmlTo` → `captionPosition`; DOM-scraping options
5
+ * (`selector`, `extraProps`, `getCaptionFromTitleOrAlt`, …), HTML-string
6
+ * options (`nextHtml`, `prevHtml`, `appendCounterTo`) and
7
+ * `supportLegacyBrowser` are gone. `container`, `addClass`/`className` and
8
+ * `index` are framework-layer props, not headless settings.
9
+ */
10
+ export type GalleryMode = 'lg-slide' | 'lg-fade' | 'lg-zoom-in' | 'lg-zoom-in-big' | 'lg-zoom-out' | 'lg-zoom-out-big' | 'lg-zoom-out-in' | 'lg-zoom-in-out' | 'lg-soft-zoom' | 'lg-scale-up' | 'lg-slide-circular' | 'lg-slide-circular-vertical' | 'lg-slide-vertical' | 'lg-slide-vertical-growth' | 'lg-slide-skew-only' | 'lg-slide-skew-only-rev' | 'lg-slide-skew-only-y' | 'lg-slide-skew-only-y-rev' | 'lg-slide-skew' | 'lg-slide-skew-rev' | 'lg-slide-skew-cross' | 'lg-slide-skew-cross-rev' | 'lg-slide-skew-ver' | 'lg-slide-skew-ver-rev' | 'lg-slide-skew-ver-cross' | 'lg-slide-skew-ver-cross-rev' | 'lg-lollipop' | 'lg-lollipop-rev' | 'lg-rotate' | 'lg-rotate-rev' | 'lg-tube';
11
+ /** Where slide captions render (2.x `appendSubHtmlTo`, without selectors). */
12
+ export type CaptionPosition = 'bar' | 'slide' | 'outer';
13
+ /**
14
+ * Gallery reading direction. `'auto'` inherits the page direction —
15
+ * resolved by the framework layer (this module is DOM-free, so `'auto'`
16
+ * reaches the runtimes unresolved, like `isMobile`).
17
+ */
18
+ export type GalleryDirection = 'ltr' | 'rtl' | 'auto';
19
+ /** `direction` with `'auto'` already resolved against the document. */
20
+ export type ResolvedGalleryDirection = 'ltr' | 'rtl';
21
+ /** Plan-010 virtualization knobs; the feature is off when the whole
22
+ * object is absent. */
23
+ export interface VirtualizationSettings {
24
+ /** Mounted-slide pool size (overrides `numberOfSlideItemsInDom`). */
25
+ slides?: number;
26
+ /**
27
+ * Thumbnail-strip windowing: overscan thumbs kept mounted on each
28
+ * side of the visible range, or 'auto' for one extra viewport.
29
+ */
30
+ thumbs?: 'auto' | number;
31
+ }
32
+ export interface GalleryCoreStrings {
33
+ closeGallery: string;
34
+ toggleMaximize: string;
35
+ previousSlide: string;
36
+ nextSlide: string;
37
+ download: string;
38
+ playVideo: string;
39
+ mediaLoadingFailed: string;
40
+ /** Accessible name of the gallery dialog when `ariaLabelledby` is not set. */
41
+ galleryLabel: string;
42
+ /**
43
+ * Template announced to assistive technology on every slide change.
44
+ * `{index}` and `{total}` are replaced with the 1-based slide position
45
+ * and the slide count; the slide caption, when present, is appended.
46
+ */
47
+ slideAnnouncement: string;
48
+ /** Label of the toolbar's More options menu button. */
49
+ moreOptions: string;
50
+ /** Share plugin: share button label. */
51
+ share: string;
52
+ /** Thumbnail plugin: strip toggle button label. */
53
+ toggleThumbnails: string;
54
+ /** Autoplay plugin: slideshow toggle button label. */
55
+ toggleAutoplay: string;
56
+ /** Fullscreen plugin: fullscreen toggle button label. */
57
+ toggleFullscreen: string;
58
+ /** Zoom plugin: zoom-in button label. */
59
+ zoomIn: string;
60
+ /** Zoom plugin: zoom-out button label. */
61
+ zoomOut: string;
62
+ /** Zoom plugin: actual-size button label. */
63
+ viewActualSize: string;
64
+ /** Rotate plugin: rotate-left button label. */
65
+ rotateLeft: string;
66
+ /** Rotate plugin: rotate-right button label. */
67
+ rotateRight: string;
68
+ /** Rotate plugin: horizontal flip button label. */
69
+ flipHorizontal: string;
70
+ /** Rotate plugin: vertical flip button label. */
71
+ flipVertical: string;
72
+ /** Comment plugin: comments toggle button label. */
73
+ toggleComments: string;
74
+ }
75
+ export interface CoreSettings {
76
+ /** Type of transition between slides. */
77
+ mode: GalleryMode;
78
+ /** Slide animation CSS easing property. */
79
+ easing: string;
80
+ /** Transition duration in ms. */
81
+ speed: number;
82
+ /**
83
+ * Commercial license key. lightGallery 3 keys start with `LIG`;
84
+ * `0000-0000-000-0000` is the temporary testing key.
85
+ */
86
+ licenseKey: string;
87
+ /** Height of the gallery, e.g. '100%', '300px'. */
88
+ height: string;
89
+ /** Width of the gallery, e.g. '100%', '300px'. */
90
+ width: string;
91
+ /**
92
+ * Start animation class applied to the outer element while opening when
93
+ * no zoom-from-origin transform is available. Empty string disables.
94
+ */
95
+ startClass: string;
96
+ /**
97
+ * Animate the opening slide from the trigger thumbnail's bounding rect.
98
+ * Needs the natural image size via the item's `lgSize` field; falls back
99
+ * to `startClass` when unavailable. On close, a slide with no thumbnail
100
+ * to return to (its trigger is hidden or collapsed behind a "+9 photos"
101
+ * tile, it has no `lgSize`, or the items came without trigger elements)
102
+ * shrinks to the centre of the stage and fades instead of flying to a
103
+ * thumbnail it cannot reach.
104
+ */
105
+ zoomFromOrigin: boolean;
106
+ /** Zoom-from-origin animation duration in ms. */
107
+ startAnimationDuration: number;
108
+ /** Backdrop fade duration in ms. */
109
+ backdropDuration: number;
110
+ /** Delay in ms before hiding controls on idle. 0 keeps them visible. */
111
+ hideBarsDelay: number;
112
+ /** Delay before the idle-hide behavior arms after opening. */
113
+ showBarsAfter: number;
114
+ /** Delay slide transitions in ms (`lg-slide-progress` window). */
115
+ slideDelay: number;
116
+ /** If true, toolbar/captions/thumbnails may overlap the media. */
117
+ allowMediaOverlap: boolean;
118
+ /** Default video size as `"width-height"`. */
119
+ videoMaxSize: string;
120
+ /** Automatically load poster images for YouTube videos. */
121
+ loadYouTubePoster: boolean;
122
+ /** Caption height used for media positioning when overlap is off. */
123
+ defaultCaptionHeight: number;
124
+ /** aria-labelledby attribute for the gallery dialog. */
125
+ ariaLabelledby: string;
126
+ /** aria-describedby attribute for the gallery dialog. */
127
+ ariaDescribedby: string;
128
+ /** Hide the page scrollbar (with padding compensation) while open. */
129
+ hideScrollbar: boolean;
130
+ /** Restore the previous scroll position when the gallery closes. */
131
+ resetScrollPosition: boolean;
132
+ /** If false the gallery cannot be closed (inline galleries). */
133
+ closable: boolean;
134
+ /** Allow vertical drag/swipe to close (forced off when not closable). */
135
+ swipeToClose: boolean;
136
+ /** Close when clicking the black area around the slide. */
137
+ closeOnTap: boolean;
138
+ /** Show the close button. */
139
+ showCloseIcon: boolean;
140
+ /** Show the maximize button (inline galleries). */
141
+ showMaximizeIcon: boolean;
142
+ /**
143
+ * Keep the toolbar on one row: when its buttons do not fit beside the
144
+ * counter, the lowest-priority ones move into a "More options" menu.
145
+ * Set to `false` to let the buttons wrap onto a second row instead.
146
+ */
147
+ toolbarOverflow: boolean;
148
+ /**
149
+ * Show the toolbar buttons that repeat a touch gesture: zoom in, zoom
150
+ * out and actual size (pinch and double-tap do the same). On by
151
+ * default; `mobileSettings` turns it off on touch devices.
152
+ */
153
+ showGestureButtons: boolean;
154
+ /** Loop back to the first slide from the last. */
155
+ loop: boolean;
156
+ /** Close on Escape. */
157
+ escKey: boolean;
158
+ /** Keyboard navigation (arrow keys). */
159
+ keyPress: boolean;
160
+ /** Trap focus within the gallery. */
161
+ trapFocus: boolean;
162
+ /** Show prev/next buttons. */
163
+ controls: boolean;
164
+ /** Bounce animation when navigating past the ends without loop. */
165
+ slideEndAnimation: boolean;
166
+ /**
167
+ * Disable prev/next buttons on first/last slide. Ignored (forced false)
168
+ * when `loop` or `slideEndAnimation` is on — 2.x parity.
169
+ */
170
+ hideControlOnEnd: boolean;
171
+ /** Navigate on mousewheel. */
172
+ mousewheel: boolean;
173
+ /**
174
+ * Gallery reading direction: keyboard arrows, swipe advance and the
175
+ * slide/thumbnail transforms follow it. Visual mirroring is the
176
+ * opt-in `lg-rtl.css` layer — load it whenever this resolves to
177
+ * `'rtl'`. `'auto'` inherits the page direction; the default stays
178
+ * `'ltr'` so upgrades never change behavior on existing pages.
179
+ */
180
+ direction: GalleryDirection;
181
+ /** Where slide captions render. */
182
+ captionPosition: CaptionPosition;
183
+ /** Number of slides to preload around the current slide. */
184
+ preload: number;
185
+ /** How many slide elements are kept mounted at a time (minimum 3). */
186
+ numberOfSlideItemsInDom: number;
187
+ /** iframe slide width. */
188
+ iframeWidth: string;
189
+ /** iframe slide height. */
190
+ iframeHeight: string;
191
+ /** iframe slide max width. */
192
+ iframeMaxWidth: string;
193
+ /** iframe slide max height. */
194
+ iframeMaxHeight: string;
195
+ /** Show the download button. */
196
+ download: boolean;
197
+ /** Show the slide counter. */
198
+ counter: boolean;
199
+ /** Minimum swipe distance in px to change slides. */
200
+ swipeThreshold: number;
201
+ /**
202
+ * Release velocity (px/ms, measured over the gesture's final
203
+ * ~100ms) at which a short swipe still changes slides — a flick.
204
+ */
205
+ flickVelocity: number;
206
+ /**
207
+ * Pinching down on an un-zoomed image and releasing closes the
208
+ * gallery (iOS Photos). Guarded: a pinch that went past fit zoom
209
+ * at any point is a zoom correction and never closes. Requires
210
+ * `closable`.
211
+ */
212
+ pinchToClose: boolean;
213
+ /** Enable touch swipe. */
214
+ enableSwipe: boolean;
215
+ /** Enable desktop mouse drag. */
216
+ enableDrag: boolean;
217
+ /**
218
+ * Large-gallery virtualization (plan 010). Off when undefined — the
219
+ * 2.x behavior: every thumbnail renders and the mounted-slide window
220
+ * is `numberOfSlideItemsInDom`. `slides` overrides the mounted-slide
221
+ * pool size; `thumbs` turns on thumbnail-strip windowing (only the
222
+ * visible thumbs plus an overscan render, with spacers preserving the
223
+ * strip geometry) — a number is the overscan thumb count per side,
224
+ * 'auto' derives one extra viewport per side. The window advances at
225
+ * commit points (release, slide change, resize), never per
226
+ * pointermove — interaction stays zero-reactivity.
227
+ */
228
+ virtualization?: VirtualizationSettings;
229
+ /**
230
+ * Announce slide changes to assistive technology through a dedicated
231
+ * polite live region (`strings.slideAnnouncement` + the slide caption).
232
+ * While enabled, the counter and caption bar are not separate live
233
+ * regions — the announcer is the single source of slide-change
234
+ * announcements. Set to `false` to restore the 2.x behavior (live
235
+ * counter and caption, no announcer).
236
+ */
237
+ ariaAnnouncements: boolean;
238
+ /** Localizable UI strings. */
239
+ strings: GalleryCoreStrings;
240
+ /** Detect mobile devices; defaults to a UA sniff in the framework layer. */
241
+ isMobile?: () => boolean;
242
+ /** Settings overrides applied when a mobile device is detected. */
243
+ mobileSettings: MobileSettings;
244
+ }
245
+ export type MobileSettings = Partial<Omit<CoreSettings, 'mobileSettings' | 'isMobile'>>;
246
+ /** User-facing shape: everything optional, strings mergeable per-key. */
247
+ export type UserSettings = Partial<Omit<CoreSettings, 'strings'>> & {
248
+ strings?: Partial<GalleryCoreStrings>;
249
+ };
250
+ export declare const coreSettingsDefaults: CoreSettings;
251
+ export interface ResolveSettingsOptions {
252
+ /**
253
+ * Whether the current device is mobile — decided by the framework layer
254
+ * (headless cannot touch `navigator`). Applies `mobileSettings`.
255
+ */
256
+ isMobile?: boolean;
257
+ /**
258
+ * Plugin default settings merged below user settings (plugin runtime). Merged
259
+ * left-to-right, never mutating any input.
260
+ */
261
+ pluginDefaults?: ReadonlyArray<Partial<CoreSettings>>;
262
+ }
263
+ /**
264
+ * Merge defaults + plugin defaults + user settings + mobile overrides into a
265
+ * resolved settings object. Non-mutating by construction: every input object
266
+ * is left untouched (2.x mutated `settings` in place; 3.x never does).
267
+ */
268
+ export declare function resolveSettings(user?: UserSettings, options?: ResolveSettingsOptions): CoreSettings;
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Share link builders + Web Share payload logic for the share plugin. The
3
+ * URL builders are ported from the 2.x `lg-*-share-utils` files as pure
4
+ * functions — the page URL fallback is a parameter instead of
5
+ * `window.location.href`. The Web Share helpers are pure too: the runtime
6
+ * hands in a structural `navigator` so nothing here touches the DOM.
7
+ */
8
+ /**
9
+ * Structural slice of a gallery item the share builders read — kept
10
+ * narrow so any runtime's item shape (including the 2.x vanilla one)
11
+ * satisfies it without casts.
12
+ */
13
+ export interface ShareItemFields {
14
+ src?: string;
15
+ alt?: string;
16
+ title?: string;
17
+ shareUrl?: string;
18
+ facebookShareUrl?: string;
19
+ tweetText?: string;
20
+ twitterShareUrl?: string;
21
+ pinterestShareUrl?: string;
22
+ pinterestText?: string;
23
+ }
24
+ export declare function getFacebookShareLink(item: ShareItemFields, currentUrl: string): string;
25
+ /**
26
+ * X (formerly Twitter) intent URL. The 2.x `tweetText`/`twitterShareUrl`
27
+ * item fields (and their `data-tweet-text` style attributes) keep working —
28
+ * only the target changed. Unlike the 2.x builder the text is URL-encoded.
29
+ */
30
+ export declare function getXShareLink(item: ShareItemFields, currentUrl: string): string;
31
+ /** @deprecated Renamed — use {@link getXShareLink} (X intent URL). */
32
+ export declare const getTwitterShareLink: typeof getXShareLink;
33
+ export declare function getPinterestShareLink(item: ShareItemFields, currentUrl: string): string;
34
+ /**
35
+ * Data handed to `navigator.share`. URL-sharing only by design: attaching
36
+ * the image itself would require fetching cross-origin bytes (a proxy),
37
+ * which the share plugin will not do.
38
+ */
39
+ export interface SharePayload {
40
+ title?: string;
41
+ text?: string;
42
+ url: string;
43
+ }
44
+ /**
45
+ * Build the Web Share payload for a slide. The per-item `shareUrl` wins,
46
+ * then the network-specific share URLs, then the page URL; text falls back
47
+ * from the tweet text to the Pinterest description.
48
+ */
49
+ export declare function getSharePayload(item: ShareItemFields, currentUrl: string): SharePayload;
50
+ /** Structural slice of `navigator` the Web Share decision needs. */
51
+ export interface NativeShareNavigator {
52
+ share?: (data: SharePayload) => Promise<void>;
53
+ canShare?: (data: SharePayload) => boolean;
54
+ }
55
+ /**
56
+ * True when the runtime can hand this payload to the OS share sheet.
57
+ * Feature-detected and never load-bearing: no `navigator.share` (or a
58
+ * `canShare` veto) simply keeps the branded dropdown menu.
59
+ */
60
+ export declare function canNativeShare(nav: NativeShareNavigator | undefined | null, payload: SharePayload): boolean;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Gesture-release physics: momentum projection and a damped-spring
3
+ * stepper. Releases compute where momentum would land (`project`),
4
+ * clamp that into bounds, and animate there with a spring seeded by the
5
+ * live release velocity — velocity stays continuous across the
6
+ * finger-lift boundary, which is most of what native feel is.
7
+ *
8
+ * The stepper advances the standard damped harmonic oscillator by its
9
+ * closed-form solution over each frame, so step size never affects the
10
+ * trajectory and the state (position + velocity) can re-seed a new
11
+ * spring at any interruption point.
12
+ */
13
+ export interface SpringState {
14
+ position: number;
15
+ /** px per ms (same unit as the windowed gesture velocity). */
16
+ velocity: number;
17
+ }
18
+ export interface SpringConfig {
19
+ /** 1 = never overshoot; < 1 overshoots and returns. */
20
+ dampingRatio?: number;
21
+ /** Rad/s — higher settles faster. */
22
+ naturalFrequency?: number;
23
+ }
24
+ /** Settling toward an in-bounds target: no overshoot. */
25
+ export declare const SPRING_SETTLE_DAMPING = 1;
26
+ /** Settling against a clamped bound: one soft bounce. */
27
+ export declare const SPRING_BOUNCE_DAMPING = 0.82;
28
+ export declare const SPRING_NATURAL_FREQUENCY = 12;
29
+ /**
30
+ * Momentum projection: how far a release keeps traveling when it loses
31
+ * `1 - decelerationRate` of its velocity every millisecond (the classic
32
+ * scroll-view constant; 0.995 ≈ half a percent per ms).
33
+ */
34
+ export declare const DECELERATION_RATE = 0.995;
35
+ export declare function project(velocity: number, decelerationRate?: number): number;
36
+ /**
37
+ * Advance a spring toward `target` by `dtMs`, exactly (closed form with
38
+ * the current state as initial conditions).
39
+ */
40
+ export declare function stepSpring(state: SpringState, target: number, dtMs: number, { dampingRatio, naturalFrequency, }?: SpringConfig): SpringState;
41
+ /** Whether a spring is close enough to stop animating. */
42
+ export declare function isSpringSettled(state: SpringState, target: number, restDelta?: number, restVelocity?: number): boolean;
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Framework-free gallery state machine. React (and later Angular/Vue) wrap
3
+ * this with their own reactivity; every transition lives here so behavior is
4
+ * identical across frameworks and testable without any DOM.
5
+ */
6
+ export type SlideDirection = 'next' | 'prev';
7
+ export interface GalleryState {
8
+ open: boolean;
9
+ currentIndex: number;
10
+ previousIndex: number;
11
+ slidesCount: number;
12
+ loop: boolean;
13
+ /**
14
+ * True once any slide media has finished loading (or failed) since the
15
+ * gallery opened — 2.x `lGalleryOn`. Distinguishes the first slide
16
+ * (backdrop/zoom entrance, no slide animation) from navigation.
17
+ */
18
+ galleryOn: boolean;
19
+ /**
20
+ * True while a slide transition runs — 2.x `lgBusy`. Navigation actions
21
+ * are ignored until `TRANSITION_END`.
22
+ */
23
+ transitioning: boolean;
24
+ /** Direction of the last navigation; drives prev/next slide classes. */
25
+ slideDirection?: SlideDirection;
26
+ /** Indexes whose media has fully loaded (`lg-complete`). */
27
+ loadedSlides: ReadonlySet<number>;
28
+ }
29
+ export type GalleryAction = {
30
+ type: 'OPEN';
31
+ index?: number;
32
+ } | {
33
+ type: 'CLOSE';
34
+ } | {
35
+ type: 'GO_TO';
36
+ index: number;
37
+ direction?: SlideDirection;
38
+ } | {
39
+ type: 'NEXT';
40
+ } | {
41
+ type: 'PREV';
42
+ } | {
43
+ type: 'SET_SLIDES_COUNT';
44
+ count: number;
45
+ } | {
46
+ type: 'SET_LOOP';
47
+ loop: boolean;
48
+ } | {
49
+ type: 'SLIDE_LOADED';
50
+ index: number;
51
+ } | {
52
+ type: 'SLIDE_ERROR';
53
+ index: number;
54
+ } | {
55
+ type: 'TRANSITION_END';
56
+ };
57
+ export interface CreateGalleryStateOptions {
58
+ slidesCount: number;
59
+ loop?: boolean;
60
+ index?: number;
61
+ }
62
+ export declare function createGalleryState(options: CreateGalleryStateOptions): GalleryState;
63
+ export declare function galleryReducer(state: GalleryState, action: GalleryAction): GalleryState;
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Thumbnail strip math (2.x `animateThumb`/`getPossibleTransformX`) as pure
3
+ * functions for the thumbnail plugin.
4
+ */
5
+ import type { ResolvedGalleryDirection } from './settings';
6
+ export type ThumbPagerPosition = 'left' | 'middle' | 'right';
7
+ /**
8
+ * Rubber-band a raw strip translate (plan 010 physics): inside the
9
+ * bounds it passes through; beyond an edge the overshoot compresses by
10
+ * the shared edge friction so the strip resists like the slide gestures.
11
+ * The release spring pulls the compressed overshoot back to the bound.
12
+ */
13
+ export declare function getElasticThumbTranslate(raw: number, totalWidth: number, stripWidth: number, friction?: number): number;
14
+ export declare function getThumbTotalWidth(count: number, thumbWidth: number, thumbMargin: number): number;
15
+ /** Clamp a strip translate into `[0, total - visible]` (never negative). */
16
+ export declare function clampThumbTranslate(translate: number, totalWidth: number, stripWidth: number): number;
17
+ /**
18
+ * The window of thumbnails that must exist in the DOM for a given strip
19
+ * translate (plan 010 virtualization): the visible range plus `overscan`
20
+ * thumbs on each side, with leading/trailing pad widths so the strip keeps
21
+ * its full scroll geometry while only the window renders.
22
+ */
23
+ export interface ThumbWindow {
24
+ /** First rendered thumb index (inclusive). */
25
+ start: number;
26
+ /** Last rendered thumb index (inclusive). */
27
+ end: number;
28
+ /** Spacer width (px) standing in for the thumbs before `start`. */
29
+ leadingPad: number;
30
+ /** Spacer width (px) standing in for the thumbs after `end`. */
31
+ trailingPad: number;
32
+ }
33
+ /**
34
+ * Compute the rendered thumb window from the strip translate. `overscan`
35
+ * is the number of extra thumbs kept mounted on each side of the visible
36
+ * range ('auto' derives one extra viewport per side — enough that a full
37
+ * flick lands on already-rendered thumbs).
38
+ */
39
+ export declare function getThumbWindow(options: {
40
+ translate: number;
41
+ stripWidth: number;
42
+ thumbWidth: number;
43
+ thumbMargin: number;
44
+ count: number;
45
+ overscan?: number | 'auto';
46
+ }): ThumbWindow;
47
+ /**
48
+ * Window covering a fling's whole flight path (plan 010): the union of
49
+ * the windows at the start and end translates, so a released strip never
50
+ * glides over unrendered thumbs — the destination is known at release.
51
+ */
52
+ export declare function getThumbCorridorWindow(options: {
53
+ from: number;
54
+ to: number;
55
+ stripWidth: number;
56
+ thumbWidth: number;
57
+ thumbMargin: number;
58
+ count: number;
59
+ overscan?: number | 'auto';
60
+ }): ThumbWindow;
61
+ /**
62
+ * Which slide a live strip translate selects in scrub mode (the strip
63
+ * drives the gallery while it moves). Proportional: the strip's full
64
+ * scroll travel maps onto the full index range, so the FIRST and LAST
65
+ * slides are always reachable — a fixed pager-point inverse cannot
66
+ * reach the ends, because the clamped translate never brings them
67
+ * under the pager slot. For long strips this converges to one index
68
+ * per thumb unit of travel. Translate is the logical strip scalar
69
+ * (RTL-agnostic); elastic overshoot clamps, pinning the ends.
70
+ * Exact inverse: {@link getScrubThumbTranslate}.
71
+ */
72
+ export declare function getScrubThumbIndex(translate: number, totalWidth: number, stripWidth: number, count: number): number;
73
+ /**
74
+ * Strip translate at which {@link getScrubThumbIndex} resolves exactly
75
+ * `index` — for aligning the strip to the scrubbed slide after the
76
+ * release glide settles. (Not `getActiveThumbTranslate`: that pager
77
+ * alignment is a different map and would re-resolve to a neighboring
78
+ * index near the ends.)
79
+ */
80
+ export declare function getScrubThumbTranslate(index: number, totalWidth: number, stripWidth: number, count: number): number;
81
+ /**
82
+ * Strip translate that brings the active thumbnail to the pager position
83
+ * (2.x `animateThumb`, including its off-by-one `- 1`).
84
+ */
85
+ export declare function getActiveThumbTranslate(index: number, thumbWidth: number, thumbMargin: number, stripWidth: number, totalWidth: number, pagerPosition: ThumbPagerPosition, direction?: ResolvedGalleryDirection): number;
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Toolbar overflow: when the toolbar's icon buttons do not fit on one row
3
+ * beside the counter, the lowest-priority buttons move into a "More
4
+ * options" menu. Pure layout arithmetic over measured widths; each runtime
5
+ * measures its own DOM, applies the result and renders the menu.
6
+ */
7
+ /** Priority of a button that never moves into the menu (close). */
8
+ export declare const TOOLBAR_PINNED: number;
9
+ /** Priority of a button the table does not know (custom plugin buttons). */
10
+ export declare const TOOLBAR_DEFAULT_PRIORITY = 20;
11
+ /** Overflow priority of a toolbar button from its class names. */
12
+ export declare function getToolbarItemPriority(classList: Iterable<string>): number;
13
+ export interface ToolbarOverflowItem {
14
+ /** Measured width, px. */
15
+ width: number;
16
+ /** From {@link getToolbarItemPriority}; higher stays longer. */
17
+ priority: number;
18
+ }
19
+ export interface ToolbarOverflowInput {
20
+ /** Width of the toolbar row, px. */
21
+ available: number;
22
+ /** Width taken by content that never moves (the counter), px. */
23
+ reserved: number;
24
+ /** Width of the More button, px. */
25
+ moreWidth: number;
26
+ /** The toolbar's icon buttons, in DOM order. */
27
+ items: readonly ToolbarOverflowItem[];
28
+ }
29
+ /**
30
+ * Indices (in DOM order) of the buttons that move into the menu; empty
31
+ * when everything fits, or when the toolbar has no width yet (not laid
32
+ * out). Lowest priority moves first; among equals, the button later in
33
+ * DOM order goes first, which is the one furthest from the close button.
34
+ * The More button's own width is paid as soon as anything moves.
35
+ */
36
+ export declare function getToolbarOverflow({ available, reserved, moreWidth, items, }: ToolbarOverflowInput): number[];
37
+ /**
38
+ * Whether a click's event path runs through the toolbar. Clicks there are
39
+ * controls, not a tap on the backdrop: Medium zoom closes on the latter
40
+ * only. The path (`event.composedPath()`) still lists a More menu item the
41
+ * click already removed from the document.
42
+ */
43
+ export declare function isToolbarEventPath(path: readonly unknown[]): boolean;
44
+ /** What the dismissal of a toolbar menu reads from the dismissing press. */
45
+ export interface MenuDismissEvent {
46
+ target: unknown;
47
+ preventDefault(): void;
48
+ stopPropagation(): void;
49
+ }
50
+ /**
51
+ * A press outside an open toolbar menu (the More options menu, the share
52
+ * dropdown) dismisses it. A press on a control passes through, so one
53
+ * click on another toolbar button both dismisses the menu and runs the
54
+ * button. A press on the backdrop around the slide is consumed instead:
55
+ * there the gallery's own tap-to-close and drag would fire, and
56
+ * dismissing a menu must not also close the gallery. Cancelling the
57
+ * pointerdown suppresses the compatibility mouse events the vanilla
58
+ * runtime listens to; stopping it keeps the pointer-driven runtimes'
59
+ * handlers from arming. Returns whether the press was consumed.
60
+ */
61
+ export declare function consumeBackdropPress(event: MenuDismissEvent): boolean;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Settle gate for a CSS transition: call back once the transition of
3
+ * `property` on `element` has actually ended.
4
+ *
5
+ * A fixed timer measured from the moment the target value is applied
6
+ * lands at the same wall-clock offset whether or not the transition has
7
+ * started, but the transition only starts at the first style recalc
8
+ * after the value lands — on a busy main thread (a gallery's first
9
+ * layout, a big thumbnail decode) that can be well past the offset.
10
+ * Anything gated on the fixed timer then fires mid-flight.
11
+ *
12
+ * Contract:
13
+ * - No `transitionstart` within `fallbackMs` → the element is not
14
+ * transitioning (reduced motion, identity transform, no CSS) and the
15
+ * gate settles on the timer, exactly like the fixed timer did.
16
+ * - `transitionstart` re-bases the timer on the real start; `transitionend`
17
+ * settles immediately. Interrupted transitions (`transitioncancel`)
18
+ * leave the timer running so a restart still settles in time.
19
+ * - Events bubbling from descendants, or for other properties, are
20
+ * ignored. The callback runs at most once.
21
+ *
22
+ * Returns a disposer; disposing after settle is a no-op.
23
+ */
24
+ export interface TransitionSettleEvent {
25
+ target: unknown;
26
+ propertyName?: string;
27
+ }
28
+ /** Structural slice of a DOM element: headless carries no DOM lib. */
29
+ export interface TransitionSettleTarget {
30
+ addEventListener(type: string, listener: (event: TransitionSettleEvent) => void): void;
31
+ removeEventListener(type: string, listener: (event: TransitionSettleEvent) => void): void;
32
+ }
33
+ export declare function onTransitionSettle(element: TransitionSettleTarget, property: string, fallbackMs: number, callback: () => void): () => void;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Rolling-window velocity tracking. Release decisions must read the
3
+ * velocity of the gesture's final instant, not its whole-gesture
4
+ * average: a drag that pauses and then flicks reads fast, and a drag
5
+ * that ends resting reads zero. Sessions push a sample per move; the
6
+ * release reads the window ending at the release timestamp.
7
+ */
8
+ export interface VelocitySample {
9
+ x: number;
10
+ y: number;
11
+ /** Timestamp in ms (same clock as the release read). */
12
+ t: number;
13
+ }
14
+ export interface Velocity {
15
+ /** px/ms, signed. */
16
+ x: number;
17
+ y: number;
18
+ }
19
+ /** How far back a release looks when reading the gesture velocity. */
20
+ export declare const VELOCITY_WINDOW_MS = 100;
21
+ /**
22
+ * Append a sample, pruning everything older than the window — the
23
+ * buffer stays a handful of entries regardless of gesture length.
24
+ */
25
+ export declare function pushVelocitySample(samples: readonly VelocitySample[], sample: VelocitySample, windowMs?: number): VelocitySample[];
26
+ /**
27
+ * Velocity (px/ms per axis) over the samples inside the window ending
28
+ * at `releaseTime`. Fewer than two recent samples — the finger rested
29
+ * before lifting — reads as zero, as does sub-pixel drift.
30
+ */
31
+ export declare function getWindowedVelocity(samples: readonly VelocitySample[], releaseTime: number, windowMs?: number): Velocity;