@enigmax/primitives 0.26.0 → 0.27.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 → chunk-2RIO4VDV.js} +2 -2
- package/dist/{chunk-DZMHY3SU.js → chunk-CPJJ3FPW.js} +17 -7
- package/dist/{chunk-QIIV2QSV.js → chunk-HUUINHPR.js} +28 -1
- package/dist/{chunk-RUEQ3TGP.js → chunk-JLZDS6CV.js} +23 -1
- package/dist/{chunk-ISXB5RUH.js → chunk-O2UJ5ZIX.js} +10 -3
- package/dist/{chunk-JJVZYW5C.js → chunk-PVDU6AZU.js} +10 -3
- package/dist/{chunk-Z3VDE7OA.js → chunk-YQV5XZIA.js} +2 -2
- package/dist/{clipboard-menu-BvXJCSFN.d.ts → clipboard-menu-eemzEBqB.d.ts} +1 -1
- package/dist/{context-BfjYGPnH.d.ts → context-DR1dpO8b.d.ts} +1 -1
- package/dist/{context-menu-D3FtTn7v.d.ts → context-menu-qqpGBkny.d.ts} +6 -0
- package/dist/index.d.ts +29 -3
- package/dist/index.js +3 -3
- package/dist/{menu-PNQRTRNV.js → menu-52PXC5PL.js} +2 -2
- package/dist/{menu-MSQSE6U5.js → menu-YIGMPFUP.js} +8 -4
- package/dist/next/index.d.ts +3 -3
- package/dist/next/index.js +5 -5
- package/dist/react/context-menu.d.ts +13 -7
- package/dist/react/context-menu.js +2 -2
- package/dist/react/image.d.ts +5 -2
- package/dist/react/image.js +1 -1
- package/dist/react/index.d.ts +3 -3
- package/dist/react/index.js +5 -5
- package/dist/react/video.d.ts +9 -3
- package/dist/react/video.js +2 -2
- package/dist/react-router/index.d.ts +3 -3
- package/dist/react-router/index.js +5 -5
- package/dist/viewer-N5WLFB24.js +3 -0
- package/package.json +1 -1
- package/recipes/context-menu/styles.css +8 -1
- package/registry.json +21 -5
- package/src/core/context-menu.ts +22 -3
- package/src/core/image-viewer.ts +47 -0
- package/src/core/player.ts +42 -0
- package/src/index.ts +3 -0
- package/src/react/context-menu/root.tsx +27 -5
- package/src/react/context-menu/styles.ts +8 -1
- package/src/react/image/icons.tsx +4 -0
- package/src/react/image/menu.tsx +5 -1
- package/src/react/image/types.ts +3 -0
- package/src/react/video/index.tsx +8 -1
- package/src/react/video/types.ts +7 -1
- package/dist/viewer-73LSE6RR.js +0 -3
|
@@ -6,12 +6,12 @@ import { jsx, jsxs } from 'react/jsx-runtime';
|
|
|
6
6
|
function toItem(source) {
|
|
7
7
|
return typeof source === "string" ? { src: source } : source;
|
|
8
8
|
}
|
|
9
|
-
var ImageViewer = lazy(() => import('./viewer-
|
|
9
|
+
var ImageViewer = lazy(() => import('./viewer-N5WLFB24.js').then((module) => ({ default: module.ImageViewer })));
|
|
10
10
|
var prefetched = false;
|
|
11
11
|
function prefetchViewer() {
|
|
12
12
|
if (prefetched) return;
|
|
13
13
|
prefetched = true;
|
|
14
|
-
void import('./viewer-
|
|
14
|
+
void import('./viewer-N5WLFB24.js');
|
|
15
15
|
}
|
|
16
16
|
var ZOOM_DEFAULTS = { min: 1, max: 8, wheel: true, doubleClick: true };
|
|
17
17
|
function Image(props) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createContextMenu, clipboardAction, performClipboardAction, inspectClipboardTarget, CLIPBOARD_PREFIX, clipboardEntries, isAction, clipboardHasText } from './chunk-
|
|
1
|
+
import { createContextMenu, clipboardAction, performClipboardAction, inspectClipboardTarget, CLIPBOARD_PREFIX, clipboardEntries, isAction, clipboardHasText } from './chunk-YQV5XZIA.js';
|
|
2
2
|
import { shortcutTokens } from './chunk-4VUHQFAT.js';
|
|
3
3
|
import { Slot } from './chunk-HS3X3XCW.js';
|
|
4
4
|
import { shortenQuery } from './chunk-4ZPMP47J.js';
|
|
@@ -23,6 +23,13 @@ var CONTEXT_MENU_STYLES = `
|
|
|
23
23
|
--enigma-menu-accent: #fbbf24;
|
|
24
24
|
--enigma-menu-danger: #f87171;
|
|
25
25
|
--enigma-menu-danger-bg: rgba(248, 113, 113, 0.12);
|
|
26
|
+
|
|
27
|
+
/* Above the lightbox, which sits at 9999, because a menu is opened FROM whatever is on
|
|
28
|
+
top: the image viewer's own three-dot menu was portalled to the same body and painted
|
|
29
|
+
underneath it, so its rows could be neither seen nor pressed. A menu is the topmost
|
|
30
|
+
transient surface on a page, and this is the number that says so. It belongs here and
|
|
31
|
+
not in the light-scheme block, or half the readers get an invalid z-index. */
|
|
32
|
+
--enigma-menu-z: 10000;
|
|
26
33
|
}
|
|
27
34
|
|
|
28
35
|
@media (prefers-color-scheme: light) {
|
|
@@ -43,7 +50,7 @@ var CONTEXT_MENU_STYLES = `
|
|
|
43
50
|
and what a menu opened at the pointer needs. Fixed rather than absolute so a scrolling
|
|
44
51
|
ancestor cannot drag it away from the place it was opened. */
|
|
45
52
|
[data-enigma-menu-panel] {
|
|
46
|
-
position: fixed; z-index:
|
|
53
|
+
position: fixed; z-index: var(--enigma-menu-z);
|
|
47
54
|
box-sizing: border-box;
|
|
48
55
|
min-width: var(--enigma-menu-min-width);
|
|
49
56
|
max-width: min(22rem, calc(100vw - 1rem));
|
|
@@ -245,6 +252,7 @@ function ContextMenuRoot(props) {
|
|
|
245
252
|
const {
|
|
246
253
|
items,
|
|
247
254
|
title,
|
|
255
|
+
searchable,
|
|
248
256
|
disabled = false,
|
|
249
257
|
fuse,
|
|
250
258
|
fuseOptions,
|
|
@@ -272,6 +280,7 @@ function ContextMenuRoot(props) {
|
|
|
272
280
|
const instance = useMemo(() => createContextMenu({
|
|
273
281
|
items,
|
|
274
282
|
title,
|
|
283
|
+
searchable,
|
|
275
284
|
fuse,
|
|
276
285
|
fuseOptions,
|
|
277
286
|
matcher,
|
|
@@ -328,8 +337,8 @@ function ContextMenuRoot(props) {
|
|
|
328
337
|
return [...clip, { type: "separator", id: `${CLIPBOARD_PREFIX}rule` }, ...rows];
|
|
329
338
|
}, []);
|
|
330
339
|
useEffect(() => {
|
|
331
|
-
instance.update({ items: withClipboard(currentItems.current), title });
|
|
332
|
-
}, [instance, signature, title, withClipboard]);
|
|
340
|
+
instance.update({ items: withClipboard(currentItems.current), title, searchable });
|
|
341
|
+
}, [instance, signature, title, searchable, withClipboard]);
|
|
333
342
|
const cancelClose = useCallback(() => {
|
|
334
343
|
window.clearTimeout(closing.current);
|
|
335
344
|
}, []);
|
|
@@ -699,6 +708,7 @@ function ContextMenuRow({ level, index, entry, children, ...props }) {
|
|
|
699
708
|
if (entry.type === "separator") return /* @__PURE__ */ jsx("div", { ...props, role: "separator", "data-enigma-menu-separator": "" });
|
|
700
709
|
return /* @__PURE__ */ jsx("p", { ...props, "data-enigma-menu-label": "", "aria-hidden": "true", children: entry.label });
|
|
701
710
|
}
|
|
711
|
+
const reserveCheck = state?.entries.some((entry2) => isAction(entry2) && entry2.checked !== void 0) ?? false;
|
|
702
712
|
const checkable = item.checked !== void 0;
|
|
703
713
|
const role = checkable ? item.group ? "menuitemradio" : "menuitemcheckbox" : "menuitem";
|
|
704
714
|
return /* @__PURE__ */ jsx(
|
|
@@ -741,13 +751,13 @@ function ContextMenuRow({ level, index, entry, children, ...props }) {
|
|
|
741
751
|
if (event.defaultPrevented || item.disabled || event.detail !== 0) return;
|
|
742
752
|
menu.instance.select(level, index);
|
|
743
753
|
},
|
|
744
|
-
children: children ?? menu.renderItem?.(item, level, index) ?? /* @__PURE__ */ jsx(ContextMenuRowContent, { item, submenu })
|
|
754
|
+
children: children ?? menu.renderItem?.(item, level, index) ?? /* @__PURE__ */ jsx(ContextMenuRowContent, { item, submenu, reserveCheck })
|
|
745
755
|
}
|
|
746
756
|
);
|
|
747
757
|
}
|
|
748
|
-
function ContextMenuRowContent({ item, submenu }) {
|
|
758
|
+
function ContextMenuRowContent({ item, submenu, reserveCheck }) {
|
|
749
759
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
750
|
-
item.checked !== void 0 && /* @__PURE__ */ jsx("span", { "data-enigma-menu-check": "", "aria-hidden": "true" }),
|
|
760
|
+
(item.checked !== void 0 || reserveCheck) && /* @__PURE__ */ jsx("span", { "data-enigma-menu-check": "", "aria-hidden": "true" }),
|
|
751
761
|
item.icon ? /* @__PURE__ */ jsx("span", { "data-enigma-menu-icon": "", children: item.icon }) : null,
|
|
752
762
|
/* @__PURE__ */ jsxs("span", { "data-enigma-menu-item-text": "", children: [
|
|
753
763
|
/* @__PURE__ */ jsx("span", { "data-enigma-menu-item-label": "", children: item.label }),
|
|
@@ -84,6 +84,33 @@ function saveAs(href, name, external = false) {
|
|
|
84
84
|
anchor.click();
|
|
85
85
|
anchor.remove();
|
|
86
86
|
}
|
|
87
|
+
function dataUrlToBlob(url) {
|
|
88
|
+
const comma = url.indexOf(",");
|
|
89
|
+
if (!url.startsWith("data:") || comma === -1) throw new Error("not a data URL");
|
|
90
|
+
const head = url.slice("data:".length, comma);
|
|
91
|
+
const body = url.slice(comma + 1);
|
|
92
|
+
const base64 = head.endsWith(";base64");
|
|
93
|
+
const type = (base64 ? head.slice(0, -";base64".length) : head) || "text/plain";
|
|
94
|
+
if (!base64) return new Blob([decodeURIComponent(body)], { type });
|
|
95
|
+
const binary = atob(body);
|
|
96
|
+
const bytes = new Uint8Array(binary.length);
|
|
97
|
+
for (let at = 0; at < binary.length; at += 1) bytes[at] = binary.charCodeAt(at);
|
|
98
|
+
return new Blob([bytes], { type });
|
|
99
|
+
}
|
|
100
|
+
function openInNewTab(url) {
|
|
101
|
+
if (typeof window === "undefined") return;
|
|
102
|
+
if (!url.startsWith("data:")) {
|
|
103
|
+
window.open(url, "_blank", "noopener,noreferrer");
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
try {
|
|
107
|
+
const href = URL.createObjectURL(dataUrlToBlob(url));
|
|
108
|
+
window.open(href, "_blank", "noopener,noreferrer");
|
|
109
|
+
setTimeout(() => URL.revokeObjectURL(href), 6e4);
|
|
110
|
+
} catch {
|
|
111
|
+
window.open(url, "_blank", "noopener,noreferrer");
|
|
112
|
+
}
|
|
113
|
+
}
|
|
87
114
|
var FLIGHT_MS = 300;
|
|
88
115
|
function flightMs(element) {
|
|
89
116
|
if (!element || typeof getComputedStyle === "undefined") return FLIGHT_MS;
|
|
@@ -105,4 +132,4 @@ function prefersReducedMotion() {
|
|
|
105
132
|
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
106
133
|
}
|
|
107
134
|
|
|
108
|
-
export { FLIGHT_MS, IDENTITY, ZOOM_DOUBLE, ZOOM_LIMITS, ZOOM_STEP, clampPan, clampScale, downloadFile, filenameFrom, fittedSize, flightFrom, flightMs, nextIndex, pinchDistance, prefersReducedMotion, wheelFactor, zoomAt };
|
|
135
|
+
export { FLIGHT_MS, IDENTITY, ZOOM_DOUBLE, ZOOM_LIMITS, ZOOM_STEP, clampPan, clampScale, dataUrlToBlob, downloadFile, filenameFrom, fittedSize, flightFrom, flightMs, nextIndex, openInNewTab, pinchDistance, prefersReducedMotion, wheelFactor, zoomAt };
|
|
@@ -79,6 +79,28 @@ async function togglePip(video) {
|
|
|
79
79
|
if (document.pictureInPictureElement) return void await document.exitPictureInPicture();
|
|
80
80
|
await video.requestPictureInPicture();
|
|
81
81
|
}
|
|
82
|
+
var SOURCE_TYPES = {
|
|
83
|
+
mp4: "video/mp4",
|
|
84
|
+
m4v: "video/mp4",
|
|
85
|
+
webm: "video/webm",
|
|
86
|
+
ogv: "video/ogg",
|
|
87
|
+
mov: "video/quicktime",
|
|
88
|
+
mkv: "video/x-matroska",
|
|
89
|
+
m3u8: "application/vnd.apple.mpegurl",
|
|
90
|
+
mpd: "application/dash+xml"
|
|
91
|
+
};
|
|
92
|
+
function sourceType(url) {
|
|
93
|
+
let path = url;
|
|
94
|
+
try {
|
|
95
|
+
path = new URL(url, typeof location === "undefined" ? "https://localhost" : location.href).pathname;
|
|
96
|
+
} catch {
|
|
97
|
+
path = url.split("?")[0].split("#")[0];
|
|
98
|
+
}
|
|
99
|
+
const name = path.split("/").pop() ?? "";
|
|
100
|
+
const dot = name.lastIndexOf(".");
|
|
101
|
+
if (dot <= 0) return void 0;
|
|
102
|
+
return SOURCE_TYPES[name.slice(dot + 1).toLowerCase()];
|
|
103
|
+
}
|
|
82
104
|
function captionTracks(list) {
|
|
83
105
|
if (!list) return [];
|
|
84
106
|
const found = [];
|
|
@@ -152,4 +174,4 @@ async function promptRemote(video) {
|
|
|
152
174
|
element.webkitShowPlaybackTargetPicker?.();
|
|
153
175
|
}
|
|
154
176
|
|
|
155
|
-
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 };
|
|
177
|
+
export { SEEK_JUMP, SEEK_STEP, SPEEDS, VOLUME_STEP, activeCaption, bufferedAhead, captionTracks, commandFor, formatTime, fractionAt, fullscreenElement, isTypingTarget, nextSpeed, progress, promptRemote, showCaption, sourceType, supportsPip, supportsRemote, toggleFullscreen, togglePip, watchRemote };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IDENTITY, prefersReducedMotion, ZOOM_LIMITS, flightFrom, nextIndex, fittedSize, clampPan, zoomAt, pinchDistance, flightMs, ZOOM_STEP, ZOOM_DOUBLE, wheelFactor } from './chunk-
|
|
1
|
+
import { IDENTITY, prefersReducedMotion, ZOOM_LIMITS, flightFrom, nextIndex, fittedSize, clampPan, zoomAt, pinchDistance, flightMs, ZOOM_STEP, ZOOM_DOUBLE, wheelFactor } from './chunk-HUUINHPR.js';
|
|
2
2
|
import { injectImageStyles } from './chunk-EYZ366LP.js';
|
|
3
3
|
import { createPortal } from 'react-dom';
|
|
4
4
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
@@ -35,7 +35,14 @@ function Dots() {
|
|
|
35
35
|
function Download() {
|
|
36
36
|
return /* @__PURE__ */ jsx(Glyph, { children: /* @__PURE__ */ jsx("path", { d: "M12 3v12M7 11l5 5 5-5M4 20h16" }) });
|
|
37
37
|
}
|
|
38
|
-
|
|
38
|
+
function NewTab() {
|
|
39
|
+
return /* @__PURE__ */ jsxs(Glyph, { children: [
|
|
40
|
+
/* @__PURE__ */ jsx("path", { d: "M14 4h6v6" }),
|
|
41
|
+
/* @__PURE__ */ jsx("path", { d: "M20 4 11 13" }),
|
|
42
|
+
/* @__PURE__ */ jsx("path", { d: "M18 14v5a1.5 1.5 0 0 1-1.5 1.5h-11A1.5 1.5 0 0 1 4 19V7.5A1.5 1.5 0 0 1 5.5 6H10" })
|
|
43
|
+
] });
|
|
44
|
+
}
|
|
45
|
+
var ImageMenu = lazy(() => import('./menu-YIGMPFUP.js').then((module) => ({ default: module.ImageMenu })));
|
|
39
46
|
function ImageViewer({
|
|
40
47
|
items,
|
|
41
48
|
index,
|
|
@@ -377,4 +384,4 @@ function MenuButton({ label, onPress, expanded }) {
|
|
|
377
384
|
);
|
|
378
385
|
}
|
|
379
386
|
|
|
380
|
-
export { Download, ImageViewer, MenuButton };
|
|
387
|
+
export { Download, ImageViewer, MenuButton, NewTab };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SPEEDS, supportsPip, supportsRemote, watchRemote, showCaption, captionTracks, activeCaption, toggleFullscreen, togglePip, promptRemote, isTypingTarget, commandFor, progress, formatTime, bufferedAhead, fullscreenElement, fractionAt } from './chunk-
|
|
1
|
+
import { SPEEDS, supportsPip, supportsRemote, watchRemote, showCaption, captionTracks, activeCaption, toggleFullscreen, togglePip, promptRemote, isTypingTarget, commandFor, progress, sourceType, formatTime, bufferedAhead, fullscreenElement, fractionAt } from './chunk-JLZDS6CV.js';
|
|
2
2
|
import { lazy, useLayoutEffect, useRef, useState, useMemo, useEffect, useCallback, Suspense } from 'react';
|
|
3
3
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
4
|
|
|
@@ -351,7 +351,7 @@ var CONTROL_DEFAULTS = {
|
|
|
351
351
|
fullscreen: true,
|
|
352
352
|
download: false
|
|
353
353
|
};
|
|
354
|
-
var VideoMenu = lazy(() => import('./menu-
|
|
354
|
+
var VideoMenu = lazy(() => import('./menu-52PXC5PL.js').then((module) => ({ default: module.VideoMenu })));
|
|
355
355
|
var injected = false;
|
|
356
356
|
function injectStyles() {
|
|
357
357
|
if (injected || typeof document === "undefined") return;
|
|
@@ -765,7 +765,14 @@ function Video(props) {
|
|
|
765
765
|
if (clickToPlay) toggle();
|
|
766
766
|
},
|
|
767
767
|
children: [
|
|
768
|
-
typeof src !== "string" && sources.map((source) =>
|
|
768
|
+
typeof src !== "string" && sources.map((source) => (
|
|
769
|
+
// The type is what lets the browser SKIP a file it cannot play without
|
|
770
|
+
// fetching it, which is the only reason to list several. Read from the
|
|
771
|
+
// extension when it was not given, and left off when the extension means
|
|
772
|
+
// nothing - a wrong type is worse than none, because the source is then
|
|
773
|
+
// skipped and the video does not play at all.
|
|
774
|
+
/* @__PURE__ */ jsx("source", { src: source.src, type: source.type ?? sourceType(source.src) }, source.src)
|
|
775
|
+
)),
|
|
769
776
|
tracks?.map((track) => /* @__PURE__ */ jsx(
|
|
770
777
|
"track",
|
|
771
778
|
{
|
|
@@ -6,7 +6,7 @@ function isAction(entry) {
|
|
|
6
6
|
return (entry.type ?? "item") === "item";
|
|
7
7
|
}
|
|
8
8
|
var CONTEXT_MENU_SEARCH_KEYS = ["label", "description", "group", "keywords"];
|
|
9
|
-
var SEARCHABLE_FROM =
|
|
9
|
+
var SEARCHABLE_FROM = 12;
|
|
10
10
|
var PAGE = 5;
|
|
11
11
|
var DEFAULT_CACHE_MS = 5 * 60 * 1e3;
|
|
12
12
|
function fold(value) {
|
|
@@ -32,7 +32,7 @@ function createContextMenu(options = {}) {
|
|
|
32
32
|
return path.join("\0");
|
|
33
33
|
}
|
|
34
34
|
function searchableFor(item, entries) {
|
|
35
|
-
const asked = item
|
|
35
|
+
const asked = (item ? item.searchable : opts.searchable) ?? "auto";
|
|
36
36
|
if (asked !== "auto") return asked;
|
|
37
37
|
return entries.filter(isAction).length >= SEARCHABLE_FROM;
|
|
38
38
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ReactNode, RefObject } from 'react';
|
|
2
|
-
import { a as ContextMenuAction, b as ContextMenuEntry, c as ContextMenuInstance, j as ContextMenuState, h as ContextMenuPoint } from './context-menu-
|
|
2
|
+
import { a as ContextMenuAction, b as ContextMenuEntry, c as ContextMenuInstance, j as ContextMenuState, h as ContextMenuPoint } from './context-menu-qqpGBkny.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* One row, as React draws it. The core carries `icon` as `unknown` because it cannot know
|
|
@@ -126,6 +126,12 @@ interface ContextMenuOptions {
|
|
|
126
126
|
/** A row was invoked. The menu has already closed unless the row keeps it open. */
|
|
127
127
|
onSelect?: (item: ContextMenuAction, path: string[]) => void;
|
|
128
128
|
onOpenChange?: (open: boolean) => void;
|
|
129
|
+
/**
|
|
130
|
+
* Whether the ROOT level draws a filter. `"auto"` (the default) grows one from
|
|
131
|
+
* `SEARCHABLE_FROM` rows; `true` puts one there whatever the count, which is what a menu
|
|
132
|
+
* filling itself from somewhere wants; `false` never does.
|
|
133
|
+
*/
|
|
134
|
+
searchable?: boolean | "auto";
|
|
129
135
|
}
|
|
130
136
|
interface ContextMenuInstance {
|
|
131
137
|
readonly state: ContextMenuState;
|
package/dist/index.d.ts
CHANGED
|
@@ -9,8 +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 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-
|
|
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-
|
|
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-qqpGBkny.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-eemzEBqB.js';
|
|
14
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';
|
|
15
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';
|
|
16
16
|
|
|
@@ -140,6 +140,23 @@ declare function filenameFrom(url: string, fallback?: string): string;
|
|
|
140
140
|
* when that is refused (no CORS header) - a tab is still better than nothing happening.
|
|
141
141
|
*/
|
|
142
142
|
declare function downloadFile(url: string, filename?: string): Promise<void>;
|
|
143
|
+
/**
|
|
144
|
+
* A `data:` URL as the bytes it stands for.
|
|
145
|
+
*
|
|
146
|
+
* Synchronous on purpose: it is used to open a tab, and a window opened after an `await` is a
|
|
147
|
+
* popup with no gesture behind it, which the browser blocks.
|
|
148
|
+
*/
|
|
149
|
+
declare function dataUrlToBlob(url: string): Blob;
|
|
150
|
+
/**
|
|
151
|
+
* The picture on its own, in another tab.
|
|
152
|
+
*
|
|
153
|
+
* Chromium refuses a top-level navigation to a `data:` URL - it was a phishing vector - so a
|
|
154
|
+
* row that just called `window.open` on one did nothing at all, silently, which is how it
|
|
155
|
+
* shipped. Those are handed over as a blob instead; everything else opens as it is.
|
|
156
|
+
*
|
|
157
|
+
* `noopener` on both: the new tab must not get a handle on the page that opened it.
|
|
158
|
+
*/
|
|
159
|
+
declare function openInNewTab(url: string): void;
|
|
143
160
|
/** How long the picture takes to fly, when the stylesheet does not say otherwise. */
|
|
144
161
|
declare const FLIGHT_MS = 300;
|
|
145
162
|
/**
|
|
@@ -249,6 +266,15 @@ declare function toggleFullscreen(container: HTMLElement, video: HTMLVideoElemen
|
|
|
249
266
|
/** Picture in picture, where the browser has it. Firefox has its own button and no API. */
|
|
250
267
|
declare function supportsPip(): boolean;
|
|
251
268
|
declare function togglePip(video: HTMLVideoElement): Promise<void>;
|
|
269
|
+
/**
|
|
270
|
+
* The type a URL's extension implies, or undefined.
|
|
271
|
+
*
|
|
272
|
+
* Read from the PATH, so a query string or a fragment cannot be mistaken for one -
|
|
273
|
+
* `/clip.mp4?token=...` is still an mp4, and `/download?file=x.webm` is not a webm, because
|
|
274
|
+
* the extension has to be on the path's last segment. A `blob:` or `data:` URL has no
|
|
275
|
+
* extension to read and gets nothing, which is the right answer: the browser sniffs.
|
|
276
|
+
*/
|
|
277
|
+
declare function sourceType(url: string): string | undefined;
|
|
252
278
|
/** One subtitle track, as the menu lists it. */
|
|
253
279
|
interface CaptionTrack {
|
|
254
280
|
/** Where it sits in the element's own `textTracks`, which is what turns it on. */
|
|
@@ -303,4 +329,4 @@ declare function watchRemote(video: HTMLVideoElement, onChange: (state: RemoteSt
|
|
|
303
329
|
*/
|
|
304
330
|
declare function promptRemote(video: HTMLVideoElement): Promise<void>;
|
|
305
331
|
|
|
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 };
|
|
332
|
+
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, dataUrlToBlob, downloadFile, filenameFrom, fittedSize, flightFrom, flightMs, formatTime, fractionAt, fullscreenElement, iconMarkup, isTypingTarget, nextIndex, nextSpeed, openInNewTab, pinchDistance, prefersReducedMotion, progress, promptRemote, showCaption, sourceType, supportsPip, supportsRemote, toggleFullscreen, togglePip, watchRemote, wheelFactor, zoomAt };
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
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-
|
|
1
|
+
export { FLIGHT_MS, IDENTITY, ZOOM_DOUBLE, ZOOM_LIMITS, ZOOM_STEP, clampPan, clampScale, dataUrlToBlob, downloadFile, filenameFrom, fittedSize, flightFrom, flightMs, nextIndex, openInNewTab, pinchDistance, prefersReducedMotion, wheelFactor, zoomAt } from './chunk-HUUINHPR.js';
|
|
2
2
|
export { createInput } from './chunk-KJINGUQN.js';
|
|
3
3
|
export { colorEquals, formatColor, hslToRgb, hsvToRgb, parseColor, rgbToHsl, rgbToHsv, toHex } from './chunk-S2FPN5ID.js';
|
|
4
4
|
export { SERVER_NETWORK_STATE, createNetworkMonitor } from './chunk-2QFTRNAZ.js';
|
|
5
5
|
export { ensureZone, normalizeDate, parseDuration, relativeTimeAttributes, relativeTimeView } from './chunk-IXVMRVD4.js';
|
|
6
6
|
export { estimatePasswordStrength, generatePassword } from './chunk-HC2ME5PU.js';
|
|
7
|
-
export { CLIPBOARD_PREFIX, CONTEXT_MENU_SEARCH_KEYS, clipboardAction, clipboardEntries, clipboardHasText, createContextMenu, inspectClipboardTarget, isAction, performClipboardAction } from './chunk-
|
|
7
|
+
export { CLIPBOARD_PREFIX, CONTEXT_MENU_SEARCH_KEYS, clipboardAction, clipboardEntries, clipboardHasText, createContextMenu, inspectClipboardTarget, isAction, performClipboardAction } from './chunk-YQV5XZIA.js';
|
|
8
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-
|
|
9
|
+
export { SEEK_JUMP, SEEK_STEP, SPEEDS, VOLUME_STEP, activeCaption, bufferedAhead, captionTracks, commandFor, formatTime, fractionAt, fullscreenElement, isTypingTarget, nextSpeed, progress, promptRemote, showCaption, sourceType, supportsPip, supportsRemote, toggleFullscreen, togglePip, watchRemote } from './chunk-JLZDS6CV.js';
|
|
10
10
|
export { createButton } from './chunk-MMQPZGSU.js';
|
|
11
11
|
export { FLAG_CDN, FLAG_RATIO, configureFlags, flagAttributes, flagConfig, flagName, flagSrc, flagView, normalizeFlagCode, resetFlagConfig } from './chunk-LMZJBOZG.js';
|
|
12
12
|
export { createNotifications } from './chunk-SNYUBXWQ.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ContextMenu, useContextMenuContext } from './chunk-
|
|
2
|
-
import './chunk-
|
|
1
|
+
import { ContextMenu, useContextMenuContext } from './chunk-CPJJ3FPW.js';
|
|
2
|
+
import './chunk-YQV5XZIA.js';
|
|
3
3
|
import './chunk-4VUHQFAT.js';
|
|
4
4
|
import './chunk-HS3X3XCW.js';
|
|
5
5
|
import './chunk-4ZPMP47J.js';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Download, MenuButton } from './chunk-
|
|
2
|
-
import { downloadFile } from './chunk-
|
|
3
|
-
import { ContextMenu, useContextMenuContext } from './chunk-
|
|
1
|
+
import { Download, NewTab, MenuButton } from './chunk-O2UJ5ZIX.js';
|
|
2
|
+
import { downloadFile, openInNewTab } from './chunk-HUUINHPR.js';
|
|
3
|
+
import { ContextMenu, useContextMenuContext } from './chunk-CPJJ3FPW.js';
|
|
4
4
|
import './chunk-EYZ366LP.js';
|
|
5
|
-
import './chunk-
|
|
5
|
+
import './chunk-YQV5XZIA.js';
|
|
6
6
|
import './chunk-4VUHQFAT.js';
|
|
7
7
|
import './chunk-HS3X3XCW.js';
|
|
8
8
|
import './chunk-4ZPMP47J.js';
|
|
@@ -14,6 +14,9 @@ function ImageMenu({ item, index, options, labels }) {
|
|
|
14
14
|
if (options.download !== false) {
|
|
15
15
|
rows.push({ id: "download", label: labels.download ?? "Download", icon: /* @__PURE__ */ jsx(Download, {}) });
|
|
16
16
|
}
|
|
17
|
+
if (options.newTab !== false) {
|
|
18
|
+
rows.push({ id: "new-tab", label: labels.newTab ?? "Open in a new tab", icon: /* @__PURE__ */ jsx(NewTab, {}) });
|
|
19
|
+
}
|
|
17
20
|
if (options.items?.length) {
|
|
18
21
|
if (rows.length > 0) rows.push({ type: "separator" });
|
|
19
22
|
rows.push(...options.items);
|
|
@@ -25,6 +28,7 @@ function ImageMenu({ item, index, options, labels }) {
|
|
|
25
28
|
clipboard: false,
|
|
26
29
|
onSelect: (row) => {
|
|
27
30
|
if (row.id === "download") void downloadFile(item.download ?? item.src, item.filename);
|
|
31
|
+
if (row.id === "new-tab") openInNewTab(item.src);
|
|
28
32
|
options.onSelect?.(row.id, item, index);
|
|
29
33
|
},
|
|
30
34
|
children: [
|
package/dist/next/index.d.ts
CHANGED
|
@@ -24,14 +24,14 @@ export { R as RecentEntry, b as RecentStore, e as createRecentStore, g as groupR
|
|
|
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
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-
|
|
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-
|
|
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-eemzEBqB.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-qqpGBkny.js';
|
|
29
29
|
export { MarqueeRect, SelectionList, SelectionListProps, SelectionRenderer, SelectionRowRender, UseSelectionOptions, UseSelectionResult, useSelection } from '../react/selection.js';
|
|
30
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';
|
|
31
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
32
|
export { Image, ImageItem, ImageLabels, ImageMenuOptions, ImageProps, ImageSource, ZoomOptions } from '../react/image.js';
|
|
33
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-
|
|
34
|
+
export { C as ContextMenuContextValue, a as ContextMenuItem, b as ContextMenuNode, u as useContextMenuContext } from '../context-DR1dpO8b.js';
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
37
|
* The Next.js entry. Same components, wired to `next/link`.
|
package/dist/next/index.js
CHANGED
|
@@ -4,11 +4,11 @@ export { useSearch } from '../chunk-45UHLZYT.js';
|
|
|
4
4
|
export { useNetworkState } from '../chunk-S653GLSF.js';
|
|
5
5
|
export { RelativeTime } from '../chunk-OCMI7R6H.js';
|
|
6
6
|
export { PasswordStrength } from '../chunk-XQHCZAPJ.js';
|
|
7
|
-
export { ContextMenu, ContextMenuContent, ContextMenuList, ContextMenuPanel, ContextMenuRoot, ContextMenuRow, ContextMenuSearch, ContextMenuTrigger, useContextMenuContext } from '../chunk-
|
|
7
|
+
export { ContextMenu, ContextMenuContent, ContextMenuList, ContextMenuPanel, ContextMenuRoot, ContextMenuRow, ContextMenuSearch, ContextMenuTrigger, useContextMenuContext } from '../chunk-CPJJ3FPW.js';
|
|
8
8
|
export { SelectionList, useSelection } from '../chunk-N6PDHMAX.js';
|
|
9
|
-
export { Image } from '../chunk-
|
|
9
|
+
export { Image } from '../chunk-2RIO4VDV.js';
|
|
10
10
|
import '../chunk-EYZ366LP.js';
|
|
11
|
-
export { Video } from '../chunk-
|
|
11
|
+
export { Video } from '../chunk-PVDU6AZU.js';
|
|
12
12
|
import { Button } from '../chunk-6BGBYUSZ.js';
|
|
13
13
|
export { getLinkComponent, setLinkComponent, useButton } from '../chunk-6BGBYUSZ.js';
|
|
14
14
|
export { Flag } from '../chunk-NPHRS2Q7.js';
|
|
@@ -20,9 +20,9 @@ export { colorEquals, formatColor, hslToRgb, hsvToRgb, parseColor, rgbToHsl, rgb
|
|
|
20
20
|
import '../chunk-2QFTRNAZ.js';
|
|
21
21
|
import '../chunk-IXVMRVD4.js';
|
|
22
22
|
export { estimatePasswordStrength, generatePassword } from '../chunk-HC2ME5PU.js';
|
|
23
|
-
export { CLIPBOARD_PREFIX, clipboardAction, clipboardEntries, clipboardHasText, createContextMenu, inspectClipboardTarget, isAction, performClipboardAction } from '../chunk-
|
|
23
|
+
export { CLIPBOARD_PREFIX, clipboardAction, clipboardEntries, clipboardHasText, createContextMenu, inspectClipboardTarget, isAction, performClipboardAction } from '../chunk-YQV5XZIA.js';
|
|
24
24
|
export { DEFAULT_SELECTION_SHORTCUTS, createSelection } from '../chunk-WSQC3PCC.js';
|
|
25
|
-
import '../chunk-
|
|
25
|
+
import '../chunk-JLZDS6CV.js';
|
|
26
26
|
import '../chunk-MMQPZGSU.js';
|
|
27
27
|
export { configureFlags, flagAttributes, flagName, flagSrc, flagView, normalizeFlagCode } from '../chunk-LMZJBOZG.js';
|
|
28
28
|
import '../chunk-SNYUBXWQ.js';
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { ReactNode, ComponentPropsWithoutRef } from 'react';
|
|
2
|
-
import { b as ContextMenuNode, a as ContextMenuItem } from '../context-
|
|
3
|
-
export { C as ContextMenuContextValue, u as useContextMenuContext } from '../context-
|
|
4
|
-
import { c as ClipboardMenuOptions } from '../clipboard-menu-
|
|
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-
|
|
6
|
-
import { g as ContextMenuOptions, b as ContextMenuEntry } from '../context-menu-
|
|
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-
|
|
2
|
+
import { b as ContextMenuNode, a as ContextMenuItem } from '../context-DR1dpO8b.js';
|
|
3
|
+
export { C as ContextMenuContextValue, u as useContextMenuContext } from '../context-DR1dpO8b.js';
|
|
4
|
+
import { c as ClipboardMenuOptions } from '../clipboard-menu-eemzEBqB.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-eemzEBqB.js';
|
|
6
|
+
import { g as ContextMenuOptions, b as ContextMenuEntry } from '../context-menu-qqpGBkny.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-qqpGBkny.js';
|
|
8
8
|
export { S as Shortcut, b as ShortcutSpec, m as matchesShortcut, p as parseShortcut, e as shortcutText, f as shortcutTokens } from '../keys-D2zJs1uB.js';
|
|
9
9
|
import '../search-DYgqRp37.js';
|
|
10
10
|
|
|
@@ -28,6 +28,12 @@ interface ContextMenuRootProps {
|
|
|
28
28
|
* selection, Cut over a selection in something writable, Paste in anything writable.
|
|
29
29
|
*/
|
|
30
30
|
clipboard?: boolean | ClipboardMenuOptions;
|
|
31
|
+
/**
|
|
32
|
+
* A filter field over the rows. `"auto"` (the default) grows one only once there are
|
|
33
|
+
* enough rows to be worth filtering; `true` asks for one whatever the count - which is
|
|
34
|
+
* what a menu whose rows are fetched wants - and `false` never draws one.
|
|
35
|
+
*/
|
|
36
|
+
searchable?: boolean | "auto";
|
|
31
37
|
/** Fuse.js's constructor, for fuzzy filtering. Omit it for the built-in matcher. */
|
|
32
38
|
fuse?: ContextMenuOptions["fuse"];
|
|
33
39
|
fuseOptions?: Record<string, unknown>;
|
|
@@ -124,7 +130,7 @@ declare function ContextMenuRow({ level, index, entry, children, ...props }: Con
|
|
|
124
130
|
* is PREPENDED to `<head>`, so anything the document already has wins on source order at
|
|
125
131
|
* equal specificity.
|
|
126
132
|
*/
|
|
127
|
-
declare const CONTEXT_MENU_STYLES = "\n:root {\n --enigma-menu-bg: #1c1c1c;\n --enigma-menu-border: #333333;\n --enigma-menu-radius: 0.625rem;\n --enigma-menu-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);\n --enigma-menu-text: #f5f5f5;\n --enigma-menu-muted: #a3a3a3;\n --enigma-menu-font-size: 0.8125rem;\n --enigma-menu-min-width: 12rem;\n --enigma-menu-max-height: 20rem;\n\n --enigma-menu-active-bg: #2a2a2a;\n --enigma-menu-accent: #fbbf24;\n --enigma-menu-danger: #f87171;\n --enigma-menu-danger-bg: rgba(248, 113, 113, 0.12);\n}\n\n@media (prefers-color-scheme: light) {\n :root {\n --enigma-menu-bg: #ffffff;\n --enigma-menu-border: #e5e5e5;\n --enigma-menu-shadow: 0 12px 32px rgba(0, 0, 0, 0.12);\n --enigma-menu-text: #171717;\n --enigma-menu-muted: #737373;\n --enigma-menu-active-bg: #f5f5f5;\n --enigma-menu-accent: #b45309;\n --enigma-menu-danger: #b91c1c;\n --enigma-menu-danger-bg: rgba(185, 28, 28, 0.08);\n }\n}\n\n/* Every panel is positioned in VIEWPORT coordinates, which is what a pointer event reports\n and what a menu opened at the pointer needs. Fixed rather than absolute so a scrolling\n ancestor cannot drag it away from the place it was opened. */\n[data-enigma-menu-panel] {\n position: fixed; z-index:
|
|
133
|
+
declare const CONTEXT_MENU_STYLES = "\n:root {\n --enigma-menu-bg: #1c1c1c;\n --enigma-menu-border: #333333;\n --enigma-menu-radius: 0.625rem;\n --enigma-menu-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);\n --enigma-menu-text: #f5f5f5;\n --enigma-menu-muted: #a3a3a3;\n --enigma-menu-font-size: 0.8125rem;\n --enigma-menu-min-width: 12rem;\n --enigma-menu-max-height: 20rem;\n\n --enigma-menu-active-bg: #2a2a2a;\n --enigma-menu-accent: #fbbf24;\n --enigma-menu-danger: #f87171;\n --enigma-menu-danger-bg: rgba(248, 113, 113, 0.12);\n\n /* Above the lightbox, which sits at 9999, because a menu is opened FROM whatever is on\n top: the image viewer's own three-dot menu was portalled to the same body and painted\n underneath it, so its rows could be neither seen nor pressed. A menu is the topmost\n transient surface on a page, and this is the number that says so. It belongs here and\n not in the light-scheme block, or half the readers get an invalid z-index. */\n --enigma-menu-z: 10000;\n}\n\n@media (prefers-color-scheme: light) {\n :root {\n --enigma-menu-bg: #ffffff;\n --enigma-menu-border: #e5e5e5;\n --enigma-menu-shadow: 0 12px 32px rgba(0, 0, 0, 0.12);\n --enigma-menu-text: #171717;\n --enigma-menu-muted: #737373;\n --enigma-menu-active-bg: #f5f5f5;\n --enigma-menu-accent: #b45309;\n --enigma-menu-danger: #b91c1c;\n --enigma-menu-danger-bg: rgba(185, 28, 28, 0.08);\n }\n}\n\n/* Every panel is positioned in VIEWPORT coordinates, which is what a pointer event reports\n and what a menu opened at the pointer needs. Fixed rather than absolute so a scrolling\n ancestor cannot drag it away from the place it was opened. */\n[data-enigma-menu-panel] {\n position: fixed; z-index: var(--enigma-menu-z);\n box-sizing: border-box;\n min-width: var(--enigma-menu-min-width);\n max-width: min(22rem, calc(100vw - 1rem));\n padding: 0.25rem;\n color: var(--enigma-menu-text);\n background: var(--enigma-menu-bg);\n border: 1px solid var(--enigma-menu-border);\n border-radius: var(--enigma-menu-radius);\n box-shadow: var(--enigma-menu-shadow);\n font-size: var(--enigma-menu-font-size);\n animation: enigma-menu-in 90ms ease-out;\n /* Measured before it is placed, and placed before it is seen: without this the panel is\n painted at 0,0 for one frame and jumps to the pointer on the next. */\n visibility: hidden;\n}\n[data-enigma-menu-panel][data-placed] { visibility: visible; }\n/* No focus ring around the panel. It takes focus so the keyboard has somewhere to be, not\n because it is a control: what MOVES is the highlighted row, drawn by [data-active] and\n announced through aria-activedescendant. A ring around the whole menu says the menu is the\n thing focused, which is not what is happening - and it appears the moment you press an\n arrow, over a surface that was already showing you where you are. Nothing is lost by\n removing it, because nothing inside is reachable by Tab: the menu owns that key. */\n[data-enigma-menu-panel]:focus,\n[data-enigma-menu-panel]:focus-visible { outline: none; }\n@keyframes enigma-menu-in {\n from { opacity: 0; transform: scale(0.98); }\n to { opacity: 1; transform: none; }\n}\n@media (prefers-reduced-motion: reduce) {\n [data-enigma-menu-panel] { animation: none; }\n}\n\n/* The heading: what the menu is acting ON. A long file name is cut rather than allowed to\n set the panel's width, and the full one stays reachable through its title attribute. */\n[data-enigma-menu-title] {\n margin: 0; padding: 0.375rem 0.5rem 0.25rem;\n font-size: 0.6875rem; font-weight: 600;\n color: var(--enigma-menu-muted);\n overflow: hidden; white-space: nowrap; text-overflow: ellipsis;\n}\n\n[data-enigma-menu-search] {\n width: 100%; box-sizing: border-box;\n padding: 0.375rem 0.5rem 0.5rem;\n font: inherit; font-size: var(--enigma-menu-font-size);\n color: var(--enigma-menu-text); background: transparent;\n border: 0; border-bottom: 1px solid var(--enigma-menu-border);\n outline: none;\n}\n[data-enigma-menu-search]::-webkit-search-cancel-button,\n[data-enigma-menu-search]::-webkit-search-decoration { -webkit-appearance: none; appearance: none; }\n\n[data-enigma-menu-list] {\n max-height: var(--enigma-menu-max-height);\n overflow-y: auto; overscroll-behavior: contain;\n}\n\n[data-enigma-menu-item] {\n display: flex; align-items: center; gap: 0.5rem;\n padding: 0.3125rem 0.5rem; border-radius: 0.375rem;\n line-height: 1.4;\n color: var(--enigma-menu-text);\n /* The hand, not the arrow. A native menu uses the arrow because the whole surface is\n drawn by the OS and nothing on a page looks like it; here the rows sit on a web page,\n where the hand is what says \"this is a thing you press\". */\n cursor: pointer; user-select: none;\n}\n[data-enigma-menu-item][data-active] { background: var(--enigma-menu-active-bg); }\n[data-enigma-menu-item][data-disabled] { opacity: 0.45; cursor: not-allowed; }\n[data-enigma-menu-item][data-destructive] { color: var(--enigma-menu-danger); }\n[data-enigma-menu-item][data-destructive][data-active] { background: var(--enigma-menu-danger-bg); }\n\n[data-enigma-menu-item-text] { display: grid; min-width: 0; }\n[data-enigma-menu-item-label] { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }\n[data-enigma-menu-item-description] {\n font-size: 0.6875rem; color: var(--enigma-menu-muted);\n overflow: hidden; white-space: nowrap; text-overflow: ellipsis;\n}\n\n[data-enigma-menu-icon] { display: inline-flex; align-items: center; flex: none; width: 1rem; max-height: 1.25em; line-height: 0; }\n\n/* The shortcut, on the right, the way every desktop menu prints it. margin-left: auto is\n what pushes it there, and flex: none is what stops a long label squashing it. */\n[data-enigma-menu-shortcut] {\n display: flex; align-items: center; gap: 0.125rem;\n flex: none; margin-left: auto; padding-left: 1.5rem;\n font-size: 0.6875rem; color: var(--enigma-menu-muted);\n font-variant-numeric: tabular-nums;\n}\n[data-enigma-menu-shortcut] kbd { font: inherit; }\n\n/* The submenu arrow shares the shortcut's slot, so a row never has both pushed apart. */\n[data-enigma-menu-arrow] {\n flex: none; margin-left: auto;\n width: 0.35rem; height: 0.35rem;\n border-right: 1.5px solid currentColor; border-top: 1.5px solid currentColor;\n transform: rotate(45deg);\n opacity: 0.6;\n}\n[data-enigma-menu-shortcut] + [data-enigma-menu-arrow] { margin-left: 0.5rem; }\n\n/* Check and radio: drawn rather than loaded, and reserving their space either way so\n choosing a row does not shift the label under the pointer. */\n[data-enigma-menu-check] {\n flex: none; width: 1rem; height: 1rem;\n display: grid; place-items: center;\n color: var(--enigma-menu-accent);\n}\n[data-enigma-menu-check]::after { content: \"\"; width: 0.35rem; height: 0.6rem; opacity: 0; }\n[data-enigma-menu-item][aria-checked=\"true\"] [data-enigma-menu-check]::after {\n opacity: 1;\n border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;\n transform: rotate(45deg) translate(-0.05rem, -0.05rem);\n}\n[data-enigma-menu-item][role=\"menuitemradio\"] [data-enigma-menu-check]::after {\n width: 0.4rem; height: 0.4rem; border-radius: 999px; background: currentColor;\n transform: none; border: 0;\n}\n\n[data-enigma-menu-separator] {\n height: 1px; margin: 0.25rem 0.25rem;\n background: var(--enigma-menu-border);\n}\n\n[data-enigma-menu-label] {\n margin: 0.375rem 0 0.125rem; padding: 0 0.5rem;\n font-size: 0.6875rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em;\n color: var(--enigma-menu-muted);\n}\n\n[data-enigma-menu-status] {\n margin: 0; padding: 0.625rem 0.5rem;\n font-size: var(--enigma-menu-font-size); color: var(--enigma-menu-muted);\n /* The quoted query is cut in the text as well, but a pasted string with no spaces has no\n break opportunity at all - so this is what stops it stretching the panel. */\n overflow-wrap: anywhere;\n}\n[data-enigma-menu-status][data-error] { color: var(--enigma-menu-danger); }\n\n/* The end-of-window marker: one pixel, so it has a box to be scrolled into. */\n[data-enigma-menu-more] { height: 1px; }\n";
|
|
128
134
|
|
|
129
135
|
type ContextMenuProps = ContextMenuRootProps & {
|
|
130
136
|
/** How many rows to put in the document at once. `Infinity` renders the lot. */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
export { CONTEXT_MENU_STYLES, ContextMenu, ContextMenuContent, ContextMenuList, ContextMenuPanel, ContextMenuRoot, ContextMenuRow, ContextMenuSearch, ContextMenuTrigger, useContextMenuContext } from '../chunk-
|
|
3
|
-
export { CLIPBOARD_PREFIX, CONTEXT_MENU_SEARCH_KEYS, clipboardAction, clipboardEntries, clipboardHasText, createContextMenu, inspectClipboardTarget, isAction, performClipboardAction } from '../chunk-
|
|
2
|
+
export { CONTEXT_MENU_STYLES, ContextMenu, ContextMenuContent, ContextMenuList, ContextMenuPanel, ContextMenuRoot, ContextMenuRow, ContextMenuSearch, ContextMenuTrigger, useContextMenuContext } from '../chunk-CPJJ3FPW.js';
|
|
3
|
+
export { CLIPBOARD_PREFIX, CONTEXT_MENU_SEARCH_KEYS, clipboardAction, clipboardEntries, clipboardHasText, createContextMenu, inspectClipboardTarget, isAction, performClipboardAction } from '../chunk-YQV5XZIA.js';
|
|
4
4
|
export { matchesShortcut, parseShortcut, shortcutText, shortcutTokens } from '../chunk-4VUHQFAT.js';
|
|
5
5
|
import '../chunk-HS3X3XCW.js';
|
|
6
6
|
import '../chunk-4ZPMP47J.js';
|
package/dist/react/image.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ComponentPropsWithoutRef, ReactNode } from 'react';
|
|
2
|
-
import { b as ContextMenuNode } from '../context-
|
|
3
|
-
import '../context-menu-
|
|
2
|
+
import { b as ContextMenuNode } from '../context-DR1dpO8b.js';
|
|
3
|
+
import '../context-menu-qqpGBkny.js';
|
|
4
4
|
import '../search-DYgqRp37.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -38,6 +38,8 @@ interface ZoomOptions {
|
|
|
38
38
|
interface ImageMenuOptions {
|
|
39
39
|
/** The download row. On whenever the menu is. */
|
|
40
40
|
download?: boolean;
|
|
41
|
+
/** The row that opens the picture on its own, in another tab. On whenever the menu is. */
|
|
42
|
+
newTab?: boolean;
|
|
41
43
|
/** Rows of your own, after the built-in ones. */
|
|
42
44
|
items?: readonly ContextMenuNode[];
|
|
43
45
|
onSelect?: (id: string, item: ImageItem, index: number) => void;
|
|
@@ -53,6 +55,7 @@ interface ImageLabels {
|
|
|
53
55
|
next?: string;
|
|
54
56
|
menu?: string;
|
|
55
57
|
download?: string;
|
|
58
|
+
newTab?: string;
|
|
56
59
|
discard?: string;
|
|
57
60
|
thumbnails?: string;
|
|
58
61
|
/** The frame itself, announced as the dialog's name. Default "Image viewer". */
|
package/dist/react/image.js
CHANGED
package/dist/react/index.d.ts
CHANGED
|
@@ -26,14 +26,14 @@ export { R as RecentEntry, b as RecentStore, e as createRecentStore, g as groupR
|
|
|
26
26
|
export { Select, SelectContent, SelectContextValue, SelectItem, SelectList, SelectMultipleProps, SelectOptionRow, SelectProps, SelectRoot, SelectRootProps, SelectSearch, SelectSingleProps, SelectTrigger, SelectValue, useSelectContext } from './select.js';
|
|
27
27
|
export { a as SelectInstance, c as SelectOption, d as SelectOptions, e as SelectState, f as createSelect } from '../select-ClSy-J1f.js';
|
|
28
28
|
export { ContextMenu, ContextMenuContent, ContextMenuContentProps, ContextMenuList, ContextMenuPanel, ContextMenuProps, ContextMenuRoot, ContextMenuRootProps, ContextMenuRow, ContextMenuSearch, ContextMenuTrigger, ContextMenuTriggerProps } from './context-menu.js';
|
|
29
|
-
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-
|
|
30
|
-
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-
|
|
29
|
+
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-eemzEBqB.js';
|
|
30
|
+
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-qqpGBkny.js';
|
|
31
31
|
export { MarqueeRect, SelectionList, SelectionListProps, SelectionRenderer, SelectionRowRender, UseSelectionOptions, UseSelectionResult, useSelection } from './selection.js';
|
|
32
32
|
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';
|
|
33
33
|
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';
|
|
34
34
|
export { Image, ImageItem, ImageLabels, ImageMenuOptions, ImageProps, ImageSource, ZoomOptions } from './image.js';
|
|
35
35
|
export { Video, VideoControls, VideoLabels, VideoProps, VideoSource, VideoTrack } from './video.js';
|
|
36
|
-
export { C as ContextMenuContextValue, a as ContextMenuItem, b as ContextMenuNode, u as useContextMenuContext } from '../context-
|
|
36
|
+
export { C as ContextMenuContextValue, a as ContextMenuItem, b as ContextMenuNode, u as useContextMenuContext } from '../context-DR1dpO8b.js';
|
|
37
37
|
|
|
38
38
|
interface UseInputResult {
|
|
39
39
|
/** Attach to the `<input>`. */
|