@enigmax/primitives 0.25.0 → 0.26.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/dist/chunk-4SZ5N7BA.js +121 -0
- package/dist/chunk-EYZ366LP.js +189 -0
- package/dist/chunk-ISXB5RUH.js +380 -0
- package/dist/chunk-JJVZYW5C.js +946 -0
- package/dist/chunk-QIIV2QSV.js +108 -0
- package/dist/chunk-RUEQ3TGP.js +155 -0
- package/dist/clipboard-menu-BvXJCSFN.d.ts +93 -0
- package/dist/context-BfjYGPnH.d.ts +54 -0
- package/dist/{clipboard-menu-B_ouitfS.d.ts → context-menu-D3FtTn7v.d.ts} +1 -91
- package/dist/index.d.ts +266 -2
- package/dist/index.js +4 -2
- package/dist/menu-MSQSE6U5.js +54 -0
- package/dist/menu-PNQRTRNV.js +33 -0
- package/dist/next/index.d.ts +6 -2
- package/dist/next/index.js +10 -6
- package/dist/react/context-menu.d.ts +8 -54
- package/dist/react/image.d.ts +109 -0
- package/dist/react/image.js +3 -0
- package/dist/react/index.d.ts +6 -2
- package/dist/react/index.js +10 -6
- package/dist/react/input.js +1 -1
- package/dist/react/video.d.ts +120 -0
- package/dist/react/video.js +3 -0
- package/dist/react-router/index.d.ts +6 -2
- package/dist/react-router/index.js +10 -6
- package/dist/viewer-73LSE6RR.js +3 -0
- package/package.json +15 -2
- package/recipes/image/styles.css +182 -0
- package/recipes/video/styles.css +154 -0
- package/registry.json +465 -0
- package/src/core/image-viewer.ts +222 -0
- package/src/core/player.ts +303 -0
- package/src/index.ts +52 -0
- package/src/react/image/icons.tsx +55 -0
- package/src/react/image/index.tsx +185 -0
- package/src/react/image/menu.tsx +76 -0
- package/src/react/image/styles.ts +213 -0
- package/src/react/image/types.ts +113 -0
- package/src/react/image/viewer.tsx +571 -0
- package/src/react/index.ts +3 -0
- package/src/react/video/icons.tsx +135 -0
- package/src/react/video/index.tsx +724 -0
- package/src/react/video/menu.tsx +66 -0
- package/src/react/video/rail.tsx +99 -0
- package/src/react/video/styles.ts +161 -0
- package/src/react/video/types.ts +135 -0
- /package/dist/{chunk-3MGBZOAU.js → chunk-RMNXVWQ4.js} +0 -0
- /package/dist/{chunk-MSOCCQGH.js → chunk-T7I6WJSN.js} +0 -0
package/dist/index.d.ts
CHANGED
|
@@ -9,7 +9,8 @@ export { R as RelativeTimeFormat, a as RelativeTimeOptions, b as RelativeTimePre
|
|
|
9
9
|
export { F as FLAG_CDN, a as FLAG_RATIO, b as FlagConfig, c as FlagFormat, d as FlagOptions, e as FlagShape, f as FlagSource, g as FlagView, h as configureFlags, i as flagAttributes, j as flagConfig, k as flagName, l as flagSrc, m as flagView, n as normalizeFlagCode, r as resetFlagConfig } from './flags-BQU1V9rE.js';
|
|
10
10
|
export { P as PaletteKey, a as PositionedRow, R as RecentEntry, b as RecentStore, c as RecentStoreOptions, d as RowGroup, e as createRecentStore, g as groupRows, i as isPaletteShortcut, m as moveActive, r as recentKey, s as shortcutLabel } from './palette-D7iuQh_T.js';
|
|
11
11
|
export { S as SELECT_SEARCH_KEYS, a as SelectInstance, b as SelectMoveKey, c as SelectOption, d as SelectOptions, e as SelectState, f as createSelect } from './select-ClSy-J1f.js';
|
|
12
|
-
export { C as
|
|
12
|
+
export { C as CONTEXT_MENU_SEARCH_KEYS, a as ContextMenuAction, b as ContextMenuEntry, c as ContextMenuInstance, d as ContextMenuLabel, e as ContextMenuLevel, f as ContextMenuMoveKey, g as ContextMenuOptions, h as ContextMenuPoint, i as ContextMenuSeparator, j as ContextMenuState, k as createContextMenu, l as isAction } from './context-menu-D3FtTn7v.js';
|
|
13
|
+
export { C as CLIPBOARD_PREFIX, a as ClipboardAction, b as ClipboardMenuLabels, c as ClipboardMenuOptions, d as ClipboardTarget, e as clipboardAction, f as clipboardEntries, g as clipboardHasText, i as inspectClipboardTarget, p as performClipboardAction } from './clipboard-menu-BvXJCSFN.js';
|
|
13
14
|
export { D as DEFAULT_SELECTION_SHORTCUTS, S as SelectionClickModifiers, a as SelectionCommand, b as SelectionCommandEvent, c as SelectionCommandName, d as SelectionInstance, e as SelectionOptions, f as SelectionShortcuts, g as SelectionState, h as createSelection } from './selection-B_pmzHpy.js';
|
|
14
15
|
export { S as Shortcut, a as ShortcutEvent, b as ShortcutSpec, T as TYPEAHEAD_MS, c as TypeaheadState, d as TypeaheadStep, i as isApplePlatform, m as matchesShortcut, p as parseShortcut, s as shortcutList, e as shortcutText, f as shortcutTokens, t as typeaheadStep } from './keys-D2zJs1uB.js';
|
|
15
16
|
|
|
@@ -39,4 +40,267 @@ declare const INPUT_ICON_PATHS: {
|
|
|
39
40
|
/** The same shapes as a standalone SVG string, for the DOM renderer below. */
|
|
40
41
|
declare function iconMarkup(paths: readonly string[]): string;
|
|
41
42
|
|
|
42
|
-
|
|
43
|
+
/**
|
|
44
|
+
* The arithmetic behind the image viewer: zoom around a point, panning that cannot lose the
|
|
45
|
+
* image, moving through a set, and getting a file onto the disk.
|
|
46
|
+
*
|
|
47
|
+
* Not a React module, and deliberately: none of this is rendering. A page drawing its own
|
|
48
|
+
* viewer, or a test, gets the same maths - and the parts that are easy to get wrong (zoom
|
|
49
|
+
* that drifts away from the cursor, a pan that strands the image off screen, a download that
|
|
50
|
+
* silently opens a tab instead) are then testable without a browser.
|
|
51
|
+
*/
|
|
52
|
+
/** How far the image is scaled, and where its centre sits relative to the frame's, in px. */
|
|
53
|
+
interface Transform {
|
|
54
|
+
scale: number;
|
|
55
|
+
x: number;
|
|
56
|
+
y: number;
|
|
57
|
+
}
|
|
58
|
+
interface ZoomLimits {
|
|
59
|
+
min: number;
|
|
60
|
+
max: number;
|
|
61
|
+
}
|
|
62
|
+
/** A box in viewport coordinates - the frame the image is being viewed in. */
|
|
63
|
+
interface Box {
|
|
64
|
+
left: number;
|
|
65
|
+
top: number;
|
|
66
|
+
width: number;
|
|
67
|
+
height: number;
|
|
68
|
+
}
|
|
69
|
+
declare const IDENTITY: Transform;
|
|
70
|
+
declare const ZOOM_LIMITS: ZoomLimits;
|
|
71
|
+
/** What a keyboard `+`/`-` step multiplies by, and the ratio a double press toggles to. */
|
|
72
|
+
declare const ZOOM_STEP = 1.35;
|
|
73
|
+
declare const ZOOM_DOUBLE = 2.5;
|
|
74
|
+
declare function clampScale(scale: number, limits?: ZoomLimits): number;
|
|
75
|
+
/**
|
|
76
|
+
* A wheel notch to a zoom factor.
|
|
77
|
+
*
|
|
78
|
+
* `deltaMode` matters: a mouse reports pixels, but Firefox reports LINES (mode 1) and a page
|
|
79
|
+
* scroll reports pages (mode 2), so treating every delta as pixels makes the same gesture
|
|
80
|
+
* zoom a hundred times harder in one browser than another. The exponential keeps a notch
|
|
81
|
+
* proportional - zooming out from 8x and in from 1x take the same number of turns.
|
|
82
|
+
*/
|
|
83
|
+
declare function wheelFactor(deltaY: number, deltaMode?: number): number;
|
|
84
|
+
/**
|
|
85
|
+
* Zoom, keeping the point under the pointer under the pointer.
|
|
86
|
+
*
|
|
87
|
+
* The defect this exists for: scaling around the frame's centre slides whatever the visitor
|
|
88
|
+
* was pointing at out from under them, so zooming into a face means zooming and then hunting
|
|
89
|
+
* for it again. The offset is corrected by how much that point moved when the scale changed.
|
|
90
|
+
*/
|
|
91
|
+
declare function zoomAt(current: Transform, factor: number, point: {
|
|
92
|
+
x: number;
|
|
93
|
+
y: number;
|
|
94
|
+
}, box: Box, limits?: ZoomLimits): Transform;
|
|
95
|
+
/**
|
|
96
|
+
* Keep the image over the frame.
|
|
97
|
+
*
|
|
98
|
+
* At 1x it is centred and there is nothing to pan. Zoomed, the offset is bounded by the half
|
|
99
|
+
* of the image that hangs outside the frame - without it a drag can throw the picture off the
|
|
100
|
+
* screen entirely, and the only way back is to close the viewer.
|
|
101
|
+
*/
|
|
102
|
+
declare function clampPan(transform: Transform, box: Box, natural: {
|
|
103
|
+
width: number;
|
|
104
|
+
height: number;
|
|
105
|
+
}): Transform;
|
|
106
|
+
/** The size an image is DRAWN at inside a frame it is fitted to, which is what pan is bounded by. */
|
|
107
|
+
declare function fittedSize(natural: {
|
|
108
|
+
width: number;
|
|
109
|
+
height: number;
|
|
110
|
+
}, box: Box): {
|
|
111
|
+
width: number;
|
|
112
|
+
height: number;
|
|
113
|
+
};
|
|
114
|
+
/** The distance between two pointers, for a pinch. */
|
|
115
|
+
declare function pinchDistance(a: {
|
|
116
|
+
x: number;
|
|
117
|
+
y: number;
|
|
118
|
+
}, b: {
|
|
119
|
+
x: number;
|
|
120
|
+
y: number;
|
|
121
|
+
}): number;
|
|
122
|
+
/**
|
|
123
|
+
* The next index in a set, skipping what has been discarded.
|
|
124
|
+
*
|
|
125
|
+
* Returns -1 when there is nothing left to show, which is the viewer's cue to close rather
|
|
126
|
+
* than to sit on an empty frame.
|
|
127
|
+
*/
|
|
128
|
+
declare function nextIndex(index: number, length: number, step: number, options?: {
|
|
129
|
+
loop?: boolean;
|
|
130
|
+
skip?: ReadonlySet<number>;
|
|
131
|
+
}): number;
|
|
132
|
+
/** The file name to save as: whatever the caller asked for, else the one in the URL. */
|
|
133
|
+
declare function filenameFrom(url: string, fallback?: string): string;
|
|
134
|
+
/**
|
|
135
|
+
* Save the file, rather than navigate to it.
|
|
136
|
+
*
|
|
137
|
+
* `<a download>` is honoured only for a same-origin URL; on a CDN the browser ignores the
|
|
138
|
+
* attribute and opens the image in a tab instead, which is not what the row said it would do.
|
|
139
|
+
* So the bytes are fetched and handed over as a blob, and the plain anchor is the fallback for
|
|
140
|
+
* when that is refused (no CORS header) - a tab is still better than nothing happening.
|
|
141
|
+
*/
|
|
142
|
+
declare function downloadFile(url: string, filename?: string): Promise<void>;
|
|
143
|
+
/** How long the picture takes to fly, when the stylesheet does not say otherwise. */
|
|
144
|
+
declare const FLIGHT_MS = 300;
|
|
145
|
+
/**
|
|
146
|
+
* How long the flight ACTUALLY lasts, read off the element.
|
|
147
|
+
*
|
|
148
|
+
* The duration lives in the stylesheet (`--enigma-image-flight`), so a project that slows it
|
|
149
|
+
* down would otherwise have the viewer give up waiting halfway through and close mid-flight.
|
|
150
|
+
* The constant above is only the answer for an element with no transition on it at all.
|
|
151
|
+
*/
|
|
152
|
+
declare function flightMs(element: Element | null): number;
|
|
153
|
+
/**
|
|
154
|
+
* The transform that puts a picture exactly over another box.
|
|
155
|
+
*
|
|
156
|
+
* This is the FLIP the lightbox opens with: the full-size image is laid out where it belongs,
|
|
157
|
+
* measured, and then drawn back ON the thumbnail with this transform - so releasing it to the
|
|
158
|
+
* identity transform is the picture growing out of the one in the page rather than a dialog
|
|
159
|
+
* appearing over it. Closing is the same transform applied in the other direction.
|
|
160
|
+
*
|
|
161
|
+
* Both boxes are the same picture, so one scale is enough; the width is used because a
|
|
162
|
+
* thumbnail is nearly always constrained by it. Null when either box has not been laid out
|
|
163
|
+
* yet, which is the caller's cue to skip the animation rather than to divide by zero.
|
|
164
|
+
*/
|
|
165
|
+
declare function flightFrom(from: Box, to: Box): Transform | null;
|
|
166
|
+
/** Whether the reader has asked for less movement. Every animation here is skipped when they have. */
|
|
167
|
+
declare function prefersReducedMotion(): boolean;
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* The arithmetic behind the video player: times, seeking, buffering, volume and the keys.
|
|
171
|
+
*
|
|
172
|
+
* None of it is rendering, so it is testable without a browser and reusable by a page that
|
|
173
|
+
* draws its own controls - the same split the colour maths and the image viewer's are in.
|
|
174
|
+
*/
|
|
175
|
+
/** The playback rates the settings menu offers, in the order it lists them. */
|
|
176
|
+
declare const SPEEDS: readonly [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2];
|
|
177
|
+
/** How far the arrows seek, in seconds, and what a bigger jump moves by. */
|
|
178
|
+
declare const SEEK_STEP = 5;
|
|
179
|
+
declare const SEEK_JUMP = 10;
|
|
180
|
+
declare const VOLUME_STEP = 0.05;
|
|
181
|
+
/**
|
|
182
|
+
* Seconds as a clock, sized by the LONGEST time it will have to show.
|
|
183
|
+
*
|
|
184
|
+
* `duration` is what stops the label changing width mid-playback: a 1h04m video passing 10:00
|
|
185
|
+
* would otherwise go from `9:59` to `10:00` to `1:00:00`, and every control after it moves.
|
|
186
|
+
*/
|
|
187
|
+
declare function formatTime(seconds: number, duration?: number): string;
|
|
188
|
+
/** A time as a fraction of the duration, safe before the metadata says what that is. */
|
|
189
|
+
declare function progress(time: number, duration: number): number;
|
|
190
|
+
/** Where a press on a horizontal rail lands, as a fraction of it. */
|
|
191
|
+
declare function fractionAt(box: {
|
|
192
|
+
left: number;
|
|
193
|
+
width: number;
|
|
194
|
+
}, clientX: number): number;
|
|
195
|
+
/**
|
|
196
|
+
* How much is buffered AHEAD of where playback is.
|
|
197
|
+
*
|
|
198
|
+
* The range under the playhead, not the largest one: a viewer who seeks past the buffer is
|
|
199
|
+
* looking at a bar that says nothing is loaded, which is true of the part they are watching.
|
|
200
|
+
*/
|
|
201
|
+
declare function bufferedAhead(ranges: TimeRanges | null, time: number, duration: number): number;
|
|
202
|
+
/** The next rate in the list, wrapping - what a repeated press on the speed row does. */
|
|
203
|
+
declare function nextSpeed(current: number, step?: number): number;
|
|
204
|
+
/** What a key press means, or null when the player should leave it to the page. */
|
|
205
|
+
type PlayerCommand = {
|
|
206
|
+
type: "toggle";
|
|
207
|
+
} | {
|
|
208
|
+
type: "seek";
|
|
209
|
+
by: number;
|
|
210
|
+
} | {
|
|
211
|
+
type: "seekTo";
|
|
212
|
+
fraction: number;
|
|
213
|
+
} | {
|
|
214
|
+
type: "volume";
|
|
215
|
+
by: number;
|
|
216
|
+
} | {
|
|
217
|
+
type: "mute";
|
|
218
|
+
} | {
|
|
219
|
+
type: "fullscreen";
|
|
220
|
+
} | {
|
|
221
|
+
type: "captions";
|
|
222
|
+
} | {
|
|
223
|
+
type: "pip";
|
|
224
|
+
};
|
|
225
|
+
/**
|
|
226
|
+
* The shortcuts, as the platform's video players define them.
|
|
227
|
+
*
|
|
228
|
+
* Space and K play, J and L jump ten, the arrows nudge five and the volume, M mutes, F is
|
|
229
|
+
* fullscreen, C captions, and a digit seeks to that tenth of the video.
|
|
230
|
+
*/
|
|
231
|
+
declare function commandFor(key: string): PlayerCommand | null;
|
|
232
|
+
/**
|
|
233
|
+
* Whether a key press belongs to the page rather than to the player.
|
|
234
|
+
*
|
|
235
|
+
* A shortcut that fires while somebody is typing turns their space bar into a pause, so the
|
|
236
|
+
* player stands down inside anything that takes text.
|
|
237
|
+
*/
|
|
238
|
+
declare function isTypingTarget(target: EventTarget | null): boolean;
|
|
239
|
+
/** Whether the document is showing something fullscreen, across the two spellings of it. */
|
|
240
|
+
declare function fullscreenElement(): Element | null;
|
|
241
|
+
/**
|
|
242
|
+
* Fullscreen, including the one platform that will not give it to a container.
|
|
243
|
+
*
|
|
244
|
+
* iOS Safari has no Fullscreen API on an arbitrary element: the only thing that can fill the
|
|
245
|
+
* screen is the video itself, through `webkitEnterFullscreen`. Without that branch the button
|
|
246
|
+
* does nothing at all on an iPhone, which is where most video is watched.
|
|
247
|
+
*/
|
|
248
|
+
declare function toggleFullscreen(container: HTMLElement, video: HTMLVideoElement | null): Promise<void>;
|
|
249
|
+
/** Picture in picture, where the browser has it. Firefox has its own button and no API. */
|
|
250
|
+
declare function supportsPip(): boolean;
|
|
251
|
+
declare function togglePip(video: HTMLVideoElement): Promise<void>;
|
|
252
|
+
/** One subtitle track, as the menu lists it. */
|
|
253
|
+
interface CaptionTrack {
|
|
254
|
+
/** Where it sits in the element's own `textTracks`, which is what turns it on. */
|
|
255
|
+
index: number;
|
|
256
|
+
label: string;
|
|
257
|
+
language: string;
|
|
258
|
+
}
|
|
259
|
+
/** Which of the element's text tracks are subtitles a viewer would choose between. */
|
|
260
|
+
declare function captionTracks(list: TextTrackList | null | undefined): CaptionTrack[];
|
|
261
|
+
/**
|
|
262
|
+
* The track the element is SHOWING, or -1.
|
|
263
|
+
*
|
|
264
|
+
* Read rather than remembered: a `default` track is showing before any button was pressed, and
|
|
265
|
+
* a player that assumed "off" would need two presses to turn something off.
|
|
266
|
+
*/
|
|
267
|
+
declare function activeCaption(list: TextTrackList | null | undefined): number;
|
|
268
|
+
/**
|
|
269
|
+
* Show one track and disable the rest. -1 turns them all off.
|
|
270
|
+
*
|
|
271
|
+
* "disabled" rather than "hidden": a hidden track still fires its cues, so a page listening to
|
|
272
|
+
* `cuechange` for its own transcript would keep receiving a language nobody asked for.
|
|
273
|
+
*/
|
|
274
|
+
declare function showCaption(list: TextTrackList | null | undefined, index: number): void;
|
|
275
|
+
/** What the cast control knows about the world. */
|
|
276
|
+
interface RemoteState {
|
|
277
|
+
/** There is somewhere to cast TO. Before the browser has looked, this is optimistic. */
|
|
278
|
+
available: boolean;
|
|
279
|
+
/** Playing on that screen right now. */
|
|
280
|
+
connected: boolean;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Whether this element can be cast at all.
|
|
284
|
+
*
|
|
285
|
+
* `disableRemotePlayback` is honoured: a page that asked for the button to be gone does not
|
|
286
|
+
* get one drawn over its video by a component.
|
|
287
|
+
*/
|
|
288
|
+
declare function supportsRemote(video: HTMLVideoElement | null): boolean;
|
|
289
|
+
/**
|
|
290
|
+
* Watch for a screen to cast to, and for the connection to it.
|
|
291
|
+
*
|
|
292
|
+
* WHY AVAILABILITY IS OPTIMISTIC WHEN THE WATCH FAILS. `watchAvailability` rejects with
|
|
293
|
+
* NotSupportedError on the platforms that can still `prompt()` - Safari, and Chromium for some
|
|
294
|
+
* sources - so treating a rejection as "no devices" hides a control that works. A button that
|
|
295
|
+
* opens an empty picker is a smaller loss than a missing one.
|
|
296
|
+
*/
|
|
297
|
+
declare function watchRemote(video: HTMLVideoElement, onChange: (state: RemoteState) => void): () => void;
|
|
298
|
+
/**
|
|
299
|
+
* Open the browser's own device picker.
|
|
300
|
+
*
|
|
301
|
+
* There is no list to draw ourselves: both APIs hand the choice to the platform, which is the
|
|
302
|
+
* only thing that can enumerate the screens on the network.
|
|
303
|
+
*/
|
|
304
|
+
declare function promptRemote(video: HTMLVideoElement): Promise<void>;
|
|
305
|
+
|
|
306
|
+
export { type Box, type CaptionTrack, FLIGHT_MS, IDENTITY, INPUT_ICON_PATHS, type PlayerCommand, type RemoteState, SEEK_JUMP, SEEK_STEP, SPEEDS, type Transform, VOLUME_STEP, ZOOM_DOUBLE, ZOOM_LIMITS, ZOOM_STEP, type ZoomLimits, activeCaption, bufferedAhead, captionTracks, clampPan, clampScale, commandFor, downloadFile, filenameFrom, fittedSize, flightFrom, flightMs, formatTime, fractionAt, fullscreenElement, iconMarkup, isTypingTarget, nextIndex, nextSpeed, pinchDistance, prefersReducedMotion, progress, promptRemote, showCaption, supportsPip, supportsRemote, toggleFullscreen, togglePip, watchRemote, wheelFactor, zoomAt };
|
package/dist/index.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
+
export { FLIGHT_MS, IDENTITY, ZOOM_DOUBLE, ZOOM_LIMITS, ZOOM_STEP, clampPan, clampScale, downloadFile, filenameFrom, fittedSize, flightFrom, flightMs, nextIndex, pinchDistance, prefersReducedMotion, wheelFactor, zoomAt } from './chunk-QIIV2QSV.js';
|
|
1
2
|
export { createInput } from './chunk-KJINGUQN.js';
|
|
3
|
+
export { colorEquals, formatColor, hslToRgb, hsvToRgb, parseColor, rgbToHsl, rgbToHsv, toHex } from './chunk-S2FPN5ID.js';
|
|
4
|
+
export { SERVER_NETWORK_STATE, createNetworkMonitor } from './chunk-2QFTRNAZ.js';
|
|
2
5
|
export { ensureZone, normalizeDate, parseDuration, relativeTimeAttributes, relativeTimeView } from './chunk-IXVMRVD4.js';
|
|
3
6
|
export { estimatePasswordStrength, generatePassword } from './chunk-HC2ME5PU.js';
|
|
4
|
-
export { colorEquals, formatColor, hslToRgb, hsvToRgb, parseColor, rgbToHsl, rgbToHsv, toHex } from './chunk-S2FPN5ID.js';
|
|
5
7
|
export { CLIPBOARD_PREFIX, CONTEXT_MENU_SEARCH_KEYS, clipboardAction, clipboardEntries, clipboardHasText, createContextMenu, inspectClipboardTarget, isAction, performClipboardAction } from './chunk-Z3VDE7OA.js';
|
|
6
8
|
export { DEFAULT_SELECTION_SHORTCUTS, createSelection } from './chunk-WSQC3PCC.js';
|
|
9
|
+
export { SEEK_JUMP, SEEK_STEP, SPEEDS, VOLUME_STEP, activeCaption, bufferedAhead, captionTracks, commandFor, formatTime, fractionAt, fullscreenElement, isTypingTarget, nextSpeed, progress, promptRemote, showCaption, supportsPip, supportsRemote, toggleFullscreen, togglePip, watchRemote } from './chunk-RUEQ3TGP.js';
|
|
7
10
|
export { createButton } from './chunk-MMQPZGSU.js';
|
|
8
11
|
export { FLAG_CDN, FLAG_RATIO, configureFlags, flagAttributes, flagConfig, flagName, flagSrc, flagView, normalizeFlagCode, resetFlagConfig } from './chunk-LMZJBOZG.js';
|
|
9
12
|
export { createNotifications } from './chunk-SNYUBXWQ.js';
|
|
10
13
|
export { createMarquee } from './chunk-UOSSNUSC.js';
|
|
11
|
-
export { SERVER_NETWORK_STATE, createNetworkMonitor } from './chunk-2QFTRNAZ.js';
|
|
12
14
|
export { INPUT_ICON_PATHS, iconMarkup } from './chunk-F25CGNQC.js';
|
|
13
15
|
export { SELECT_SEARCH_KEYS, createSelect } from './chunk-NONGREXC.js';
|
|
14
16
|
export { TYPEAHEAD_MS, isApplePlatform, matchesShortcut, parseShortcut, shortcutList, shortcutText, shortcutTokens, typeaheadStep } from './chunk-4VUHQFAT.js';
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Download, MenuButton } from './chunk-ISXB5RUH.js';
|
|
2
|
+
import { downloadFile } from './chunk-QIIV2QSV.js';
|
|
3
|
+
import { ContextMenu, useContextMenuContext } from './chunk-DZMHY3SU.js';
|
|
4
|
+
import './chunk-EYZ366LP.js';
|
|
5
|
+
import './chunk-Z3VDE7OA.js';
|
|
6
|
+
import './chunk-4VUHQFAT.js';
|
|
7
|
+
import './chunk-HS3X3XCW.js';
|
|
8
|
+
import './chunk-4ZPMP47J.js';
|
|
9
|
+
import { useRef } from 'react';
|
|
10
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
11
|
+
|
|
12
|
+
function ImageMenu({ item, index, options, labels }) {
|
|
13
|
+
const rows = [];
|
|
14
|
+
if (options.download !== false) {
|
|
15
|
+
rows.push({ id: "download", label: labels.download ?? "Download", icon: /* @__PURE__ */ jsx(Download, {}) });
|
|
16
|
+
}
|
|
17
|
+
if (options.items?.length) {
|
|
18
|
+
if (rows.length > 0) rows.push({ type: "separator" });
|
|
19
|
+
rows.push(...options.items);
|
|
20
|
+
}
|
|
21
|
+
return /* @__PURE__ */ jsxs(
|
|
22
|
+
ContextMenu.Root,
|
|
23
|
+
{
|
|
24
|
+
items: rows,
|
|
25
|
+
clipboard: false,
|
|
26
|
+
onSelect: (row) => {
|
|
27
|
+
if (row.id === "download") void downloadFile(item.download ?? item.src, item.filename);
|
|
28
|
+
options.onSelect?.(row.id, item, index);
|
|
29
|
+
},
|
|
30
|
+
children: [
|
|
31
|
+
/* @__PURE__ */ jsx(Trigger, { label: labels.menu ?? "More" }),
|
|
32
|
+
/* @__PURE__ */ jsx(ContextMenu.Content, {})
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
function Trigger({ label }) {
|
|
38
|
+
const menu = useContextMenuContext("Image.Menu");
|
|
39
|
+
const ref = useRef(null);
|
|
40
|
+
return /* @__PURE__ */ jsx("span", { ref, style: { display: "contents" }, children: /* @__PURE__ */ jsx(
|
|
41
|
+
MenuButton,
|
|
42
|
+
{
|
|
43
|
+
label,
|
|
44
|
+
expanded: menu.state.open,
|
|
45
|
+
onPress: () => {
|
|
46
|
+
const box = ref.current?.firstElementChild?.getBoundingClientRect();
|
|
47
|
+
if (!box) return;
|
|
48
|
+
menu.open({ x: box.right, y: box.bottom + 6 });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
) });
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export { ImageMenu };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ContextMenu, useContextMenuContext } from './chunk-DZMHY3SU.js';
|
|
2
|
+
import './chunk-Z3VDE7OA.js';
|
|
3
|
+
import './chunk-4VUHQFAT.js';
|
|
4
|
+
import './chunk-HS3X3XCW.js';
|
|
5
|
+
import './chunk-4ZPMP47J.js';
|
|
6
|
+
import { useEffect } from 'react';
|
|
7
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
8
|
+
|
|
9
|
+
function VideoMenu({ rows, title, onSelect, onReady }) {
|
|
10
|
+
return /* @__PURE__ */ jsxs(
|
|
11
|
+
ContextMenu.Root,
|
|
12
|
+
{
|
|
13
|
+
items: rows,
|
|
14
|
+
title,
|
|
15
|
+
clipboard: false,
|
|
16
|
+
onSelect,
|
|
17
|
+
children: [
|
|
18
|
+
/* @__PURE__ */ jsx(Publish, { onReady }),
|
|
19
|
+
/* @__PURE__ */ jsx(ContextMenu.Content, {})
|
|
20
|
+
]
|
|
21
|
+
}
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
function Publish({ onReady }) {
|
|
25
|
+
const menu = useContextMenuContext("Video.Menu");
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
onReady(menu.open);
|
|
28
|
+
return () => onReady(null);
|
|
29
|
+
}, [menu.open, onReady]);
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export { VideoMenu };
|
package/dist/next/index.d.ts
CHANGED
|
@@ -23,11 +23,15 @@ export { PaletteContent, PaletteContextValue, PaletteField, PaletteFooter, Palet
|
|
|
23
23
|
export { R as RecentEntry, b as RecentStore, e as createRecentStore, g as groupRows, i as isPaletteShortcut, m as moveActive, r as recentKey, s as shortcutLabel } from '../palette-D7iuQh_T.js';
|
|
24
24
|
export { Select, SelectContent, SelectContextValue, SelectItem, SelectList, SelectMultipleProps, SelectOptionRow, SelectProps, SelectRoot, SelectRootProps, SelectSearch, SelectSingleProps, SelectTrigger, SelectValue, useSelectContext } from '../react/select.js';
|
|
25
25
|
export { a as SelectInstance, c as SelectOption, d as SelectOptions, e as SelectState, f as createSelect } from '../select-ClSy-J1f.js';
|
|
26
|
-
export { ContextMenu, ContextMenuContent, ContextMenuContentProps,
|
|
27
|
-
export { C as CLIPBOARD_PREFIX,
|
|
26
|
+
export { ContextMenu, ContextMenuContent, ContextMenuContentProps, ContextMenuList, ContextMenuPanel, ContextMenuProps, ContextMenuRoot, ContextMenuRootProps, ContextMenuRow, ContextMenuSearch, ContextMenuTrigger, ContextMenuTriggerProps } from '../react/context-menu.js';
|
|
27
|
+
export { C as CLIPBOARD_PREFIX, a as ClipboardAction, b as ClipboardMenuLabels, c as ClipboardMenuOptions, d as ClipboardTarget, e as clipboardAction, f as clipboardEntries, g as clipboardHasText, i as inspectClipboardTarget, p as performClipboardAction } from '../clipboard-menu-BvXJCSFN.js';
|
|
28
|
+
export { a as ContextMenuAction, b as ContextMenuEntry, c as ContextMenuInstance, g as ContextMenuOptions, j as ContextMenuState, k as createContextMenu, l as isAction } from '../context-menu-D3FtTn7v.js';
|
|
28
29
|
export { MarqueeRect, SelectionList, SelectionListProps, SelectionRenderer, SelectionRowRender, UseSelectionOptions, UseSelectionResult, useSelection } from '../react/selection.js';
|
|
29
30
|
export { D as DEFAULT_SELECTION_SHORTCUTS, a as SelectionCommand, b as SelectionCommandEvent, c as SelectionCommandName, d as SelectionInstance, e as SelectionOptions, f as SelectionShortcuts, g as SelectionState, h as createSelection } from '../selection-B_pmzHpy.js';
|
|
30
31
|
export { S as Shortcut, b as ShortcutSpec, i as isApplePlatform, m as matchesShortcut, p as parseShortcut, e as shortcutText, f as shortcutTokens } from '../keys-D2zJs1uB.js';
|
|
32
|
+
export { Image, ImageItem, ImageLabels, ImageMenuOptions, ImageProps, ImageSource, ZoomOptions } from '../react/image.js';
|
|
33
|
+
export { Video, VideoControls, VideoLabels, VideoProps, VideoSource, VideoTrack } from '../react/video.js';
|
|
34
|
+
export { C as ContextMenuContextValue, a as ContextMenuItem, b as ContextMenuNode, u as useContextMenuContext } from '../context-BfjYGPnH.js';
|
|
31
35
|
|
|
32
36
|
/**
|
|
33
37
|
* The Next.js entry. Same components, wired to `next/link`.
|
package/dist/next/index.js
CHANGED
|
@@ -1,29 +1,33 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
export { useInput } from '../chunk-
|
|
2
|
+
export { useInput } from '../chunk-T7I6WJSN.js';
|
|
3
|
+
export { useSearch } from '../chunk-45UHLZYT.js';
|
|
4
|
+
export { useNetworkState } from '../chunk-S653GLSF.js';
|
|
3
5
|
export { RelativeTime } from '../chunk-OCMI7R6H.js';
|
|
4
6
|
export { PasswordStrength } from '../chunk-XQHCZAPJ.js';
|
|
5
7
|
export { ContextMenu, ContextMenuContent, ContextMenuList, ContextMenuPanel, ContextMenuRoot, ContextMenuRow, ContextMenuSearch, ContextMenuTrigger, useContextMenuContext } from '../chunk-DZMHY3SU.js';
|
|
6
8
|
export { SelectionList, useSelection } from '../chunk-N6PDHMAX.js';
|
|
9
|
+
export { Image } from '../chunk-4SZ5N7BA.js';
|
|
10
|
+
import '../chunk-EYZ366LP.js';
|
|
11
|
+
export { Video } from '../chunk-JJVZYW5C.js';
|
|
7
12
|
import { Button } from '../chunk-6BGBYUSZ.js';
|
|
8
13
|
export { getLinkComponent, setLinkComponent, useButton } from '../chunk-6BGBYUSZ.js';
|
|
9
14
|
export { Flag } from '../chunk-NPHRS2Q7.js';
|
|
10
15
|
export { Toaster, toast, useSonner } from '../chunk-WPTBURIC.js';
|
|
11
16
|
export { createNotificationQueue, defaultQueue, useNotifications } from '../chunk-QYMUIW5I.js';
|
|
12
17
|
export { useMarquee } from '../chunk-ZWR2EXHQ.js';
|
|
13
|
-
export { useSearch } from '../chunk-45UHLZYT.js';
|
|
14
|
-
export { useNetworkState } from '../chunk-S653GLSF.js';
|
|
15
18
|
import '../chunk-KJINGUQN.js';
|
|
19
|
+
export { colorEquals, formatColor, hslToRgb, hsvToRgb, parseColor, rgbToHsl, rgbToHsv, toHex } from '../chunk-S2FPN5ID.js';
|
|
20
|
+
import '../chunk-2QFTRNAZ.js';
|
|
16
21
|
import '../chunk-IXVMRVD4.js';
|
|
17
22
|
export { estimatePasswordStrength, generatePassword } from '../chunk-HC2ME5PU.js';
|
|
18
|
-
export { colorEquals, formatColor, hslToRgb, hsvToRgb, parseColor, rgbToHsl, rgbToHsv, toHex } from '../chunk-S2FPN5ID.js';
|
|
19
23
|
export { CLIPBOARD_PREFIX, clipboardAction, clipboardEntries, clipboardHasText, createContextMenu, inspectClipboardTarget, isAction, performClipboardAction } from '../chunk-Z3VDE7OA.js';
|
|
20
24
|
export { DEFAULT_SELECTION_SHORTCUTS, createSelection } from '../chunk-WSQC3PCC.js';
|
|
25
|
+
import '../chunk-RUEQ3TGP.js';
|
|
21
26
|
import '../chunk-MMQPZGSU.js';
|
|
22
27
|
export { configureFlags, flagAttributes, flagName, flagSrc, flagView, normalizeFlagCode } from '../chunk-LMZJBOZG.js';
|
|
23
28
|
import '../chunk-SNYUBXWQ.js';
|
|
24
29
|
import '../chunk-UOSSNUSC.js';
|
|
25
|
-
|
|
26
|
-
export { Input } from '../chunk-3MGBZOAU.js';
|
|
30
|
+
export { Input } from '../chunk-RMNXVWQ4.js';
|
|
27
31
|
import '../chunk-KVLSOQTI.js';
|
|
28
32
|
import '../chunk-F25CGNQC.js';
|
|
29
33
|
export { PaletteContent, PaletteField, PaletteFooter, PaletteItem, PaletteList, PaletteRoot, PaletteTrigger, SearchPalette, usePaletteContext } from '../chunk-FGBIZDV2.js';
|
|
@@ -1,59 +1,13 @@
|
|
|
1
|
-
import { ReactNode,
|
|
2
|
-
import {
|
|
3
|
-
export { C as
|
|
1
|
+
import { ReactNode, ComponentPropsWithoutRef } from 'react';
|
|
2
|
+
import { b as ContextMenuNode, a as ContextMenuItem } from '../context-BfjYGPnH.js';
|
|
3
|
+
export { C as ContextMenuContextValue, u as useContextMenuContext } from '../context-BfjYGPnH.js';
|
|
4
|
+
import { c as ClipboardMenuOptions } from '../clipboard-menu-BvXJCSFN.js';
|
|
5
|
+
export { C as CLIPBOARD_PREFIX, a as ClipboardAction, b as ClipboardMenuLabels, d as ClipboardTarget, e as clipboardAction, f as clipboardEntries, g as clipboardHasText, i as inspectClipboardTarget, p as performClipboardAction } from '../clipboard-menu-BvXJCSFN.js';
|
|
6
|
+
import { g as ContextMenuOptions, b as ContextMenuEntry } from '../context-menu-D3FtTn7v.js';
|
|
7
|
+
export { C as CONTEXT_MENU_SEARCH_KEYS, a as ContextMenuAction, c as ContextMenuInstance, d as ContextMenuLabel, e as ContextMenuLevel, f as ContextMenuMoveKey, h as ContextMenuPoint, i as ContextMenuSeparator, j as ContextMenuState, k as createContextMenu, l as isAction } from '../context-menu-D3FtTn7v.js';
|
|
4
8
|
export { S as Shortcut, b as ShortcutSpec, m as matchesShortcut, p as parseShortcut, e as shortcutText, f as shortcutTokens } from '../keys-D2zJs1uB.js';
|
|
5
9
|
import '../search-DYgqRp37.js';
|
|
6
10
|
|
|
7
|
-
/**
|
|
8
|
-
* One row, as React draws it. The core carries `icon` as `unknown` because it cannot know
|
|
9
|
-
* what a node is; here it is one.
|
|
10
|
-
*/
|
|
11
|
-
interface ContextMenuItem extends Omit<ContextMenuAction, "icon" | "items"> {
|
|
12
|
-
icon?: ReactNode;
|
|
13
|
-
items?: readonly ContextMenuNode[];
|
|
14
|
-
}
|
|
15
|
-
/** Anything that can appear in a menu, with React's icon type. */
|
|
16
|
-
type ContextMenuNode = ContextMenuItem | Exclude<ContextMenuEntry, ContextMenuAction>;
|
|
17
|
-
interface ContextMenuContextValue {
|
|
18
|
-
instance: ContextMenuInstance;
|
|
19
|
-
state: ContextMenuState;
|
|
20
|
-
/**
|
|
21
|
-
* Open at a point, over what the press landed on. False when there was nothing to show,
|
|
22
|
-
* so the press is left alone.
|
|
23
|
-
*
|
|
24
|
-
* `target` is what the clipboard rows are built from - the field or the selection under
|
|
25
|
-
* the pointer - and a caller that leaves it out gets a menu with none of them, which is
|
|
26
|
-
* the right answer for a menu opened from somewhere that is not a press.
|
|
27
|
-
*/
|
|
28
|
-
open: (point: ContextMenuPoint, target?: EventTarget | null) => boolean;
|
|
29
|
-
close: () => void;
|
|
30
|
-
/** ids the parts need to point at each other. */
|
|
31
|
-
ids: {
|
|
32
|
-
trigger: string;
|
|
33
|
-
};
|
|
34
|
-
panelId: (level: number) => string;
|
|
35
|
-
itemId: (level: number, index: number) => string;
|
|
36
|
-
triggerRef: RefObject<HTMLElement | null>;
|
|
37
|
-
/** Which panel the keyboard is in. Always the deepest open one. */
|
|
38
|
-
onMenuKeyDown: (event: React.KeyboardEvent) => void;
|
|
39
|
-
/** How long the pointer must rest on a row before its submenu opens, and before one closes. */
|
|
40
|
-
delays: {
|
|
41
|
-
open: number;
|
|
42
|
-
close: number;
|
|
43
|
-
};
|
|
44
|
-
/** Drop the pending close, wherever it was scheduled. Called wherever the pointer lands. */
|
|
45
|
-
cancelClose: () => void;
|
|
46
|
-
/** Close everything below `level`, after the beat - replacing any close already waiting. */
|
|
47
|
-
scheduleClose: (level: number) => void;
|
|
48
|
-
/** Draw a row instead of the default icon / label / shortcut. */
|
|
49
|
-
renderItem?: (item: ContextMenuItem, level: number, index: number) => ReactNode;
|
|
50
|
-
/** Shown while a fetched submenu has not answered. */
|
|
51
|
-
loadingLabel: ReactNode;
|
|
52
|
-
/** Shown when a filter matched nothing, or a fetched submenu came back with nothing. */
|
|
53
|
-
emptyLabel: ReactNode;
|
|
54
|
-
}
|
|
55
|
-
declare function useContextMenuContext(part: string): ContextMenuContextValue;
|
|
56
|
-
|
|
57
11
|
interface ContextMenuRootProps {
|
|
58
12
|
/** The rows. A list with nothing selectable in it opens no menu at all. */
|
|
59
13
|
items: readonly ContextMenuNode[];
|
|
@@ -216,4 +170,4 @@ declare namespace ContextMenu {
|
|
|
216
170
|
var Item: typeof ContextMenuRow;
|
|
217
171
|
}
|
|
218
172
|
|
|
219
|
-
export { CONTEXT_MENU_STYLES, ClipboardMenuOptions, ContextMenu,
|
|
173
|
+
export { CONTEXT_MENU_STYLES, ClipboardMenuOptions, ContextMenu, ContextMenuContent, type ContextMenuContentProps, ContextMenuEntry, ContextMenuItem, ContextMenuList, type ContextMenuListProps, ContextMenuNode, ContextMenuOptions, ContextMenuPanel, type ContextMenuPanelProps, type ContextMenuProps, ContextMenuRoot, type ContextMenuRootProps, ContextMenuRow, type ContextMenuRowProps, ContextMenuSearch, type ContextMenuSearchProps, ContextMenuTrigger, type ContextMenuTriggerProps };
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { ComponentPropsWithoutRef, ReactNode } from 'react';
|
|
2
|
+
import { b as ContextMenuNode } from '../context-BfjYGPnH.js';
|
|
3
|
+
import '../context-menu-D3FtTn7v.js';
|
|
4
|
+
import '../search-DYgqRp37.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The prop shapes for `<Image>`, split from the component so the viewer's chunk can import
|
|
8
|
+
* them without pulling the component in - the same arrangement `<Input>` is in.
|
|
9
|
+
*
|
|
10
|
+
* WHAT IS ON BY DEFAULT is the whole design of this API: an image that opens and zooms, and
|
|
11
|
+
* nothing else. A gallery's arrows, its thumbnails, a menu and a discard action are each a
|
|
12
|
+
* decision about the page they sit in, so each is a prop you turn on rather than one you
|
|
13
|
+
* remember to turn off.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/** One image in a set: a URL, or the URL plus what is known about it. */
|
|
17
|
+
type ImageSource = string | ImageItem;
|
|
18
|
+
interface ImageItem {
|
|
19
|
+
src: string;
|
|
20
|
+
alt?: string;
|
|
21
|
+
/** A smaller file for the strip and for the frame while the full one loads. */
|
|
22
|
+
thumbnail?: string;
|
|
23
|
+
/** The URL to save, when the file to download is not the one being shown. */
|
|
24
|
+
download?: string;
|
|
25
|
+
/** Saved under this name instead of the one in the URL. */
|
|
26
|
+
filename?: string;
|
|
27
|
+
caption?: ReactNode;
|
|
28
|
+
}
|
|
29
|
+
interface ZoomOptions {
|
|
30
|
+
/** How far out. 1 is the fitted image; below it the picture is smaller than its frame. */
|
|
31
|
+
min?: number;
|
|
32
|
+
max?: number;
|
|
33
|
+
/** Zoom on the wheel. On by default - it is the gesture every image viewer answers. */
|
|
34
|
+
wheel?: boolean;
|
|
35
|
+
/** A double press toggles between fitted and this. `false` leaves the gesture alone. */
|
|
36
|
+
doubleClick?: boolean;
|
|
37
|
+
}
|
|
38
|
+
interface ImageMenuOptions {
|
|
39
|
+
/** The download row. On whenever the menu is. */
|
|
40
|
+
download?: boolean;
|
|
41
|
+
/** Rows of your own, after the built-in ones. */
|
|
42
|
+
items?: readonly ContextMenuNode[];
|
|
43
|
+
onSelect?: (id: string, item: ImageItem, index: number) => void;
|
|
44
|
+
}
|
|
45
|
+
/** Every string the viewer says, for a UI that is not in English. */
|
|
46
|
+
interface ImageLabels {
|
|
47
|
+
open?: string;
|
|
48
|
+
close?: string;
|
|
49
|
+
zoomIn?: string;
|
|
50
|
+
zoomOut?: string;
|
|
51
|
+
reset?: string;
|
|
52
|
+
previous?: string;
|
|
53
|
+
next?: string;
|
|
54
|
+
menu?: string;
|
|
55
|
+
download?: string;
|
|
56
|
+
discard?: string;
|
|
57
|
+
thumbnails?: string;
|
|
58
|
+
/** The frame itself, announced as the dialog's name. Default "Image viewer". */
|
|
59
|
+
viewer?: string;
|
|
60
|
+
/** `{index}` and `{total}` are replaced. Default "{index} of {total}". */
|
|
61
|
+
counter?: string;
|
|
62
|
+
}
|
|
63
|
+
interface ImageProps extends Omit<ComponentPropsWithoutRef<"img">, "children" | "onSelect"> {
|
|
64
|
+
src: string;
|
|
65
|
+
alt: string;
|
|
66
|
+
/**
|
|
67
|
+
* The set this image belongs to. Without it the viewer shows this one image; with it the
|
|
68
|
+
* arrows, the strip and the discard action have something to move through.
|
|
69
|
+
*/
|
|
70
|
+
images?: readonly ImageSource[];
|
|
71
|
+
/** Where in `images` this one is. Found by `src` when it is left out. */
|
|
72
|
+
index?: number;
|
|
73
|
+
/** Click to see it larger. ON by default: it is what an image in a page is expected to do. */
|
|
74
|
+
lightbox?: boolean;
|
|
75
|
+
/** Zoom, with the wheel and the keyboard. ON by default. */
|
|
76
|
+
zoom?: boolean | ZoomOptions;
|
|
77
|
+
/**
|
|
78
|
+
* The picture flies out of the page into the viewer, and back into it on the way out. ON
|
|
79
|
+
* by default, and skipped anyway for a reader who has asked for less movement.
|
|
80
|
+
*/
|
|
81
|
+
animate?: boolean;
|
|
82
|
+
/** Arrows, the counter, and Left/Right on the keyboard. Off by default. */
|
|
83
|
+
navigation?: boolean;
|
|
84
|
+
/** The strip of previews along the bottom. Off by default. */
|
|
85
|
+
thumbnails?: boolean;
|
|
86
|
+
/** The three dots, and what is under them. Off by default. */
|
|
87
|
+
menu?: boolean | ImageMenuOptions;
|
|
88
|
+
/**
|
|
89
|
+
* Take an image out of the set and move to the next one. Off by default, because it is
|
|
90
|
+
* destructive and only the caller knows whether it means anything on their page.
|
|
91
|
+
*/
|
|
92
|
+
discardable?: boolean;
|
|
93
|
+
onDiscard?: (item: ImageItem, index: number) => void;
|
|
94
|
+
/** Whether the arrows and the strip wrap around at the ends. On by default. */
|
|
95
|
+
loop?: boolean;
|
|
96
|
+
/** The caption under the frame, when the item carries none of its own. */
|
|
97
|
+
caption?: ReactNode;
|
|
98
|
+
onOpenChange?: (open: boolean) => void;
|
|
99
|
+
onIndexChange?: (index: number, item: ImageItem) => void;
|
|
100
|
+
/** The viewer's stylesheet, injected once. There is no useful unstyled lightbox. */
|
|
101
|
+
styles?: boolean;
|
|
102
|
+
labels?: ImageLabels;
|
|
103
|
+
/** Props for the element wrapping the thumbnail - this is what you position. */
|
|
104
|
+
wrapperProps?: ComponentPropsWithoutRef<"span">;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
declare function Image(props: ImageProps): ReactNode;
|
|
108
|
+
|
|
109
|
+
export { Image, type ImageItem, type ImageLabels, type ImageMenuOptions, type ImageProps, type ImageSource, type ZoomOptions };
|